/*****************************************************************************/ /* */ /* Copyright (C) 1999-2023 M. Held */ /* */ /* This code is not in the public domain. All rights reserved! Please make */ /* sure to read the full copyright statement contained in "README.txt" or in */ /* the "main" file of this code, such as "main.cc". */ /* */ /*****************************************************************************/ /* */ /* Written by: Martin Held */ /* */ /* E-Mail: held@cs.sbg.ac.at */ /* Fax Mail: (+43 662) 8044-172 */ /* Voice Mail: (+43 662) 8044-6304 */ /* Snail Mail: Martin Held */ /* FB Informatik */ /* Universitaet Salzburg */ /* A-5020 Salzburg, Austria */ /* */ /*****************************************************************************/ /* */ /* get standard libraries */ /* */ #include #include #include #include #include /* */ /* get my header files */ /* */ #include "fpkernel.h" #include "vronivector.h" #include "vroni_object.h" #include "defs.h" #include "numerics.h" #include "random.h" #define BLOCK_SIZE 1024 #define PAGE_SIZE 32768 void vroniObject::SetSupportVtxFlag(vr_bool flag) { support_vtx_added = flag; return; } vr_bool vroniObject::GetSupportVtxFlag() { return support_vtx_added; } /* */ /* the functions */ /* GetNumberOfPoints(), */ /* GetNumberOfSegments(), */ /* GetNumberOfArcs() */ /* report the current numbers of points, segments and circular arcs! */ /* please note that these numbers may change during the execution of VRONI, */ /* e.g., when VRONI encounters an intersection. */ /* */ int vroniObject::GetNumberOfPoints(void) { return num_pnts; /* note that this number increases by four during */ /* the construction of the VD due to the insertion */ /* of four dummy corner points around the input */ /* data; recall the use of the run-time option */ /* "--bound". */ } int vroniObject::GetNumberOfSegments(void) { return num_segs; } int vroniObject::GetNumberOfArcs(void) { return num_arcs; } void vroniObject::ExtendPnts(int number) { int mnp; mnp = num_pnts + number; if (max_num_pnts < mnp) { max_num_pnts = mnp; gentlyResizeSTLVector(pnts, max_num_pnts, "data:pnts"); } assert(mnp > 4); assert(num_pnts > 4); pnts[mnp-1] = pnts[num_pnts-1]; pnts[mnp-2] = pnts[num_pnts-2]; num_pnts -= 2; #ifdef GRAPHICS if (graphics) { AddPntToBuffer(mnp-1, PntColor); AddPntToBuffer(mnp-2, PntColor); } #endif return; } void vroniObject::ResizePnts(int number) { number += 5; if (max_num_pnts < number) { max_num_pnts = number; gentlyResizeSTLVector(pnts, max_num_pnts, "data:pnts"); } return; } #ifdef EXT_APPL_PNTS void vroniObject::InitPntSite(pnt *pointer, double_arg x, double_arg y, eap_type ext_appl) #else void vroniObject::InitPntSite(pnt *pointer, double_arg x, double_arg y) #endif { pointer->p.x = x; pointer->p.y = y; pointer->vd = NIL; pointer->node = NIL; pointer->s = false; pointer->del = false; pointer->vis = false; #ifdef EXT_APPL_PNTS pointer->ext_appl = ext_appl; #endif #ifdef GRAPHICS pointer->draw = false; #endif #ifdef ORDERED ++site_counter; pointer->key = site_counter; #endif #ifdef WRITE_VD pointer->idx = NIL; pointer->vd_edge = NIL; #endif return; } #ifdef EXT_APPL_PNTS int vroniObject::StorePnt(double_arg x, double_arg y, eap_type ext_appl) #else int vroniObject::StorePnt(double_arg x, double_arg y) #endif { int i; if (num_pnts <= 1) num_pnts = 2; if (num_pnts >= max_num_pnts) { // MODIF modifico quantità di memoria richiesta dall'allocazione in analogia con std::vector // max_num_pnts += PAGE_SIZE; max_num_pnts = num_pnts * 2 ; gentlyResizeSTLVector(pnts, max_num_pnts, "data:pnts"); } if ((i = num_pnts) == 2) { #ifdef EXT_APPL_PNTS InitPntSite(&(pnts[0]), -DBL_MAX, -DBL_MAX, ext_appl); InitPntSite(&(pnts[1]), -DBL_MAX, DBL_MAX, ext_appl); #else InitPntSite(&(pnts[0]), -DBL_MAX, -DBL_MAX); InitPntSite(&(pnts[1]), -DBL_MAX, DBL_MAX); #endif } #ifdef EXT_APPL_PNTS InitPntSite(&(pnts[i]), x, y, ext_appl); #else InitPntSite(&(pnts[i]), x, y); #endif ++num_pnts; return i; } #ifdef EXT_APPL_SITES int vroniObject::StoreSeg(int i1, int i2, eas_type ext_appl) #else int vroniObject::StoreSeg(int i1, int i2) #endif { int i; seg *pointer; assert(InPntsList(i1)); assert(InPntsList(i2)); if (num_segs >= max_num_segs) { // MODIF modifico quantità di memoria richiesta dall'allocazione in analogia con std::vector // max_num_segs += PAGE_SIZE; max_num_segs = ( num_segs + 1) * 2 ; gentlyResizeSTLVector(segs, max_num_segs, "data:segs"); } pointer = &(segs[num_segs]); pointer->i1 = i1; pointer->i2 = i2; pointer->vd = NIL; #ifdef EXT_APPL_SITES pointer->ext_appl = ext_appl; #endif #ifdef GRAPHICS pointer->draw = false; #endif #ifdef ORDERED ++site_counter; pointer->key = site_counter; #endif #ifdef WRITE_VD pointer->vd_edge = NIL; #endif i = num_segs; ++num_segs; return i; } #ifdef EXT_APPL_SITES int vroniObject::StoreArc(int i1, int i2, double_arg xc, double_arg yc, vr_bool ccw, eas_type ext_appl) #else int vroniObject::StoreArc(int i1, int i2, double_arg xc, double_arg yc, vr_bool ccw) #endif { int i; double r1, r2; arc *pointer; assert(InPntsList(i1)); assert(InPntsList(i2)); if (num_arcs >= max_num_arcs) { // MODIF modifico quantità di memoria richiesta dall'allocazione in analogia con std::vector // max_num_arcs += PAGE_SIZE; max_num_arcs = ( num_arcs + 1) * 2 ; gentlyResizeSTLVector(arcs, max_num_arcs, "data:arcs"); } pointer = &(arcs[num_arcs]); pointer->i1 = i1; pointer->i2 = i2; pointer->c.x = xc; pointer->c.y = yc; pointer->ccw = ccw; r1 = PntPntDist(pnts[i1].p, pointer->c); r2 = PntPntDist(pnts[i2].p, pointer->c); pointer->r = (r1 + r2) / 2.0; pointer->vd = NIL; #ifdef EXT_APPL_SITES pointer->ext_appl = ext_appl; #endif #ifdef GRAPHICS pointer->draw = false; #endif #ifdef ORDERED ++site_counter; pointer->key = site_counter; #endif i = num_arcs; ++num_arcs; return i; } #ifdef GRAPHICS void vroniObject::MarkDrawSite(int i, t_site type) { switch(type) { case(PNT): assert(InPntsList(i)); pnts[i].draw = true; break; case(SEG): assert(InSegsList(i)); segs[i].draw = true; break; case(ARC): assert(InArcsList(i)); arcs[i].draw = true; break; default: break; } return; } void vroniObject::ResetDrawSite(int i, t_site type) { switch(type) { case(PNT): assert(InPntsList(i)); pnts[i].draw = false; break; case(SEG): assert(InSegsList(i)); segs[i].draw = false; break; case(ARC): assert(InArcsList(i)); arcs[i].draw = false; break; default: break; } return; } #endif void vroniObject::InitPnts(int number) { if (max_num_pnts < number) { max_num_pnts = number; gentlyResizeSTLVector(pnts, max_num_pnts, "data:pnts"); } num_pnts = 0; return; } void vroniObject::InitStoragePnts(int number) { if (max_num_pnts < number) { max_num_pnts = number; gentlyResizeSTLVector(pnts, max_num_pnts, "data:pnts"); } return; } void vroniObject::FreeInputData() { pnts.clear(); segs.clear(); arcs.clear(); #ifdef RANDOM m_rnd_sites.clear(); #endif #ifdef FORCED fcd_sites.clear(); #endif #ifdef SORTED srt_sites.clear(); #endif #ifdef ORDERED ord_sites.clear(); #endif max_num_arcs = 0; num_arcs = 0; max_num_segs = 0; num_segs = 0; max_num_pnts = 0; num_pnts = 0; #ifdef RANDOM m_max_num_rnd_sites = 0; m_num_rnd_sites = 0; #endif #ifdef FORCED max_num_fcd_sites = 0; num_fcd_sites = 0; #endif #ifdef SORTED max_num_srt_sites = 0; num_srt_sites = 0; #endif #ifdef ORDERED max_num_ord_sites = 0; num_ord_sites = 0; #endif return; } void vroniObject::InitSegs(int number) { if (max_num_segs < number) { max_num_segs = number; gentlyResizeSTLVector(segs, max_num_segs, "data:segs"); } num_segs = 0; return; } void vroniObject::InitStorageSegs(int number) { if (max_num_segs < number) { max_num_segs = number; gentlyResizeSTLVector(segs, max_num_segs, "data:segs"); } return; } void vroniObject::InitArcs(int number) { if (max_num_arcs < number) { max_num_arcs = number; gentlyResizeSTLVector(arcs, max_num_arcs, "data:arcs"); } num_arcs = 0; return; } void vroniObject::InitStorageArcs(int number) { if (max_num_arcs < number) { max_num_arcs = number; gentlyResizeSTLVector(arcs, max_num_arcs, "data:arcs"); } return; } /* */ /* this routine returns the bounding box of the entries of */ /* "pnts[2,...,num_pnts-1]". */ /* */ void vroniObject::SetBoundingBox(void) { int i; if (num_pnts <= 2) return; assert(!bbox_initialized); bb_min.x = GetPntCoords(2).x; bb_max.x = bb_min.x; bb_min.y = GetPntCoords(2).y; bb_max.y = bb_min.y; for (i = 3; i < num_pnts; ++i) { if (GetPntCoords(i).x < bb_min.x) bb_min.x = GetPntCoords(i).x; else if (GetPntCoords(i).x > bb_max.x) bb_max.x = GetPntCoords(i).x; if (GetPntCoords(i).y < bb_min.y) bb_min.y = GetPntCoords(i).y; else if (GetPntCoords(i).y > bb_max.y) bb_max.y = GetPntCoords(i).y; } /* */ /* add two dummy corner points. later on, after the bounding box is */ /* known, they will be replaced by the true corners. see the meaning */ /* of the run-time option "--bound". */ /* */ #ifdef EXT_APPL_PNTS pnts[0].ext_appl = pnts[1].ext_appl = eap_NIL; (void) StorePnt( DBL_MAX, -DBL_MAX, eap_NIL); (void) StorePnt( DBL_MAX, DBL_MAX, eap_NIL); #else (void) StorePnt( DBL_MAX, -DBL_MAX); (void) StorePnt( DBL_MAX, DBL_MAX); #endif bbox_initialized = true; return; } void vroniObject::CheckBoundingBox(void) { int i, k; assert(bbox_added); k = num_pnts - 2; for (i = 2; i < k; ++i) { assert(GetPntCoords(i).x >= bb_min.x); assert(GetPntCoords(i).x <= bb_max.x); assert(GetPntCoords(i).y >= bb_min.y); assert(GetPntCoords(i).y <= bb_max.y); } i = num_pnts - 1; assert(pnts[0].p.x == pnts[1].p.x); assert(pnts[0].p.y < pnts[1].p.y); assert(pnts[k].p.x == pnts[i].p.x); assert(pnts[k].p.y < pnts[i].p.y); assert(pnts[0].p.x < pnts[k].p.x); assert(pnts[0].p.y == pnts[k].p.y); assert(pnts[1].p.x < pnts[i].p.x); assert(pnts[1].p.y == pnts[i].p.y); assert(pnts[0].p.x < pnts[2].p.x); assert(pnts[i].p.x > pnts[2].p.x); assert(pnts[0].p.y < pnts[2].p.y); assert(pnts[i].p.y > pnts[2].p.y); return; } vr_bool vroniObject::InPntsList(int index) { return ((index >= 0) && (index < num_pnts) && (num_pnts <= max_num_pnts)); } vr_bool vroniObject::InSegsList(int index) { return ((index >= 0) && (index < num_segs) && (num_segs <= max_num_segs)); } vr_bool vroniObject::InArcsList(int index) { return ((index >= 0) && (index < num_arcs) && (num_arcs <= max_num_arcs)); } #ifdef EXT_APPL_PNTS int vroniObject::HandlePnt(double_arg xc1, double_arg yc1, eap_type ext_appl) #else int vroniObject::HandlePnt(double_arg xc1, double_arg yc1) #endif { int i1; #ifdef EXT_APPL_PNTS i1 = StorePnt(xc1, yc1, ext_appl); #else i1 = StorePnt(xc1, yc1); #endif #ifdef GRAPHICS if (graphics) AddPntToBuffer(i1, PntColor); #endif return i1; } #ifdef EXT_APPL_SITES void vroniObject::HandleSeg(double_arg xc1, double_arg yc1, double_arg xc2, double_arg yc2, eas_type ext_appl) #else void vroniObject::HandleSeg(double_arg xc1, double_arg yc1, double_arg xc2, double_arg yc2) #endif { int i1, i2, i3; #ifdef EXT_APPL_PNTS i1 = StorePnt(xc1, yc1, ext_appl); i2 = StorePnt(xc2, yc2, ext_appl); #else i1 = StorePnt(xc1, yc1); i2 = StorePnt(xc2, yc2); #endif ExtApplHandleSeg; /* external-application */ #ifdef EXT_APPL_SITES i3 = StoreSeg(i1, i2, ext_appl); #else i3 = StoreSeg(i1, i2); #endif #ifdef GRAPHICS if (graphics) { AddPntToBuffer(i1, PntColor); AddPntToBuffer(i2, PntColor); AddSegToBuffer(i3, SegColor); } #endif return; } #ifdef EXT_APPL_SITES void vroniObject::AddSeg(int *i1, double_arg xc2, double_arg yc2, eas_type ext_appl) #else void vroniObject::AddSeg(int *i1, double_arg xc2, double_arg yc2) #endif { int i2, i3; #ifdef EXT_APPL_PNTS i2 = StorePnt(xc2, yc2, {ext_appl.first, ext_appl.second + 1}); #else i2 = StorePnt(xc2, yc2); #endif #ifdef EXT_APPL_SITES i3 = StoreSeg(*i1, i2, ext_appl); #else i3 = StoreSeg(*i1, i2); #endif *i1 = i2; #ifdef GRAPHICS if (graphics) { AddSegToBuffer(i3, SegColor); AddPntToBuffer(i2, PntColor); } #endif return; } #ifdef EXT_APPL_SITES void vroniObject::AddArc(int *i1, double_arg xc3, double_arg yc3, double_arg xc2, double_arg yc2, int attr, eas_type ext_appl) #else void vroniObject::AddArc(int *i1, double_arg xc3, double_arg yc3, double_arg xc2, double_arg yc2, int attr) #endif { int i2, i3; #ifdef EXT_APPL_PNTS i2 = StorePnt(xc3, yc3, {ext_appl.first, ext_appl.second + 1}); #else i2 = StorePnt(xc3, yc3); #endif assert((attr == ARC) || (attr == -ARC)); #ifdef EXT_APPL_SITES if (attr == ARC) i3 = StoreArc(*i1, i2, xc2, yc2, true, ext_appl); else i3 = StoreArc(i2, *i1, xc2, yc2, false, ext_appl); #else if (attr == ARC) i3 = StoreArc(*i1, i2, xc2, yc2, true); else i3 = StoreArc(i2, *i1, xc2, yc2, false); #endif #ifdef GRAPHICS if (graphics) { AddPntToBuffer(i2, PntColor); AddArcToBuffer(i3, SegColor); } #endif *i1 = i2; return; } #ifdef EXT_APPL_SITES void vroniObject::HandleArc(double_arg xc1, double_arg yc1, double_arg xc2, double_arg yc2, double_arg xc3, double_arg yc3, int attr, eas_type ext_appl) #else void vroniObject::HandleArc(double_arg xc1, double_arg yc1, double_arg xc2, double_arg yc2, double_arg xc3, double_arg yc3, int attr) #endif { int i1, i2, i3; #ifdef EXT_APPL_PNTS i1 = StorePnt(xc1, yc1, ext_appl); i2 = StorePnt(xc2, yc2, ext_appl); #else i1 = StorePnt(xc1, yc1); i2 = StorePnt(xc2, yc2); #endif ExtApplHandleArc; assert((attr == ARC) || (attr == -ARC)); #ifdef EXT_APPL_SITES if (attr == ARC) i3 = StoreArc(i1, i2, xc3, yc3, true, ext_appl); else i3 = StoreArc(i2, i1, xc3, yc3, false, ext_appl); #else if (attr == ARC) i3 = StoreArc(i1, i2, xc3, yc3, true); else i3 = StoreArc(i2, i1, xc3, yc3, false); #endif #ifdef GRAPHICS if (graphics) { AddPntToBuffer(i1, PntColor); AddPntToBuffer(i2, PntColor); AddArcToBuffer(i3, SegColor); } #endif return; } #ifdef EXT_APPL_SITES void vroniObject::CloseSeg(int i1, int i2, eas_type ext_appl) #else void vroniObject::CloseSeg(int i1, int i2) #endif { int i3; #ifdef EXT_APPL_SITES i3 = StoreSeg(i1, i2, ext_appl); #else i3 = StoreSeg(i1, i2); #endif #ifdef GRAPHICS if (graphics) AddSegToBuffer(i3, SegColor); #endif return; } #ifdef EXT_APPL_SITES void vroniObject::CloseArc(int i1, int i2, double_arg xc2, double_arg yc2, int attr, eas_type ext_appl) #else void vroniObject::CloseArc(int i1, int i2, double_arg xc2, double_arg yc2, int attr) #endif { int i3; assert((attr == ARC) || (attr == -ARC)); #ifdef EXT_APPL_SITES if (attr == ARC) i3 = StoreArc(i1, i2, xc2, yc2, true, ext_appl); else i3 = StoreArc(i2, i1, xc2, yc2, false, ext_appl); #else if (attr == ARC) i3 = StoreArc(i1, i2, xc2, yc2, true); else i3 = StoreArc(i2, i1, xc2, yc2, false); #endif #ifdef GRAPHICS if (graphics) { AddPntToBuffer(i2, PntColor); AddArcToBuffer(i3, SegColor); } #endif return; } void vroniObject::ResetInputData(void) { num_pnts = 0; num_segs = 0; num_arcs = 0; #ifdef RANDOM m_num_rnd_sites = 0; #endif #ifdef FORCED num_fcd_sites = 0; #endif #ifdef SORTED num_srt_sites = 0; #endif #ifdef ORDERED site_counter = 0; num_ord_sites = 0; #endif support_vtx_added = false; data_scaled = false; scale_factor = 1.0; shift.x = 0.0; shift.y = 0.0; dxf_poly_started = false; dxf_vertex_added = false; dxf_vertex_index = NIL; dxf_vertex_first = NIL; bbox_added = false; bbox_initialized = false; num_pnts_added = 0; num_pnts_deleted = 0; num_segs_deleted = 0; num_arcs_deleted = 0; return; } void vroniObject::AddDummyCorners(int bound) { int i; double delta_x, delta_y; assert(!bbox_added); assert(bbox_initialized); delta_x = (bb_max.x - bb_min.x); if (eq(delta_x, ZERO)) delta_x = (bound + 0.01); else delta_x *= (bound + 0.01); delta_y = (bb_max.y - bb_min.y); if (eq(delta_y, ZERO)) delta_y = (bound + 0.01); else delta_y *= (bound + 0.01); if (delta_x < (0.5 * delta_y)) delta_x = 0.5 * delta_y; else if (delta_y < (0.5 * delta_x)) delta_y = 0.5 * delta_x; /* */ /* let the user assign coordinates to the four dummy corners by setting */ /* delta_x and delta_y. Please make sure to use only positive values that */ /* are at least as large as the x- and y-lengths of the old bounding box! */ /* */ ExtApplAddDummyCorners; /* */ /* assign coordinates */ /* */ assert(GetPntCoords(0).x == -DBL_MAX); assert(GetPntCoords(0).y == -DBL_MAX); SetXCoord(0, bb_min.x - delta_x); SetYCoord(0, bb_min.y - delta_y); assert(GetPntCoords(1).x == -DBL_MAX); assert(GetPntCoords(1).y == DBL_MAX); SetXCoord(1, bb_min.x - delta_x); SetYCoord(1, bb_max.y + delta_y); i = num_pnts - 2; assert(GetPntCoords(i).x == DBL_MAX); assert(GetPntCoords(i).y == -DBL_MAX); SetXCoord(i, bb_max.x + delta_x); SetYCoord(i, bb_min.y - delta_y); i = num_pnts - 1; assert(GetPntCoords(i).x == DBL_MAX); assert(GetPntCoords(i).y == DBL_MAX); SetXCoord(i, bb_max.x + delta_x); SetYCoord(i, bb_max.y + delta_y); SetMaxOffset(0.49 * sqrt(delta_x * delta_x + delta_y * delta_y)); delta_x = bb_max.x - bb_min.x + 2.0 * delta_x; delta_y = bb_max.y - bb_min.y + 2.0 * delta_y; SetRootTooLarge(sqrt(delta_x * delta_x + delta_y * delta_y)); bbox_added = true; return; } /* */ /* scale the data if necessary. */ /* */ void vroniObject::ScaleData(void) { int i, k; double xy, x_ext, y_ext; x_ext = bb_max.x - bb_min.x; y_ext = bb_max.y - bb_min.y; xy = VroniMax(x_ext, y_ext); xy = VroniMax(xy, ZERO); scale_factor = 1.0; shift.x = (bb_min.x + bb_max.x)/2.0; shift.y = (bb_min.y + bb_max.y)/2.0; if (xy > (2.0 + ZERO)) { do { scale_factor /= 2.0; } while ((xy * scale_factor) > (2.0 + ZERO)); data_scaled = true; } else if (xy < 0.5) { do { scale_factor *= 2.0; } while ((xy * scale_factor) < 0.5); data_scaled = true; } else if ((bb_max.x > ( 1.0 + ZERO)) || (bb_max.y > ( 1.0 + ZERO)) || (bb_min.x < ( 0.0 - ZERO)) || (bb_min.y < ( 0.0 - ZERO))) { data_scaled = true; } if (data_scaled) { k = num_pnts - 2; for (i = 2; i < k; ++i) { SetXCoord(i, (GetPntCoords(i).x - shift.x) * scale_factor); SetYCoord(i, (GetPntCoords(i).y - shift.y) * scale_factor); } for (i = 0; i < num_arcs; ++i) { arcs[i].c.x = (GetArcCenter(i).x - shift.x) * scale_factor; arcs[i].c.y = (GetArcCenter(i).y - shift.y) * scale_factor; arcs[i].r *= scale_factor; } bb_min.x = (bb_min.x - shift.x) * scale_factor; bb_min.y = (bb_min.y - shift.y) * scale_factor; bb_max.x = (bb_max.x - shift.x) * scale_factor; bb_max.y = (bb_max.y - shift.y) * scale_factor; } else { shift.x = 0.0; shift.y = 0.0; scale_factor = 1.0; } return; } int vroniObject::SplitSeg(int i1, int i2) { int i3, i4; assert(InSegsList(i1)); assert(InPntsList(i2)); i4 = Get2ndVtx(i1, SEG); #ifdef EXT_APPL_SITES i3 = StoreSeg(i2, i4, GetExtApplSeg(i1)); #else i3 = StoreSeg(i2, i4); #endif Set2ndVtx(i1, SEG, i2); restart = true; return i3; } int vroniObject::SplitArc(int i1, int i2) { int i3, i4; coord p3; double radius; assert(InArcsList(i1)); assert(InPntsList(i2)); #ifdef TRACE if (center) { printf("splitting arc %d at the point \n pnts[%d]=(%24.20f,%24.20f)\n", i1, i2, pnts[i2].p.x, pnts[i2].p.y); PrintSiteData(i1, ARC, "before split"); } #endif i4 = Get2ndVtx(i1, ARC); p3 = GetArcCenter(i1); #ifdef EXT_APPL_SITES i3 = StoreArc(i2, i4, p3.x, p3.y, GetArcOrientation(i1), GetExtApplArc(i1)); #else i3 = StoreArc(i2, i4, p3.x, p3.y, GetArcOrientation(i1)); #endif Set2ndVtx(i1, ARC, i2); radius = GetArcRadius(i1); SetArcRadius(i3, radius); #ifdef TRACE if (center) { PrintSiteData(i1, ARC, "old after split"); PrintSiteData(i3, ARC, "new after split"); } #endif restart = true; return i3; } void vroniObject::MergePoints(int i1, int i2) { coord p, q, w; p = GetPntCoords(i1); q = GetPntCoords(i2); w = MidPoint(p, q); SetXCoord(i1, w.x); SetYCoord(i1, w.y); SetXCoord(i2, w.x); SetYCoord(i2, w.y); // MODIF visto che uno dei due punti viene cancellato, uniformo anche le ext_appl. Serve nel caso in cui // uno dei due punti deriva da intersezione ( quindi non ha punto originario di riferimento) if ( pnts[i1].ext_appl.second == -1) pnts[i1].ext_appl = pnts[i2].ext_appl ; else if ( pnts[i2].ext_appl.second == -1) pnts[i2].ext_appl = pnts[i1].ext_appl ; restart = true; return; } void vroniObject::ResetFlags(void) { int i, number; for (i = 0; i < num_pnts; ++i) { pnts[i].vd = NIL; pnts[i].node = NIL; pnts[i].vis = false; pnts[i].s = false; #ifdef GRAPHICS pnts[i].draw = false; #endif } for (i = 0; i < num_segs; ++i) { segs[i].vd = NIL; #ifdef GRAPHICS segs[i].draw = false; #endif } number = num_arcs; for (i = 0; i < number; ++i) { arcs[i].vd = NIL; #ifdef GRAPHICS arcs[i].draw = false; #endif } return; } void vroniObject::RemoveSegment(int i) { int j; ExtApplRemoveSeg; j = num_segs - 1; CopySegData(i, j); #ifdef GRAPHICS if (graphics) ResetDrawSite(j, SEG); #endif num_segs = j; #ifdef GRAPHICS if (graphics) UpdateBuffer(); #endif restart = true; ++num_segs_deleted; return; } void vroniObject::RemoveArc(int i) { int j; ExtApplRemoveArc; j = num_arcs - 1; CopyArcData(i, j); #ifdef GRAPHICS if (graphics) ResetDrawSite(j, ARC); #endif num_arcs = j; restart = true; ++num_arcs_deleted; return; } #ifdef ORDERED int key_comp(const void *a, const void *b) { if (((ordered_sites*)a)->key > ((ordered_sites*)b)->key) return -1; else if (((ordered_sites*)a)->key < ((ordered_sites*)b)->key) return 1; else return 0; } #endif #ifdef SORTED int key_comp(const void *a, const void *b) { #ifdef INVERSE if (((sorted_sites*)a)->lgth < ((sorted_sites*)b)->lgth) return -1; else if (((sorted_sites*)a)->lgth > ((sorted_sites*)b)->lgth) return 1; else return 0; #else if (((sorted_sites*)a)->lgth > ((sorted_sites*)b)->lgth) return -1; else if (((sorted_sites*)a)->lgth < ((sorted_sites*)b)->lgth) return 1; else return 0; #endif } #endif void vroniObject::InitSiteOrder(t_site type) { int i, number; int start; #ifdef FORCED FILE *input; #endif if (type == PNT) { number = num_pnts - 2; start = 3; } else if (type == SEG) { number = num_segs; start = 0; } else if (type == ARC) { number = num_arcs; start = 0; } else { VD_Warning("InitSiteOrder - unknown site type!"); return; } #ifdef ORDERED /* ORDERED sites */ if (max_num_ord_sites < number) { max_num_ord_sites = number; gentlyResizeSTLVector(ord_sites, max_num_ord_sites, "data:ord_sites"); } if (type == PNT) { assert(start == 3); for (i = 3; i < number; ++i) { ord_sites[i-3].ind = i; ord_sites[i-3].key = pnts[i].key; } } else if (type == SEG) { for (i = 0; i < number; ++i) { ord_sites[i].ind = i; ord_sites[i].key = segs[i].key; } } else if (type == ARC) { for (i = 0; i < number; ++i) { ord_sites[i].ind = i; ord_sites[i].key = arcs[i].key; } } num_ord_sites = number - start; /* */ /* sort segs according to their original keys */ /* */ qsort(&ord_sites[0], num_ord_sites, sizeof(ordered_sites), key_comp); #else #ifdef SORTED /* SORTED sites */ if (max_num_srt_sites < number) { max_num_srt_sites = number; gentlyResizeSTLVector(srt_sites, max_num_srt_sites, "data:srt_sites"); } if (type == SEG) { for (i = start; i < number; ++i) { srt_sites[i].ind = i; srt_sites[i].lgth = GetSegLgth(i); } /* */ /* sort segs according to their length, either in increasing or in */ /* decreasing (-DINVERSE) order. */ /* */ num_srt_sites = number - start; qsort(&srt_sites[0], num_srt_sites, sizeof(sorted_sites), key_comp); } else { num_srt_sites = 0; for (i = start; i < number; ++i) { srt_sites[num_srt_sites].ind = i; ++num_srt_sites; } } #else #ifdef RANDOM /* RANDOM sites */ if (m_max_num_rnd_sites < number) { m_max_num_rnd_sites = number; gentlyResizeSTLVector(m_rnd_sites, m_max_num_rnd_sites, "data:rnd_sites"); } m_num_rnd_sites = 0; for (i = start; i < number; ++i) { m_rnd_sites[m_num_rnd_sites] = i; ++m_num_rnd_sites; } m_cur_rnd_sites = m_num_rnd_sites; #else #ifdef FORCED /* FORCED site order */ if (max_num_fcd_sites < number) { max_num_fcd_sites = number; gentlyResizeSTLVector(fcd_sites, max_num_fcd_sites, "data:fcd_sites"); } if (type == PNT) input = OpenFileVD("forced_order_pnts.txt", "r"); else if (type == SEG) input = OpenFileVD("forced_order_segs.txt", "r"); else input = OpenFileVD("forced_order_arcs.txt", "r"); number -= start; for (i = 0; i < number; ++i) { if (EOF == fscanf(input, "%d", &(fcd_sites[i]))) throw std::runtime_error("VRONI error: InitSiteOrder() - premature end of file!"); } num_fcd_sites = number; cur_fcd_sites = 0; #else /* no specific site order */ if (type == PNT) nosr = 3; else nosr = 0; #endif #endif #endif #endif return; } int vroniObject::GetNextSite(void) { #ifdef ORDERED /* ORDERED sites */ assert(num_ord_sites > 0); --num_ord_sites; return (ord_sites[num_ord_sites].ind); #else #ifdef SORTED /* SORTED sites */ assert(num_srt_sites > 0); --num_srt_sites; return (srt_sites[num_srt_sites].ind); #else #ifdef RANDOM /* RANDOM sites */ int i, j; assert(m_cur_rnd_sites > 0); assert(m_cur_rnd_sites <= m_num_rnd_sites); i = RandomInteger(m_cur_rnd_sites); assert((i >= 0) && (i < m_cur_rnd_sites)); j = m_rnd_sites[i]; --m_cur_rnd_sites; m_rnd_sites[i] = m_rnd_sites[m_cur_rnd_sites]; return j; #else #ifdef FORCED /* FORCED sites */ assert(cur_fcd_sites < num_fcd_sites); return (fcd_sites[cur_fcd_sites++]); #else /* no specific order */ int j; j = nosr; ++nosr; return j;; #endif #endif #endif #endif } void vroniObject::DXFStartPoly(void) { dxf_poly_started = true; dxf_vertex_added = false; dxf_vertex_index = NIL; dxf_vertex_first = NIL; return; } void vroniObject::DXFClosePoly(double bulge) { int i3; coord center; double radius; int attr; assert(dxf_vertex_added); attr = SEG; HandleBulge(GetPntCoords(dxf_vertex_index), GetPntCoords(dxf_vertex_first), &bulge, ¢er, &radius, &attr); if (attr == SEG) { #ifdef EXT_APPL_SITES i3 = StoreSeg(dxf_vertex_index, dxf_vertex_first, eas_NIL); #else i3 = StoreSeg(dxf_vertex_index, dxf_vertex_first); #endif #ifdef GRAPHICS if (graphics) AddSegToBuffer(i3, SegColor); #endif } else { #ifdef EXT_APPL_SITES if (attr == ARC) i3 = StoreArc(dxf_vertex_index, dxf_vertex_first, center.x, center.y, true, eas_NIL); else i3 = StoreArc(dxf_vertex_first, dxf_vertex_index, center.x, center.y, false, eas_NIL); #else if (attr == ARC) i3 = StoreArc(dxf_vertex_index, dxf_vertex_first, center.x, center.y, true); else i3 = StoreArc(dxf_vertex_first, dxf_vertex_index, center.x, center.y, false); #endif #ifdef GRAPHICS if (graphics) AddArcToBuffer(i3, SegColor); #endif } return; } void vroniObject::DXFAddPolyVertex(double_arg xc1, double_arg yc1, double bulge) { int attr; coord center, p2; double radius; if (!dxf_poly_started) { DXFStartPoly(); } if (dxf_vertex_added) { assert(InPntsList(dxf_vertex_index)); attr = SEG; p2 = MakeVec( xc1, yc1); HandleBulge(GetPntCoords(dxf_vertex_index), p2, &bulge, ¢er, &radius, &attr); if (attr == SEG) { #ifdef EXT_APPL_SITES AddSeg(&dxf_vertex_index, xc1, yc1, eas_NIL); #else AddSeg(&dxf_vertex_index, xc1, yc1); #endif } else { #ifdef EXT_APPL_SITES AddArc(&dxf_vertex_index, xc1, yc1, center.x, center.y, attr, eas_NIL); #else AddArc(&dxf_vertex_index, xc1, yc1, center.x, center.y, attr); #endif } } else { #ifdef EXT_APPL_PNTS dxf_vertex_index = HandlePnt(xc1, yc1, eap_NIL); #else dxf_vertex_index = HandlePnt(xc1, yc1); #endif dxf_vertex_added = true; dxf_vertex_first = dxf_vertex_index; } return; } void vroniObject::CheckIsolatedPnts(void) { int i; assert(bbox_added); i = 2; while (HasIncidentSite(i) || IsDeletedPnt(i)) ++i; isolated_pnts = (i < (num_pnts - 2)); #ifdef TRACE printf("i = %d, num_pnts = %d\n", i, num_pnts); #endif return; } void vroniObject::PrintSiteData(int s, t_site t, const char *string) { if (t == PNT) { assert(InPntsList(s)); FP_printf("%s, pnt %d: (%24.20f %24.20f), vd: %d, node: %d\n", string, s, FP_PRNTARG(pnts[s].p.x), FP_PRNTARG(pnts[s].p.y), FP_PRNTARG(pnts[s].vd), FP_PRNTARG(pnts[s].node)); if (pnts[s].s) printf(" incident site, "); else printf(" no incident site, "); if (pnts[s].vis) printf("visited, "); else printf("not visited, "); if (pnts[s].del) printf("to be deleted.\n"); else printf("to be kept.\n"); } else if (t == SEG) { assert(InSegsList(s)); printf("%s, seg %d: start = %d, end = %d, vd = %d\n", string, s, segs[s].i1, segs[s].i2, segs[s].vd); } else if (t == ARC) { assert(InArcsList(s)); FP_printf("%s, arc %3d: start = %3d, end = %3d, vd = %3d, r = %24.20f\n", string, s, arcs[s].i1, arcs[s].i2, arcs[s].vd, FP_PRNTARG(arcs[s].r)); FP_printf(" start pnts[%3d]: (%24.20f %24.20f)\n", arcs[s].i1, FP_PRNTARG(pnts[arcs[s].i1].p.x), FP_PRNTARG(pnts[arcs[s].i1].p.y)); FP_printf(" end pnts[%3d]: (%24.20f %24.20f)\n", arcs[s].i2, FP_PRNTARG(pnts[arcs[s].i2].p.x), FP_PRNTARG(pnts[arcs[s].i2].p.y)); FP_printf(" center: (%24.20f %24.20f)\n", FP_PRNTARG(arcs[s].c.x), FP_PRNTARG(arcs[s].c.y)); FP_printf(" start normal: (%24.20f %24.20f)\n", FP_PRNTARG(arcs[s].ns.x), FP_PRNTARG(arcs[s].ns.y)); FP_printf(" end normal: (%24.20f %24.20f)\n", FP_PRNTARG(arcs[s].ne.x), FP_PRNTARG(arcs[s].ne.y)); FP_printf(" chord: (%24.20f %24.20f\n", FP_PRNTARG(arcs[s].a), FP_PRNTARG(arcs[s].b)); FP_printf(" %24.20f)\n", FP_PRNTARG(arcs[s].d)); } else { printf("information for site %3d of type %3d is not available\n", s, t); } return; } #ifdef TRACE #endif #ifdef GRAPHICS void vroniObject::FindClosestPnt(double_arg x1, double_arg y1) { double dist, dist_min, x, y; int i, i_min; i = 2; i_min = 2; x = x1 - pnts[i].p.x; y = y1 - pnts[i].p.y; dist_min = x * x + y * y; for (i = 3; i < num_pnts-2; ++i) { if (pnts[i].draw) { x = x1 - pnts[i].p.x; y = y1 - pnts[i].p.y; dist = x * x + y * y; if (dist < dist_min) { dist_min = dist; i_min = i; } } } AddToCurBuffer(i_min, PNT, AlertColor); #ifdef TRACE PrintSiteData(i_min, PNT, "closest"); #endif return; } void vroniObject::FindClosestSeg(double_arg x1, double_arg y1) { double dist, dist_min, lgth, a, b, c; int i, i_min; coord p, q; i = 0; i_min = 0; p.x = x1; p.y = y1; lgth = GetSegLgth(i); assert(!(eq(lgth, ZERO))); GetSegEqnData(i, &a, &b, &c); dist_min = AbsPntLineDist(a, b, c, p); for (i = 1; i < num_segs; ++i) { if (segs[i].draw) { lgth = GetSegLgth(i); assert(!(eq(lgth, ZERO))); GetSegEqnData(i, &a, &b, &c); q = GetSegStartCoord(i); dist = AbsPntSegDist(q, p, a, b, c, lgth, TINY); if (dist < dist_min) { dist_min = dist; i_min = i; } } } AddToCurBuffer(i_min, SEG, AlertColor); #ifdef TRACE PrintSiteData(i_min, SEG, "closest"); #endif return; } #endif #include "ext_appl_data.cc"