How to fill a heart?

Asked

Viewed 1,352 times

1

when contouring a heart:

#include <stdio.h>
#include <stdlib.h>
#define TAM_MAX_PONTOS_EXTERNOS 300
#include <math.h>

typedef struct{
  float x;
  float y;
  } ponto;

int main()
{
    printf("Programa que plota o coracao\n");
     float *t_array = malloc(TAM_MAX_PONTOS_EXTERNOS * sizeof(float));
     ponto *pontos_array = malloc(TAM_MAX_PONTOS_EXTERNOS * sizeof(ponto));

     t_array[0] = 0.0;
     int i;
     for (i=1; i<TAM_MAX_PONTOS_EXTERNOS; i++)
        t_array[i] = t_array[i-1] + 0.1;

    for (i=0; i<TAM_MAX_PONTOS_EXTERNOS; i++){
        pontos_array[i].x = 16*pow(sin(t_array[i]),3);
        pontos_array[i].y = 13*cos(t_array[i]) - 5*cos(2*t_array[i]) - 2*cos(3*t_array[i])-cos(4*t_array[i]);
    }

    FILE *arquivo;
    arquivo = fopen("dados.dat", "w");


    for (i=0; i<TAM_MAX_PONTOS_EXTERNOS; i++)
        fprintf(arquivo, "%f\t%f\n", pontos_array[i].x, pontos_array[i].y);

    fclose(arquivo);


    FILE *scriptFile;
    scriptFile = fopen("scriptFile.scp", "w");
    fprintf(scriptFile, "plot 'dados.dat'");
    fclose(scriptFile);
    system("gnuplot scriptFile.scp -persistent");


    return 0;

How can I fill it? So move from figure 1 to figure 2;Contorno de um símbolo de coração em um plano bidimensionalSímbolo de um coração preenchido em um plano bidimensional

Since there are already the coordinates of the outline and need to do a for inside the file and then divide the point_Array by some number and multiply by the variable of the for?

1 answer

1

The answer is unfortunately a little more complicated than you would like. For the following reason: your program does not draw - your program calls the "gnuplot" which does the drawing externally.

What your program does is generate the coordinate pairs (x,y) given the parametric (mathematical) functions within the second loop.

Only for gnuplot, what appears is a sparse data cloud - it’s not a closed curve - what it does is mark each point of the cloud with a colored tag. If you try to change your program to store more values, you will certainly be able to generate points within the heart figure - but they will still be sparse points, not a solid image. (gnuplot is a pretty powerful program in itself - it’s even possible that it itself supports parametric curves and can draw closed 2D figruas - but that’s another problem too).

So - just to be clear - if your program were actually generating the image, and not just pairs (x,y) - it would have an array in memory, say 10024x768 positions, where each position would represent a pixel - and then export this array using an image file manipulation library - to generate a file. PNG or . JPG on disk directly (and not calling an external program).

There are other options, such as libraries that represent an image directly on the screen, such as gtk+ or Qt - if you want to do this in C, maybe a cool one is the "Cairo" library that is in C and allows you to generate the output for both the screen and a disk file -alias Cairo will certainly have calls that allow you to pass your points, and from them form a curve, which can be interpreted as a closed image, which can then be filled. Understanding and using Cairo will however be a little complicated - but it can be a good way: https://cairographics.org/

Now, as for your program as is, for each pair (x,y) generated in the current form, make a second loop with an "r" variable that varies from 0 to 1, and multiply the x and y coordinates by r and write it to the output file. As described above, this would be an sparse cloud and a way to fill this cloud with is to change the parameters "pt" (point type) and "ps" (point size) of Gnuplot to each point to be a circle with a given radius larger.

To avoid large arrays, we can adjust the program to write the values directly to disk, instead of storing them in an array, only to then go through the array once and save each pair of values to disk. Similarly, the value of the parameter "t" stored in t_array can be calculated directly, there being no need to have an array with all its predetermined values. The finl program can be something like that:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define TAM_MAX_PONTOS_EXTERNOS 300
#define PONTOS_POR_RAIO 15
#define step 0.1

typedef struct{
  float x;
  float y;
  } ponto;

int main() {
    FILE *arquivo;
    double r, t;
    ponto P0, P;
    int i;

    printf("Programa que plota o coracao\n");
    // float *t_array = malloc(TAM_MAX_PONTOS_EXTERNOS * sizeof(float));
    // ponto *pontos_array = malloc(TAM_MAX_PONTOS_EXTERNOS * sizeof(ponto));

    arquivo = fopen("dados.dat", "w");
    t = 0;
    for (i=0; i<TAM_MAX_PONTOS_EXTERNOS; i++) {
        P0.x = 16*pow(sin(t),3);
        P0.y = 13*cos(t) - 5*cos(2*t) - 2*cos(3*t)-cos(4*t);
        for (r=0; r < 1.0; r+=1.0/PONTOS_POR_RAIO) {
            P.x = r * P0.x;
            P.y = r * P0.y;
            fprintf(arquivo, "%f\t%f\n", P.x, P.y);
        }
        t += 0.1;
    }

    fclose(arquivo);


    FILE *scriptFile;
    scriptFile = fopen("scriptFile.scp", "w");
    fprintf(scriptFile, "plot 'dados.dat' pt 7 ps 3");
    fclose(scriptFile);
    system("gnuplot scriptFile.scp -persistent");

    return 0;
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.