PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ 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 1677 of file measures.c.

1681{
1682 POINT2D pts_A[16]; /* Points on A that might be the nearest */
1683 POINT2D pts_B[16]; /* Points on B that might be the nearest */
1684 uint32_t ai = 0, bi = 0; /* Number of points in pts_A and pts_B */
1685 POINT2D center_A, center_B; /* Center points of arcs A and B */
1686 double radius_A, radius_B, d; /* Radii of arcs A and B */
1687 int is_disjoint, is_overlapping, is_contained, is_same_center;
1688 POINT2D intersectionPts[2];
1689
1690 if (dl->mode != DIST_MIN)
1691 lwerror("lw_dist2d_arc_arc only supports mindistance");
1692
1693 /* What if one or both of our "arcs" is actually a point? */
1694 if (lw_arc_is_pt(B1, B2, B3) && lw_arc_is_pt(A1, A2, A3))
1695 return lw_dist2d_pt_pt(B1, A1, dl);
1696 else if (lw_arc_is_pt(B1, B2, B3))
1697 return lw_dist2d_pt_arc(B1, A1, A2, A3, dl);
1698 else if (lw_arc_is_pt(A1, A2, A3))
1699 return lw_dist2d_pt_arc(A1, B1, B2, B3, dl);
1700
1701 /* Calculate centers and radii of circles. */
1702 radius_A = lw_arc_center(A1, A2, A3, &center_A);
1703 radius_B = lw_arc_center(B1, B2, B3, &center_B);
1704
1705 /* Two co-linear arcs?!? That's two segments. */
1706 if (radius_A < 0 && radius_B < 0)
1707 return lw_dist2d_seg_seg(A1, A3, B1, B3, dl);
1708
1709 /* A is co-linear, delegate to lw_dist_seg_arc here. */
1710 if (radius_A < 0)
1711 return lw_dist2d_seg_arc(A1, A3, B1, B2, B3, dl);
1712
1713 /* B is co-linear, delegate to lw_dist_seg_arc here. */
1714 if (radius_B < 0)
1715 return lw_dist2d_seg_arc(B1, B3, A1, A2, A3, dl);
1716
1717 /* Circle relationships */
1718 d = distance2d_pt_pt(&center_A, &center_B);
1719 is_disjoint = (d > (radius_A + radius_B));
1720 is_contained = (d < fabs(radius_A - radius_B));
1721 is_same_center = p2d_same(&center_A, &center_B);
1722 is_overlapping = ! (is_disjoint || is_contained || is_same_center);
1723
1724 /*
1725 * Prime the array of potential closest points with the
1726 * arc end points, which frequently participate in closest
1727 * points.
1728 */
1729 pts_A[ai++] = *A1;
1730 pts_A[ai++] = *A3;
1731 pts_B[bi++] = *B1;
1732 pts_B[bi++] = *B3;
1733
1734 /*
1735 * Overlapping circles might have a zero distance
1736 * case if the circle intersection points are inside both
1737 * arcs.
1738 */
1739 if (is_overlapping)
1740 {
1741 /*
1742 * Find the two points the circles intersect at.
1743 */
1744 uint32_t npoints = lw_dist2d_circle_circle_intersections(
1745 &center_A, radius_A,
1746 &center_B, radius_B,
1747 intersectionPts);
1748 for (uint32_t i = 0; i < npoints; i++)
1749 {
1750 /*
1751 * If an intersection point is contained in both
1752 * arcs, that is a location of zero distance, so
1753 * we are done calculating.
1754 */
1755 if (lw_pt_in_arc(&intersectionPts[i], A1, A2, A3) &&
1756 lw_pt_in_arc(&intersectionPts[i], B1, B2, B3))
1757 {
1758 lw_dist2d_distpts_set(dl, 0.0, &intersectionPts[i], &intersectionPts[i]);
1759 return LW_TRUE;
1760 }
1761 }
1762 }
1763
1764 /*
1765 * Join the circle centers and find the places that
1766 * line intersects the circles. Where those places
1767 * are in the arcs, they are potential sites of the
1768 * closest points.
1769 */
1770 if (is_disjoint || is_contained || is_overlapping)
1771 {
1772 if (!is_same_center)
1773 {
1774 /* Add points on A that intersect line from center_A to center_B */
1776 A1, A2, A3,
1777 &center_A, radius_A, &center_B,
1778 pts_A, &ai);
1779
1780 /* Add points on B that intersect line from center_B to center_A */
1782 B1, B2, B3,
1783 &center_B, radius_B, &center_A,
1784 pts_B, &bi);
1785 }
1786
1787 /* Add points on A that intersect line to B1 */
1789 A1, A2, A3,
1790 &center_A, radius_A, B1,
1791 pts_A, &ai);
1792
1793 /* Add points on A that intersect line to B3 */
1795 A1, A2, A3,
1796 &center_A, radius_A, B3,
1797 pts_A, &ai);
1798
1799 /* Add points on B that intersect line to A1 */
1801 B1, B2, B3,
1802 &center_B, radius_B, A1,
1803 pts_B, &bi);
1804
1805 /* Add points on B that intersect line to A3 */
1807 B1, B2, B3,
1808 &center_B, radius_B, A3,
1809 pts_B, &bi);
1810 }
1811
1812 /*
1813 * Now just brute force check all pairs of participating
1814 * points, to find the pair that is closest together.
1815 */
1816 for (uint32_t i = 0; i < ai; i++)
1817 for (uint32_t j = 0; j < bi; j++)
1818 lw_dist2d_pt_pt(&pts_A[i], &pts_B[j], dl);
1819
1820 return LW_TRUE;
1821}
#define LW_TRUE
Return types for functions with status returns.
Definition liblwgeom.h:93
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.
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) .
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:91
int p2d_same(const POINT2D *p1, const POINT2D *p2)
Definition lwalgorithm.c:57
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
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:1626
double distance2d_pt_pt(const POINT2D *p1, const POINT2D *p2)
Definition measures.c:2344
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:1830
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:2312
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:1566
#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: