How to fill a heart?

1

When making an outline of 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 do I fill it out? So move from Figure 1 to Figure 2;

Since there are already the contour coordinates and need to make a for inside the file and then divide the Array_point by some number and multiply by the for variable?

    
asked by anonymous 18.06.2016 / 03:28

1 answer

1

The answer is unfortunately a bit more complicated than you'd like. For the following reason: your program does the drawing - your program calls the "gnuplot" that does the drawing externally.

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

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

So, just to be clear - if your program were even generating the image, 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 that array using an image file manipulation library - to generate a .PNG or .JPG file on the disk directly (and not by calling an external program).

There are other options, such as libraries that represent image directly on the screen, such as gtk + or qt - if you want to do this in C, maybe a legal one is the cairo library that is in C and allows you to generate output for both screen as well as a file on disk -alias to Cairo certainly will 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 however will be a little tricky - but it can be a good path: link

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

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

#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;
}
    
20.06.2016 / 06:05