PostGIS  3.3.9dev-r@@SVN_REVISION@@

◆ lw_dist2d_arc_arc()

int lw_dist2d_arc_arc ( const POINT2D A1,
const POINT2D A2,
const POINT2D A3,
const POINT2D B1,
const POINT2D B2,
const POINT2D B3,
DISTPTS dl 
)

Definition at line 1687 of file measures.c.

1691 {
1692  POINT2D pts_A[16]; /* Points on A that might be the nearest */
1693  POINT2D pts_B[16]; /* Points on B that might be the nearest */
1694  uint32_t ai = 0, bi = 0; /* Number of points in pts_A and pts_B */
1695  POINT2D center_A, center_B; /* Center points of arcs A and B */
1696  double radius_A, radius_B, d; /* Radii of arcs A and B */
1697  int is_disjoint, is_overlapping, is_contained, is_same_center;
1698  POINT2D intersectionPts[2];
1699 
1700  if (dl->mode != DIST_MIN)
1701  lwerror("lw_dist2d_arc_arc only supports mindistance");
1702 
1703  /* What if one or both of our "arcs" is actually a point? */
1704  if (lw_arc_is_pt(B1, B2, B3) && lw_arc_is_pt(A1, A2, A3))
1705  return lw_dist2d_pt_pt(B1, A1, dl);
1706  else if (lw_arc_is_pt(B1, B2, B3))
1707  return lw_dist2d_pt_arc(B1, A1, A2, A3, dl);
1708  else if (lw_arc_is_pt(A1, A2, A3))
1709  return lw_dist2d_pt_arc(A1, B1, B2, B3, dl);
1710 
1711  /* Calculate centers and radii of circles. */
1712  radius_A = lw_arc_center(A1, A2, A3, &center_A);
1713  radius_B = lw_arc_center(B1, B2, B3, &center_B);
1714 
1715  /* Two co-linear arcs?!? That's two segments. */
1716  if (radius_A < 0 && radius_B < 0)
1717  return lw_dist2d_seg_seg(A1, A3, B1, B3, dl);
1718 
1719  /* A is co-linear, delegate to lw_dist_seg_arc here. */
1720  if (radius_A < 0)
1721  return lw_dist2d_seg_arc(A1, A3, B1, B2, B3, dl);
1722 
1723  /* B is co-linear, delegate to lw_dist_seg_arc here. */
1724  if (radius_B < 0)
1725  return lw_dist2d_seg_arc(B1, B3, A1, A2, A3, dl);
1726 
1727  /* Circle relationships */
1728  d = distance2d_pt_pt(&center_A, &center_B);
1729  is_disjoint = (d > (radius_A + radius_B));
1730  is_contained = (d < fabs(radius_A - radius_B));
1731  is_same_center = p2d_same(&center_A, &center_B);
1732  is_overlapping = ! (is_disjoint || is_contained || is_same_center);
1733 
1734  /*
1735  * Prime the array of potential closest points with the
1736  * arc end points, which frequently participate in closest
1737  * points.
1738  */
1739  pts_A[ai++] = *A1;
1740  pts_A[ai++] = *A3;
1741  pts_B[bi++] = *B1;
1742  pts_B[bi++] = *B3;
1743 
1744  /*
1745  * Overlapping circles might have a zero distance
1746  * case if the circle intersection points are inside both
1747  * arcs.
1748  */
1749  if (is_overlapping)
1750  {
1751  /*
1752  * Find the two points the circles intersect at.
1753  */
1754  uint32_t npoints = lw_dist2d_circle_circle_intersections(
1755  &center_A, radius_A,
1756  &center_B, radius_B,
1757  intersectionPts);
1758  for (uint32_t i = 0; i < npoints; i++)
1759  {
1760  /*
1761  * If an intersection point is contained in both
1762  * arcs, that is a location of zero distance, so
1763  * we are done calculating.
1764  */
1765  if (lw_pt_in_arc(&intersectionPts[i], A1, A2, A3) &&
1766  lw_pt_in_arc(&intersectionPts[i], B1, B2, B3))
1767  {
1768  lw_dist2d_distpts_set(dl, 0.0, &intersectionPts[i], &intersectionPts[i]);
1769  return LW_TRUE;
1770  }
1771  }
1772  }
1773 
1774  /*
1775  * Join the circle centers and find the places that
1776  * line intersects the circles. Where those places
1777  * are in the arcs, they are potential sites of the
1778  * closest points.
1779  */
1780  if (is_disjoint || is_contained || is_overlapping)
1781  {
1782  if (!is_same_center)
1783  {
1784  /* Add points on A that intersect line from center_A to center_B */
1786  A1, A2, A3,
1787  &center_A, radius_A, &center_B,
1788  pts_A, &ai);
1789 
1790  /* Add points on B that intersect line from center_B to center_A */
1792  B1, B2, B3,
1793  &center_B, radius_B, &center_A,
1794  pts_B, &bi);
1795  }
1796 
1797  /* Add points on A that intersect line to B1 */
1799  A1, A2, A3,
1800  &center_A, radius_A, B1,
1801  pts_A, &ai);
1802 
1803  /* Add points on A that intersect line to B3 */
1805  A1, A2, A3,
1806  &center_A, radius_A, B3,
1807  pts_A, &ai);
1808 
1809  /* Add points on B that intersect line to A1 */
1811  B1, B2, B3,
1812  &center_B, radius_B, A1,
1813  pts_B, &bi);
1814 
1815  /* Add points on B that intersect line to A3 */
1817  B1, B2, B3,
1818  &center_B, radius_B, A3,
1819  pts_B, &bi);
1820  }
1821 
1822  /*
1823  * Now just brute force check all pairs of participating
1824  * points, to find the pair that is closest together.
1825  */
1826  for (uint32_t i = 0; i < ai; i++)
1827  for (uint32_t j = 0; j < bi; j++)
1828  lw_dist2d_pt_pt(&pts_A[i], &pts_B[j], dl);
1829 
1830  return LW_TRUE;
1831 }
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:108
double lw_arc_center(const POINT2D *p1, const POINT2D *p2, const POINT2D *p3, POINT2D *result)
Determines the center of the circle defined by the three given points.
Definition: lwalgorithm.c:237
int lw_arc_is_pt(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3)
Returns true if arc A is actually a point (all vertices are the same) .
Definition: lwalgorithm.c:114
int lw_pt_in_arc(const POINT2D *P, const POINT2D *A1, const POINT2D *A2, const POINT2D *A3)
Returns true if P is on the same side of the plane partition defined by A1/A3 as A2 is.
Definition: lwalgorithm.c:84
int p2d_same(const POINT2D *p1, const POINT2D *p2)
Definition: lwalgorithm.c:50
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
static uint32_t lw_dist2d_circle_circle_intersections(const POINT2D *cA, double rA, const POINT2D *cB, double rB, POINT2D *I)
Calculates the intersection points of two overlapping circles.
Definition: measures.c:1637
double distance2d_pt_pt(const POINT2D *p1, const POINT2D *p2)
Definition: measures.c:2354
int lw_dist2d_pt_arc(const POINT2D *P, const POINT2D *A1, const POINT2D *A2, const POINT2D *A3, DISTPTS *dl)
Definition: measures.c:1495
static void lw_dist2d_distpts_set(DISTPTS *dl, double distance, const POINT2D *p1, const POINT2D *p2)
Definition: measures.c:81
int lw_dist2d_seg_seg(const POINT2D *A, const POINT2D *B, const POINT2D *C, const POINT2D *D, DISTPTS *dl)
Finds the shortest distance between two segments.
Definition: measures.c:1840
int lw_dist2d_seg_arc(const POINT2D *A1, const POINT2D *A2, const POINT2D *B1, const POINT2D *B2, const POINT2D *B3, DISTPTS *dl)
Calculate the shortest distance between an arc and an edge.
Definition: measures.c:1351
int lw_dist2d_pt_pt(const POINT2D *thep1, const POINT2D *thep2, DISTPTS *dl)
Compares incoming points and stores the points closest to each other or most far away from each other...
Definition: measures.c:2322
static int lw_dist2d_circle_intersections(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3, const POINT2D *center_A, double radius_A, const POINT2D *P, POINT2D *I, uint32_t *ni)
Calculates the intersection points of a circle and line.
Definition: measures.c:1577
#define DIST_MIN
Definition: measures.h:44
int mode
Definition: measures.h:54

References DIST_MIN, distance2d_pt_pt(), lw_arc_center(), lw_arc_is_pt(), lw_dist2d_circle_circle_intersections(), lw_dist2d_circle_intersections(), lw_dist2d_distpts_set(), lw_dist2d_pt_arc(), lw_dist2d_pt_pt(), lw_dist2d_seg_arc(), lw_dist2d_seg_seg(), lw_pt_in_arc(), LW_TRUE, lwerror(), DISTPTS::mode, and p2d_same().

Referenced by lw_dist2d_ptarrayarc_ptarrayarc(), rect_leaf_node_distance(), rect_leaf_node_intersects(), and test_lw_dist2d_arc_arc().

Here is the call graph for this function:
Here is the caller graph for this function: