67 #ifndef _graphicsproceduralshape_cpp
68 #define _graphicsproceduralshape_cpp
70 #include "Graphics/Procedural/shape.h"
71 #include "Graphics/Procedural/multishape.h"
72 #include "Graphics/Procedural/path.h"
74 #include "Graphics/meshmanager.h"
76 #include "MathTools/mathtools.h"
87 Mezzanine::Boole _SortAngles(std::pair<Mezzanine::Real,Mezzanine::UInt8> One, std::pair<Mezzanine::Real,Mezzanine::UInt8> Two)
89 return ( One.first < Two.first );
119 this->Index[0] = Index0;
120 this->Index[1] = Index1;
121 this->OnVertex[0] =
false;
122 this->OnVertex[1] =
false;
151 if( Intersections.empty() ) {
193 const Shape* InputShapes[2];
194 InputShapes[0] =
this;
195 InputShapes[1] = &Other;
197 while( !Intersections.empty() )
200 UInt8 shapeSelector = 0;
202 Vector2 currentPosition = Intersections.begin()->Position;
204 Whole currentSegment = firstIntersection.
Index[ shapeSelector ];
205 Intersections.erase( Intersections.begin() );
206 outputShape.
AddPoint( currentPosition );
208 Char8 IsIncreasing = 0;
210 if( !this->
_FindWhereToGo(InputShapes, OpType, firstIntersection, shapeSelector, IsIncreasing, currentSegment) ) {
219 Real distanceToNextIntersection = std::numeric_limits<Real>::max();
221 Whole nextPoint = currentSegment + ( IsIncreasing == 1 ? 1 : 0 );
222 Boole nextPointIsOnIntersection =
false;
226 if( currentSegment == it->Index[shapeSelector] ) {
227 if( ( ( it->Position - currentPosition ).DotProduct( it->Position - InputShapes[shapeSelector]->
GetPoint(nextPoint) ) < 0 ) ||
228 ( it->OnVertex[shapeSelector] && nextPoint == it->Index[shapeSelector] ) )
231 Real d = ( it->Position - currentPosition ).Length();
232 if( d < distanceToNextIntersection ) {
234 found_next_intersection = it;
235 distanceToNextIntersection = d;
239 if( nextPoint == it->Index[shapeSelector] && it->OnVertex[shapeSelector] )
240 nextPointIsOnIntersection =
true;
244 if( currentSegment == firstIntersection.
Index[shapeSelector] ) {
246 if( ( firstIntersection.
Position - currentPosition ).DotProduct( firstIntersection.
Position - InputShapes[shapeSelector]->
GetPoint(nextPoint) ) < 0 ) {
247 Real d = ( firstIntersection.
Position - currentPosition ).Length();
248 if( d > 0. && d < distanceToNextIntersection ) {
256 if( found_next_intersection != Intersections.end() ) {
258 Intersections.erase(found_next_intersection);
260 Boole result = this->
_FindWhereToGo(InputShapes, OpType, currentIntersection, shapeSelector, IsIncreasing, currentSegment);
262 OGRE_EXCEPT(Ogre::Exception::ERR_INTERNAL_ERROR,
"We should not be here!",
"Procedural::Shape::_booleanOperation(const Procedural::Shape&, Procedural::BooleanOperationType)");
266 if( !nextPointIsOnIntersection ) {
267 if( IsIncreasing == 1 ) {
268 currentPosition = InputShapes[shapeSelector]->
GetPoint( currentSegment + 1 );
270 currentPosition = InputShapes[shapeSelector]->
GetPoint( currentSegment );
273 outputShape.
AddPoint(currentPosition);
275 currentSegment = MathTools::WrappedModulo( currentSegment + IsIncreasing,InputShapes[shapeSelector]->
GetSegCount() );
279 outputMultiShape.
AddShape(outputShape);
281 return outputMultiShape;
291 default:
return true;
302 if( ( Dot < 0 && ShapeSelector == 0) || ( Dot > 0 && ShapeSelector == 1 ) )
315 UInt8 IncomingDirection;
318 if( IsIncreasing == 0 ) {
319 IncomingDirection = 255;
321 IncomingDirection = ShapeSelector + ( IsIncreasing == 1 ? 2 : 0 );
323 for(
UInt8 i = 0 ; i < 2 ; i++ )
330 Directions[ i ] = -Directions[ 2 + i ];
333 for(
UInt8 i = 0 ; i < 4 ; i++ )
339 std::pair<Real,UInt8> SortedDirections[4];
342 for(
Integer i = 0 ; i < 4 ; i++ )
345 SortedDirections[i].first = 0;
347 SortedDirections[i].first = Sides[0] * Directions[0].
AngleTo( Directions[i] );
349 SortedDirections[i].second = i;
352 std::sort(SortedDirections, SortedDirections + 4, _SortAngles);
355 if( Sides[0] != Sides[ SortedDirections[1].second ] ) {
356 IsOutside[0] = IsOutside[ SortedDirections[1].second ] =
true;
357 IsOutside[ SortedDirections[2].second ] = IsOutside[ SortedDirections[3].second ] =
false;
359 IsOutside[ SortedDirections[1].second ] = IsOutside[ SortedDirections[2].second ] =
true;
360 IsOutside[ SortedDirections[3].second ] = IsOutside[ SortedDirections[0].second ] =
false;
364 for(
unsigned short i = 0 ; i < 4 ; i++ )
366 if( ( IsOutside[i] == this->
_IsLookingForOutside( OpType, i % 2 ) ) && ( i != IncomingDirection ) ) {
367 ShapeSelector = i % 2;
368 IsIncreasing = i / 2 == 0 ? 1 : -1;
369 CurrentSegment = Intersection.
Index[ ShapeSelector ];
377 Integer NextShapeSelector = ( ShapeSelector + 1 ) % 2;
380 IsIncreasing = this->
_IsIncreasing( Dot, OpType, NextShapeSelector );
382 ShapeSelector = NextShapeSelector;
384 CurrentSegment = Intersection.
Index[ ShapeSelector ];
391 for(
unsigned short SelfSeg = 0 ; SelfSeg < this->
GetSegCount() ; ++SelfSeg )
395 for(
unsigned short OtherSeg = 0 ; OtherSeg < Other.
GetSegCount() ; ++OtherSeg )
410 if( Seg2.PointA.SquaredDistance( Result.second ) < 1e-8 ) {
413 if( Seg2.PointB.SquaredDistance( Result.second ) < 1e-8 ) {
418 Intersections.push_back( Inter );
429 Ogre::ManualObject* TempMan =
new Ogre::ManualObject(
"TempMan");
430 TempMan->begin(
"BaseWhiteNoLighting",Ogre::RenderOperation::OT_LINE_STRIP);
448 if( this->
Points.empty() ) {
453 for(
Point2DIterator it = pointList.begin() ; it != pointList.end() ; ++it )
454 { *it += refVector; }
455 this->
Points.insert( this->
Points.end(), pointList.begin(), pointList.end() );
463 for(
Whole i = First ; i <= Last ; ++i )
473 {
return ( this->
Points.size() - 1 ) + ( this->
Closed ? 1 : 0 ); }
478 for(
Whole Index = 0 ; Index < this->
Points.size() - 1 ; ++Index )
479 { Length += ( this->
Points[ Index + 1 ] - this->
Points[Index] ).Length(); }
481 Length += ( this->
Points.back() - *(this->
Points.begin()) ).Length();
490 Integer ClosestSegmentIndex = -1;
491 Real ClosestSegmentDistance = std::numeric_limits<Real>::max();
492 Vector2 ClosestSegmentIntersection;
498 if( A.
Y != B.
Y && ( A.
Y - Point.
Y ) * ( B.
Y - Point.
Y ) <= 0.0 ) {
499 Vector2 Intersect( A.
X + ( Point.
Y - A.
Y ) * ( B.
X - A.
X ) / ( B.
Y - A.
Y ), Point.
Y );
500 Real Dist = MathTools::Abs( Point.
X - Intersect.
X );
501 if( Dist < ClosestSegmentDistance ) {
502 ClosestSegmentIndex = CurrSeg;
503 ClosestSegmentDistance = Dist;
504 ClosestSegmentIntersection = Intersect;
508 if( ClosestSegmentIndex != -1 ) {
509 if( this->
GetNormalAfter( ClosestSegmentIndex ).X * ( Point.
X - ClosestSegmentIntersection.
X ) < 0 ) {
525 for(
Whole Index = 0 ; Index < this->
Points.size() ; ++Index )
526 { sqRadius = std::max( sqRadius, this->
Points[Index].SquaredLength() ); }
527 return MathTools::Sqrt(sqRadius);
534 if( Coord < 0.0 || Coord > 1.0 )
538 return A + ( ( B - A ) * Coord );
543 if( this->
Points.size() < 2 )
549 if( Coord > NextLen ) {
554 if( !this->
Closed && Index >= this->
Points.size() - 2 ) {
555 return this->
Points.back();
575 for(
Integer CurrPoint = NumPoints - 1 ; CurrPoint >= 0 ; CurrPoint-- )
578 this->
Points.push_back( ( Pos * -1.0 ) + Point );
581 for(
Integer CurrPoint = 0 ; CurrPoint < NumPoints ; CurrPoint++ )
584 this->
Points.push_back( ( Pos * -1.0 ) + Point );
595 for(
Integer CurrPoint = 0 ; CurrPoint < NumPoints ; CurrPoint++ )
599 if( Pos != this->
Points.at(CurrPoint) ) {
600 this->
Points.push_back(Pos);
604 for(
Integer CurrPoint = NumPoints - 1 ; CurrPoint >= 0 ; CurrPoint-- )
608 if( Pos != this->
Points.at(CurrPoint) ) {
609 this->
Points.push_back(Pos);
652 this->
Points.push_back(Point);
664 if( this->
Points.empty() ) {
665 this->
Points.push_back( Point );
667 this->
Points.push_back( Point + *( this->
Points.end() - 1 ) );
674 if( this->
Points.empty() ) {
690 this->
Points.insert( this->
Points.begin() + Index, Point );
701 return this->
Points.size();
707 return MathTools::WrappedModulo( Index, this->
Points.size() );
738 Real c = MathTools::Cos( Angle );
739 Real s = MathTools::Sin( Angle );
744 it->X = c * x - s * y;
745 it->Y = s * x + c * y;
752 return this->
Scale(Scaling,Scaling);
767 return this->
Scale(Scaling.
X,Scaling.
Y);
777 if( !this->
Closed && Index == this->
Points.size() - 1 && Index > 0) {
788 if( !this->
Closed && Index == 1) {
848 for(
unsigned short CurrPoint = 1 ; CurrPoint < this->
Points.size() ; ++CurrPoint )
850 if( X < this->
Points[CurrPoint].X ) {
851 X = this->
Points[CurrPoint].X;
857 if( Alpha1 < Alpha2 ) {
889 for(
Whole Index = 0 ; Index < this->
Points.size() ; Index++ )
891 for(
Integer Index = this->
Points.size() - 1 ; Index >= 0 ; Index-- )
898 for(
Whole Index = 0 ; Index < this->
Points.size() ; Index++ )
904 for(
Whole Index = 0 ; Index < this->
Points.size() ; Index++ )
static Vector2 Unit_Y()
Gets a vector representing the Y unit of a Vector2.
MultiShape _BooleanOperation(const Shape &Other, const Procedural::BooleanOperation OpType) const
Performs a boolean operation between this shape and another shape.
Point2DContainer::iterator Point2DIterator
Iterator type for a Point2DContainer.
Vector2 GetDirectionBefore(const Whole Index) const
Gets the direction from a point to the previous point in the sequence.
std::vector< IntersectionInShape > IntersectionContainer
Basic container type for the storage of Intersections in this class.
Vector2 Perpendicular() const
Generates a Vector2 that is perpendicular to this vector.
Boole _IsLookingForOutside(const Procedural::BooleanOperation OpType, const Char8 ShapeSelector) const
Gets whether or not the current boolean operation is looking for outside edges of the two shapes bein...
Shape & AddPoint(const Vector2 &Point)
Adds a point to the shape.
Procedural::ShapeSide FindRealOutSide() const
On a closed shape, find if the outside is located on the right or on the left.
bool Boole
Generally acts a single bit, true or false.
const Vector2 & GetPoint(const Integer Index) const
Gets a point by index which can be out of bounds and will wrap.
Boole IsPointInside(const Vector2 &Point) const
Tells whether a point is inside a shape or not.
Vector2 GetDirectionAfter(const Whole Index) const
Gets the direction of a point to the next point in the sequence.
Point2DContainer & GetPointsReference()
Gets raw vector data of this shape as a non-const reference.
IntersectionTestResult Intersects(const LineSegment2D &Other) const
Gets whether or not another line segment intersects with this one.
Whole GetPointCount() const
Gets the number of points in this shape.
Procedural::ShapeSide GetOutSide() const
Gets which side is the OutSide of this shape.
MultiShape & AddShape(const Shape &ToAdd)
Adds a shape to this MultiShape.
Vector2 GetPosition(const Whole Index, const Real Coord) const
Gets the position on a segment. the provided index is out of bounds or the Coord is outside of the ra...
Shape & Mirror(Boole Flip=false)
Create a symetric copy of the points in this shape at the origin point.
~Shape()
Class destructor.
#define MEZZ_EXCEPTION(num, desc)
An easy way to throw exceptions with rich information.
This class is used to check and modify the properties of a graphics mesh.
int Integer
A datatype used to represent any integer close to.
Shape & Reflect(const Vector2 &Normal)
Reflect all points in this shape against a zero-origined line with a given normal.
Char8 _IsIncreasing(const Real Dot, const Procedural::BooleanOperation OpType, const Char8 ShapeSelector) const
Gets whether or not the segment being operated on is to be incremented.
Shape & Reverse()
Reverses direction/ordering of the segments in this shape.
IntersectionContainer::iterator IntersectionIterator
Iterator type for Intersections stored in this class.
Shape & Scale(const Real Scaling)
Applies the given scale to all the points in this shape.
Shape & Translate(const Vector2 &Trans)
Applies the given translation to all the points in this shape.
MultiShape Thicken(const Real Amount)
Applies a "thickness" to a shape, ie a bit like the extruder, but in 2D.
Shape & AppendShapeRel(const Shape &Other)
Appends all the points from another shape to this shape with their positions relative to the position...
IntersectionInShape(const Whole Index0, const Whole Index1, Vector2 Intersect)
Class constructor.
Real AngleTo(const Vector2 &Other) const
Gets an oriented angle between this Vector2 and another Vector2.
uint8_t UInt8
An 8-bit unsigned integer.
Boole Closed
Whether or not the first point and last point should be connected, closing the shape.
Vector2 GetAvgDirection(const Whole Index) const
Gets the averaged direction from the specified point to both the next and previous points in the sequ...
This implements the exception hiearchy for Mezzanine.
MultiShape BooleanDifference(const Shape &Other) const
Computes the difference between this shape and another one.
Point2DContainer::const_iterator ConstPoint2DIterator
Const Iterator type for a Point2DContainer.
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.
Shape & AppendShape(const Shape &Other)
Appends all the points from another shape to this shape.
Vector2 PointA
The first point defining the segment.
float Real
A Datatype used to represent a real floating point number.
char Char8
A datatype to represent one character.
Vector2 Reflect(const Vector2 &Normal) const
Gets a reflection vector to the line with the given normal.
Procedural::ShapeSide OutSide
Sets which extreme side of this shape is to be considered the outside of the shape. Useful when a shape is not closed.
ShapeSide
An enum used to express which side to work with in Shape operations.
std::vector< Vector2 > Point2DContainer
Basic container type for the storage of 2D points.
Path & AddPoint(const Vector3 &ToAdd)
Adds a point to this path.
static MeshManager * GetSingletonPtr()
Fetches a pointer to the singleton.
Real Y
Coordinate on the Y vector.
Completely merges the the two buffers.
Shape & MirrorAroundPoint(const Real X, const Real Y, Boole Flip=false)
Create a symetric copy of the points in this shape at an arbitrary point.
Shape & Close()
Makes this a closed shape, connecting the last point to the first point.
Shape ExtractSubShape(const Whole First, const Whole Last)
Extracts a part of the shape as a new shape.
Real X
Coordinate on the X vector.
Path ConvertToPath() const
Converts the shape to a 3D path.
Shape & Rotate(const Real Angle)
Applies the given rotation to all the points in this shape.
This is used to represent a point on a 2 dimentional area, such as a screen.
MultiShape BooleanIntersect(const Shape &Other) const
Computes the intersection between this shape and another one.
Point2DContainer GetPoints() const
Gets a copy of raw vector data of this shape.
Real FindBoundingRadius() const
Computes the radius of a bounding circle centered on the origin of this shape.
Shape & SetOutSide(const Procedural::ShapeSide Side)
Sets which side is the OutSide of this shape.
Whole GetSegCount() const
Gets the number of segments in this shape.
Convenience class storing data on the point in a 2D shape where multiple segments intersect...
BooleanOperation
An enum used to describe which boolean operation to take when processing two triangle buffers...
Real SquaredDistance(const Vector2 &Other) const
Gets the squared distance between this and another vector.
Real GetTotalLength() const
Gets the total length of all segments in this shape.
Gets only the parts of the two buffers that aren't overlapping.
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.
Use the left side of the shape.
Boole OnVertex[2]
An Array storing whether the intersection is on or very near a vertex belonging to either shape being...
Thrown when parameters are checked at runtime and found invalid.
Gets only the parts of the two buffers that are overlapping.
MultiShape BooleanUnion(const Shape &Other) const
Computes the union between this shape and another one.
Shape & Reset()
Clears all points from this shape.
Vector2 Position
The position of the intersection.
Vector2 GetNormalBefore(const Whole Index) const
Gets the normal of the segment before the specified point.
This is used to represent a point in space, or a vector through space.
Shape & AddPointRel(const Vector2 &Point)
Adds a point to the shape, relative to the last position added.
Boole IsClosed() const
Gets whether or not this shape is closed.
The bulk of the engine components go in this namspace.
Point2DContainer Points
Container storing all of the points that form this shape.
Shape & MirrorAroundAxis(const Vector2 &Axis, Boole Flip=false)
Create a symetric copy of the points in this shape at an arbitrary axis.
unsigned long Whole
Whole is an unsigned integer, it will be at least 32bits in size.
Vector2 PointB
The second point defining the segment.
Mesh * GenerateMesh(const String &Name, const String &Group) const
Outputs a mesh representing this shape.
void _AppendToManualObject(Ogre::ManualObject *Object) const
Appends the shape vertices to a manual object being edited.
Vector2 GetNormal() const
Gets the normal of this Vector2.
Vector2 GetAvgNormal(const Whole Index) const
Gets the averaged normal of the segments before and after the specified point.
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()
Class constructor.
Vector2 GetNormalAfter(const Whole Index) const
Gets the normal of the segment after the specified point.
Use the right side of the shape.
Shape & GetShape(const Whole Index)
Gets a shape by index.
A grouping of individual 2D shapes used to express more elaborate shapes.
Whole Index[2]
An Array storing indexes to points that are the first vertices of segments that intersect for each of...
Boole _FindWhereToGo(const Shape *InputShapes[], const Procedural::BooleanOperation OpType, const IntersectionInShape &Intersection, UInt8 &ShapeSelector, Char8 &IsIncreasing, Whole &CurrentSegment) const
Determines which segment to follow when an intersection is encountered.
A collection of interconnected 3D points used to express path through 3D space.
std::string String
A datatype used to a series of characters.
Shape & InsertPoint(const Whole Index, const Real X, const Real Y)
Inserts a point to the shape.
Shape & SwitchSide()
Toggles the currently set "OutSide".
void _FindAllIntersections(const Shape &Other, IntersectionContainer &Intersections) const
Finds all detectable intersections between this shape and another shape.
Boole IsOutsideRealOutside() const
Gets whether the currently set OutSide is the real Outside.