Files
SaraP 739088af9f Vroni 7.8 :
- aggiornamento versione.
2025-01-29 16:24:30 +01:00

1562 lines
38 KiB
C++

/*****************************************************************************/
/* */
/* Copyright (C) 1999-2025 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 <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <float.h>
#include <math.h>
/* */
/* 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);
RandomInteger(m_cur_rnd_sites, i);
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, &center, &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, &center, &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"