/*****************************************************************************/ /* */ /* F I S T : Fast, Industrial-Strength Triangulation */ /* */ /*****************************************************************************/ /* */ /* (C) Martin Held */ /* (C) Universitaet Salzburg, Salzburg, Austria */ /* */ /* This code is not in the public domain. All rights reserved! Please make */ /* sure to read the full copyright statement contained in api_functions.cpp. */ /* */ /*****************************************************************************/ /* */ /* get standard libraries */ /* */ #include #include #include #include #include #include #include /* */ /* get my header files */ /* */ #include "fpkernel.h" #include "martin.h" #include "defs.h" #include "list.h" #include "basic.h" #include "header.h" #ifdef GRAPHICS #include "graphics.h" #endif /* */ /* function prototypes of functions provided in this file */ /* */ void InitIOListDefaults(iolistdef *iolist); void ResetIOListData(iolistdef *iolist); void Read2DInputData(global_struct *all); void StartPoly(global_struct *all); void CloseCurrentPoly(global_struct *all); void DXFStartPoly(global_struct *all); void DXFCloseCurrentPoly(global_struct *all, double bulge); #ifdef EXT_APPL_SITES void AddPolyVertex(global_struct *all, double xc1, double yc1, eas_type eas_data); #else void AddPolyVertex(global_struct *all, double xc1, double yc1); #endif void DXFAddPolyVertex(global_struct *all, double xc1, double yc1, double bulge); void EnsureClosedPolygon(global_struct *all); #ifdef EXT_APPL_SITES int HandlePnt(global_struct *all, double xc1, double yc1, eas_type eas_data); void HandleSeg(global_struct *all, double xc1, double yc1, double xc2, double yc2, eas_type eas_data); void HandleArc(global_struct *all, double xc1, double yc1, double xc2, double yc2, double xc3, double yc3, int attr, eas_type eas_data); #else int HandlePnt(global_struct *all, double xc1, double yc1); void HandleSeg(global_struct *all, double xc1, double yc1, double xc2, double yc2); void HandleArc(global_struct *all, double xc1, double yc1, double xc2, double yc2, double xc3, double yc3, int attr); #endif void InitIOListDefaults(iolistdef *iolist) { iolist->new_pnts = 0; iolist->first_pnt = NIL; iolist->last_pnt = NIL; iolist->curr_loop = NIL; iolist->last_ind = NIL; iolist->poly_vertex_number = NIL; return; } void ResetIOListData(iolistdef *iolist) { iolist->new_pnts = 0; iolist->first_pnt = NIL; iolist->last_pnt = NIL; iolist->last_ind = NIL; return; } void Read2DInputData(global_struct *all) { /* */ /* read 2D data from input file */ /* */ if (all->rt_opt.verbose) { fprintf(stdout, "\n...reading the input data: "); fflush(stdout); } if (all->rt_opt.read_input) { ReadPolygon(all); } else if (all->rt_opt.read_poly) { ReadPoly(all); } else if (all->rt_opt.read_dxf) { ReadDXFFile(all); } else if (all->rt_opt.read_lines) { ReadPolyLines(all); } else { throw WRONG_INPUT_OPTION; } if (all->rt_opt.verbose) { fprintf(stdout, "done!\n"); fflush(stdout); } return; } void EnsureClosedPolygon(global_struct *all) { /* */ /* make sure that all polygons are closed even when my code is used not */ /* properly. */ /* */ if (all->c_iolist.curr_loop != NIL) CloseCurrentPoly(all); return; } void StartPoly(global_struct *all) { iolistdef *iolist = &all->c_iolist; listdef *list = &all->c_list; /* */ /* make sure that all polygons are closed even when my code is used not */ /* properly. */ /* */ if ((iolist->curr_loop != NIL) && (iolist->poly_vertex_number >= 1)) CloseCurrentPoly(all); /* */ /* start a new polygon. */ /* */ if (iolist->curr_loop == NIL) iolist->curr_loop = MakeLoopHeader(list); iolist->first_pnt = NIL; iolist->last_pnt = NIL; iolist->last_ind = NIL; iolist->poly_vertex_number = NIL; ExtApplFuncStartPoly; return; } void CloseCurrentPoly(global_struct *all) { iolistdef *iolist = &all->c_iolist; listdef *list = &all->c_list; #ifdef GRAPHICS redrawdef *redraw = &all->c_redraw; #endif list_ind ind; assert(iolist->curr_loop != NIL); ExtApplFuncClosePoly_1; if (iolist->poly_vertex_number < 1) { /* */ /* polygon with no vertex? let's forget it! */ /* */ DecrementLoops(list); } else { #ifdef GRAPHICS if (all->rt_opt.graphics) AddEdgeToBuffer(redraw, iolist->last_pnt, iolist->first_pnt, PolyColor); #endif if (iolist->poly_vertex_number == 1) { /* */ /* polygon with only one vertex? we'll add one dummy vertex. */ /* */ iolist->last_ind = list->loops[iolist->curr_loop]; ind = MakeNode(list, iolist->first_pnt); InsertAfter(list, iolist->last_ind, ind); iolist->last_ind = ind; iolist->last_pnt = iolist->first_pnt; iolist->poly_vertex_number += 1; } if (iolist->poly_vertex_number == 2) { /* */ /* polygon with only two vertices? we'll add one dummy vertex. */ /* */ ind = GetPrevNode(list, iolist->last_ind); //i = GetIndex(list, ind); SetAngle(list, ind, -2); ind = MakeNode(list, iolist->last_pnt); InsertAfter(list, iolist->last_ind, ind); iolist->last_ind = ind; SetAngle(list, ind, -2); } DeleteHook(list, iolist->curr_loop); } ExtApplFuncClosePoly_2; iolist->curr_loop = NIL; iolist->first_pnt = NIL; iolist->last_pnt = NIL; iolist->last_ind = NIL; iolist->poly_vertex_number = NIL; return; } #ifdef EXT_APPL_SITES void AddPolyVertex(global_struct *all, double xc1, double yc1, eas_type eas_data) #else void AddPolyVertex(global_struct *all, double xc1, double yc1) #endif { iolistdef *iolist = &all->c_iolist; listdef *list = &all->c_list; datadef *data = &all->c_data; #ifdef GRAPHICS redrawdef *redraw = &all->c_redraw; #endif int j; list_ind ind; assert(iolist->curr_loop != NIL); if (iolist->first_pnt == NIL) { ExtApplFuncAddPolyVertex_1; iolist->poly_vertex_number = 1; #ifdef EXT_APPL_SITES iolist->first_pnt = StorePnt(data, xc1, yc1, eas_data); #else iolist->first_pnt = StorePnt(data, xc1, yc1); #endif iolist->last_pnt = iolist->first_pnt; #ifdef GRAPHICS if (all->rt_opt.graphics) AddPntToBuffer(redraw, iolist->first_pnt, PntsColor); #endif iolist->last_ind = list->loops[iolist->curr_loop]; ind = MakeNode(list, iolist->first_pnt); InsertAfter(list, iolist->last_ind, ind); iolist->last_ind = ind; if (xc1 < all->bb_min.x) all->bb_min.x = xc1; if (xc1 > all->bb_max.x) all->bb_max.x = xc1; if (yc1 < all->bb_min.y) all->bb_min.y = yc1; if (yc1 > all->bb_max.y) all->bb_max.y = yc1; ExtApplFuncAddPolyVertex_2; } else { ExtApplFuncAddPolyVertex_3; iolist->poly_vertex_number += 1; #ifdef EXT_APPL_SITES j = StorePnt(data, xc1, yc1, eas_data); #else j = StorePnt(data, xc1, yc1); #endif #ifdef GRAPHICS if (all->rt_opt.graphics) { AddPntToBuffer(redraw, j, PntsColor); AddEdgeToBuffer(redraw, iolist->last_pnt, j, PolyColor); } #endif iolist->last_pnt = j; ind = MakeNode(list, j); InsertAfter(list, iolist->last_ind, ind); iolist->last_ind = ind; if (xc1 < all->bb_min.x) all->bb_min.x = xc1; else if (xc1 > all->bb_max.x) all->bb_max.x = xc1; if (yc1 < all->bb_min.y) all->bb_min.y = yc1; else if (yc1 > all->bb_max.y) all->bb_max.y = yc1; ExtApplFuncAddPolyVertex_4; } return; } void DXFAddPolyVertex(global_struct *all, double xc1, double yc1, double bulge) { if (bulge != C_0_0) FIST_Warning("DXFAddPolyVertex() - non-zero bulge ignored!\n"); #ifdef EXT_APPL_SITES AddPolyVertex(all, xc1, yc1, eas_NIL); #else AddPolyVertex(all, xc1, yc1); #endif return; } void DXFCloseCurrentPoly(global_struct *all, double bulge) { if (bulge != C_0_0) FIST_Warning("DXFCloseCurrentPoly() - non-zero bulge ignored!\n"); CloseCurrentPoly(all); return; } void DXFStartPoly(global_struct *all) { StartPoly(all); return; } #ifdef EXT_APPL_SITES int HandlePnt(global_struct *all, double xc1, double yc1, eas_type eas_data) #else int HandlePnt(global_struct *all, double xc1, double yc1) #endif { /* */ /* we convert the isolated point into a dummy triangle that consists of */ /* three zero-length edges. */ /* */ StartPoly(all); #ifdef EXT_APPL_SITES AddPolyVertex(all, xc1, yc1, eas_data); #else AddPolyVertex(all, xc1, yc1); #endif CloseCurrentPoly(all); /* */ /* we don't have/use a return value within FIST, but need it for */ /* compatibility reasons with other codes of mine. */ /* */ return NIL; } #ifdef EXT_APPL_SITES void HandleSeg(global_struct *all, double xc1, double yc1, double xc2, double yc2, eas_type eas_data) #else void HandleSeg(global_struct *all, double xc1, double yc1, double xc2, double yc2) #endif { /* */ /* we convert the line segment into a dummy triangle that consists of the */ /* line segment doubled plus one zero-length edge. */ /* */ StartPoly(all); #ifdef EXT_APPL_SITES AddPolyVertex(all, xc1, yc1, eas_data); AddPolyVertex(all, xc2, yc2, eas_data); #else AddPolyVertex(all, xc1, yc1); AddPolyVertex(all, xc2, yc2); #endif CloseCurrentPoly(all); return; } #ifdef EXT_APPL_SITES void HandleArc(global_struct *all, double xc1, double yc1, double xc2, double yc2, double xc3, double yc3, int attr, eas_type eas_data) #else void HandleArc(global_struct *all, double xc1, double yc1, double xc2, double yc2, double xc3, double yc3, int attr) #endif { machine_double delta_x, delta_y, radius, angle_s, angle_e; machine_double incr, alpha; int number; #ifdef EXT_APPL_SITES AddPolyVertex(all, xc1, yc1, eas_data); #else AddPolyVertex(all, xc1, yc1); #endif delta_x = TO_MDOUBLE(xc1) - TO_MDOUBLE(xc3); delta_y = TO_MDOUBLE(yc1) - TO_MDOUBLE(yc3); radius = sqrt(delta_x * delta_x + delta_y * delta_y); delta_x = TO_MDOUBLE(all->bb_max.x) - TO_MDOUBLE(all->bb_min.x); delta_y = TO_MDOUBLE(all->bb_max.y) - TO_MDOUBLE(all->bb_min.y); incr = MD_2PI * Max(delta_x, delta_y) / (150.0 * radius * sqrt(radius)); if (incr < (MD_2PI / 100.0)) incr = MD_2PI / 100.0; if (incr > (MD_PI / 10.0)) incr = MD_PI / 10.0; if (attr == 1) { angle_s = atan2(TO_MDOUBLE(yc1) - TO_MDOUBLE(yc3), TO_MDOUBLE(xc1) - TO_MDOUBLE(xc3)); angle_e = atan2(TO_MDOUBLE(yc2) - TO_MDOUBLE(yc3), TO_MDOUBLE(xc2) - TO_MDOUBLE(xc3)); if (angle_s < 0.0) angle_s += MD_2PI; if (angle_e < 0.0) angle_e += MD_2PI; if (angle_e < angle_s) angle_e += MD_2PI; number = (int) ((angle_e - angle_s) / incr); ++number; incr = (angle_e - angle_s) / number; angle_e -= incr / 2.0; alpha = angle_s + incr; while (alpha < angle_e) { xc1 = xc3 + radius * cos(alpha); yc1 = yc3 + radius * sin(alpha); #ifdef EXT_APPL_SITES AddPolyVertex(all, xc1, yc1, eas_data); #else AddPolyVertex(all, xc1, yc1); #endif alpha += incr; } } else if (attr == -1) { angle_s = atan2(TO_MDOUBLE(yc1) - TO_MDOUBLE(yc3), TO_MDOUBLE(xc1) - TO_MDOUBLE(xc3)); angle_e = atan2(TO_MDOUBLE(yc2) - TO_MDOUBLE(yc3), TO_MDOUBLE(xc2) - TO_MDOUBLE(xc3)); if (angle_s < 0.0) angle_s += MD_2PI; if (angle_e < 0.0) angle_e += MD_2PI; if (angle_s < angle_e) angle_s += MD_2PI; number = (int) ((angle_s - angle_e) / incr); ++number; incr = (angle_s - angle_e) / number; angle_e += incr / 2.0; alpha = angle_s - incr; while (alpha > angle_e) { xc1 = xc3 + radius * cos(alpha); yc1 = yc3 + radius * sin(alpha); #ifdef EXT_APPL_SITES AddPolyVertex(all, xc1, yc1, eas_data); #else AddPolyVertex(all, xc1, yc1); #endif alpha -= incr; } } else { FIST_Warning("HandleArc() - unknown data format!\n"); } return; }