Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements #158

Merged
merged 7 commits into from
Nov 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci_builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
pip install conan
conan --version
conan profile detect

- name: "Build: compiled, shared, boost"
run: conan create CDT/ -o as_compiled_library=True -o shared=True -o use_boost=True -o enable_testing=True --build missing
- name: "Build: compiled, shared, without boost"
Expand Down
1 change: 1 addition & 0 deletions CDT/include/CDTUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ struct CDT_EXPORT PtTriLocation
OnEdge1,
OnEdge2,
OnEdge3,
OnVertex,
};
};

Expand Down
20 changes: 14 additions & 6 deletions CDT/include/CDTUtils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,14 @@ CDT_INLINE_IF_HEADER_ONLY Index cw(Index i)

CDT_INLINE_IF_HEADER_ONLY bool isOnEdge(const PtTriLocation::Enum location)
{
return location > PtTriLocation::Outside;
return location == PtTriLocation::OnEdge1 ||
location == PtTriLocation::OnEdge2 ||
location == PtTriLocation::OnEdge3;
}

CDT_INLINE_IF_HEADER_ONLY Index edgeNeighbor(const PtTriLocation::Enum location)
{
assert(location >= PtTriLocation::OnEdge1);
assert(isOnEdge(location));
return static_cast<Index>(location - PtTriLocation::OnEdge1);
}

Expand Down Expand Up @@ -138,12 +140,18 @@ PtTriLocation::Enum locatePointTriangle(
if(edgeCheck == PtLineLocation::Right)
return PtTriLocation::Outside;
if(edgeCheck == PtLineLocation::OnLine)
result = PtTriLocation::OnEdge2;
{
result = (result == PtTriLocation::Inside) ? PtTriLocation::OnEdge2
: PtTriLocation::OnVertex;
}
edgeCheck = locatePointLine(p, v3, v1);
if(edgeCheck == PtLineLocation::Right)
return PtTriLocation::Outside;
if(edgeCheck == PtLineLocation::OnLine)
result = PtTriLocation::OnEdge3;
{
result = (result == PtTriLocation::Inside) ? PtTriLocation::OnEdge3
: PtTriLocation::OnVertex;
}
return result;
}

Expand All @@ -155,7 +163,7 @@ CDT_INLINE_IF_HEADER_ONLY Index opoNbr(const Index vertIndex)
return Index(2);
if(vertIndex == Index(2))
return Index(0);
throw std::runtime_error("Invalid vertex index");
assert(false && "Invalid vertex index");
}

CDT_INLINE_IF_HEADER_ONLY Index opoVrt(const Index neighborIndex)
Expand All @@ -166,7 +174,7 @@ CDT_INLINE_IF_HEADER_ONLY Index opoVrt(const Index neighborIndex)
return Index(0);
if(neighborIndex == Index(2))
return Index(1);
throw std::runtime_error("Invalid neighbor index");
assert(false && "Invalid neighbor index");
}

CDT_INLINE_IF_HEADER_ONLY Index
Expand Down
182 changes: 152 additions & 30 deletions CDT/include/Triangulation.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <iterator>
#include <stack>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>

Expand Down Expand Up @@ -78,8 +79,13 @@ struct CDT_EXPORT IntersectingConstraintEdges
*/
enum Enum
{
Ignore, ///< constraint edge intersections are not checked
Resolve, ///< constraint edge intersections are resolved
NotAllowed, ///< constraint edge intersections are not allowed
TryResolve, ///< attempt to resolve constraint edge intersections
/**
* No checks: slightly faster but less safe.
* User must provide a valid input without intersecting constraints.
*/
DontCheck,
};
};

Expand All @@ -91,6 +97,141 @@ struct CDT_EXPORT IntersectingConstraintEdges
typedef unsigned short LayerDepth;
typedef LayerDepth BoundaryOverlapCount;

/**
* Contains source location info: file, function, line
*/
class SourceLocation
{
public:
SourceLocation(const std::string& file, const std::string& func, int line)
: m_file(file)
, m_func(func)
, m_line(line)
{}
const std::string& file() const
{
return m_file;
}
const std::string& func() const
{
return m_func;
}
int line() const
{
return m_line;
}

private:
std::string m_file;
std::string m_func;
int m_line;
};

/// Macro for getting source location
#define CDT_SOURCE_LOCATION \
SourceLocation(std::string(__FILE__), std::string(__func__), __LINE__)

/**
* Base class for errors. Contains error description and source location: file,
* function, line
*/
class Error : public std::runtime_error
{
public:
/// Constructor
Error(const std::string& description, const SourceLocation& srcLoc)
: std::runtime_error(
description + "\nin '" + srcLoc.func() + "' at " + srcLoc.file() +
":" + std::to_string(srcLoc.line()))
, m_description(description)
, m_srcLoc(srcLoc)
{}
/// Get error description
const std::string& description() const
{
return m_description;
}
/// Get source location from where the error was thrown
const SourceLocation& sourceLocation() const
{
return m_srcLoc;
}

private:
std::string m_description;
SourceLocation m_srcLoc;
};

