Files
vroni/arc_pnt_pnt.cc
T
SaraP 739088af9f Vroni 7.8 :
- aggiornamento versione.
2025-01-29 16:24:30 +01:00

308 lines
13 KiB
C++

/*****************************************************************************/
/* */
/* Copyright (C) 2007-2025 S. Huber, 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: Stefan Huber, 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 <stdlib.h>
#include <stdio.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 "roots.h"
/* */
/* computes the center cntr and the radius r2 of the circle tangential */
/* to the arct arcs[i] and passing through the points pnts[j],pnts[k]. */
/* it returns false if the radius is too large to be computed numerically, */
/* or if it is obvious that problems have occurred. if two centers exist */
/* then we choose the center that lies on the Voronoi edge e. the vr_bool */
/* flag problematic is set if a center was computed but its correctness is */
/* doubtful. */
/* */
vr_bool vroniObject::ArcPntPntCntr(int i, int j, int k, int e,
coord* cntr, double *r2,
vr_bool *problematic)
{
int t;
coord c1, c2, c3;
double rr1, rr2, rr3, eps;
#ifdef VRONI_DBG_WARN
coord spi, epi;
#endif
coord v;
coord centers[VRONI_MAXSOL];
double radii[VRONI_MAXSOL];
vr_bool j_on_i = false;
int num_sol = 0, best_sol = NIL, cocirc = 0;
double dist2, dist3;
double sign = 1.0;
assert(InArcsList(i));
assert(InPntsList(j));
assert(InPntsList(k));
*problematic = false;
/* */
/* check whether the two points are identical. */
/* */
if (j == k) {
VD_Dbg_Warning("ArcPntPntCntr() - two identical points!");
return false;
}
/* */
/* we sort the two point indices in order to guarantee that the center of */
/* these three sites is always computed consistently. */
/* */
SortTwoNumbers(j, k, t);
c1 = GetArcCenter(i);
rr1 = GetArcRadius(i);
rr2 = 0.0;
rr3 = 0.0;
/* */
/* check whether one of the points is an endpoint of arcs[i]. */
/* */
if (IsArcStartPnt(i, k) || IsArcEndPnt(i, k)) VroniSwap(j, k, t);
c2 = GetPntCoords(j);
c3 = GetPntCoords(k);
if (IsArcStartPnt(i, j) || IsArcEndPnt(i, j)) {
if (IsArcStartPnt(i, k) || IsArcEndPnt(i, k)) {
/* */
/* both points are endpoints of the arc */
/* */
*cntr = c1;
*r2 = rr1;
return true;
}
else {
dist2 = 0.0;
dist3 = PntPntDist(c1,c3) - rr1;
j_on_i = true;
}
}
else {
dist2 = PntPntDist(c1,c2) - rr1;
dist3 = PntPntDist(c1,c3) - rr1;
}
eps = ZERO;
#ifdef TRACE
if ((e == 107) && (i == 6)) { printf("arc%d-pnt%d-pnt%d: \n(%20.16f, %20.16f) %20.16f;\n%d:(%20.16f, %20.16f);\n%d:(%20.16f, %20.16f)\n", i, j, k, c1.x, c1.y, rr1, j, c2.x, c2.y, k, c3.x, c3.y);
if (IsArcStartPnt(i, j)) printf("%d is start of arc %d\n", j, i);
if (IsArcEndPnt(i, j)) printf("%d is end of arc %d\n", j, i);
if (IsArcStartPnt(i, k)) printf("%d is start of arc %d\n", k, i);
if (IsArcEndPnt(i, k)) printf("%d is end of arc %d\n", k, i);
spi = GetArcStartCoord(i);
epi = GetArcEndCoord(i);
printf("%20.16f %20.16f %20.16f %20.16f %20.16f %20.16f\n",
spi.x, spi.y, epi.x, epi.y, c1.x, c1.y);
}
#endif
while (eps <= ZERO_MAX) {
cocirc = 0;
num_sol = 0;
if (eq(dist2, eps)) {
if (!j_on_i && DoArcPntIntersect(i, c2, eps)) {
/* */
/* c2 is inside of CI of i and on i */
/* */
VD_Dbg_Warning("ArcPntPntCntr() - point lies in interior of arc!");
SetInvalidSites(i, ARC, j, PNT, eps);
restart = false;
return false;
}
cocirc = 1;
}
if (eq(dist3, eps)) {
if (DoArcPntIntersect(i, c3, eps)) {
/* */
/* c3 is inside of CI of i and on i */
/* */
VD_Dbg_Warning("ArcPntPntCntr() - point lies in interior of arc!");
SetInvalidSites(i, ARC, k, PNT, eps);
restart = false;
return false;
}
++cocirc;
}
if (cocirc == 2) {
/* */
/* the two points lie on the same circle as i */
/* */
centers[0] = c1;
radii[0] = rr1;
num_sol = 1;
}
else if (j_on_i) {
/* */
/* point j is on arc */
/* */
v = VecSub(c2, c1);
num_sol = IntersectRayPoint(c2, v, c3, centers, radii, eps);
}
else {
/* */
/* standard case: find solution that is equidistant to three */
/* (degenerate) circles. */
/* */
if (dist2 <= -eps) {
sign = -1.0;
#ifdef VRONI_WARN
if (dist3 > eps) {
VD_Warning("ArcPntPntCntr() - sign mismatch!");
coord spi, epi;
spi = GetArcStartCoord(i);
epi = GetArcEndCoord(i);
c1 = GetArcCenter(i);
printf("%20.16f %20.16f %20.16f %20.16f %20.16f %20.16f\n",
spi.x, spi.y, epi.x, epi.y, c1.x, c1.y);
c2 = GetPntCoords(j);
printf("%20.16f %20.16f\n", c2.x, c2.y);
c3 = GetPntCoords(k);
printf("%20.16f %20.16f\n", c3.x, c3.y);
printf("dist2 = %20.16f\n", dist2);
printf("dist3 = %20.16f\n", dist3);
printf("eps = %20.16f\n", eps);
}
#endif
}
else if (dist2 >= eps) {
sign = 1.0;
#ifdef VRONI_WARN
if (dist3 < -eps) {
VD_Warning("ArcPntPntCntr() - sign mismatch!");
coord spi, epi;
spi = GetArcStartCoord(i);
epi = GetArcEndCoord(i);
c1 = GetArcCenter(i);
printf("%20.16f %20.16f %20.16f %20.16f %20.16f %20.16f\n",
spi.x, spi.y, epi.x, epi.y, c1.x, c1.y);
c2 = GetPntCoords(j);
printf("%20.16f %20.16f\n", c2.x, c2.y);
c3 = GetPntCoords(k);
printf("%20.16f %20.16f\n", c3.x, c3.y);
printf("dist2 = %20.16f\n", dist2);
printf("dist3 = %20.16f\n", dist3);
printf("eps = %20.16f\n", eps);
printf("checking for containment\n");
printf("c3 on circle: %d\n", DoArcPntIntersect(i, c3, eps));
}
#endif
}
else {
sign = Sign(dist3);
}
num_sol = CircPntPntCenters(c1, c2, c3, rr1, sign, centers, radii);
if (num_sol == 0)
num_sol = CircCircCircCenters(c1, c2, c3, rr1, rr2, rr3, centers,
radii, eps);
}
/* */
/* classify all solutions and pick the best solution */
/* */
best_sol = ClassifySolutions(i, j, k, e, ARC, PNT, PNT,
false, true, true, centers, radii,
&num_sol, eps, problematic);
assert((0 <= best_sol) && (best_sol < num_sol));
if (!*problematic) {
*cntr = centers[best_sol];
*r2 = radii[best_sol];
return true;
}
else {
eps *= 10.0;
}
}
if (eq(rr1, ZERO_MAX)) {
/* */
/* this is an arc with a very small radius; we replace it by a seg */
/* */
VD_Dbg_Warning("ArcPntPntCntr() - arc with small radius!");
ReplaceArc(i);
restart = true;
return false;
}
else if (eq(PntPntDist(GetArcStartCoord(i), GetArcEndCoord(i)), ZERO_MAX)) {
/* */
/* this is an arc with a very short cord; we replace it by a seg */
/* */
VD_Dbg_Warning("ArcPntPntCntr() - arc with short cord!");
ReplaceArc(i);
restart = true;
return false;
}
else if (eq(PntPntDist(c2,c3), ZERO_MAX)) {
/* */
/* both points are very close to each other. */
/* */
VD_Dbg_Warning("ArcPntPntCntr() - points are too close!");
SetInvalidSites(j, PNT, k, PNT, ZERO_MAX);
restart = false;
return false;
}
#ifdef VRONI_DBG_WARN
spi = GetArcStartCoord(i);
epi = GetArcEndCoord(i);
c1 = GetArcCenter(i);
printf("\nCenter not computed for arc(%d)-pnt(%d)-pnt(%d):\n",
i, j, k);
printf("%20.16f %20.16f %20.16f %20.16f %20.16f %20.16f\n",
spi.x, spi.y, epi.x, epi.y, c1.x, c1.y);
c2 = GetPntCoords(j);
printf("%20.16f %20.16f\n", c2.x, c2.y);
c3 = GetPntCoords(k);
printf("%20.16f %20.16f\n", c3.x, c3.y);
#endif
*cntr = centers[best_sol];
*r2 = radii[best_sol];
restart = false;
return false;
}