Skip to content

Commit

Permalink
Add CircularArcIntersector
Browse files Browse the repository at this point in the history
  • Loading branch information
dbaston committed Sep 27, 2024
1 parent e142764 commit 6ec05f0
Show file tree
Hide file tree
Showing 14 changed files with 1,167 additions and 148 deletions.
9 changes: 9 additions & 0 deletions include/geos/algorithm/Angle.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,15 @@ class GEOS_DLL Angle {
///
static double normalizePositive(double angle);

/// Returns true if angle x is within the counterclockwise
/// arc from angle a to angle b
///
/// @param angle angle to test
/// @param from starting angle of arc
/// @param to ending angle of arc
///
/// @return true if `angle` is within [from, to]
static bool isWithin(double angle, double from, double to);

/// Computes the unoriented smallest difference between two angles.
///
Expand Down
93 changes: 93 additions & 0 deletions include/geos/algorithm/CircularArcIntersector.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/**********************************************************************
*
* GEOS - Geometry Engine Open Source
* http://geos.osgeo.org
*
* Copyright (C) 2024 ISciences, LLC
*
* This is free software; you can redistribute and/or modify it under
* the terms of the GNU Lesser General Public Licence as published
* by the Free Software Foundation.
* See the COPYING file for more information.
*
**********************************************************************/

#pragma once

#include <array>
#include <cstdint>

#include <geos/geom/Coordinate.h>
#include <geos/geom/CircularArc.h>
#include <geos/geom/LineSegment.h>

namespace geos::algorithm {

class CircularArcIntersector {
public:
using CoordinateXY = geom::CoordinateXY;
using CircularArc = geom::CircularArc;
using Envelope = geom::Envelope;

enum intersection_type : uint8_t {
NO_INTERSECTION = 0,
ONE_POINT_INTERSECTION = 1,
TWO_POINT_INTERSECTION = 2,
COCIRCULAR_INTERSECTION = 3,
};

intersection_type getResult() const
{
return result;
}

const CoordinateXY& getPoint(std::uint8_t i) const
{
return intPt[i];
}

const std::array<CoordinateXY, 3>& getArc(std::uint8_t i) const
{
return intArc[i];
}

std::uint8_t getNumPoints() const
{
return nPt;
}

std::uint8_t getNumArcs() const
{
return nArc;
}

/// Determines whether and where a circular arc intersects a line segment.
///
/// Sets the appropriate value of intersection_type and stores the intersection
/// points, if any.
void intersects(const CircularArc& arc, const CoordinateXY& p0, const CoordinateXY& p1);

void intersects(const CircularArc& arc, const geom::LineSegment& seg)
{
intersects(arc, seg.p0, seg.p1);
}

/// Determines whether and where two circular arcs intersect.
///
/// Sets the appropriate value of intesection_type and stores the intersection
/// points and/or arcs, if any.
void intersects(const CircularArc& arc1, const CircularArc& arc2);

private:

void intersects(const CoordinateXY& p0, const CoordinateXY& p1, const CoordinateXY& q0, const CoordinateXY& q1);

std::array<CoordinateXY, 2> intPt;
std::array<std::array<CoordinateXY, 3>, 2> intArc;
intersection_type result;
std::uint8_t nPt = 0;
std::uint8_t nArc = 0;

};

}
11 changes: 11 additions & 0 deletions include/geos/algorithm/CircularArcs.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

#pragma once

#include <array>

#include <geos/export.h>
#include <geos/geom/Coordinate.h>
#include <geos/geom/Envelope.h>
Expand All @@ -31,6 +33,15 @@ class GEOS_DLL CircularArcs {
/// Expand an envelope to include an arc defined by three points
static void expandEnvelope(geom::Envelope& e, const geom::CoordinateXY& p0, const geom::CoordinateXY& p1,
const geom::CoordinateXY& p2);


/// Return three points defining a arc defined by a circle center, radius, and start/end angles
static std::array<geom::CoordinateXY, 3>
createArc(const geom::CoordinateXY& center, double radius, double start, double end, bool ccw);

/// Return the point defined by a circle center, radius, and angle
static geom::CoordinateXY createPoint(const geom::CoordinateXY& center, double radius, double theta);

};

}
Expand Down
1 change: 1 addition & 0 deletions include/geos/geom/CircularArc.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class GEOS_DLL CircularArc {
}

/// Return the radius of the circle associated with this arc
///
double getRadius() const {
if (!m_radius_known) {
m_radius = getCenter().distance(p0);
Expand Down
1 change: 1 addition & 0 deletions include/geos/math/DD.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ class GEOS_DLL DD {
friend GEOS_DLL DD operator* (const DD &lhs, double rhs);
friend GEOS_DLL DD operator/ (const DD &lhs, const DD &rhs);
friend GEOS_DLL DD operator/ (const DD &lhs, double rhs);
friend GEOS_DLL DD operator- (const DD& x);

static DD determinant(const DD &x1, const DD &y1, const DD &x2, const DD &y2);
static DD determinant(double x1, double y1, double x2, double y2);
Expand Down
14 changes: 14 additions & 0 deletions src/algorithm/Angle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,20 @@ Angle::normalizePositive(double angle)
return angle;
}

static bool angleLEQ(double x, double y) {
return x <= y || (y == 0 && x <= Angle::PI_TIMES_2);
}

static bool angleGEQ(double x, double y) {
return x >= y || (x == 0 && Angle::PI_TIMES_2 >= y); // FIXME second part not needed?
}

/// Returns true if angle x is within the counterclockwise
/// arc from angle a to angle b
bool Angle::isWithin(double x, double a, double b) {
return angleGEQ(x, a) && angleLEQ(x, b);
}

/* public static */
double
Angle::diff(double ang1, double ang2)
Expand Down
Loading

0 comments on commit 6ec05f0

Please sign in to comment.