/**
* Error thrown when triangulation modification is attempted after it was
* finalized
*/
class FinalizedError : public Error
{
public:
FinalizedError(const SourceLocation& srcLoc)
: Error(
"Triangulation was finalized with 'erase...' method. Further "
"modification is not possible.",
srcLoc)
{}
};

/**
* Error thrown when duplicate vertex is detected during vertex insertion
*/
class DuplicateVertexError : public Error
{
public:
DuplicateVertexError(
const VertInd v1,
const VertInd v2,
const SourceLocation& srcLoc)
: Error(
"Duplicate vertex detected: #" + std::to_string(v1) +
" is a duplicate of #" + std::to_string(v2),
srcLoc)
, m_v1(v1)
, m_v2(v2)
{}
VertInd v1() const
{
return m_v1;
}
VertInd v2() const
{
return m_v2;
}

private:
VertInd m_v1, m_v2;
};

/**
* Error thrown when intersecting constraint edges are detected, but
* triangulation is not configured to attempt to resolve them
*/
class IntersectingConstraintsNotAllowed : public Error
{
public:
IntersectingConstraintsNotAllowed(
const Edge& e1,
const Edge& e2,
const SourceLocation& srcLoc)
: Error(
"Intersecting constraint edges detected: (" +
std::to_string(e1.v1()) + ", " + std::to_string(e1.v2()) +
") intersects (" + std::to_string(e2.v1()) + ", " +
std::to_string(e2.v2()) + ")",
srcLoc)
, m_e1(e1)
, m_e2(e2)
{}

private:
Edge m_e1, m_e2;
};

/**
* @defgroup Triangulation Triangulation Class
* Class performing triangulations.
Expand Down Expand Up @@ -365,10 +506,7 @@ class CDT_EXPORT Triangulation
void addNewVertex(const V2d<T>& pos, TriInd iT);
void insertVertex(VertInd iVert);
void insertVertex(VertInd iVert, VertInd walkStart);
void ensureDelaunayByEdgeFlips(
const V2d<T>& v1,
VertInd iV1,
std::stack<TriInd>& triStack);
void ensureDelaunayByEdgeFlips(VertInd iV1, std::stack<TriInd>& triStack);
/// Flip fixed edges and return a list of flipped fixed edges
std::vector<Edge> insertVertex_FlipFixedEdges(VertInd iV1);

Expand Down Expand Up @@ -461,7 +599,7 @@ class CDT_EXPORT Triangulation
std::stack<TriInd> insertVertexOnEdge(VertInd v, TriInd iT1, TriInd iT2);
array<TriInd, 2> trianglesAt(const V2d<T>& pos) const;
array<TriInd, 2>
walkingSearchTrianglesAt(const V2d<T>& pos, VertInd startVertex) const;
walkingSearchTrianglesAt(VertInd iV, VertInd startVertex) const;
TriInd walkTriangles(VertInd startVertex, const V2d<T>& pos) const;
/// Given triangle and its vertex find opposite triangle and the other three
/// vertices and surrounding neighbors
Expand All @@ -476,12 +614,7 @@ class CDT_EXPORT Triangulation
TriInd& n2,
TriInd& n3,
TriInd& n4);
bool isFlipNeeded(
const V2d<T>& v,
VertInd iV1,
VertInd iV2,
VertInd iV3,
VertInd iV4) const;
bool isFlipNeeded(VertInd iV1, VertInd iV2, VertInd iV3, VertInd iV4) const;
void changeNeighbor(TriInd iT, TriInd oldNeighbor, TriInd newNeighbor);
void changeNeighbor(
TriInd iT,
Expand Down Expand Up @@ -670,11 +803,7 @@ void Triangulation<T, TNearPointLocator>::insertVertices(
TGetVertexCoordY getY)
{
if(isFinalized())
{
throw std::runtime_error(
"Triangulation was finalized with 'erase...' method. Inserting new "
"vertices is not possible");
}
throw FinalizedError(CDT_SOURCE_LOCATION);

const bool isFirstTime = vertices.empty();
const T max = std::numeric_limits<T>::max();
Expand Down Expand Up @@ -719,15 +848,11 @@ void Triangulation<T, TNearPointLocator>::insertEdges(
TGetEdgeVertexStart getStart,
TGetEdgeVertexEnd getEnd)
{
// state shared between different runs for performance gains
if(isFinalized())
throw FinalizedError(CDT_SOURCE_LOCATION);

std::vector<TriangulatePseudopolygonTask> tppIterations;
EdgeVec remaining;
if(isFinalized())
{
throw std::runtime_error(
"Triangulation was finalized with 'erase...' method. Inserting new "
"edges is not possible");
}
for(; first != last; ++first)
{
// +3 to account for super-triangle vertices
Expand All @@ -751,11 +876,8 @@ void Triangulation<T, TNearPointLocator>::conformToEdges(
TGetEdgeVertexEnd getEnd)
{
if(isFinalized())
{
throw std::runtime_error(
"Triangulation was finalized with 'erase...' method. Conforming to "
"new edges is not possible");
}
throw FinalizedError(CDT_SOURCE_LOCATION);

tryInitNearestPointLocator();
// state shared between different runs for performance gains
std::vector<ConformToEdgeTask> remaining;
Expand Down
Loading