67 #ifndef _graphicsproceduraltriangulator_cpp
68 #define _graphicsproceduraltriangulator_cpp
70 #include "Graphics/Procedural/triangulator.h"
71 #include "Graphics/Procedural/shape.h"
72 #include "Graphics/Procedural/multishape.h"
74 #include "MathTools/mathtools.h"
76 #include "stringtool.h"
78 #include "matrix4x4.h"
169 return ( ( Index0 == this->
Indexes[0] || Index0 == this->
Indexes[1] || Index0 == this->
Indexes[2] ) &&
188 Real invDenom = 1.0 / ( dot00 * dot11 - dot01 * dot01 );
189 Real u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
190 Real v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
193 return ( u >= 0 ) && ( v >= 0 ) && ( u + v - 1 <= 0 );
253 for(
Integer Index = 0 ; Index < 3 ; ++Index )
255 if( Tri.
Indexes[Index] == this->Index0 || Tri.
Indexes[Index] == this->Index1 || Tri.
Indexes[Index] == this->Index2 )
274 Real MaxTriangleSize = 0.0;
275 for(
Point2DIterator PointIt = List.begin() ; PointIt != List.end() ; ++PointIt )
277 MaxTriangleSize = std::max<Real>( MaxTriangleSize, MathTools::Abs( PointIt->X ) );
278 MaxTriangleSize = std::max<Real>( MaxTriangleSize, MathTools::Abs( PointIt->Y ) );
281 List.push_back(
Vector2( -3 * MaxTriangleSize, -3 * MaxTriangleSize ) );
282 List.push_back(
Vector2( 3 * MaxTriangleSize, -3 * MaxTriangleSize ) );
283 List.push_back(
Vector2( 0.0, 3 * MaxTriangleSize) );
285 Integer MaxTriangleIndex = List.size() - 3;
287 SuperTriangle.
Indexes[0] = MaxTriangleIndex;
288 SuperTriangle.
Indexes[1] = MaxTriangleIndex + 1;
289 SuperTriangle.
Indexes[2] = MaxTriangleIndex + 2;
290 TriBuf.push_back( SuperTriangle );
294 for(
UInt16 PointIndex = 0 ; PointIndex < List.size() - 3 ; ++PointIndex )
296 std::list< std::list<DelaunayTriangle>::iterator > BorderlineTriangles;
298 Vector2& CurrPoint = List[ PointIndex ];
299 std::set<DelaunaySegment> Segments;
300 for( DelaunayTriangleBuffer::iterator TriIt = TriBuf.begin() ; TriIt != TriBuf.end() ; )
304 if( !TriIt->IsDegenerate() ) {
305 for(
Integer TriPointIndex = 0 ; TriPointIndex < 3 ; ++TriPointIndex )
307 DelaunaySegment DSeg1( TriIt->Indexes[ TriPointIndex ], TriIt->Indexes[ ( TriPointIndex + 1 ) % 3 ] );
308 if( Segments.find(DSeg1) != Segments.end() ) {
309 Segments.erase(DSeg1);
310 }
else if( Segments.find( DSeg1.
Inverse() ) != Segments.end() ) {
311 Segments.erase( DSeg1.
Inverse() );
313 Segments.insert(DSeg1);
317 TriIt = TriBuf.erase(TriIt);
319 BorderlineTriangles.push_back(TriIt);
329 std::set<DelaunaySegment> CopySegment = Segments;
330 for( std::list< std::list<DelaunayTriangle>::iterator >::iterator BorderItIt = BorderlineTriangles.begin() ; BorderItIt != BorderlineTriangles.end() ; BorderItIt++ )
332 DelaunayTriangleBuffer::iterator BorderTriIt = (*BorderItIt);
333 Boole TriRemoved =
false;
334 for( std::set<DelaunaySegment>::iterator SegIt = CopySegment.begin() ; SegIt != CopySegment.end() && !TriRemoved ; ++SegIt )
336 Boole IsTriangleIntersected =
false;
337 for(
Integer SegIndex = 0 ; SegIndex < 2 ; ++SegIndex )
339 Integer Index1 = ( SegIndex == 0 ) ? SegIt->Index1 : SegIt->Index2;
341 for(
Integer TriCheckIndex = 0 ; TriCheckIndex < 3 ; ++TriCheckIndex )
344 if( BorderTriIt->Indexes[ TriCheckIndex ] == Index1 ||
345 BorderTriIt->Indexes[ TriCheckIndex ] == Index2 ||
346 BorderTriIt->Indexes[ ( TriCheckIndex + 1 ) % 3 ] == Index1 ||
347 BorderTriIt->Indexes[ ( TriCheckIndex + 1 ) % 3 ] == Index2 )
349 LineSegment2D Seg2( BorderTriIt->GetPoint( TriCheckIndex ), BorderTriIt->GetPoint( ( TriCheckIndex + 1 ) % 3 ) );
353 IsTriangleIntersected =
true;
358 if( IsTriangleIntersected ) {
359 if( !BorderTriIt->IsDegenerate() ) {
360 for(
Integer TriPointIndex = 0 ; TriPointIndex < 3 ; ++TriPointIndex )
362 DelaunaySegment DSeg1( BorderTriIt->Indexes[ TriPointIndex ], BorderTriIt->Indexes[ ( TriPointIndex + 1 ) % 3 ] );
363 if( Segments.find(DSeg1) != Segments.end() ) {
364 Segments.erase(DSeg1);
365 }
else if( Segments.find( DSeg1.
Inverse() ) != Segments.end() ) {
366 Segments.erase( DSeg1.
Inverse() );
368 Segments.insert(DSeg1);
372 TriBuf.erase(BorderTriIt);
379 for( std::set<DelaunaySegment>::iterator EdgeIt = Segments.begin() ; EdgeIt != Segments.end() ; ++EdgeIt )
382 EdgeTriangle.
SetVertices( EdgeIt->Index1, EdgeIt->Index2, PointIndex );
384 TriBuf.push_back(EdgeTriangle);
403 for( IndexContainer::const_iterator SegIndexIt = SegmentListIndices.begin() ; SegIndexIt != SegmentListIndices.end() ; ++SegIndexIt )
408 Boole IsAlreadyIn =
false;
409 for( DelaunayTriangleBuffer::iterator TriIt = TriBuf.begin() ; TriIt != TriBuf.end() ; ++TriIt )
411 if( TriIt->ContainsSegment(Index1,Index2) ) {
423 for( DelaunaySegmentContainer::iterator DelSegIt = DelSegList.begin() ; DelSegIt != DelSegList.end() ; DelSegIt++ )
426 std::set<DelaunaySegment> Segments;
427 LineSegment2D Seg1( List[DelSegIt->Index1], List[DelSegIt->Index2] );
428 for( DelaunayTriangleBuffer::iterator DelTriIt = TriBuf.begin() ; DelTriIt != TriBuf.end() ; )
430 Boole IsTriangleIntersected =
false;
432 for(
Integer TriPoint = 0 ; TriPoint < 3 ; ++TriPoint )
435 if( DelTriIt->Indexes[ TriPoint ] == DelSegIt->Index1 ||
436 DelTriIt->Indexes[ TriPoint ] == DelSegIt->Index2 ||
437 DelTriIt->Indexes[ ( TriPoint + 1 ) % 3 ] == DelSegIt->Index1 ||
438 DelTriIt->Indexes[ ( TriPoint + 1 ) % 3 ] == DelSegIt->Index2 )
440 if( DelTriIt->IsDegenerate() ) {
441 if( DelTriIt->Indexes[ TriPoint ] == DelSegIt->Index1 || DelTriIt->Indexes[ ( TriPoint + 1 ) % 3 ] == DelSegIt->Index1 ) {
442 DegenIndex = DelSegIt->Index1;
443 }
else if( DelTriIt->Indexes[ TriPoint ] == DelSegIt->Index2 || DelTriIt->Indexes[ ( TriPoint + 1 ) % 3 ] == DelSegIt->Index2 ) {
444 DegenIndex = DelSegIt->Index2;
446 IsTriangleIntersected =
true;
451 LineSegment2D Seg2( DelTriIt->GetPoint( TriPoint ), DelTriIt->GetPoint( ( TriPoint + 1 ) % 3 ) );
454 IsTriangleIntersected =
true;
458 if( IsTriangleIntersected ) {
459 for(
Integer TriPoint = 0 ; TriPoint < 3 ; ++TriPoint )
461 DelaunaySegment DelSeg1( DelTriIt->Indexes[ TriPoint ], DelTriIt->Indexes[ ( TriPoint + 1 ) % 3 ] );
462 if( Segments.find(DelSeg1) != Segments.end() ) {
463 Segments.erase(DelSeg1);
464 }
else if( Segments.find( DelSeg1.
Inverse() ) != Segments.end() ) {
465 Segments.erase( DelSeg1.
Inverse() );
467 Segments.insert(DelSeg1);
470 DelTriIt = TriBuf.erase( DelTriIt );
479 Integer Point = DelSegIt->Index1;
480 Boole IsAbove =
true;
481 while( Segments.size() > 0 )
484 for( std::set<DelaunaySegment>::iterator SegSetIt = Segments.begin() ; SegSetIt != Segments.end() ; ++SegSetIt )
486 if( SegSetIt->Index1 == Point || SegSetIt->Index2 == Point ) {
487 if( SegSetIt->Index1 == Point ) {
488 Point = SegSetIt->Index2;
490 Point = SegSetIt->Index1;
492 Segments.erase(SegSetIt);
493 if( Point == DelSegIt->Index2 ) {
495 }
else if( Point != DelSegIt->Index1 ) {
497 PointsAbove.push_back(Point);
499 PointsBelow.push_back(Point);
515 for( DelaunayTriangleBuffer::iterator TriIt = TriBuf.begin() ; TriIt != TriBuf.end() ; )
519 if( IsTriangleOut ) {
520 TriIt = TriBuf.erase(TriIt);
526 for( DelaunayTriangleBuffer::iterator TriIt = TriBuf.begin() ; TriIt != TriBuf.end() ; )
530 if( IsTriangleOut ) {
531 TriIt = TriBuf.erase(TriIt);
542 if( InputPoints.size() == 0 )
544 if( InputPoints.size() ==1 ) {
548 TriBuf.push_back(Tri);
552 IndexContainer::const_iterator CurrentPoint = InputPoints.begin();
556 Boole IsDelaunay =
true;
558 for( IndexContainer::const_iterator it = InputPoints.begin() ; it != InputPoints.end() ; ++it )
560 if( Cir.
IsInside( List[*it] ) && (*it != *CurrentPoint) ) {
575 TriBuf.push_back(Tri);
583 if( !Set1.empty() ) {
586 if( !Set2.empty() ) {
599 for(
size_t CurrPoint = 0 ; CurrPoint < Points.size() ; ++CurrPoint )
601 Vector2 VP2 = Points[CurrPoint];
608 for(
size_t CurrIndex = 0 ; CurrIndex < IndexBuffer.size() / 3 ; ++CurrIndex )
610 Buffer.
AddIndex( IndexBuffer[ CurrIndex * 3 ] );
611 Buffer.
AddIndex( IndexBuffer[ CurrIndex * 3 + 2 ] );
612 Buffer.
AddIndex( IndexBuffer[ CurrIndex * 3 + 1 ] );
629 SegmentListIndices.push_back( SegIndex );
634 Whole TotalIndex = 0;
640 SegmentListIndices.push_back( TotalIndex + SegIndex );
641 SegmentListIndices.push_back( TotalIndex + CurrShape.
GetBoundedIndex( SegIndex + 1 ) );
646 typedef std::map<Vector2,Integer,Vector2LengthCompare> PointIndexMap;
647 PointIndexMap PointMap;
651 if( SegIt->PointA.SquaredDistance( SegIt->PointB ) < 1e-6 ) {
655 PointIndexMap::iterator PointIt = PointMap.find( SegIt->PointA );
656 if( PointIt != PointMap.end() ) {
657 SegmentListIndices.push_back( PointIt->second );
659 PointMap[ SegIt->PointA ] = Vertices.size();
660 SegmentListIndices.push_back( Vertices.size() );
661 Vertices.push_back( SegIt->PointA );
664 PointIt = PointMap.find( SegIt->PointB );
665 if( PointIt != PointMap.end() ) {
666 SegmentListIndices.push_back( PointIt->second );
668 PointMap[ SegIt->PointB ] = Vertices.size();
669 SegmentListIndices.push_back( Vertices.size() );
670 Vertices.push_back( SegIt->PointB );
676 for(
Whole PointIndex = 0 ; PointIndex < 3 ; PointIndex++ )
678 PointIndexMap::iterator TriPointIt = PointMap.find( (*this->
ManualSuperTriangle)[PointIndex] );
679 if( TriPointIt != PointMap.end() ) {
681 SuperTriangle.
Indexes[PointIndex] = TriPointIt->second;
685 SuperTriangle.
Indexes[PointIndex] = Vertices.size();
690 DelaunayTriBuf.push_back(SuperTriangle);
693 this->
Delaunay(Vertices,DelaunayTriBuf);
697 for( DelaunayTriangleBuffer::iterator TriIt = DelaunayTriBuf.begin() ; TriIt != DelaunayTriBuf.end() ; ++TriIt )
699 if( !TriIt->IsDegenerate() ) {
700 Indexes.push_back( TriIt->Indexes[0] );
701 Indexes.push_back( TriIt->Indexes[1] );
702 Indexes.push_back( TriIt->Indexes[2] );
Boole ContainsSegment(const Integer Index0, const Integer Index1) const
Checks to see of the segment specified via Indexes is a part of this triangle.
Integer Indexes[3]
An array of indexes forming the triangle.
Triangulator & SetManualSuperTriangle(Triangle2D *Tri)
Sets manual super triangle.
Point2DContainer::iterator Point2DIterator
Iterator type for a Point2DContainer.
DelaunaySegment Inverse() const
Gets the inverse of this segment.
A triangle formed from 3 points in a Point2DContainer.
virtual ~Triangulator()
Class destructor.
Thrown when an unknown internal error occurred.
Triangle2D * ManualSuperTriangle
A pointer to an optional triangle that encompasses all points to be triangulated. ...
void _AddConstraints(DelaunayTriangleBuffer &TriBuf, const Point2DContainer &List, const IndexContainer &SegmentListIndices) const
Forces specific segments to be present in the resulting triangulation.
DelaunaySegment(const Integer First, const Integer Second)
Class constructor.
bool Boole
Generally acts a single bit, true or false.
~TouchSuperTriangle()
Class destructor.
std::list< DelaunayTriangle > DelaunayTriangleBuffer
A container type for the storage of DelaunayTriangles.
Boole IsPointInside(const Vector2 &Point) const
Tells whether a point is inside a shape or not.
std::vector< LineSegment2D > SegmentContainer
Convenience typedef for the storage of segments to be processed by this class.
A geometry math class for expressing a triangle in 2D space.
IntersectionTestResult Intersects(const LineSegment2D &Other) const
Gets whether or not another line segment intersects with this one.
const Shape * ShapeToTriangulate
A pointer to the Shape to be triangulated.
Boole IsInside(const Vector2 &Point) const
Gets whether or not a point is inside this circle.
A convenience buffer that stores vertices and indices of a mesh to be generated.
#define MEZZ_EXCEPTION(num, desc)
An easy way to throw exceptions with rich information.
int Integer
A datatype used to represent any integer close to.
Triangulator & SetShapeToTriangulate(const Shape *TriShape)
Sets shape to triangulate.
A 4x4 matrix math class for the representation of full transforms.
Boole IsDegenerate() const
Checks if this triangle is degenerate.
Real GetDeterminant() const
Gets the Determinant of this Matrix.
SegmentContainer * SegmentListToTriangulate
A pointer to a container of segments forming the shape to triangulate.
Boole IsPointInside(const Vector2 &Point) const
Checks to see if a point is inside this triangle.
This implements the exception hiearchy for Mezzanine.
Integer FindSegNumber(const Integer Index0, const Integer Index1) const
Gets the index of a segment within this triangle. a valid segment index is not found then an INTERNAL...
DelaunayTriangle(const Point2DContainer *List)
Class constructor.
std::pair< Boole, Vector2 > IntersectionTestResult
This is a type used for the return of a intersection test.
Real DotProduct(const Vector2 &Other) const
This is used to calculate the dotproduct of this and another vector.
Boole IsClosed() const
Gets whether or not every Shape in this MultiShape is closed.
float Real
A Datatype used to represent a real floating point number.
A generic circle class for geometry calculations.
std::vector< DelaunaySegment > DelaunaySegmentContainer
Convenience typedef for the storage of delaunay segments to be processed by this class.
Boole IsPointInside(const Vector2 &Point) const
Gets whether or not a point is inside this MultiShape.
std::vector< Integer > IndexContainer
A container of Integers used to represent the indicies of a shape.
std::vector< Vector2 > Point2DContainer
Basic container type for the storage of 2D points.
uint16_t UInt16
An 16-bit unsigned integer.
Returned when the specified point is inside the circumcircle.
Triangulator()
Class constructor.
Real Y
Coordinate on the Y vector.
void Delaunay(Point2DContainer &List, DelaunayTriangleBuffer &TriBuf) const
Performs a Delaunay Triangulation on a provided list of points in 2D space and populates a triangle b...
Returned when the specified point is exceedingly close to being outside the circumcircle.
Real X
Coordinate on the X vector.
This is used to represent a point on a 2 dimentional area, such as a screen.
A segment of 2 points in a Point2DContainer.
Point2DContainer GetPoints() const
Gets a copy of raw vector data of this shape.
Integer Index1
The first index of the segment.
Whole GetSegCount() const
Gets the number of segments in this shape.
const Point2DContainer * Points
An array of Vector2's that for all the triangles/segments being operated on.
Point2DContainer GetPoints() const
Gets a container of all the points in this MultiShape.
Real SquaredLength() const
Gets the length of this vector squared.
Boole RemoveOutside
Stores whether or not the super triangle should be removed at the end of triangulation.
A generator class that implements the Delaunay Triangulation algorithm.
~DelaunayTriangle()
Class destructor.
Thrown when the available information should have worked but failed for unknown reasons.
Whole GetBoundedIndex(const Integer Index) const
Converts a potentially unsafe Integer index into a safe Whole index.
void AddPoint(TriangleBuffer &Buffer, const Vector3 &Loc, const Vector3 &Norm, const Vector2 &UV) const
Adds a new point to a triangle buffer, using the format defined for that MeshGenerator.
TouchSuperTriangle(const Integer First, const Integer Second, const Integer Third)
Class constructor.
Triangulator & SetRemoveOutside(const Boole Remove)
Sets if the outside of the shape must be removed.
void Triangulate(IndexContainer &Indexes, Point2DContainer &Vertices) const
Executes the Constrained Delaunay Triangulation algorithm. INVALID_STATE_EXCEPTION will be thrown if ...
String GetDebugDescription() const
Gets a string description of this triangle.
Whole GetNumShapes() const
Gets the number of shapes in this MultiShape.
static Vector3 Unit_Z()
Gets a vector representing the Z unit of a Vector3.
TriangleBuffer & AddIndex(const Integer Index)
Adds an index to the index buffer.
This is used to represent a point in space, or a vector through space.
Boole IsClosed() const
Gets whether or not this shape is closed.
InsideType IsPointInsideCircumcircle(const Vector2 &Point) const
Checks to see if a point is inside the Circumcircle generated from this triangle. ...
The bulk of the engine components go in this namspace.
InsideType
An enum used to describe the proximity of a point to the edge of a Circumcircle generated by the Dela...
unsigned long Whole
Whole is an unsigned integer, it will be at least 32bits in size.
~DelaunaySegment()
Class destructor.
Triangulator & SetSegmentListToTriangulate(SegmentContainer *Segments)
Sets segment list to triangulate.
Triangulator & SetMultiShapeToTriangulate(const MultiShape *TriMultiShape)
Sets multi shape to triangulate.
Returned when the specified point is outside the circumcircle.
void _RecursiveTriangulatePolygon(const DelaunaySegment &CuttingSeg, const IndexContainer &InputPoints, DelaunayTriangleBuffer &TriBuf, const Point2DContainer &List) const
Recursively generates a Delaunay triangle from a container of points.
Boole operator()(const DelaunayTriangle &Tri)
Functor operator.
Boole operator<(const DelaunaySegment &Other) const
Less-than compare operator.
A geometry math class for expressing a line connecting 2 points in 2D space.
A collection of interconnected 2D points used to express an arbitrary 2D shape.
Shape & GetShape(const Whole Index)
Gets a shape by index.
Vector2 GetMidPoint() const
Gets the central point of this triangle.
Boole operator==(const DelaunayTriangle &Other) const
Equality comparison operator.
virtual void AddToTriangleBuffer(TriangleBuffer &Buffer) const
Adds the vertices and indices as configured in this generator to a triangle buffer.
A grouping of individual 2D shapes used to express more elaborate shapes.
const MultiShape * MultiShapeToTriangulate
A pointer to the MultiShape to be triangulated.
void MakeDirectIfNeeded()
Will conditionally re-arrange the vertices of this triangle.
std::string String
A datatype used to a series of characters.
Integer Index2
The second index of the segment.
void SetVertices(const Integer Index0, const Integer Index1, const Integer Index2)
Sets the points that form this triangle.
Vector2 GetPoint(const Integer Point) const
Gets a point in the Point2DContainer by index.