Files
vroni/arc_arc_seg.cc
T
SaraP f3e15b8c8d vroni 7.6 :
- aggiunti file della libreria e progetto visual studio.
2023-09-06 15:44:02 +02:00

434 lines
18 KiB
C++

/*****************************************************************************/
/* */
/* Copyright (C) 2007-2023 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 "vroni_object.h"
#include "vronivector.h"
#include "fpkernel.h"
#include "defs.h"
#include "numerics.h"
#include "roots.h"
/* */
/* Calculate the Voronoi center of two arcs and segment */
/* */
vr_bool vroniObject::ArcArcSegCntr(int i, int j, int k, int e,
coord* cntr, double *r2,
vr_bool *problematic, int *site)
{
int m, n1;
coord c1, c2;
double rr1, rr2, t;
double s1a, s1b, s1c;
coord centers[VRONI_MAXSOL];
double radii[VRONI_MAXSOL];
int num_sol = 0, best_sol = NIL;
double eps = ZERO;
coord spi, spj, epj, epi;
coord ep, sp, v, w;
vr_bool counter_tangential, no_check, is_special;
vr_bool spi_in_common, epi_in_common;
int i_in, j_in, k_in;
double d_c1c2;
i_in = i;
j_in = j;
k_in = k;
*problematic = false;
/* */
/* Guarantee that permutations of i,j lead to same center */
/* */
SortTwoNumbers(i, j, m);
/* */
/* Check whether the three cites are all in lists */
/* */
assert(InArcsList(i));
assert(InArcsList(j));
assert(InSegsList(k));
/* */
/* check whether the two arcs are identical. */
/* */
if (i == j) {
VD_Dbg_Warning("ArcArcSegCntr() - the same arc!");
return false;
}
m = Get1stVtx(i, ARC);
if (IsArcStartPnt(j, m) || IsArcEndPnt(j, m)) {
m = Get2ndVtx(i, ARC);
if (IsArcStartPnt(j, m) || IsArcEndPnt(j, m)) {
if (le(PntPntDist(GetArcCenter(i),GetArcCenter(j)),
GetIntersectionThreshold())) {
SetInvalidSites(i, ARC, j, ARC, GetIntersectionThreshold());
restart = false;
return false; /* duplicate arcs ! */
}
}
}
/* */
/* check whether the three sites share a common end point */
/* */
m = Get1stVtx(k, SEG);
if (IsArcStartPnt(i, m) || IsArcEndPnt(i, m)) {
if (IsArcStartPnt(j, m) || IsArcEndPnt(j, m)) {
*cntr = GetPntCoords(m);
*r2 = 0.0;
*site = m;
return true; /* common end point */
}
}
m = Get2ndVtx(k, SEG);
if (IsArcStartPnt(i, m) || IsArcEndPnt(i, m)) {
if (IsArcStartPnt(j, m) || IsArcEndPnt(j, m)) {
*cntr = GetPntCoords(m);
*r2 = 0.0;
*site = m;
return true; /* common end point */
}
}
c1 = GetArcCenter(i);
c2 = GetArcCenter(j);
rr1 = GetArcRadius(i);
rr2 = GetArcRadius(j);
spi = GetArcStartCoord(i);
spj = GetArcStartCoord(j);
epj = GetArcEndCoord(j);
epi = GetArcEndCoord(i);
GetSegEqnData(k, &s1a, &s1b, &s1c);
s1c *= -1;
d_c1c2 = PntPntDist(c1,c2);
//printf(" arc%d-arc%d-seg%d with (%e,%e;%e), (%e,%e;%e), (%e,%e,%e) \n", i, j, k,
// c1.x, c1.y,rr1, c2.x,c2.y,rr2, s1a,s1b,s1c);
while (eps <= ZERO_MAX) {
is_special = false;
no_check = false;
num_sol = 0;
/* */
/* check whether one endpoint of arc i is very close to one endpoint */
/* of j */
/* */
if ((PntPntDist(spi,spj) <= eps) || (PntPntDist(spi,epj) <= eps)) {
spi_in_common = true;
epi_in_common = false;
}
else if ((PntPntDist(epi,spj) <= eps) || (PntPntDist(epi,epj) <= eps)) {
spi_in_common = false;
epi_in_common = true;
}
else {
spi_in_common = false;
epi_in_common = false;
}
if (spi_in_common || epi_in_common) {
counter_tangential = ((VecDet(c1,c2,spi) + VecDet(c1,c2,epi)) *
(VecDet(c1,c2,spj) + VecDet(c1,c2,epj)) <= eps);
if (counter_tangential &&
(Abs(d_c1c2 - Abs(rr1-rr2)) <= eps)) {
/* */
/* the arcs are (nearly) tangential and have a point in common */
/* */
//printf("\ttwo tangential arcs %d-%d and seg %d\n", i, j, k);
n1 = GetStartNode(e);
if (!IsNodeDeleted(n1)) n1 = GetEndNode(e);
GetNodeData(n1, &v, &t);
num_sol = 1;
centers[0] = v;
radii[0] = t;
is_special = true;
if (!IsNodeDeleted(n1)) {
/* */
/* get start point and direction of the ray on which the */
/* bisector lies */
/* */
if (spi_in_common) ep = spi;
else ep = epi;
v = VecSub(ep, c1);
num_sol = IntersectRaySegment(ep, v, s1a, s1b, s1c, centers,
radii, eps);
}
else {
no_check = true;
}
}
else if (counter_tangential && (Abs(d_c1c2 - rr1-rr2) <= eps)) {
/* */
/* the arcs are counter-tangential and lie on different sides */
/* of the line through their centers */
/* */
if (spi_in_common) ep = spi;
else ep = epi;
v = VecSub(ep, c1);
num_sol = IntersectRaySegment(ep, v, s1a, s1b, s1c, centers, radii,
eps);
is_special = true;
}
}
if (!is_special) {
if ((d_c1c2 <= eps) && (Abs(rr1-rr2) <= eps)) {
/* */
/* the arcs lie (nearly) on the same circle but do not share an */
/* end point: their common center is the only possible VD node */
/* */
centers[0] = MidPoint(c1, c2);
radii[0] = (rr1 + rr2) / 2.0;
num_sol = 1;
is_special = true;
}
else if (Abs(Abs(c1.x*s1a+c1.y*s1b-s1c)-rr1) <= eps) {
/* */
/* the arc and the line are tangential. check whether they */
/* share an end point */
/* */
counter_tangential = true;
if (PntPntDist(spi,GetSegStartCoord(k)) <= eps) {
ep = GetSegStartCoord(k);
sp = GetSegEndCoord(k);
v = VecSub(sp, ep);
w = VecSub(epi, ep);
counter_tangential = (VecDotProd(v, w) < 0.0) ? false : true;
}
else if (PntPntDist(epi,GetSegStartCoord(k)) <= eps) {
ep = GetSegStartCoord(k);
sp = GetSegEndCoord(k);
v = VecSub(sp, ep);
w = VecSub(spi, ep);
counter_tangential = (VecDotProd(v, w) < 0.0) ? false : true;
}
else if (PntPntDist(spi,GetSegEndCoord(k)) <= eps) {
ep = GetSegEndCoord(k);
sp = GetSegStartCoord(k);
v = VecSub(sp, ep);
w = VecSub(epi, ep);
counter_tangential = (VecDotProd(v, w) < 0.0) ? false : true;
}
else if (PntPntDist(epi,GetSegEndCoord(k)) <= eps) {
ep = GetSegEndCoord(k);
sp = GetSegStartCoord(k);
v = VecSub(sp, ep);
w = VecSub(spi, ep);
counter_tangential = (VecDotProd(v, w) < 0.0) ? false : true;
}
if (!counter_tangential) {
//printf("arc%d and seg%d tangential, 2nd arc%d\n", i,k,j);
v = MakeVec(-s1a, -s1b);
num_sol = IntersectRayCircle(ep, v, c2, rr2, centers, radii,
eps);
is_special = true;
}
}
else if (Abs(Abs(c2.x*s1a+c2.y*s1b-s1c) - rr2) <= eps) {
/* */
/* the arc and the line are tangential. check whether they */
/* share an end point */
/* */
counter_tangential = true;
if (PntPntDist(spj,GetSegStartCoord(k)) <= eps) {
ep = GetSegStartCoord(k);
sp = GetSegEndCoord(k);
v = VecSub(sp, ep);
w = VecSub(epj, ep);
counter_tangential = (VecDotProd(v, w) < 0.0) ? false : true;
}
else if (PntPntDist(epj,GetSegStartCoord(k)) <= eps) {
ep = GetSegStartCoord(k);
sp = GetSegEndCoord(k);
v = VecSub(sp, ep);
w = VecSub(spj, ep);
counter_tangential = (VecDotProd(v, w) < 0.0) ? false : true;
}
else if (PntPntDist(spj,GetSegEndCoord(k)) <= eps) {
ep = GetSegEndCoord(k);
sp = GetSegStartCoord(k);
v = VecSub(sp, ep);
w = VecSub(epj, ep);
counter_tangential = (VecDotProd(v, w) < 0.0) ? false : true;
}
else if (PntPntDist(epj,GetSegEndCoord(k)) <= eps) {
ep = GetSegEndCoord(k);
sp = GetSegStartCoord(k);
v = VecSub(sp, ep);
w = VecSub(spj, ep);
counter_tangential = (VecDotProd(v, w) < 0.0) ? false : true;
}
if (!counter_tangential) {
//printf("arc%d and seg%d tangential, 2nd arc%d\n", i,k,j);
v = MakeVec(-s1a, -s1b);
num_sol = IntersectRayCircle(ep, v, c1, rr1, centers, radii,
eps);
is_special = true;
}
}
}
if (!is_special) {
/* */
/* and finally the general case... */
/* */
//printf("ordinary\n");
num_sol = CircCircSegCenters(c1, c2, rr1, rr2, s1a,s1b,s1c, centers,
radii, eps);
}
if ((num_sol > 0) && no_check)
best_sol = 0;
else
/* */
/* classify all solutions and pick the best solution */
/* */
best_sol = ClassifySolutions(i_in, j_in, k_in, e, ARC, ARC, SEG,
false, true, true, centers, radii,
&num_sol, eps, problematic);
assert((0 <= best_sol) && (best_sol < num_sol));
#ifdef TRACE
if ((i_in == 4) && (j_in == 2) && (k_in == 2)) {
printf("problematic = %d, eps = %20.16f\n", *problematic, eps);
printf("num_sol = %d, best_sol = %d\n", num_sol, best_sol);
printf("center = (%20.16f %20.16f)\n", centers[best_sol].x,
centers[best_sol].y);
printf("radius = %20.16f\n", radii[best_sol]);
printf("zero_max = %20.16f\n", ZERO_MAX);
printf("e = %d: i = %d, j = %d, k = %d\n", e, i_in, j_in, k_in);
}
#endif
if (!*problematic) {
*cntr = centers[best_sol];
*r2 = radii[best_sol];
return true;
}
else {
eps *= 10.0;
}
}
if (eq(GetArcRadius(i), ZERO_MAX)) {
/* */
/* this is an arc with a very small radius; we replace it by */
/* a seg */
/* */
VD_Dbg_Warning("ArcArcSegCntr() - arc with small radius!");
ReplaceArc(i);
restart = true;
return false;
}
else if (eq(GetArcRadius(j), ZERO_MAX)) {
/* */
/* this is an arc with a very small radius; we replace it by */
/* a seg */
/* */
VD_Dbg_Warning("ArcArcSegCntr() - arc with small radius!");
ReplaceArc(j);
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("ArcArcSegCntr() - arc with short cord!");
ReplaceArc(i);
restart = true;
return false;
}
else if (eq(PntPntDist(GetArcStartCoord(j), GetArcEndCoord(j)), ZERO_MAX)) {
/* */
/* this is an arc with a very short cord; we replace it by a seg */
/* */
VD_Dbg_Warning("ArcArcSegCntr() - arc with short cord!");
ReplaceArc(j);
restart = true;
return false;
}
else if (eq(GetSegLgth(k), ZERO_MAX)) {
/* */
/* this is a seg with a very small length; we replace it */
/* */
VD_Dbg_Warning("ArcArcSegCntr() - seg with small length!");
ReplaceSeg(k);
restart = true;
return false;
}
else if (CheckIntersectionsLocally(i, ARC, j, ARC, k, SEG)) {
restart = true;
return false;
}
#ifdef VRONI_DBG_WARN
spi = GetArcStartCoord(i);
spj = GetArcStartCoord(j);
epi = GetArcEndCoord(i);
epj = GetArcEndCoord(j);
c1 = GetArcCenter(i);
c2 = GetArcCenter(j);
printf("\nCenter not computed for arc-arc-seg and edge e = %d:\n",
e);
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);
printf("%20.16f %20.16f %20.16f %20.16f %20.16f %20.16f\n",
spj.x, spj.y, epj.x, epj.y, c2.x, c2.y);
ep = GetSegStartCoord(k);
sp = GetSegEndCoord(k);
printf("%20.16f %20.16f %20.16f %20.16f\n",
sp.x, sp.y, ep.x, ep.y);
#endif
*cntr = centers[best_sol];
*r2 = radii[best_sol];
restart = false;
return false;
}