From b5210c4d6555430b640d6acd3673b292201eba03 Mon Sep 17 00:00:00 2001 From: Trammell Hudson Date: Sun, 15 Feb 2015 16:13:32 -0500 Subject: [PATCH] move inset into stl_3d --- faces.c | 137 +------------------------------------------------------ stl_3d.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++ stl_3d.h | 11 +++++ 3 files changed, 145 insertions(+), 136 deletions(-) diff --git a/faces.c b/faces.c index 486382d..4343925 100644 --- a/faces.c +++ b/faces.c @@ -57,141 +57,6 @@ svg_circle( } -// Determines the intersection point of the line defined by points A and B with the -// line defined by points C and D. -// -// Returns YES if the intersection point was found, and stores that point in X,Y. -// Returns NO if there is no determinable intersection point, in which case X,Y will -// be unmodified. - -static int -line_intersect( - double Ax, double Ay, - double Bx, double By, - double Cx, double Cy, - double Dx, double Dy, - double *X, double *Y -) -{ - // Fail if either line is undefined. - if ((Ax==Bx && Ay==By) || (Cx==Dx && Cy==Dy)) - return 0; - - // (1) Translate the system so that point A is on the origin. - Bx-=Ax; By-=Ay; - Cx-=Ax; Cy-=Ay; - Dx-=Ax; Dy-=Ay; - - // Discover the length of segment A-B. - const double distAB=sqrt(Bx*Bx+By*By); - - // (2) Rotate the system so that point B is on the positive X axis. - const double theCos=Bx/distAB; - const double theSin=By/distAB; - - double newX=Cx*theCos+Cy*theSin; - Cy =Cy*theCos-Cx*theSin; Cx=newX; - newX=Dx*theCos+Dy*theSin; - Dy =Dy*theCos-Dx*theSin; Dx=newX; - - // Fail if the lines are parallel. - if (Cy==Dy) return 0; - - // (3) Discover the position of the intersection point along line A-B. - const double ABpos=Dx+(Cx-Dx)*Dy/(Dy-Cy); - - // (4) Apply the discovered position to line A-B in the original coordinate system. - *X=Ax+ABpos*theCos; - *Y=Ay+ABpos*theSin; - - return 1; -} - - - -/** Compute the inset coordinate. - * http://alienryderflex.com/polygon_inset/ -// Given the sequentially connected points (a,b), (c,d), and (e,f), this -// function returns, in (C,D), a bevel-inset replacement for point (c,d). -// -// Note: If vectors (a,b)->(c,d) and (c,d)->(e,f) are exactly 180° opposed, -// or if either segment is zero-length, this function will do -// nothing; i.e. point (C,D) will not be set. - - */ -void -inset( - const refframe_t * const ref, - const double inset_dist, - double * const x_out, - double * const y_out, - const v3_t p0, // previous point - const v3_t p1, // current point to inset - const v3_t p2 // next point -) -{ - double a, b, c, d, e, f; - v3_project(ref, p0, &a, &b); - v3_project(ref, p1, &c, &d); - v3_project(ref, p2, &e, &f); - - double c1 = c; - double d1 = d; - double c2 = c; - double d2 = d; - - // Calculate length of line segments. - const double dx1 = c-a; - const double dy1 = d-b; - const double dist1 = sqrt(dx1*dx1+dy1*dy1); - const double dx2 = e-c; - const double dy2 = f-d; - const double dist2 = sqrt(dx2*dx2+dy2*dy2); - - // Exit if either segment is zero-length. - if (dist1==0. || dist2==0.) - { - *x_out = *y_out = 0; - fprintf(stderr, "inset fail\n"); - return; - } - - // Inset each of the two line segments. - double insetX, insetY; - - insetX = dy1/dist1 * inset_dist; - a+=insetX; - c1+=insetX; - - insetY = -dx1/dist1 * inset_dist; - b+=insetY; - d1+=insetY; - - insetX = dy2/dist2 * inset_dist; - e+=insetX; - c2+=insetX; - - insetY = -dx2/dist2 * inset_dist; - f+=insetY; - d2+=insetY; - - // If inset segments connect perfectly, return the connection point. - if (c1==c2 && d1==d2) - { - *x_out = c1; - *y_out = d1; - return; - } - - // Return the intersection point of the two inset segments (if any). - if (line_intersect(a,b,c1,d1,c2,d2,e,f, x_out, y_out)) - return; - - *x_out = *y_out = 0; - fprintf(stderr, "inset failed 2\n"); -} - - int main(void) { @@ -247,7 +112,7 @@ main(void) for (int j = 0 ; j < vertex_count ; j++) { double x, y; - inset(&ref, inset_distance, &x, &y, + refframe_inset(&ref, inset_distance, &x, &y, vertex_list[(j+0) % vertex_count]->p, vertex_list[(j+1) % vertex_count]->p, vertex_list[(j+2) % vertex_count]->p diff --git a/stl_3d.c b/stl_3d.c index 2aa88f7..1d39e6d 100644 --- a/stl_3d.c +++ b/stl_3d.c @@ -335,3 +335,136 @@ v3_project( } +// Determines the intersection point of the line defined by points A and B with the +// line defined by points C and D. +// +// Returns YES if the intersection point was found, and stores that point in X,Y. +// Returns NO if there is no determinable intersection point, in which case X,Y will +// be unmodified. + +static int +line_intersect( + double Ax, double Ay, + double Bx, double By, + double Cx, double Cy, + double Dx, double Dy, + double *X, double *Y +) +{ + // Fail if either line is undefined. + if ((Ax==Bx && Ay==By) || (Cx==Dx && Cy==Dy)) + return 0; + + // (1) Translate the system so that point A is on the origin. + Bx-=Ax; By-=Ay; + Cx-=Ax; Cy-=Ay; + Dx-=Ax; Dy-=Ay; + + // Discover the length of segment A-B. + const double distAB=sqrt(Bx*Bx+By*By); + + // (2) Rotate the system so that point B is on the positive X axis. + const double theCos=Bx/distAB; + const double theSin=By/distAB; + + double newX=Cx*theCos+Cy*theSin; + Cy =Cy*theCos-Cx*theSin; Cx=newX; + newX=Dx*theCos+Dy*theSin; + Dy =Dy*theCos-Dx*theSin; Dx=newX; + + // Fail if the lines are parallel. + if (Cy==Dy) return 0; + + // (3) Discover the position of the intersection point along line A-B. + const double ABpos=Dx+(Cx-Dx)*Dy/(Dy-Cy); + + // (4) Apply the discovered position to line A-B in the original coordinate system. + *X=Ax+ABpos*theCos; + *Y=Ay+ABpos*theSin; + + return 1; +} + + + +/** Compute the inset coordinate. + * http://alienryderflex.com/polygon_inset/ +// Given the sequentially connected points (a,b), (c,d), and (e,f), this +// function returns, in (C,D), a bevel-inset replacement for point (c,d). +// +// Note: If vectors (a,b)->(c,d) and (c,d)->(e,f) are exactly 180° opposed, +// or if either segment is zero-length, this function will do +// nothing; i.e. point (C,D) will not be set. + + */ +void +refframe_inset( + const refframe_t * const ref, + const double inset_dist, + double * const x_out, + double * const y_out, + const v3_t p0, // previous point + const v3_t p1, // current point to inset + const v3_t p2 // next point +) +{ + double a, b, c, d, e, f; + v3_project(ref, p0, &a, &b); + v3_project(ref, p1, &c, &d); + v3_project(ref, p2, &e, &f); + + double c1 = c; + double d1 = d; + double c2 = c; + double d2 = d; + + // Calculate length of line segments. + const double dx1 = c-a; + const double dy1 = d-b; + const double dist1 = sqrt(dx1*dx1+dy1*dy1); + const double dx2 = e-c; + const double dy2 = f-d; + const double dist2 = sqrt(dx2*dx2+dy2*dy2); + + // Exit if either segment is zero-length. + if (dist1==0. || dist2==0.) + { + *x_out = *y_out = 0; + fprintf(stderr, "inset fail\n"); + return; + } + + // Inset each of the two line segments. + double insetX, insetY; + + insetX = dy1/dist1 * inset_dist; + a+=insetX; + c1+=insetX; + + insetY = -dx1/dist1 * inset_dist; + b+=insetY; + d1+=insetY; + + insetX = dy2/dist2 * inset_dist; + e+=insetX; + c2+=insetX; + + insetY = -dx2/dist2 * inset_dist; + f+=insetY; + d2+=insetY; + + // If inset segments connect perfectly, return the connection point. + if (c1==c2 && d1==d2) + { + *x_out = c1; + *y_out = d1; + return; + } + + // Return the intersection point of the two inset segments (if any). + if (line_intersect(a,b,c1,d1,c2,d2,e,f, x_out, y_out)) + return; + + *x_out = *y_out = 0; + fprintf(stderr, "inset failed 2\n"); +} diff --git a/stl_3d.h b/stl_3d.h index 04d0d1b..b6e47ef 100644 --- a/stl_3d.h +++ b/stl_3d.h @@ -82,6 +82,17 @@ refframe_init( ); +void +refframe_inset( + const refframe_t * const ref, + const double inset_dist, + double * const x_out, + double * const y_out, + const v3_t p0, // previous point + const v3_t p1, // current point to inset + const v3_t p2 // next point +); + /** Project a 3D point onto a 2D space */ void v3_project(