f3e15b8c8d
- aggiunti file della libreria e progetto visual studio.
1501 lines
51 KiB
C++
1501 lines
51 KiB
C++
/*****************************************************************************/
|
|
/* */
|
|
/* Copyright (C) 2001-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-611 */
|
|
/* Voice Mail: (+43 662) 8044-6304 */
|
|
/* Snail Mail: Martin Held */
|
|
/* FB Informatik */
|
|
/* Universitaet Salzburg */
|
|
/* A-5020 Salzburg, Austria */
|
|
/* */
|
|
/*****************************************************************************/
|
|
|
|
/* */
|
|
/* get my header files */
|
|
/* */
|
|
#include "vroni_object.h"
|
|
|
|
|
|
void vroniObject::FindMostViolatedRecursiveSeg(int e, /* current VD edge */
|
|
int k0, /* start node of */
|
|
/* recursive scan */
|
|
int i1, /* pnt that coincides */
|
|
/* with k0 */
|
|
int j, /* segment to be */
|
|
/* inserted into VD */
|
|
int k, /* current node */
|
|
int *n, /* closest node found */
|
|
/* by scan */
|
|
double *dist) /* distance of */
|
|
/* node n */
|
|
{
|
|
coord p, q;
|
|
double dist2, rad, a, b, c, lgth;
|
|
int e1, e2, k1, n2;
|
|
#ifdef TRACE
|
|
vr_bool trace_mvns = true;
|
|
#endif
|
|
|
|
assert(InEdgesList(e));
|
|
assert(InPntsList(i1));
|
|
assert(InNodesList(k0));
|
|
assert(InNodesList(k));
|
|
assert(InSegsList(j));
|
|
assert(!(IsLftSite(e, i1, PNT) && IsRgtSite(e, i1, PNT)));
|
|
assert(GetNodeSite(k0) == i1);
|
|
|
|
|
|
k1 = GetOtherNode(e, k);
|
|
assert(InNodesList(k1));
|
|
#ifdef TRACE
|
|
if (trace_mvns) {
|
|
printf("FMVRS: e = %d, i1 = %d, j = %d, k = %d, k0 = %d, k1 = %d\n",
|
|
e, i1, j, k, k0, k1);
|
|
printf(" node_site(k1) = %d, deg-2(k1) = %d\n",
|
|
GetNodeSite(k1), IsDeg2Node(k1));
|
|
}
|
|
#endif
|
|
if (k1 == k0) {
|
|
/* */
|
|
/* we have returned to the start! */
|
|
/* */
|
|
*dist = DBL_MAX;
|
|
*n = NIL;
|
|
return;
|
|
}
|
|
|
|
if (GetNodeSite(k1) == i1) {
|
|
e1 = GetCCWEdge(e, k1);
|
|
e2 = GetCWEdge(e, k1);
|
|
FindMostViolatedRecursiveSeg(e1, k0, i1, j, k1, n, dist);
|
|
if (e1 != e2) {
|
|
FindMostViolatedRecursiveSeg(e2, k0, i1, j, k1, &n2, &dist2);
|
|
if (dist2 < *dist) {
|
|
*n = n2;
|
|
*dist = dist2;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
GetNodeData(k1, &q, &rad);
|
|
GetSegEqnData(j, &a, &b, &c);
|
|
lgth = GetSegLgth(j);
|
|
p = GetSegStartCoord(j);
|
|
*dist = AbsPntSegDist(p, q, a, b, c, lgth, TINY) - rad;
|
|
*n = k1;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* */
|
|
/* find the Voronoi node on the Voronoi boundary of the point pnts[i1] */
|
|
/* whose Voronoi disk is violated the most by the insertion of segs[j]. */
|
|
/* note that pnts[i1] and pnts[i2] are the endpoints of segs[j]. if */
|
|
/* the Voronoi cells of pnts[i1] and pnts[i2] share nodes then we take */
|
|
/* one of those nodes, and set node_shared = true. */
|
|
/* */
|
|
int vroniObject::FindMostViolatedNodeSeg(int i1, /* start point of seg */
|
|
int i2, /* end point of seg */
|
|
int j, /* segment to be inserted */
|
|
vr_bool *node_shared,
|
|
double *diff)
|
|
{
|
|
int e, e1, e0, k, k0, k_min = NIL, n, n1;
|
|
coord p, q;
|
|
double dist, dist1, dist_min, rad;
|
|
double a, b, c, lgth;
|
|
vr_bool shared0, shared, shared1;
|
|
#ifdef TRACE
|
|
vr_bool trace_mvns = true;
|
|
#endif
|
|
|
|
assert(InPntsList(i1));
|
|
assert(InPntsList(i2));
|
|
assert(InSegsList(j));
|
|
assert(IsSegStartPnt(j, i1) || IsSegEndPnt(j, i1));
|
|
assert(IsSegStartPnt(j, i2) || IsSegEndPnt(j, i2));
|
|
|
|
/* */
|
|
/* so far, no segment that is incident at this point has been inserted.*/
|
|
/* we'll scan the Voronoi region of the point in order to find the */
|
|
/* node whose Voronoi disk is most violated by the insertion of the */
|
|
/* segment segs[j]. */
|
|
/* */
|
|
e = GetVDPtr(i1, PNT);
|
|
assert(InEdgesList(e));
|
|
assert(IsLftSite(e, i1, PNT) || IsRgtSite(e, i1, PNT));
|
|
GetSegEqnData(j, &a, &b, &c);
|
|
lgth = GetSegLgth(j);
|
|
assert(!eq(lgth, ZERO));
|
|
p = GetSegStartCoord(j);
|
|
|
|
if (IsRgtSite(e, i1, PNT)) k = GetEndNode(e);
|
|
else k = GetStartNode(e);
|
|
|
|
assert(InNodesList(k));
|
|
e0 = e;
|
|
dist_min = LARGE;
|
|
dist = LARGE;
|
|
shared0 = false;
|
|
shared = IsLftRgtSite(e, i1, PNT) && IsLftRgtSite(e, i2, PNT);
|
|
|
|
#ifdef TRACE
|
|
if (trace_mvns)
|
|
printf("FMVNS: i1 = %d, i2 = %d, j = %d, k = %d\n", i1, i2, j, k);
|
|
#endif
|
|
|
|
do {
|
|
e1 = GetCCWEdge(e, k);
|
|
shared1 = IsLftRgtSite(e1, i1, PNT) && IsLftRgtSite(e1, i2, PNT);
|
|
shared = shared || shared1;
|
|
|
|
#ifdef TRACE
|
|
if (trace_mvns)
|
|
PrintNodeData(k, "checking");
|
|
#endif
|
|
if (GetNodeSite(k) == NIL) {
|
|
/* */
|
|
/* check whether q is in the cone of influence of segs[j]. */
|
|
/* */
|
|
GetNodeData(k, &q, &rad);
|
|
dist = AbsPntSegDist(p, q, a, b, c, lgth, TINY) - rad;
|
|
if (shared) {
|
|
/* */
|
|
/* this node belongs to the VD cells of pnts i1 and i2 */
|
|
/* */
|
|
if ((dist < dist_min) || (!shared0)) {
|
|
#ifdef TRACE
|
|
if (trace_mvns){
|
|
printf("node %d accepted (shared)\n", k);
|
|
printf("old distance: %f, new distance: %f\n",
|
|
dist_min, dist);
|
|
PrintNodeData(k, "FindMostViolatedSeg");
|
|
}
|
|
#endif
|
|
dist_min = dist;
|
|
k_min = k;
|
|
shared0 = true;
|
|
}
|
|
}
|
|
else if (dist < dist_min) {
|
|
/* */
|
|
/* so far we have not found a node that is shared by both cells */
|
|
/* */
|
|
#ifdef TRACE
|
|
if (trace_mvns){
|
|
printf("node %d accepted\n", k);
|
|
printf("old distance: %f, new distance: %f\n",
|
|
dist_min, dist);
|
|
PrintNodeData(k, "FindMostViolatedSeg");
|
|
}
|
|
#endif
|
|
dist_min = dist;
|
|
k_min = k;
|
|
}
|
|
}
|
|
e = e1;
|
|
k = GetOtherNode(e, k);
|
|
shared = shared1;
|
|
|
|
} while (e != e0);
|
|
|
|
*node_shared = shared0;
|
|
*diff = dist_min;
|
|
|
|
if (((k_min == NIL) || (dist_min >= 0.0)) && HasIncidentSite(i1)) {
|
|
/* */
|
|
/* at least one segment is already incident at this point. */
|
|
/* */
|
|
*node_shared = false;
|
|
k = GetPntNode(i1);
|
|
assert(InNodesList(k));
|
|
assert(GetNodeSite(k) == i1);
|
|
assert(IsDeg2Node(k));
|
|
e = GetIncidentEdge(k);
|
|
assert(InEdgesList(e));
|
|
assert((k == GetStartNode(e)) || (k == GetEndNode(e)));
|
|
e1 = GetCCWEdge(e, k);
|
|
assert(GetCWEdge(e, k) == e1);
|
|
assert(!(IsLftSite(e, i1, PNT) && IsRgtSite(e, i1, PNT)));
|
|
k0 = k;
|
|
|
|
#ifdef TRACE
|
|
if (trace_mvns)
|
|
printf("1st recursive call of FMVRS: e = %d, k0 = %d\n",
|
|
e, k0);
|
|
#endif
|
|
FindMostViolatedRecursiveSeg(e, k0, i1, j, k, &n, &dist);
|
|
#ifdef TRACE
|
|
if (trace_mvns)
|
|
printf("2nd recursive call of FMVRS: e1 = %d, k0 = %d\n",
|
|
e1, k0);
|
|
#endif
|
|
FindMostViolatedRecursiveSeg(e1, k0, i1, j, k, &n1, &dist1);
|
|
|
|
if (dist < dist1) {
|
|
k_min = n;
|
|
*diff = dist;
|
|
}
|
|
else {
|
|
k_min = n1;
|
|
*diff = dist1;
|
|
}
|
|
}
|
|
|
|
return k_min;
|
|
}
|
|
|
|
|
|
|
|
/* */
|
|
/* this routine first checks whether all VD nodes on the boundary of the */
|
|
/* Voronoi cell of site i of type t have been marked for deletion due to */
|
|
/* the insertion of the line segment i0. (as a matter of fact, t == PNT !) */
|
|
/* it then constructs a point on the boundary of the Voronoi cell of i */
|
|
/* which is guaranteed to be closer to pnt i than to seg i0. */
|
|
/* */
|
|
vr_bool vroniObject::PreserveVoronoiCellSeg(int i, t_site t, int i0)
|
|
{
|
|
int e, n, e0, k, k0, s, s0;
|
|
double dist, a, b, c, r0_2, r_2, r2, ap, bp, cp, d, d0, lgth;
|
|
coord p, q, q0, v, w, u;
|
|
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) {
|
|
#ifdef GRAPHICS
|
|
if (graphics) AddToCurBuffer(i, t, AlertColor);
|
|
#endif
|
|
printf("in PreserveVoronoiCellSeg for site %d of type %d and line %d\n",
|
|
i, t, i0);
|
|
printf("start - (%f, %f)\n", pnts[segs[i0].i1].p.x,
|
|
pnts[segs[i0].i1].p.y);
|
|
printf("end - (%f, %f)\n", pnts[segs[i0].i2].p.x,
|
|
pnts[segs[i0].i2].p.y);
|
|
printf("pnt - (%f, %f)\n", pnts[i].p.x, pnts[i].p.y);
|
|
}
|
|
#endif
|
|
assert((t == PNT) && InPntsList(i));
|
|
|
|
/* */
|
|
/* we'll find a bisector on the boundary of the Voronoi cell of site i */
|
|
/* for which we can guarantee that some part of it will survive the */
|
|
/* insertion of the line segment segs[i0]. we will insert a dummy node */
|
|
/* on this bisector in order to prevent its removal. after the insertion */
|
|
/* of segs[i0] we will remove the dummy node. */
|
|
/* */
|
|
/* scan the Voronoi cell in CCW order and check whether all nodes */
|
|
/* really are to be deleted. */
|
|
/* */
|
|
e = GetVDPtr(i, t);
|
|
assert(InEdgesList(e));
|
|
assert(IsLftSite(e, i, t) || IsRgtSite(e, i, t));
|
|
|
|
if (IsRgtSite(e, i, t)) k = GetEndNode(e);
|
|
else k = GetStartNode(e);
|
|
e0 = e;
|
|
|
|
do {
|
|
if (!IsNodeVisited(k)) {
|
|
/* */
|
|
/* hm... this Voronoi cell has undeleted nodes! */
|
|
/* */
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) {
|
|
printf("the node %d of this Voronoi cell is undeleted\n", k);
|
|
}
|
|
#endif
|
|
u = GetNodeCoord(k);
|
|
return true;
|
|
}
|
|
e = GetCCWEdge(e, k);
|
|
k = GetOtherNode(e, k);
|
|
} while (e != e0);
|
|
|
|
/* */
|
|
/* indeed, all Voronoi nodes of this cell are to be deleted. */
|
|
/* */
|
|
if (IsSegStartPnt(i0, i) || IsSegEndPnt(i0, i)) {
|
|
/* */
|
|
/* check whether there exists a node with radius 0.0. */
|
|
/* */
|
|
e = GetVDPtr(i, t);
|
|
if (IsRgtSite(e, i, t)) k = GetEndNode(e);
|
|
else k = GetStartNode(e);
|
|
e0 = e;
|
|
do {
|
|
if (i == GetNodeSite(k)) {
|
|
GetNodeData(k, &q, &r2);
|
|
assert(r2 == 0.0);
|
|
InsertSiteNode(e, q, n, i);
|
|
MarkNodeChecked(n);
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) {
|
|
printf("dummy node with radius 0 inserted\n");
|
|
#ifdef GRAPHICS
|
|
if (graphics) AddToCurBuffer(n, VDN, AlertColor);
|
|
#endif
|
|
}
|
|
#endif
|
|
return true;
|
|
}
|
|
e = GetCCWEdge(e, k);
|
|
k = GetOtherNode(e, k);
|
|
} while (e != e0);
|
|
|
|
return false;
|
|
}
|
|
|
|
/* */
|
|
/* compute the coefficients of the equation of the line through p and */
|
|
/* the direction vector v of a ray that starts at p, points away from */
|
|
/* segs[i0], and is perpendicular to segs[i0]. */
|
|
/* */
|
|
p = GetPntCoords(i);
|
|
GetSegEqnData(i0, &a, &b, &c);
|
|
dist = PntLineDist(a, b, c, p);
|
|
if (eq(dist, zero)) {
|
|
lgth = GetSegLgth(i0);
|
|
u = GetSegStartCoord(i0);
|
|
if (IsInSegConeZero(u, p, a, b, lgth, zero) == 0) {
|
|
SetInvalidSites(i0, SEG, i, PNT, zero);
|
|
VD_Dbg_Warning("PreserveVoronoiCellSeg() - point lies on line!");
|
|
if (IsInvalidData(false)) {
|
|
restart = true;
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
if (dist > 0.0) {
|
|
ap = b;
|
|
bp = -a;
|
|
}
|
|
else {
|
|
ap = -b;
|
|
bp = a;
|
|
}
|
|
cp = - ap * p.x - bp * p.y;
|
|
v = MakeVec( -bp, ap);
|
|
|
|
/* */
|
|
/* scan the boundary of the VD cell of p and find a VD edge whose */
|
|
/* end points lie on different sides of the ray through p */
|
|
/* */
|
|
e = GetVDPtr(i, t);
|
|
if (IsRgtSite(e, i, t)) {
|
|
k = GetEndNode(e);
|
|
k0 = GetStartNode(e);
|
|
}
|
|
else {
|
|
k = GetStartNode(e);
|
|
k0 = GetEndNode(e);
|
|
}
|
|
GetNodeData(k0, &q0, &r0_2);
|
|
d0 = PntLineDist(ap, bp, cp, q0);
|
|
s0 = SignEps(d0, ZERO);
|
|
e0 = e;
|
|
|
|
do {
|
|
GetNodeData(k, &q, &r_2);
|
|
d = PntLineDist(ap, bp, cp, q);
|
|
s = SignEps(d, ZERO);
|
|
|
|
if ((s * s0 < 0) && gt(r_2, ZERO) && gt(r0_2, ZERO)) {
|
|
/* */
|
|
/* the nodes q0 and q lie on different sides of the line */
|
|
/* through p. */
|
|
/* */
|
|
if (IntersectRayBisector(i, v, e, &w, &r2)) {
|
|
if (IsBetweenVoronoiNodes(e, w, zero)) {
|
|
n = StoreNode(w.x, w.y, r2);
|
|
InsertDummyNode(e, n, true);
|
|
MarkNodeDummy(n);
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) {
|
|
printf("dummy node inserted in PreserveVoronoiCellSeg\n");
|
|
#ifdef GRAPHICS
|
|
if (graphics) AddToCurBuffer(n, VDN, AlertColor);
|
|
#endif
|
|
}
|
|
#endif
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
s0 = s;
|
|
q0 = q;
|
|
r0_2 = r_2;
|
|
e = GetCCWEdge(e, k);
|
|
k = GetOtherNode(e, k);
|
|
} while (e != e0);
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
/* */
|
|
/* the insertion of seg i0 has caused a loop of VD nodes to get marked as */
|
|
/* deleted. all edges of the loop are stored in a stack (array) between the */
|
|
/* indices start and number. we scan the loop and insert a point on one */
|
|
/* loop edge that is guaranteed to be closer to one defining site of that */
|
|
/* loop edge than to the new seg i0. */
|
|
/* */
|
|
vr_bool vroniObject::BreakLoopSeg(int i0)
|
|
{
|
|
int start, number, n, k, j, e = 0, k0, s1, s0;
|
|
double a, b, c, lgth, d1, d0, r2, r1_2, r0_2, dist, dist1, ap, bp, cp;
|
|
int i = 0, i1;
|
|
coord u, p, q, q1, q0, v, w;
|
|
t_site t, t1;
|
|
|
|
GetLoopStackSize(number);
|
|
GetLoopStackMin(start);
|
|
|
|
if (start >= number) return true; /* false alarm: no edge within loop ! */
|
|
|
|
lgth = GetSegLgth(i0);
|
|
u = GetSegStartCoord(i0);
|
|
|
|
for (j = start; j < number; ++j) {
|
|
/* */
|
|
/* scan all VD edges of the loop */
|
|
/* */
|
|
GetLoopStackElement(j, e);
|
|
GetSegEqnData(i0, &a, &b, &c);
|
|
GetLftSiteData(e, &i, &t);
|
|
if (t == SEG) { /* we are not interested in a seg as defining site */
|
|
GetRgtSiteData(e, &i, &t);
|
|
}
|
|
else if (t == PNT) {
|
|
GetRgtSiteData(e, &i1, &t1);
|
|
if (t1 == PNT) {
|
|
/* */
|
|
/* two pnts define the current loop edge. we pick the pnt that */
|
|
/* is further from seg i0. */
|
|
/* */
|
|
q = GetPntCoords(i);
|
|
dist = AbsPntSegDist(u, q, a, b, c, lgth, TINY);
|
|
q = GetPntCoords(i1);
|
|
dist1 = AbsPntSegDist(u, q, a, b, c, lgth, TINY);
|
|
if (dist1 < dist) i = i1;
|
|
}
|
|
}
|
|
if (t == PNT) {
|
|
/* */
|
|
/* only if a pnt defines the current loop edge. we'll send a ray */
|
|
/* through p := pnts[i] and check whether it intersects the */
|
|
/* current loop edge. if p is an endpoint of seg i0 then we'll */
|
|
/* use the supporting line of seg i0; otherwise, we'll use a normal */
|
|
/* onto i0. in either case, we make sure to point the ray into the */
|
|
/* proper direction. */
|
|
/* */
|
|
p = GetPntCoords(i);
|
|
if (IsSegStartPnt(i0, i)) {
|
|
ap = a;
|
|
bp = b;
|
|
cp = c;
|
|
}
|
|
else if (IsSegEndPnt(i0, i)) {
|
|
ap = -a;
|
|
bp = -b;
|
|
cp = -c;
|
|
}
|
|
else {
|
|
dist = PntLineDist(a, b, c, p);
|
|
if (eq(dist, zero)) {
|
|
if (IsInSegConeZero(u, p, a, b, lgth, zero) == 0) {
|
|
SetInvalidSites(i0, SEG, i, PNT, zero);
|
|
VD_Dbg_Warning("BreakLoopSeg() - point lies on line!");
|
|
if (IsInvalidData(false)) restart = true;
|
|
return false;
|
|
}
|
|
}
|
|
if (dist < 0.0) {
|
|
a = -a;
|
|
b = -b;
|
|
c = -c;
|
|
}
|
|
|
|
ap = b;
|
|
bp = -a;
|
|
cp = - ap * p.x - bp * p.y;
|
|
}
|
|
|
|
k = GetStartNode(e);
|
|
k0 = GetEndNode(e);
|
|
GetNodeData(k0, &q0, &r0_2);
|
|
d0 = PntLineDist(ap, bp, cp, q0);
|
|
s0 = SignEps(d0, ZERO);
|
|
GetNodeData(k, &q1, &r1_2);
|
|
d1 = PntLineDist(ap, bp, cp, q1);
|
|
s1 = SignEps(d1, ZERO);
|
|
|
|
if ((s1 * s0 < 0) && gt(r1_2, ZERO) && gt(r0_2, ZERO) &&
|
|
IsNodeDeleted(k) && IsNodeDeleted(k0)) {
|
|
/* */
|
|
/* the nodes q0 and q1 lie on different sides of the ray */
|
|
/* through p; thus, the ray intersects the current loop edge! */
|
|
/* we insert the point of intersection as dummy node. */
|
|
/* */
|
|
v = MakeVec( -bp, ap);
|
|
if (IntersectRayBisector(i, v, e, &w, &r2)) {
|
|
if (IsBetweenVoronoiNodes(e, w, zero)) {
|
|
n = StoreNode(w.x, w.y, r2);
|
|
InsertDummyNode(e, n, true);
|
|
MarkNodeDummy(n);
|
|
#ifdef TRACE
|
|
#ifdef GRAPHICS
|
|
if (debug_flag_VD && graphics) AddToCurBuffer(n, VDN, AlertColor);
|
|
#endif
|
|
#endif
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
|
|
void vroniObject::MarkNonRecursiveSeg(int e, int n, int i,
|
|
std::stack<int>& e_stack,
|
|
std::stack<int>& n_stack,
|
|
std::stack<int>& i_stack)
|
|
{
|
|
int i0, i1, i2, k, e1, e2, k1, k2;
|
|
t_site t1, t2;
|
|
coord p, q;
|
|
double dist, rad, a, b, c, lgth;
|
|
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) {
|
|
printf("MarkNonRecursiveSeg edge e = %d, site i = %d\n", e, i);
|
|
PrintNodeData(n, "search started here");
|
|
}
|
|
#endif
|
|
|
|
k = GetOtherNode(e, n);
|
|
|
|
do {
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) {
|
|
printf("MarkNonRecursiveSeg - new node k = %d\n", k);
|
|
PrintNodeData(k, "new");
|
|
}
|
|
#endif
|
|
if (!IsNodeUnchecked(k))
|
|
/* */
|
|
/* this node has already been visited; make sure to avoid a loop. */
|
|
/* */
|
|
return;
|
|
|
|
if (IsDeg2Node(k)) {
|
|
e1 = GetCCWEdge(e, k);
|
|
assert(GetCWEdge(e, k) == e1);
|
|
k1 = GetOtherNode(e1, k);
|
|
i0 = GetNodeSite(k);
|
|
if (i0 != NIL) {
|
|
/* */
|
|
/* this is a degree-2 node that coincides with an endpoint of a */
|
|
/* segment. it should not be deleted! */
|
|
/* */
|
|
/* if (IsSegStartPnt(i, i0) || IsSegEndPnt(i, i0)) { */
|
|
MarkNodeChecked(k);
|
|
return;
|
|
}
|
|
|
|
GetNodeData(k, &q, &rad);
|
|
GetSegEqnData(i, &a, &b, &c);
|
|
lgth = GetSegLgth(i);
|
|
p = GetSegStartCoord(i);
|
|
dist = AbsPntSegDist(p, q, a, b, c, lgth, TINY) - rad;
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) {
|
|
printf("dist-rad of deg-2 node %2d is %26.22f\n", k, dist);
|
|
}
|
|
#endif
|
|
|
|
if (le(dist, zero)) {
|
|
MarkNodeVisited(k);
|
|
#ifdef TRACE
|
|
#ifdef GRAPHICS
|
|
if (graphics) AddToCurBuffer(k, VDN, CurrColor);
|
|
#endif
|
|
if (debug_flag_VD) {
|
|
printf("node %2d to be deleted\n", k);
|
|
}
|
|
#endif
|
|
/* */
|
|
/* make sure that we don't delete an entire Voronoi cell. */
|
|
/* */
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) {
|
|
PrintNodeData(k1, "might be checked next");
|
|
PrintEdgeData(e1, "incident edge");
|
|
}
|
|
#endif
|
|
if (IsNodeVisited(k1)) {
|
|
GetLftSiteData(e1, &i1, &t1);
|
|
GetRgtSiteData(e1, &i2, &t2);
|
|
if (t1 == PNT)
|
|
if (!HasIncidentSite(i1))
|
|
AddToPreserveBuffer(i1, t1);
|
|
if (t2 == PNT)
|
|
if (!HasIncidentSite(i2))
|
|
AddToPreserveBuffer(i2, t2);
|
|
return;
|
|
}
|
|
else {
|
|
if (IsNodeUnchecked(k1)) {
|
|
e = e1;
|
|
n = k;
|
|
k = k1;
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) {
|
|
printf("MarkNonRecursiveSeg edge e = %d, ",
|
|
e);
|
|
printf("node n = %d of status %d, site i = %d\n",
|
|
n, GetNodeStatus(n), i);
|
|
printf("MarkNonRecursiveSeg new node k =%d\n",
|
|
k);
|
|
PrintNodeData(k, "new");
|
|
}
|
|
#endif
|
|
}
|
|
else {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
MarkNodeChecked(k);
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) PrintNodeData(k, "checked");
|
|
#ifdef GRAPHICS
|
|
if (graphics) AddToCurBuffer(k, VDN, GridColor);
|
|
#endif
|
|
#endif
|
|
return;
|
|
}
|
|
}
|
|
} while (IsDeg2Node(k));
|
|
|
|
i0 = GetNodeSite(k);
|
|
if (IsSegStartPnt(i, i0) || IsSegEndPnt(i, i0)) {
|
|
MarkNodeVisited(k);
|
|
return;
|
|
}
|
|
|
|
GetNodeData(k, &q, &rad);
|
|
GetSegEqnData(i, &a, &b, &c);
|
|
lgth = GetSegLgth(i);
|
|
p = GetSegStartCoord(i);
|
|
dist = AbsPntSegDist(p, q, a, b, c, lgth, TINY) - rad;
|
|
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) {
|
|
printf("dist-rad of deg-? node %2d is %20.16f\n", k, dist);
|
|
if (le(dist, zero)) {
|
|
printf("yes, dist <= zero = %20.16f\n", zero);
|
|
}
|
|
else {
|
|
printf("no, dist > zero = %20.16f\n", zero);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (le(dist, zero)) {
|
|
MarkNodeVisited(k);
|
|
#ifdef TRACE
|
|
#ifdef GRAPHICS
|
|
if (graphics) AddToCurBuffer(k, VDN, CurrColor);
|
|
#endif
|
|
if (debug_flag_VD) {
|
|
printf("node %2d to be deleted\n", k);
|
|
PrintNodeData(k, "deleted");
|
|
}
|
|
#endif
|
|
|
|
e1 = GetCCWEdge(e, k);
|
|
e2 = GetCWEdge(e, k);
|
|
k1 = GetEndNode(e1);
|
|
if (k1 == k) {
|
|
GetRgtSiteData(e1, &i1, &t1);
|
|
}
|
|
else {
|
|
assert(k == GetStartNode(e1));
|
|
GetLftSiteData(e1, &i1, &t1);
|
|
}
|
|
assert((IsLftSite(e2, i1, t1)) || (IsRgtSite(e2, i1, t1)));
|
|
|
|
k1 = GetOtherNode(e1, k);
|
|
k2 = GetOtherNode(e2, k);
|
|
/* */
|
|
/* make sure that we don't delete an entire Voronoi cell. */
|
|
/* */
|
|
if (IsNodeVisited(k1)) {
|
|
GetOtherSiteData(e1, i1, t1, &i2, &t2);
|
|
if (t2 == PNT)
|
|
if (!HasIncidentSite(i2))
|
|
AddToPreserveBuffer(i2, t2);
|
|
if (IsNodeVisited(k2)) {
|
|
if (t1 == PNT)
|
|
if (!HasIncidentSite(i1))
|
|
AddToPreserveBuffer(i1, t1);
|
|
GetOtherSiteData(e2, i1, t1, &i2, &t2);
|
|
if (t2 == PNT)
|
|
if(!HasIncidentSite(i2))
|
|
AddToPreserveBuffer(i2, t2);
|
|
}
|
|
}
|
|
else if (IsNodeVisited(k2)) {
|
|
GetOtherSiteData(e2, i1, t1, &i2, &t2);
|
|
if (t2 == PNT)
|
|
if (!HasIncidentSite(i2))
|
|
AddToPreserveBuffer(i2, t2);
|
|
}
|
|
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) {
|
|
PrintNodeData(k1, "might be checked next");
|
|
PrintEdgeData(e1, "incident edge");
|
|
PrintNodeData(k2, "might be checked next");
|
|
PrintEdgeData(e2, "incident edge");
|
|
}
|
|
#endif
|
|
if (IsNodeUnchecked(k2)) {
|
|
e_stack.push(e2);
|
|
n_stack.push(k);
|
|
i_stack.push(i);
|
|
#ifdef TRACE
|
|
++stack_size;
|
|
#endif
|
|
}
|
|
if (IsNodeUnchecked(k1)) {
|
|
e_stack.push(e1);
|
|
n_stack.push(k);
|
|
i_stack.push(i);
|
|
#ifdef TRACE
|
|
++stack_size;
|
|
#endif
|
|
}
|
|
#ifdef TRACE
|
|
if (stack_size > max_stack_size) max_stack_size = stack_size;
|
|
#endif
|
|
}
|
|
else {
|
|
MarkNodeChecked(k);
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) PrintNodeData(k, "checked");
|
|
#ifdef GRAPHICS
|
|
if (graphics) AddToCurBuffer(k, VDN, GridColor);
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void vroniObject::MarkRecursiveSeg(int e, int n, int i)
|
|
{
|
|
/* */
|
|
/* since deep recursions turned out to be a problem on some platforms, we */
|
|
/* resort to a stack to avoid explicit recursive calls. */
|
|
/* */
|
|
std::stack<int> e_stack, n_stack, i_stack;
|
|
|
|
#ifdef TRACE
|
|
stack_size = 0;
|
|
max_stack_size = 0;
|
|
#endif
|
|
|
|
MarkNonRecursiveSeg(e, n, i, e_stack, n_stack, i_stack);
|
|
|
|
while (!e_stack.empty()) {
|
|
|
|
assert((e_stack.size() == n_stack.size()) &&
|
|
(n_stack.size() == i_stack.size()));
|
|
|
|
e = e_stack.top();
|
|
e_stack.pop();
|
|
n = n_stack.top();
|
|
n_stack.pop();
|
|
i = i_stack.top();
|
|
i_stack.pop();
|
|
#ifdef TRACE
|
|
--stack_size;
|
|
#endif
|
|
|
|
MarkNonRecursiveSeg(e, n, i, e_stack, n_stack, i_stack);
|
|
}
|
|
|
|
#ifdef TRACE
|
|
printf("max_stack_size = %16d\n", max_stack_size);
|
|
#endif
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void vroniObject::InsertSegIntoVD(int i)
|
|
{
|
|
int k, j, j1, j2, n1, n2, n3;
|
|
int e, e0, e1, e2, e3;
|
|
t_site t0, t1, t2, t3;
|
|
int i0, i1, i2, i3;
|
|
int e1l, e1r, n1l, n1r, e2l, e2r, n2l, n2r, e3l, e3r, n3l, n3r;
|
|
vr_bool node_shared, preserved, broken;
|
|
double dist_min;
|
|
|
|
assert(InSegsList(i));
|
|
|
|
#ifdef GRAPHICS
|
|
if (graphics) {
|
|
ResetCurBuffer();
|
|
ResetVDBuffer();
|
|
}
|
|
#endif
|
|
|
|
ResetPreserveBuffer;
|
|
|
|
/* */
|
|
/* get the indices of the start point and of the end point of the segment.*/
|
|
/* */
|
|
j1 = Get1stVtx(i, SEG);
|
|
assert(InPntsList(j1));
|
|
j2 = Get2ndVtx(i, SEG);
|
|
assert(InPntsList(j2));
|
|
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) {
|
|
printf("inserting seg %d with start %d and end %d\n", i, j1, j2);
|
|
printf("0\n%20.16f %20.16f %20.16f %20.16f\n",
|
|
pnts[j1].p.x, pnts[j1].p.y, pnts[j2].p.x, pnts[j2].p.y);
|
|
}
|
|
#endif
|
|
|
|
/* */
|
|
/* find the nearest Voronoi nodes in the Voronoi cells of j1 and j2. */
|
|
/* */
|
|
SetThreshold(zero, -ZERO);
|
|
|
|
/* */
|
|
/* find the nearest Voronoi nodes in the Voronoi cells of j1 and j2. */
|
|
/* */
|
|
n1 = FindMostViolatedNodeSeg(j1, j2, i, &node_shared, &dist_min);
|
|
if (n1 == NIL) {
|
|
SetThreshold(zero, TINY);
|
|
n1 = FindMostViolatedNodeSeg(j1, j2, i, &node_shared, &dist_min);
|
|
if (n1 == NIL) {
|
|
VD_Dbg_Warning("InsertSegIntoVD() - most violated node not found!");
|
|
if (IsInvalidData(true)) {
|
|
restart = true;
|
|
return;
|
|
}
|
|
else {
|
|
VD_Warning("InsertSegIntoVD() - desperate mode for MVN");
|
|
n1 = DesperateFindMostViolatedNodeSeg(j1, i);
|
|
node_shared = false;
|
|
assert(n1 != NIL);
|
|
}
|
|
}
|
|
}
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) {
|
|
printf("InsertSegIntoVD - start node is %d; node_shared = %d\n",
|
|
n1, node_shared);
|
|
}
|
|
#endif
|
|
#ifdef VRONI_INFO
|
|
UpdateRelaxationMemory(zero);
|
|
#endif
|
|
|
|
assert(InNodesList(n1));
|
|
MarkNodeUnchecked(n1);
|
|
|
|
if (node_shared) {
|
|
n2 = n1;
|
|
}
|
|
else {
|
|
SetThreshold(zero, -ZERO);
|
|
n2 = FindMostViolatedNodeSeg(j2, j1, i, &node_shared, &dist_min);
|
|
if (n2 == NIL) {
|
|
SetThreshold(zero, TINY);
|
|
n2 = FindMostViolatedNodeSeg(j2, j1, i, &node_shared, &dist_min);
|
|
if (n2 == NIL) {
|
|
VD_Dbg_Warning("InsertSegIntoVD() - most violated node not found!");
|
|
if (IsInvalidData(true)) {
|
|
restart = true;
|
|
return;
|
|
}
|
|
else {
|
|
VD_Warning("InsertSegIntoVD() - desperate mode for MVN");
|
|
n2 = DesperateFindMostViolatedNodeSeg(j2, i);
|
|
node_shared = false;
|
|
assert(n2 != NIL);
|
|
}
|
|
}
|
|
}
|
|
if (n1 != n2) {
|
|
assert(InNodesList(n2));
|
|
MarkNodeUnchecked(n2);
|
|
}
|
|
else {
|
|
node_shared = true;
|
|
}
|
|
}
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) {
|
|
printf("InsertSegIntoVD - end node is %d\n", n2);
|
|
}
|
|
#endif
|
|
#ifdef VRONI_INFO
|
|
UpdateRelaxationMemory(zero);
|
|
#endif
|
|
|
|
SetThreshold(zero, TINY);
|
|
|
|
do {
|
|
/* */
|
|
/* mark all Voronoi nodes that are to be deleted. */
|
|
/* */
|
|
#ifdef GRAPHICS
|
|
if (graphics) {
|
|
MarkDrawSite(i, SEG);
|
|
AddToCurBuffer(i, SEG, SiteCurrColor);
|
|
#ifdef TRACE
|
|
AddToCurBuffer(n1, VDN, DTColor);
|
|
AddToCurBuffer(n2, VDN, VDColor);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
if (IsDeg2Node(n1)) {
|
|
e1 = GetIncidentEdge(n1);
|
|
e2 = GetCCWEdge(e1, n1);
|
|
e3 = e1;
|
|
GetLftSiteData(e1, &i1, &t1);
|
|
GetRgtSiteData(e1, &i2, &t2);
|
|
MarkNodeVisited(n1);
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) {
|
|
printf("\n+++++ First call of MarkRecursiveSeg()\n");
|
|
}
|
|
#endif
|
|
MarkRecursiveSeg(e1, n1, i);
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) {
|
|
printf("\n+++++ Second call of MarkRecursiveSeg()\n");
|
|
}
|
|
#endif
|
|
MarkRecursiveSeg(e2, n1, i);
|
|
}
|
|
else {
|
|
e1 = GetIncidentEdge(n1);
|
|
e2 = GetCCWEdge(e1, n1);
|
|
e3 = GetCCWEdge(e2, n1);
|
|
MarkNodeVisited(n1);
|
|
GetLftSiteData(e1, &i1, &t1);
|
|
GetRgtSiteData(e1, &i2, &t2);
|
|
GetLftSiteData(e2, &i3, &t3);
|
|
if (((i3 == i1) && (t3 == t1)) ||
|
|
((i3 == i2) && (t3 == t2)))
|
|
GetRgtSiteData(e2, &i3, &t3);
|
|
assert(!(((i3 == i1) && (t3 == t1)) &&
|
|
((i3 == i2) && (t3 == t2))));
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) {
|
|
printf("\n==== First call of MarkRecursiveSeg()\n");
|
|
}
|
|
#endif
|
|
MarkRecursiveSeg(e1, n1, i);
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) {
|
|
printf("\n==== Second call of MarkRecursiveSeg()\n");
|
|
}
|
|
#endif
|
|
MarkRecursiveSeg(e2, n1, i);
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) {
|
|
printf("\n==== Third call of MarkRecursiveSeg()\n");
|
|
}
|
|
#endif
|
|
MarkRecursiveSeg(e3, n1, i);
|
|
}
|
|
|
|
/* */
|
|
/* check whether we've reached the end node n2. if it has not been */
|
|
/* reached then we'll enlarge the tolerance threshold zero and we'll */
|
|
/* try again. */
|
|
/* */
|
|
if (!IsNodeVisited(n2)) {
|
|
IncreaseThreshold(zero);
|
|
if (gt(zero, ZERO_MAX)) {
|
|
VD_Dbg_Warning("InsertSegIntoVD() - path not constructed!");
|
|
if (IsInvalidData(true)) {
|
|
restart = true;
|
|
return;
|
|
}
|
|
else {
|
|
VD_Warning("InsertSegIntoVD() - desperate mode (path)");
|
|
MarkNodeUnchecked(n2);
|
|
n2 = n1;
|
|
desperate = true;
|
|
troubles = true;
|
|
}
|
|
}
|
|
else {
|
|
ResetPreserveBuffer;
|
|
ResetNodeStatus(e1, n1);
|
|
ResetNodeStatus(e2, n1);
|
|
if (!IsDeg2Node(n1)) ResetNodeStatus(e3, n1);
|
|
}
|
|
#ifdef GRAPHICS
|
|
if (graphics) ResetCurBuffer();
|
|
#endif
|
|
}
|
|
#ifdef VRONI_DBG_WARN
|
|
else if (gt(zero, ZERO) && !quiet) {
|
|
printf("InsertSegIntoVD() -");
|
|
printf(" not reached end node till zero = %20.16f for seg %d!\n",
|
|
zero, i);
|
|
}
|
|
#endif
|
|
} while (!IsNodeVisited(n2));
|
|
|
|
#ifdef VRONI_INFO
|
|
UpdateRelaxationMemory(zero);
|
|
#endif
|
|
|
|
/* */
|
|
/* make sure that no VD cell is completely deleted. */
|
|
/* */
|
|
for (j = 0; j < num_preserve; ++j) {
|
|
SetThreshold(zero, ZERO);
|
|
do {
|
|
preserved = PreserveVoronoiCellSeg(preserve[j].site,
|
|
preserve[j].type, i);
|
|
if (!preserved) {
|
|
if (restart) return;
|
|
IncreaseThreshold(zero);
|
|
if (gt(zero, ZERO_MAX)) {
|
|
VD_Dbg_Warning("InsertSegIntoVD() - cell not preserved!");
|
|
if (IsInvalidData(true)) {
|
|
restart = true;
|
|
return;
|
|
}
|
|
else {
|
|
VD_Warning("InsertSegIntoVD() - desperate mode (preserve)");
|
|
DesperatePreserveVoronoiCellSeg(preserve[j].site,
|
|
preserve[j].type, i);
|
|
preserved = true;
|
|
}
|
|
}
|
|
}
|
|
#ifdef VRONI_DBG_WARN
|
|
else if (gt(zero, ZERO) && !quiet) {
|
|
printf("InsertSegIntoVD() - ");
|
|
printf("cell not preserved till zero = %20.16f for seg %d!\n",
|
|
zero, i);
|
|
}
|
|
#endif
|
|
} while (!preserved);
|
|
#ifdef VRONI_INFO
|
|
UpdateRelaxationMemory(zero);
|
|
#endif
|
|
}
|
|
ResetPreserveBuffer;
|
|
|
|
/* */
|
|
/* make sure that the structure that will be removed forms a tree. */
|
|
/* */
|
|
e1 = GetIncidentEdge(n1);
|
|
MarkNodeDeleted(n1);
|
|
ResetLoopStack();
|
|
while (LoopExists(e1, n1, &n3)) {
|
|
PurifyLoop(n1, n3);
|
|
SetThreshold(zero, ZERO);
|
|
do {
|
|
broken = BreakLoopSeg(i);
|
|
if (!broken) {
|
|
if (restart) return;
|
|
IncreaseThreshold(zero);
|
|
if (gt(zero, ZERO_MAX)) {
|
|
VD_Dbg_Warning("InsertSegIntoVD() - loop not removed!");
|
|
if (IsInvalidData(true)) {
|
|
restart = true;
|
|
return;
|
|
}
|
|
else {
|
|
VD_Warning("InsertSegIntoVD() - desperate mode (loop)");
|
|
DesperateBreakLoopSeg(i);
|
|
broken = true;
|
|
}
|
|
}
|
|
}
|
|
if (broken) {
|
|
#ifdef VRONI_DBG_WARN
|
|
if (gt(zero, ZERO) && le(zero, ZERO_MAX) && !quiet) {
|
|
printf("InsertSegIntoVD() - ");
|
|
printf("loop not broken till zero = %20.16f for seg %d!\n",
|
|
zero, i);
|
|
}
|
|
#endif
|
|
ResetLoopStack();
|
|
e1 = GetIncidentEdge(n1);
|
|
ResetTreeDeleteStatus(e1, n1);
|
|
if (n3 == n1) {
|
|
e2 = GetCCWEdge(e1, n1);
|
|
ResetTreeDeleteStatus(e2, n1);
|
|
e3 = GetCCWEdge(e2, n1);
|
|
if (e3 != e1) ResetTreeDeleteStatus(e3, n1);
|
|
}
|
|
MarkNodeDeleted(n1);
|
|
}
|
|
} while (!broken);
|
|
#ifdef VRONI_INFO
|
|
UpdateRelaxationMemory(zero);
|
|
#endif
|
|
}
|
|
e1 = GetIncidentEdge(n1);
|
|
e2 = GetCCWEdge(e1, n1);
|
|
ResetLoopStack();
|
|
while (LoopExists(e2, n1, &n3)) {
|
|
PurifyLoop(n1, n3);
|
|
SetThreshold(zero, ZERO);
|
|
do {
|
|
broken = BreakLoopSeg(i);
|
|
if (!broken) {
|
|
if (restart) return;
|
|
IncreaseThreshold(zero);
|
|
if (gt(zero, ZERO_MAX)) {
|
|
VD_Dbg_Warning("InsertSegIntoVD() - loop not removed!");
|
|
if (IsInvalidData(true)) {
|
|
restart = true;
|
|
return;
|
|
}
|
|
else {
|
|
VD_Warning("InsertSegIntoVD() - desperate mode (loop)");
|
|
DesperateBreakLoopSeg(i);
|
|
broken = true;
|
|
}
|
|
}
|
|
}
|
|
if (broken) {
|
|
#ifdef VRONI_DBG_WARN
|
|
if (gt(zero, ZERO) && le(zero, ZERO_MAX) && !quiet) {
|
|
printf("InsertSegIntoVD() - ");
|
|
printf("loop not broken till zero = %20.16f for seg %d!\n",
|
|
zero, i);
|
|
}
|
|
#endif
|
|
ResetLoopStack();
|
|
e2 = GetCCWEdge(e1, n1);
|
|
ResetTreeDeleteStatus(e2, n1);
|
|
if (n3 == n1) {
|
|
e3 = GetCCWEdge(e2, n1);
|
|
if (e3 != e1) ResetTreeDeleteStatus(e3, n1);
|
|
}
|
|
}
|
|
} while (!broken);
|
|
#ifdef VRONI_INFO
|
|
UpdateRelaxationMemory(zero);
|
|
#endif
|
|
}
|
|
e2 = GetCCWEdge(e1, n1);
|
|
e3 = GetCCWEdge(e2, n1);
|
|
ResetLoopStack();
|
|
if (e3 != e1) {
|
|
while (LoopExists(e3, n1, &n3)) {
|
|
PurifyLoop(n1, n3);
|
|
SetThreshold(zero, ZERO);
|
|
do {
|
|
broken = BreakLoopSeg(i);
|
|
if (!broken) {
|
|
if (restart) return;
|
|
IncreaseThreshold(zero);
|
|
if (gt(zero, ZERO_MAX)) {
|
|
VD_Dbg_Warning("InsertSegIntoVD() - loop not removed!");
|
|
if (IsInvalidData(true)) {
|
|
restart = true;
|
|
return;
|
|
}
|
|
else {
|
|
VD_Warning("InsertSegIntoVD() - desperate mode (loop)");
|
|
DesperateBreakLoopSeg(i);
|
|
broken = true;
|
|
}
|
|
}
|
|
}
|
|
if (broken) {
|
|
#ifdef VRONI_DBG_WARN
|
|
if (gt(zero, ZERO) && le(zero, ZERO_MAX) && !quiet) {
|
|
printf("InsertSegIntoVD() - ");
|
|
printf("loop not broken till zero = %20.16f for seg %d!\n",
|
|
zero, i);
|
|
}
|
|
#endif
|
|
ResetLoopStack();
|
|
e3 = GetCCWEdge(e2, n1);
|
|
ResetTreeDeleteStatus(e3, n1);
|
|
}
|
|
} while (!broken);
|
|
#ifdef VRONI_INFO
|
|
UpdateRelaxationMemory(zero);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/* */
|
|
/* recursively discard all nodes and edges that are to be deleted. */
|
|
/* also, we insert the new Voronoi nodes and edges. */
|
|
/* */
|
|
if (IsDeg2Node(n1)) {
|
|
e1 = GetIncidentEdge(n1);
|
|
e2 = GetCCWEdge(e1, n1);
|
|
|
|
#ifdef TRACE
|
|
if (debug_flag_VD)
|
|
printf("*** 1st call of UpdateRecursive - i = %d, n1 = %d, e1 = %d\n",
|
|
i, n1, e1);
|
|
#endif
|
|
UpdateRecursive(i, SEG, n1, e1, &e1l, &e1r, &n1l, &n1r);
|
|
if (restart) return;
|
|
|
|
#ifdef TRACE
|
|
if (debug_flag_VD)
|
|
printf("*** 2nd call of UpdateRecursive - i = %d, n1 = %d, e2 = %d\n",
|
|
i, n1, e2);
|
|
#endif
|
|
UpdateRecursive(i, SEG, n1, e2, &e2l, &e2r, &n2l, &n2r);
|
|
if (restart) return;
|
|
|
|
/* */
|
|
/* close the two Voronoi cells around nodes[n], which is to be */
|
|
/* deleted. */
|
|
/* */
|
|
/* cell 1: */
|
|
/* */
|
|
if (GetEndNode(e1r) == n1r) {
|
|
GetRgtSiteData(e1r, &i0, &t0);
|
|
}
|
|
else {
|
|
assert(GetStartNode(e1r) == n1r);
|
|
GetLftSiteData(e1r, &i0, &t0);
|
|
}
|
|
e0 = StoreEdge(n1r, n2l, i, i0, SEG, t0);
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) {
|
|
printf("new edge %2d between sites (%2d/0, %2d/%1d) computed\n",
|
|
e0, i, i0, t0);
|
|
printf("edge %d - start node %d, end node %d\n", e0, n1r, n2l);
|
|
}
|
|
#endif
|
|
SetVDPtr(i0, t0, e0); /* make sure the VD edge pointer is up-to-date! */
|
|
CloseVoronoiCell(e1r, e0, e2l, n1r, n2l);
|
|
|
|
/* */
|
|
/* cell 2: */
|
|
/* */
|
|
if (GetEndNode(e2r) == n2r) {
|
|
GetRgtSiteData(e2r, &i0, &t0);
|
|
}
|
|
else {
|
|
assert(GetStartNode(e2r) == n2r);
|
|
GetLftSiteData(e2r, &i0, &t0);
|
|
}
|
|
e0 = StoreEdge(n2r, n1l, i, i0, SEG, t0);
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) {
|
|
printf("new edge %2d between sites (%2d/0, %2d/%1d) computed\n",
|
|
e0, i, i0, t0);
|
|
printf("edge %d - start node %d, end node %d\n", e0, n2r, n1l);
|
|
}
|
|
#endif
|
|
SetVDPtr(i0, t0, e0); /* make sure the VD edge pointer is up-to-date! */
|
|
CloseVoronoiCell(e2r, e0, e1l, n2r, n1l);
|
|
}
|
|
else {
|
|
e1 = GetIncidentEdge(n1);
|
|
e2 = GetCCWEdge(e1, n1);
|
|
e3 = GetCCWEdge(e2, n1);
|
|
|
|
#ifdef TRACE
|
|
if (debug_flag_VD)
|
|
printf("*** 1st call of UpdateRecursive - i = %d, n1 = %d, e1 = %d\n",
|
|
i, n1, e1);
|
|
#endif
|
|
UpdateRecursive(i, SEG, n1, e1, &e1l, &e1r, &n1l, &n1r);
|
|
if (restart) return;
|
|
|
|
#ifdef TRACE
|
|
if (debug_flag_VD)
|
|
printf("*** 2nd call of UpdateRecursive - i = %d, n1 = %d, e2 = %d\n",
|
|
i, n1, e2);
|
|
#endif
|
|
UpdateRecursive(i, SEG, n1, e2, &e2l, &e2r, &n2l, &n2r);
|
|
if (restart) return;
|
|
|
|
#ifdef TRACE
|
|
if (debug_flag_VD)
|
|
printf("*** 3rd call of UpdateRecursive - i = %d, n1 = %d, e3 = %d\n",
|
|
i, n1, e3);
|
|
#endif
|
|
UpdateRecursive(i, SEG, n1, e3, &e3l, &e3r, &n3l, &n3r);
|
|
if (restart) return;
|
|
|
|
/* */
|
|
/* close the three Voronoi cells around nodes[n], which is to be */
|
|
/* deleted. */
|
|
/* */
|
|
/* cell 1: */
|
|
/* */
|
|
if (GetEndNode(e1r) == n1r) {
|
|
GetRgtSiteData(e1r, &i0, &t0);
|
|
}
|
|
else {
|
|
assert(GetStartNode(e1r) == n1r);
|
|
GetLftSiteData(e1r, &i0, &t0);
|
|
}
|
|
e0 = StoreEdge(n1r, n2l, i, i0, SEG, t0);
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) {
|
|
printf("new edge %2d between sites (%2d/0, %2d/%1d) computed\n",
|
|
e0, i, i0, t0);
|
|
printf("edge %d - start node %d, end node %d\n", e0, n1r, n2l);
|
|
}
|
|
#endif
|
|
SetVDPtr(i0, t0, e0); /* make sure the VD edge pointer is up-to-date! */
|
|
CloseVoronoiCell(e1r, e0, e2l, n1r, n2l);
|
|
|
|
/* */
|
|
/* cell 2: */
|
|
/* */
|
|
if (GetEndNode(e2r) == n2r) {
|
|
GetRgtSiteData(e2r, &i0, &t0);
|
|
}
|
|
else {
|
|
assert(GetStartNode(e2r) == n2r);
|
|
GetLftSiteData(e2r, &i0, &t0);
|
|
}
|
|
e0 = StoreEdge(n2r, n3l, i, i0, SEG, t0);
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) {
|
|
printf("new edge %2d between sites (%2d/0, %2d/%1d) computed\n",
|
|
e0, i, i0, t0);
|
|
printf("edge %d - start node %d, end node %d\n", e0, n2r, n3l);
|
|
}
|
|
#endif
|
|
SetVDPtr(i0, t0, e0); /* make sure the VD edge pointer is up-to-date! */
|
|
CloseVoronoiCell(e2r, e0, e3l, n2r, n3l);
|
|
|
|
/* */
|
|
/* cell 3: */
|
|
/* */
|
|
if (GetEndNode(e3r) == n3r) {
|
|
GetRgtSiteData(e3r, &i0, &t0);
|
|
}
|
|
else {
|
|
assert(GetStartNode(e3r) == n3r);
|
|
GetLftSiteData(e3r, &i0, &t0);
|
|
}
|
|
e0 = StoreEdge(n3r, n1l, i, i0, SEG, t0);
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) {
|
|
printf("new edge %2d between sites (%2d/0, %2d/%1d) computed\n",
|
|
e0, i, i0, t0);
|
|
printf("edge %d - start node %d, end node %d\n", e0, n3r, n1l);
|
|
}
|
|
#endif
|
|
SetVDPtr(i0, t0, e0); /* make sure the VD edge pointer is up-to-date! */
|
|
CloseVoronoiCell(e3r, e0, e1l, n3r, n1l);
|
|
}
|
|
|
|
/* */
|
|
/* delete node nodes[n1] */
|
|
/* */
|
|
DeleteNode(n1);
|
|
#ifdef TRACE
|
|
if (debug_flag_VD) printf("node %2d has been deleted!\n", n1);
|
|
#endif
|
|
|
|
/* */
|
|
/* set the Voronoi pointer for site segs[i] */
|
|
/* */
|
|
SetVDPtr(i, SEG, e0);
|
|
|
|
DeleteDummyNodes();
|
|
|
|
/* */
|
|
/* make sure to have (dummy) degree-2 Voronoi nodes at the apices of the */
|
|
/* parabolic Voronoi arcs around seg[i]. */
|
|
/* */
|
|
e = GetVDPtr(i, SEG);
|
|
assert(InEdgesList(e));
|
|
assert(IsLftSite(e, i, SEG) || IsRgtSite(e, i, SEG));
|
|
if (IsRgtSite(e, i, SEG)) k = GetEndNode(e);
|
|
else k = GetStartNode(e);
|
|
e0 = e;
|
|
GetOtherSiteData(e, i, SEG, &i1, &t1);
|
|
do {
|
|
i0 = i1;
|
|
t0 = t1;
|
|
if (t1 == PNT || t1 == ARC) InsertApexDegreeTwoNodeSeg(e, i, i1, t1);
|
|
e = GetCCWEdge(e, k);
|
|
k = GetOtherNode(e, k);
|
|
GetOtherSiteData(e, i, SEG, &i1, &t1);
|
|
if ((i1 == i0) && (t1 == t0) && (e != e0)) {
|
|
e = GetCCWEdge(e, k);
|
|
k = GetOtherNode(e, k);
|
|
GetOtherSiteData(e, i, SEG, &i1, &t1);
|
|
}
|
|
} while (e != e0);
|
|
|
|
#ifndef NDEBUG
|
|
i1 = Get1stVtx(i, SEG);
|
|
assert(GetVDPtr(i1, PNT) != NIL);
|
|
i2 = Get2ndVtx(i, SEG);
|
|
assert(GetVDPtr(i2, PNT) != NIL);
|
|
#endif
|
|
|
|
#ifdef GRAPHICS
|
|
if (graphics) {
|
|
e = GetVDPtr(i, SEG);
|
|
assert(InEdgesList(e));
|
|
assert(IsLftSite(e, i, SEG) || IsRgtSite(e, i, SEG));
|
|
if (IsRgtSite(e, i, SEG)) k = GetEndNode(e);
|
|
else k = GetStartNode(e);
|
|
e0 = e;
|
|
do {
|
|
AddToCurBuffer(e, VDE, VDCurrColor);
|
|
e = GetCCWEdge(e, k);
|
|
k = GetOtherNode(e, k);
|
|
} while (e != e0);
|
|
}
|
|
#endif
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
// #undef TRACE
|