$ git clone http://gcodetool.ion.nu/gcodetool.git
commit a041b54c558d677af05beb61b64dcea6325b203b
Author: Alicia <...>
Date: Sat Oct 26 16:03:51 2019 +0200
Added center of mass calculation to the info subcommand and a -p argument to the preview subcommand to mark a point in space.
diff --git a/info.c b/info.c
index 27e700e..c4e7916 100644
--- a/info.c
+++ b/info.c
@@ -68,6 +68,7 @@ int gtool_info(const char* filename)
unsigned int tooltempcount=0;
double* bedtemps=0;
unsigned int bedtempcount=0;
+ double centermass[4]={0,0,0,0};
double eoffset=0;
// Loop through gcode and analyze commands
while((cmd=gcode_readcommand(gcode)))
@@ -84,14 +85,19 @@ int gtool_info(const char* filename)
char move=(!isnan(xval) || !isnan(yval));
if(!isnan(fval)){frate=fval;}
if(!isnan(zval)){zpos=zval;} // Take things like 'lift head' into account, don't treat as Z until there's a positive E
- // Printing line length
if(!isnan(eval) && move && eval>0)
{
+ // Printing line length
double xdist=x.last-(isnan(xval)?x.last:xval);
double ydist=y.last-(isnan(yval)?y.last:yval);
double dist=sqrt(xdist*xdist+ydist*ydist);
// printf("Print distance: %f\n", dist);
minmax(&emove, dist);
+ // Center of mass
+ centermass[0]+=(isnan(xval)?x.last:(xval+x.last)/2)*(eval-e.last);
+ centermass[1]+=(isnan(yval)?y.last:(yval+y.last)/2)*(eval-e.last);
+ centermass[2]+=(isnan(zpos)?layer.last:zpos)*(eval-e.last);
+ centermass[3]+=eval-e.last;
// Layer heights
if(!isnan(zpos))
{
@@ -168,7 +174,7 @@ int gtool_info(const char* filename)
if(i==bedtempcount-1 && bedtemps[i]==0){break;}
printf("%s%.*f°C", (i>0)?", ":"", pd(bedtemps[i]));
}
- if(i>0 && i==bedtempcount){printf(" (WARNING: This gcode file appears to leave to bed heater on)");}
+ if(i>0 && i==bedtempcount){printf(" (WARNING: This gcode file appears to leave the bed heater on)");}
printf("\n");
printf("Tool temperature(s): ");
for(i=0; i<tooltempcount; ++i)
@@ -176,7 +182,7 @@ int gtool_info(const char* filename)
if(i==tooltempcount-1 && tooltemps[i]==0){break;}
printf("%s%.*f°C", (i>0)?", ":"", pd(tooltemps[i]));
}
- if(i>0 && i==tooltempcount){printf(" (WARNING: This gcode file appears to leave to tool heater on)");}
+ if(i>0 && i==tooltempcount){printf(" (WARNING: This gcode file appears to leave the tool heater on)");}
printf("\n");
printf("Size(X): %.*fmm (%.*f - %.*f)\n", pd(x.max-x.min), pd(x.min), pd(x.max));
printf("Size(Y): %.*fmm (%.*f - %.*f)\n", pd(y.max-y.min), pd(y.min), pd(y.max));
@@ -187,6 +193,10 @@ int gtool_info(const char* filename)
printf("Un-retraction length: %.*fmm\n", pd(retraction.max));
printf("Number of retractions: %u\n", retractcount);
printf("Filament use: %.*fmm\n", pd(e.max-e.min+eoffset));
+ centermass[0]/=centermass[3];
+ centermass[1]/=centermass[3];
+ centermass[2]/=centermass[3];
+ printf("Center of mass: %.*f x %.*f x %.*f\n", pd(centermass[0]), pd(centermass[1]), pd(centermass[2]));
printf("Retraction speed: %.*fmm/s - %.*fmm/s\n", pd(retractspeed.min/60), pd(retractspeed.max/60));
printf("Print speed: %.*fmm/s - %.*fmm/s\n", pd(printspeed.min/60), pd(printspeed.max/60));
printf("Travel speed: %.*fmm/s - %.*fmm/s\n", pd(travelspeed.min/60), pd(travelspeed.max/60));
diff --git a/preview.c b/preview.c
index b59c37a..3274693 100644
--- a/preview.c
+++ b/preview.c
@@ -30,6 +30,7 @@ struct line // TODO: Consider non-planar printing?
{
double x[2];
double y[2];
+ char special;
};
struct vectorlayer
@@ -46,18 +47,22 @@ struct vectors
unsigned int current;
};
-static void vector_draw(struct vectors* v, double startx, double starty, double endx, double endy, double z)
+static void vector_draw(struct vectors* v, double startx, double starty, double endx, double endy, double z, char special)
{
if(v->layers && v->layers[v->current].z!=z)
{
for(v->current=0; v->current<v->layercount; ++v->current)
{
- if(v->layers[v->current].z==z){break;}
+ if(v->layers[v->current].z>=z){break;}
}
}
- if(v->current==v->layercount)
+ if(v->current==v->layercount || v->layers[v->current].z!=z)
{
v->layers=realloc(v->layers, sizeof(struct vectorlayer)*(++v->layercount));
+ if(v->current+1<v->layercount) // Insert a layer rather than adding one on top
+ {
+ memmove(&v->layers[v->current+1], &v->layers[v->current], (v->layercount-v->current-1)*sizeof(struct vectorlayer));
+ }
v->layers[v->current].z=z;
v->layers[v->current].lines=0;
v->layers[v->current].linecount=0;
@@ -69,6 +74,7 @@ static void vector_draw(struct vectors* v, double startx, double starty, double
l->x[1]=endx;
l->y[0]=starty;
l->y[1]=endy;
+ l->special=special;
}
static void cb_drawline(struct img* img, int* x, int* y, unsigned char r, unsigned char g, unsigned char b, double linewidth) // Generic line drawing implementation for display methods that don't have their own line drawing functions
@@ -105,7 +111,7 @@ static void cb_drawline(struct img* img, int* x, int* y, unsigned char r, unsign
}
}
-int gtool_preview(const char* filename, struct img* img, double angle, double zrot)
+int gtool_preview(const char* filename, struct img* img, double angle, double zrot, double* point)
{
struct gcode* gcode=gcode_read(filename);
if(!gcode){return -1;}
@@ -146,7 +152,7 @@ int gtool_preview(const char* filename, struct img* img, double angle, double zr
if(!isnan(eval) && eval>olde && move)
{
olde=eval;
- vector_draw(&vectors, oldx, oldy, xval, yval, zval);
+ vector_draw(&vectors, oldx, oldy, xval, yval, zval, 0);
if(isnan(max[0]) || xval>max[0]){max[0]=xval;}
if(isnan(max[1]) || yval>max[1]){max[1]=yval;}
if(isnan(max[2]) || zval>max[2]){max[2]=zval;}
@@ -166,6 +172,17 @@ int gtool_preview(const char* filename, struct img* img, double angle, double zr
}
gcode_free(gcode);
double center[]={(min[0]+max[0])/2, (min[1]+max[1])/2, (min[2]+max[2])/2};
+ if(!isnan(point[0]+point[1]+point[2])) // Draw cross to mark the point
+ {
+ vector_draw(&vectors, min[0]-5, point[1], max[0]+5, point[1], point[2], 1);
+ vector_draw(&vectors, point[0], min[1]-5, point[0], max[1]+5, point[2], 1);
+ double z;
+ for(z=min[2]-5; z<max[2]+5; z+=0.1)
+ {
+ vector_draw(&vectors, point[0]-0.2, point[1], point[0]+0.2, point[1], z, 1);
+ vector_draw(&vectors, point[0], point[1]-0.2, point[0], point[1]+0.2, z, 1);
+ }
+ }
// Figure out how to scale things
double scale=0;
unsigned int i;
@@ -198,10 +215,12 @@ if(fabs(angle)>M_PI_2){i=vectors.layercount-1-i;}
// TODO: Do this more cleanly
struct line line;
struct line* l=&line;
+// Rotate X and Y around Z
l->y[0]=sin(zrot)*cy(oldl->y[0])+cos(zrot)*cx(oldl->x[0]);
l->x[0]=sin(zrot+M_PI_2)*cy(oldl->y[0])+cos(zrot+M_PI_2)*cx(oldl->x[0]);
l->y[1]=sin(zrot)*cy(oldl->y[1])+cos(zrot)*cx(oldl->x[1]);
l->x[1]=sin(zrot+M_PI_2)*cy(oldl->y[1])+cos(zrot+M_PI_2)*cx(oldl->x[1]);
+// Rotate the resulting Y around X
l->y[0]=l->y[0]*cos(angle)+(vectors.layers[i].z-center[2])*scale*sin(angle);
l->y[1]=l->y[1]*cos(angle)+(vectors.layers[i].z-center[2])*scale*sin(angle);
#define polcmp(n) ((n[0]>=0&&n[1]>=0) || (n[0]<0&&n[1]<0)) // Polarity comparison
@@ -210,7 +229,12 @@ l->y[1]=l->y[1]*cos(angle)+(vectors.layers[i].z-center[2])*scale*sin(angle);
if(fabs(l->y[0])>img->height/2 && fabs(l->y[1])>img->height/2 && polcmp(l->y)){continue;}
int x[]={l->x[0]+img->width/2, l->x[1]+img->width/2};
int y[]={l->y[0]+img->height/2, l->y[1]+img->height/2};
- img->drawline(img, x, y, c, c/1.05, c/2, linescale);
+ if(oldl->special)
+ {
+ img->drawline(img, x, y, 255, 0, 0, linescale);
+ }else{
+ img->drawline(img, x, y, c, c/1.05, c/2, linescale);
+ }
}
if(fabs(angle)>M_PI_2){i=vectors.layercount-1-i;}
}
@@ -243,6 +267,7 @@ int gtool_preview_arg(int argc, char** argv)
const char* outfile=0;
double rx=0,rz=0;
int width=0,height=0;
+ double point[3]={NAN,NAN,NAN};
struct img*(*imginit)(int width, int height, const char* filename)=0;
int i;
for(i=2; i<argc; ++i)
@@ -282,6 +307,19 @@ int gtool_preview_arg(int argc, char** argv)
width=strtol(argv[++i], &end, 0);
if(end && end[0]){height=strtol(&end[1], 0, 0);}else{height=width;}
}
+ else if((!strcmp(argv[i], "-p") || !strcmp(argv[i], "--point")) && i+1<argc)
+ {
+ ++i;
+ char* y=strchr(argv[i], 'x');
+ if(!y){continue;} // TODO: Warn about invalid coordinate format
+ while(strchr("x, ",y[0])){y=&y[1];}
+ char* z=strchr(y, 'x');
+ if(!z){continue;}
+ while(strchr("x, ",z[0])){z=&z[1];}
+ point[0]=strtod(argv[i],0);
+ point[1]=strtod(y,0);
+ point[2]=strtod(z,0);
+ }
else if(!filename)
{
filename=argv[i];
@@ -295,6 +333,7 @@ int gtool_preview_arg(int argc, char** argv)
"--r[xz] <angle> = rotate X or Z <angle> degrees\n"
"-o/--output <method> <file> = select output method and filename\n"
"-s/--size <width>x<height> = set output size\n"
+ "-p/--point <X>x<Y>x<Z> = point at a point in space\n"
"TODO: scale etc.\n"
"\n"
"Available output methods:\n"
@@ -323,5 +362,5 @@ int gtool_preview_arg(int argc, char** argv)
img=gtool_preview_pnm(width, height, "preview.pnm"); // Last resort
}
if(!img->drawline){img->drawline=cb_drawline;}
- return gtool_preview(filename, img, rx, rz);
+ return gtool_preview(filename, img, rx, rz, point);
}