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

1060 lines
32 KiB
C++

/*****************************************************************************/
/* */
/* Copyright (C) 2001-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-611 */
/* Voice Mail: (+43 662) 8044-6304 */
/* Snail Mail: Martin Held */
/* FB Informatik */
/* Universitaet Salzburg */
/* A-5020 Salzburg, Austria */
/* */
/*****************************************************************************/
/* */
/* get standard libraries */
/* */
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <float.h>
/* */
/* get my header files */
/* */
#include "fpkernel.h"
#include "vronivector.h"
#include "vroni_object.h"
#include "defs.h"
#include "numerics.h"
#include "wmat.h"
#include "offset.h"
#ifdef MAT
#define ComputeContact(S, P, Q, A, B, T) \
{\
if (S) { \
P.x = Q.x - A * T; \
P.y = Q.y - B * T; \
} \
else { \
P.x = Q.x + A * T; \
P.y = Q.y + B * T; \
} \
}
#define WmatErrorCheck(dist, wmat_dist_sq, ZERO, wmat_cosine, cosine, i, t, r1, r2) \
{\
if (gt(dist - wmat_dist_sq, ZERO) && gt(wmat_cosine - cosine, ZERO)) { \
if ((t < r1) || (t > r2)) { \
printf("WMAT violation I for edge %d and parameter %f\n", i, t); \
printf("wmat_cosine = %f, cosine = %f\n", wmat_cosine, cosine); \
printf("wmat_dist_sq = %20.16f, dist = %20.16f\n", wmat_dist_sq, dist); \
printf("r1 = %20.16f, r2 = %20.16f\n", r1, r2);\
} \
} \
else if ((t >= r1) && (t <= r2)) { \
if (lt(dist - wmat_dist_sq, ZERO) || lt(wmat_cosine - cosine, ZERO)) { \
printf("WMAT violation II for edge %d and parameter %f\n", i, t); \
printf("wmat_cosine = %f, cosine = %f\n", wmat_cosine, cosine); \
printf("wmat_dist_sq = %20.16f, dist = %20.16f\n", wmat_dist_sq, dist); \
printf("r1 = %20.16f, r2 = %20.16f\n", r1, r2);\
} \
} \
}
/* */
/* the weighted medial axis (WMAT) is the subset of all those points P of */
/* the Voronoi diaram (VD) that meet the following requirements: */
/* (1) the clearance disk centered at P touches the input sites in at */
/* least two disjoint contact points C1 and C2. */
/* (2) the distance between C1 and C2 is greater than the (user-defined) */
/* threshold wmat_dist. */
/* (3) the angle formed by (C1,P,C2) is greater than the (user-defined) */
/* threshold wmat_angle. */
/* note that the WMAT is identical to the standard medial axis (MAT) for */
/* wmat_dist = wmat_angle = 0. see wmat.pdf in ../READMEs for a figure. */
/* */
/* for edge i of the VD, we store the WMAT data in the record */
/* edges[i].w_mat as follows: */
/* the vr_bool in_w_mat is true if a portion of this VD edge also belongs */
/* to the WMAT. */
/* r_min and r_max denote the minimum and maximum contour clearances of */
/* those points of this VD edge that belong to the WMAT. due to our specific */
/* parameterization of the VD edges, we have */
/* min{t1,t2} <= r_min <= r_max <= max{t1,t2}, where t1 and t2 are the */
/* contour clearances (radii) of the start node and end node of the VD edge. */
/* let P1 be the point on the VD edge that corresponds to the clearance */
/* radius r_min, and P2 the point that corresponds to r_max. the */
/* intersection (contact point) of the left defining site of the VD edge */
/* with a disk with radius r_min centered at P1 is stored in lft_mn_pnt,*/
/* and the intersection (contact point) of the right defining defining site */
/* of the VD edge with a disk with radius r_min centered at P1 is stored */
/* in rgt_mn_pnt. similar for P2 and lft_mx_pnt, rgt_mx_pnt. */
/* */
/* For closed contours, a one-sided computation of the WMAT may be requested */
/* by specifying the run-time options "--left_offset" or "--right_offset". */
/* */
vr_bool vroniObject::GetWMATStatus(void)
{
return WMAT_computed;
}
void vroniObject::ResetWMATStatus(void)
{
int i, num_edges;
num_edges = GetNumberOfEdges();
for (i = 0; i < num_edges; ++i) {
SetWmatEdge(i, false);
}
WMAT_computed = false;
return;
}
#ifdef WMAT
void vroniObject::CheckWMAT(double wmat_dist, double wmat_angle)
{
int num_edges, i, j, n1, n2, lft, rgt;
t_site t_lft, t_rgt;
double t, t1, t2, t3, r1, r2, a1, a2, b1, b2, c1, c2;
coord p1, p2, q1, q2, u1, u2;
double delta, wmat_dist_sq, wmat_cosine, cosine, dist;
vr_bool s1, s2;
num_edges = GetNumberOfEdges();
wmat_cosine = cos(wmat_angle);
wmat_dist_sq = wmat_dist * wmat_dist;
delta = 0.1 * wmat_dist;
// if (lt(delta, SMALL)) delta = SMALL; /* must not be equal to 0.0!!!! */ // KO ?
if ( delta < SMALL)
delta = SMALL; /* must not be equal to 0.0!!!! */
for (i = 4; i < num_edges; ++i) {
if (IsWmatEdge(i)) {
n1 = GetStartNode(i);
n2 = GetEndNode(i);
GetNodeData(n1, &p1, &t1);
GetNodeData(n2, &p2, &t2);
if (t1 > t2) {
VroniSwap(t1, t2, r1);
}
else {
p1 = p2;
}
r1 = GetWmatRMin(i);
r2 = GetWmatRMax(i);
GetLftSiteData(i, &lft, &t_lft);
GetRgtSiteData(i, &rgt, &t_rgt);
if ((t_lft == PNT) && (t_rgt == SEG)) {
VroniSwap(lft, rgt, j);
t_lft = SEG;
t_rgt = PNT;
}
t3 = t2 + delta * 0.5;
if (t_lft == SEG) {
GetSegEqnData(lft, &a1, &b1, &c1);
if (PntLineDist(a1, b1, c1, p1) >= 0.0) s1 = true;
else s1 = false;
if (t_rgt == SEG) {
/* */
/* SEG-SEG: line bisector */
/* */
GetSegEqnData(rgt, &a2, &b2, &c2);
if (PntLineDist(a2, b2, c2, p1) >= 0.0) {
s2 = true;
if (s1) cosine = a1 * a2 + b1 * b2;
else cosine = - a1 * a2 - b1 * b2;
}
else {
s2 = false;
if (s1) cosine = - a1 * a2 - b1 * b2;
else cosine = a1 * a2 + b1 * b2;
}
for (t = t1; t < t3; t += delta) {
if (t > t2) t = t2;
EvaluateLineData(i, t, &p2);
ComputeContact(s1, q1, p2, a1, b1, t);
ComputeContact(s2, q2, p2, a2, b2, t);
dist = PntPntDistSq(q1, q2);
WmatErrorCheck(dist, wmat_dist_sq, ZERO, wmat_cosine, cosine,
i, t, r1, r2);
}
}
else if (t_rgt == PNT) {
/* */
/* SEG-PNT: parabola bisector */
/* */
assert(!(IsSegStartPnt(lft, rgt) || IsSegEndPnt(lft, rgt)));
q2 = GetPntCoords(rgt);
for (t = t1; t < t3; t += delta) {
if (t > t2) t = t2;
EvaluateParabolaData(i, lft, t, &p2);
ComputeContact(s1, q1, p2, a1, b1, t);
dist = PntPntDistSq(q1, q2);
u2 = VecSub(p2, q2);
if (s1) cosine = a1 * u2.x + b1 * u2.y;
else cosine = - a1 * u2.x - b1 * u2.y;
if (eq(t, TINY)) cosine = 1.0;
else cosine /= t;
WmatErrorCheck(dist, wmat_dist_sq, ZERO, wmat_cosine, cosine,
i, t, r1, r2);
}
}
else {
throw std::runtime_error("VRONI error: CheckWMAT() - cannot handle this site type!");
}
}
else if (t_lft == PNT) {
/* */
/* PNT-PNT: (hyperbola) line bisector */
/* */
q1 = GetPntCoords(lft);
q2 = GetPntCoords(rgt);
dist = PntPntDistSq(q1, q2);
for (t = t1; t < t3; t += delta) {
if (t > t2) t = t2;
EvaluateHyperbolaData(i, t, &p2);
u1 = VecSub(p2, q1);
u2 = VecSub(p2, q2);
if (eq(t, TINY))
cosine = 1.0;
else
cosine = VecDotProd(u1, u2) / (t * t);
WmatErrorCheck(dist, wmat_dist_sq, ZERO, wmat_cosine, cosine,
i, t, r1, r2);
}
}
else {
throw std::runtime_error("VRONI error: CheckWMAT() - cannot handle this site type!");
}
}
}
return;
}
#endif
#ifdef WMAT
void vroniObject::ComputeWMATParabola(int i, int i1, int i2, double_arg wmat_cosine,
double_arg wmat_dist_sq)
#else
void vroniObject::ComputeWMATParabola(int i, int i1, int i2)
#endif
{
int n1, n2;
coord p1, p2, p;
double t1, t2, t_min, delta;
t_site site2 = PNT;
#ifdef WMAT
double a1, b1, c1, d, t_max;
coord q1, q2;
vr_bool s1;
#endif
assert(InEdgesList(i));
assert(InSegsList(i1));
assert(InPntsList(i2));
#ifdef GENUINE_ARCS
GetLftSiteData(i, &n2, &site2);
if (site2 == SEG) GetRgtSiteData(i, &n2, &site2);
assert((site2 == PNT) || (site2 == ARC));
#endif
if ((site2 == PNT) && (IsSegStartPnt(i1, i2) || IsSegEndPnt(i1, i2)) ) {
SetWmatEdge(i, false);
return;
}
n1 = GetStartNode(i);
n2 = GetEndNode(i);
GetNodeData(n1, &p1, &t1);
GetNodeData(n2, &p2, &t2);
if (t2 < t1) {
VroniSwap(t1, t2, t_min);
VroniSwap(p1, p2, p);
}
if (le(t2, ZERO)) { /* degenerate segment */
SetWmatEdge(i, false);
return;
}
#ifdef WMAT
GetSegEqnData(i1, &a1, &b1, &c1);
q1 = GetPntCoords(i2);
d = PntLineDist(a1, b1, c1, q1);
if (d < 0.0) {
s1 = false;
d = -d;
}
else {
s1 = true;
}
/* */
/* let delta be the distance between p1 and the contact point on the */
/* line segment, for a disk with clearance radius t. we get */
/* delta * delta = 2 * t * d ... yields lower bound for t. */
/* */
if (eq(d, ZERO)) {
if (wmat_dist_sq == 0.0) {
t_min = 0.0;
}
else {
SetWmatEdge(i, false);
return;
}
}
else {
t_min = wmat_dist_sq * 0.5 / d;
}
if (t_min >= t2) { /* distance too small */
SetWmatEdge(i, false);
return;
}
/* */
/* d = t * (1 - cos(wmat_angle)) ... yields upper bound for t. */
/* */
delta = 1 - wmat_cosine;
if (eq(delta, TINY))
t_max = DBL_MAX;
else
t_max = d / delta;
t_min = VroniMax(t1, t_min);
t_max = VroniMin(t2, t_max);
if (t_max <= t_min) { /* angle too small */
SetWmatEdge(i, false);
return;
}
SetWmatRMin(i, t_min);
SetWmatRMax(i, t_max);
/* */
/* make sure that the parameterization formula is initialized */
/* */
if (GetEdgeDataInit(i)) {
CreateParabolaData(i);
SetEdgeDataInit(i, false);
}
/* */
/* compute the contact points */
/* */
if (IsLftSite(i, i1, SEG)) {
assert(IsRgtSite(i, i2, PNT));
EvaluateParabolaData(i, i1, t_min, &q1);
ComputeContact(s1, p2, q1, a1, b1, t_min);
SetWmatLftMnPnt(i, p2);
SetWmatRgtMnPnt(i, p1);
EvaluateParabolaData(i, i1, t_max, &q2);
ComputeContact(s1, p2, q2, a1, b1, t_max);
SetWmatLftMxPnt(i, p2);
SetWmatRgtMxPnt(i, p1);
}
else {
assert(IsRgtSite(i, i1, SEG));
assert(IsLftSite(i, i2, PNT));
EvaluateParabolaData(i, i2, t_min, &q1);
ComputeContact(s1, p2, q1, a1, b1, t_min);
SetWmatLftMnPnt(i, p1);
SetWmatRgtMnPnt(i, p2);
EvaluateParabolaData(i, i2, t_max, &q2);
ComputeContact(s1, p2, q2, a1, b1, t_max);
SetWmatLftMxPnt(i, p1);
SetWmatRgtMxPnt(i, p2);
}
#endif
if (t1 == 0.0) {
delta = PntPntDist(p1, p2) - t2;
if (gt(delta, ZERO)) {
SetWmatEdge(i, true);
}
else {
SetWmatEdge(i, false);
}
}
else {
SetWmatEdge(i, true);
}
return;
}
#ifdef WMAT
void vroniObject::ComputeWMATHyperbola(int i, int i1, int i2, double_arg wmat_cosine,
double_arg wmat_dist_sq)
#else
void vroniObject::ComputeWMATHyperbola(int i)
#endif
{
int n1, n2;
double t1, t2, t_max;
coord p1, p2, p;
double delta;
#ifdef WMAT
double d_sq;
coord q1, q2;
#endif
assert(InEdgesList(i));
n1 = GetStartNode(i);
n2 = GetEndNode(i);
GetNodeData(n1, &p1, &t1);
GetNodeData(n2, &p2, &t2);
if (t2 < t1) {
VroniSwap(t1, t2, t_max);
VroniSwap(p1, p2, p);
}
if (le(t2, ZERO)) { /* degenerate segment */
SetWmatEdge(i, false);
return;
}
#ifdef WMAT
assert(InPntsList(i1));
assert(InPntsList(i2));
q1 = GetPntCoords(i1);
q2 = GetPntCoords(i2);
d_sq = PntPntDistSq(q1, q2);
if (d_sq <= wmat_dist_sq) { /* distance is too small */
SetWmatEdge(i, false);
return;
}
/* */
/* d_sq = 2 * t * t * (1 - cos(wmat_angle)) ... yields upper bound for t */
/* */
delta = 1 - wmat_cosine;
if (eq(delta, TINY))
t_max = DBL_MAX;
else
t_max = sqrt(0.5 * d_sq / delta);
if (t2 < t_max) {
SetWmatRMax(i, t2);
}
else if (t_max <= t1) {
SetWmatEdge(i, false);
return;
}
else {
SetWmatRMax(i, t_max);
}
SetWmatRMin(i, t1);
/* */
/* store the contact points */
/* */
SetWmatLftMnPnt(i, q1);
SetWmatLftMxPnt(i, q1);
SetWmatRgtMnPnt(i, q2);
SetWmatRgtMxPnt(i, q2);
/* */
/* make sure that the parameterization formula is initialized */
/* */
if (GetEdgeDataInit(i)) {
CreateHyperbolaData(i);
SetEdgeDataInit(i, false);
}
#endif
if (t1 == 0.0) {
delta = PntPntDist(p1, p2) - t2;
if (gt(delta, ZERO)) {
SetWmatEdge(i, true);
}
else {
SetWmatEdge(i, false);
}
}
else {
SetWmatEdge(i, true);
}
return;
}
#ifdef WMAT
void vroniObject::ComputeWMATLine(int i, int i1, int i2, double wmat_cosine,
double wmat_dist_sq)
#else
void vroniObject::ComputeWMATLine(int i)
#endif
{
int n1, n2;
double t1, t2, t_min, delta;
coord p1, p2, q1;
#ifdef WMAT
double a1, b1, c1, a2, b2, c2, cosine;
coord q2;
vr_bool s1, s2;
#endif
assert(InEdgesList(i));
n1 = GetStartNode(i);
n2 = GetEndNode(i);
GetNodeData(n1, &p1, &t1);
GetNodeData(n2, &p2, &t2);
if (t1 <= t2) {
q1 = p2;
}
else {
q1 = p1;
VroniSwap(t1, t2, t_min);
}
if (le(t2, ZERO)) { /* degnerate segment */
SetWmatEdge(i, false);
return;
}
#ifdef WMAT
assert(InSegsList(i1));
assert(InSegsList(i2));
GetSegEqnData(i1, &a1, &b1, &c1);
GetSegEqnData(i2, &a2, &b2, &c2);
/* */
/* compute the cosine of the angle between the normals; make sure that */
/* normals point into the correct direction. */
/* */
if (PntLineDist(a1, b1, c1, q1) >= 0.0) {
s1 = true;
if (PntLineDist(a2, b2, c2, q1) >= 0.0) {
s2 = true;
cosine = a1 * a2 + b1 * b2;
}
else {
s2 = false;
cosine = - a1 * a2 - b1 * b2;
}
}
else {
s1 = false;
if (PntLineDist(a2, b2, c2, q1) >= 0.0) {
s2 = true;
cosine = - a1 * a2 - b1 * b2;
}
else {
s2 = false;
cosine = a1 * a2 + b1 * b2;
}
}
if (cosine >= wmat_cosine) { /* angle is too small */
SetWmatEdge(i, false);
return;
}
delta = 1 - cosine;
if (eq(delta, TINY))
t_min = DBL_MAX;
else
t_min = sqrt(0.5 * wmat_dist_sq / delta);
if (t_min >= t2) {
SetWmatEdge(i, false);
return;
}
else {
t_min = VroniMax(t1, t_min);
SetWmatRMin(i, t_min);
}
SetWmatRMax(i, t2);
/* */
/* make sure that the parameterization formula is initialized */
/* */
if (GetEdgeDataInit(i)) {
CreateLineData(i);
SetEdgeDataInit(i, false);
}
/* */
/* compute the contact points */
/* */
assert(IsLftSite(i, i1, SEG));
assert(IsRgtSite(i, i2, SEG));
if (t1 == t2) q1 = p1;
else EvaluateLineData(i, t_min, &q1);
ComputeContact(s1, p1, q1, a1, b1, t_min);
SetWmatLftMnPnt(i, p1);
ComputeContact(s2, p2, q1, a2, b2, t_min);
SetWmatRgtMnPnt(i, p2);
if (t1 == t2) q2 = p2;
else EvaluateLineData(i, t2, &q2);
ComputeContact(s1, p1, q2, a1, b1, t2);
SetWmatLftMxPnt(i, p1);
ComputeContact(s2, p2, q2, a2, b2, t2);
SetWmatRgtMxPnt(i, p2);
#endif
if (t1 == 0.0) {
delta = PntPntDist(p1, p2) - t2;
if (gt(delta, ZERO)) {
SetWmatEdge(i, true);
}
else {
SetWmatEdge(i, false);
}
}
else {
SetWmatEdge(i, true);
}
return;
}
#ifdef WMAT
void vroniObject::ComputeWMATEdge(int e, double_arg wmat_cosine, double_arg wmat_dist_sq)
#else
void vroniObject::ComputeWMATEdge(int e)
#endif
{
int i1, i2;
t_site ltype, rtype;
assert(InEdgesList(e));
GetLftSiteData(e, &i1, &ltype);
GetRgtSiteData(e, &i2, &rtype);
switch(ltype) {
case(PNT):
switch(rtype) {
case(PNT): /* PNT-PNT: line (hyperbolic) bisector */
#ifdef WMAT
ComputeWMATHyperbola(e, i1, i2, wmat_cosine, wmat_dist_sq);
#else
ComputeWMATHyperbola(e);
#endif
break;
case(SEG): /* PNT-SEG: parabola bisector */
#ifdef WMAT
ComputeWMATParabola(e, i2, i1, wmat_cosine, wmat_dist_sq);
#else
ComputeWMATParabola(e, i2, i1);
#endif
break;
case(ARC):
#ifdef GENUINE_ARCS
#ifndef WMAT
ComputeWMATHyperbola(e);
#endif
#endif
break;
default:
break;
}
break;
case(SEG):
switch(rtype) {
case(PNT): /* SEG-PNT: parabola bisector */
#ifdef WMAT
ComputeWMATParabola(e, i1, i2, wmat_cosine, wmat_dist_sq);
#else
ComputeWMATParabola(e, i1, i2);
#endif
break;
case(SEG): /* SEG-SEG: line bisector */
#ifdef WMAT
ComputeWMATLine(e, i1, i2, wmat_cosine, wmat_dist_sq);
#else
ComputeWMATLine(e);
#endif
break;
case(ARC):
#ifdef GENUINE_ARCS
#ifndef WMAT
ComputeWMATParabola(e,i1,i2);
#endif
#endif
break;
default:
break;
}
break;
case(ARC):
#ifdef GENUINE_ARCS
#ifndef WMAT
switch(rtype) {
case(PNT):
ComputeWMATHyperbola(e);
break;
case(SEG):
ComputeWMATParabola(e, i2, i1);
break;
case(ARC):
ComputeWMATHyperbola(e);
break;
default:
break;
}
#endif
#endif
break;
default:
break;
}
return;
}
void vroniObject::ComputeWMAT(double wmat_angle, double wmat_dist,
vr_bool time, vr_bool left_wmat, vr_bool right_wmat)
{
int i, j, not_needed;
vr_bool unrestricted;
#ifdef WMAT
double wmat_dist_sq, wmat_cosine;
#endif
assert(GetVDStatus());
assert(scale_factor > 0.0);
if (GetNodesSqdFlag()) TakeSquareOfNodes();
if (!GetDeg2Flag()) InsertDegreeTwoNodes();
if (wmat_angle < 0.0) wmat_angle = 0.0;
else if(wmat_angle > M_PI) wmat_angle = M_PI;
if (wmat_dist < 0.0) wmat_dist = 0.0;
#ifdef WMAT
wmat_dist = ScaleV(wmat_dist);
wmat_dist_sq = wmat_dist * wmat_dist;
wmat_cosine = cos(wmat_angle);
#endif
if (left_wmat && right_wmat) {
left_wmat = right_wmat = false;
}
/* */
/* first call to this function. allocate memory and initialize the */
/* flags for the edge data. */
/* */
#ifdef WMAT
#ifdef GENUINE_ARCS
if (num_arcs > 0)
throw std::runtime_error("VRONI error: ComputeWMAT() - computation of wMAT not supported for circular arcs!");
#endif
VD_Info("...computing weighted medial axis -- ");
#else
VD_Info("...computing medial axis -- ");
#endif
if (time) cpu_time_wmat = elapsed();
#ifdef GRAPHICS
if (graphics) ResetCurBuffer();
#endif
unrestricted = !(left_wmat || right_wmat);
/* */
/* allocate memory and initialize the flags for the edge data. */
/* */
InitializeEdgeData(unrestricted, left_wmat, false, &not_needed);
/* */
/* let the user call some application-specific function */
/* */
ExtApplFuncWMATInit;
j = -1;
AdvanceActiveEdge(i, j, false);
while (i != NIL) {
/* */
/* compute the WMAT-data for this edge */
/* */
#ifdef WMAT
ComputeWMATEdge(i, wmat_cosine, wmat_dist_sq);
#else
ComputeWMATEdge(i);
#endif
/* */
/* let the user call some application-specific function */
/* */
ExtApplFuncWMATLoop;
AdvanceActiveEdge(i, j, false);
}
if (time) cpu_time_wmat = elapsed();
VD_Info("done!\n");
WMAT_computed = true;
/* */
/* let the user call some application-specific function */
/* */
ExtApplFuncWMATComputed;
#ifdef GRAPHICS
if (graphics) {
AddWMATToBuffer();
}
#endif
#ifdef WMAT
#ifndef NDEBUG
CheckWMAT(wmat_dist, wmat_angle);
#endif
#endif
/* */
/* let the user call some application-specific function */
/* */
ExtApplFuncWMATDone;
return;
}
/* */
/* this function adds the edges of the wMAT to VRONI's graphics buffer for */
/* subsequent graphics display. please note that all conic VD edges are */
/* approximated by straight-line segments relative to a heuristically chosen */
/* approximation threshold prior to output! */
/* */
#ifdef GRAPHICS
void vroniObject::AddWMATToBuffer(void)
{
double delta_x, delta_y, delta;
///void SetStepSize(double_arg delta);
t_site t_lft, t_rgt;
int num_edges, i, lft, rgt;
coord u, v;
#ifdef WMAT
double t1, t2;
#else
double t1, t2, t;
int n1, n2;
coord dummy;
#endif
num_edges = GetNumberOfEdges();
/* */
/* compute the discretization threshold for approximating non-linear */
/* bisectors. */
/* */
delta_x = bb_max.x - bb_min.x;
delta_y = bb_max.y - bb_min.y;
delta = VroniMax(delta_x, delta_y);
if (le(delta, ZERO)) delta = ZERO;
SetStepSize(delta);
for (i = 4; i < num_edges; ++i) {
if (IsWmatEdge(i)) {
#ifdef WMAT
t1 = GetWmatRMin(i);
t2 = GetWmatRMax(i);
#else
n1 = GetStartNode(i);
n2 = GetEndNode(i);
GetNodeData(n1, &u, &t1);
GetNodeData(n2, &v, &t2);
if (t2 < t1) {
VroniSwap(t1, t2, t);
VroniSwap(u, v, dummy);
}
#endif
GetLftSiteData(i, &lft, &t_lft);
GetRgtSiteData(i, &rgt, &t_rgt);
switch(t_lft) {
case(PNT):
switch(t_rgt) {
case(PNT): /* PNT-PNT: line (hyperbola) bisector */
#ifdef WMAT
EvaluateHyperbolaData(i, t1, &u);
EvaluateHyperbolaData(i, t2, &v);
#endif
AddEdgeToBuffer(u.x, u.y, v.x, v.y, WMATColor);
break;
case(SEG): /* PNT-SEG: parabola bisector */
#ifdef WMAT
if (IsSegStartPnt(rgt, lft) || IsSegEndPnt(rgt, lft)) {
EvaluateLineData(i, t1, &u);
EvaluateLineData(i, t2, &v);
}
else {
EvaluateParabolaData(i, rgt, t1, &u);
EvaluateParabolaData(i, rgt, t2, &v);
}
#endif
AddParabolaToBuffer(i, t1, t2, u, v, WMATColor);
break;
case(ARC):
#ifdef GENUINE_ARCS
AddHyperbolaEllipseToBuffer(i, t1, t2, u, v, WMATColor);
#endif
break;
default:
break;
}
break;
case(SEG):
switch(t_rgt) {
case(PNT): /* SEG-PNT: parabola bisector */
#ifdef WMAT
if (IsSegStartPnt(lft, rgt) || IsSegEndPnt(lft, rgt)) {
EvaluateLineData(i, t1, &u);
EvaluateLineData(i, t2, &v);
}
else {
EvaluateParabolaData(i, lft, t1, &u);
EvaluateParabolaData(i, lft, t2, &v);
}
#endif
AddParabolaToBuffer(i, t1, t2, u, v, WMATColor);
break;
case(SEG): /* SEG-SEG: line bisector */
#ifdef WMAT
if (GetEdgeFlagDeg(i)) {
GetNodeData(GetStartNode(i), &u, &t1);
GetNodeData(GetEndNode(i), &v, &t2);
}
else {
EvaluateLineData(i, t1, &u);
EvaluateLineData(i, t2, &v);
}
#endif
AddEdgeToBuffer(u.x, u.y, v.x, v.y, WMATColor);
break;
case(ARC):
#ifdef GENUINE_ARCS
AddParabolaToBuffer(i, t1, t2, u, v, WMATColor);
#endif
break;
default:
break;
}
break;
case(ARC):
#ifdef GENUINE_ARCS
switch(t_rgt) {
case(PNT):
#ifdef WMAT
if (IsArcStartPnt(lft, rgt) || IsArcEndPnt(lft, rgt)) {
EvaluateLineData(i, t1, &u);
EvaluateLineData(i, t2, &v);
}
else {
EvaluateParabolaData(i, lft, t1, &u);
EvaluateParabolaData(i, lft, t2, &v);
}
#endif
AddHyperbolaEllipseToBuffer(i, t1, t2, u, v, WMATColor);
break;
case(SEG):
#ifdef WMAT
if (GetEdgeFlagDeg(i)) {
GetNodeData(GetStartNode(i), &u, &t1);
GetNodeData(GetEndNode(i), &v, &t2);
}
else {
EvaluateLineData(i, t1, &u);
EvaluateLineData(i, t2, &v);
}
#endif
AddParabolaToBuffer(i, t1, t2, u, v, WMATColor);
break;
case(ARC):
AddHyperbolaEllipseToBuffer(i, t1, t2, u, v, WMATColor);
break;
default:
break;
}
#endif
break;
default:
break;
}
}
}
return;
}
#endif
#ifdef EXT_APPL_WMAT
eam_type vroniObject::GetExtApplWMAT(int E)
{
assert(InEdgesList(E));
return edges[E].w_mat.ext_appl;
}
void vroniObject::SetExtApplWMAT(int E, eam_type ext_appl)
{
assert(InEdgesList(E));
edges[E].w_mat.ext_appl = ext_appl;
return;
}
#endif
#include "ext_appl_wmat.cc"
#endif