Spinning Topp Logo BlackTopp Studios
inc
path.cpp
1 // © Copyright 2010 - 2016 BlackTopp Studios Inc.
2 /* This file is part of The Mezzanine Engine.
3 
4  The Mezzanine Engine is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  The Mezzanine Engine is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with The Mezzanine Engine. If not, see <http://www.gnu.org/licenses/>.
16 */
17 /* The original authors have included a copy of the license specified above in the
18  'Docs' folder. See 'gpl.txt'
19 */
20 /* We welcome the use of the Mezzanine engine to anyone, including companies who wish to
21  Build professional software and charge for their product.
22 
23  However there are some practical restrictions, so if your project involves
24  any of the following you should contact us and we will try to work something
25  out:
26  - DRM or Copy Protection of any kind(except Copyrights)
27  - Software Patents You Do Not Wish to Freely License
28  - Any Kind of Linking to Non-GPL licensed Works
29  - Are Currently In Violation of Another Copyright Holder's GPL License
30  - If You want to change our code and not add a few hundred MB of stuff to
31  your distribution
32 
33  These and other limitations could cause serious legal problems if you ignore
34  them, so it is best to simply contact us or the Free Software Foundation, if
35  you have any questions.
36 
37  Joseph Toppi - toppij@gmail.com
38  John Blackwood - makoenergy02@gmail.com
39 */
40 /*
41  -----------------------------------------------------------------------------
42  This source file is part of ogre-procedural
43 
44  For the latest info, see http://code.google.com/p/ogre-procedural/
45 
46  Copyright (c) 2010-2013 Michael Broutin
47 
48  Permission is hereby granted, free of charge, to any person obtaining a copy
49  of this software and associated documentation files (the "Software"), to deal
50  in the Software without restriction, including without limitation the rights
51  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
52  copies of the Software, and to permit persons to whom the Software is
53  furnished to do so, subject to the following conditions:
54 
55  The above copyright notice and this permission notice shall be included in
56  all copies or substantial portions of the Software.
57 
58  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
61  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
62  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
63  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
64  THE SOFTWARE.
65  -----------------------------------------------------------------------------
66  */
67 #ifndef _graphicsproceduralpath_cpp
68 #define _graphicsproceduralpath_cpp
69 
70 #include "Graphics/Procedural/path.h"
71 #include "Graphics/Procedural/shape.h"
72 
73 #include "Graphics/meshmanager.h"
74 
75 #include "MathTools/mathtools.h"
76 
77 #include "Ogre.h"
78 
79 namespace Mezzanine
80 {
81  namespace Graphics
82  {
83  namespace Procedural
84  {
86  Closed(false)
87  { }
88 
90  Points(Begin,End),
91  Closed(false)
92  { }
93 
94  Path::Path(const Point3DContainer& DataSet) :
95  Points(DataSet),
96  Closed(false)
97  { }
98 
100  { }
101 
102  ///////////////////////////////////////////////////////////////////////////////
103  // Utility
104 
105  void Path::BuildFromSegmentSoup(const LineSeg3DVec& Segments, PathContainer& GeneratedPaths)
106  {
107  typedef std::multimap<Vector3,Vector3,Vector3LengthCompare> Vec3MultiMap;
108  typedef Vec3MultiMap::iterator Vec3MapIterator;
109  typedef std::pair<Vec3MapIterator, Vec3MapIterator> Vec3MapRange;
110  typedef std::pair<Vector3,Vector3> Vec3Pair;
111 
112  Vec3MultiMap SegmentMap;
113  for( ConstLineSeg3DIterator SegIt = Segments.begin() ; SegIt != Segments.end() ; ++SegIt )
114  {
115  SegmentMap.insert( Vec3Pair( SegIt->PointA, SegIt->PointB ) );
116  SegmentMap.insert( Vec3Pair( SegIt->PointB, SegIt->PointA ) );
117  }
118  while( !SegmentMap.empty() )
119  {
120  Vector3 HeadFirst = SegmentMap.begin()->first;
121  Vector3 HeadSecond = SegmentMap.begin()->second;
122  Path CurrPath;
123  CurrPath.AddPoint(HeadFirst);
124  CurrPath.AddPoint(HeadSecond);
125  Vec3MapIterator FirstSeg = SegmentMap.begin();
126  Vec3MapRange Correspondants2 = SegmentMap.equal_range(HeadSecond);
127  for( Vec3MapIterator CorrIt = Correspondants2.first ; CorrIt != Correspondants2.second ; )
128  {
129  Vec3MapIterator RemoveIt = CorrIt++;
130  if( ( RemoveIt->second - FirstSeg->first ).SquaredLength() < 1e-8 ) {
131  SegmentMap.erase(RemoveIt);
132  }
133  }
134  SegmentMap.erase(FirstSeg);
135  Boole FoundSomething = true;
136  while( !SegmentMap.empty() && FoundSomething )
137  {
138  FoundSomething = false;
139  Vec3MapIterator Next = SegmentMap.find(HeadSecond);
140  if( Next != SegmentMap.end() ) {
141  FoundSomething = true;
142  HeadSecond = Next->second;
143  CurrPath.AddPoint(HeadSecond);
144  Vec3MapRange Correspondants = SegmentMap.equal_range(HeadSecond);
145  for( Vec3MapIterator CorrIt = Correspondants.first ; CorrIt != Correspondants.second ; )
146  {
147  Vec3MapIterator RemoveIt = CorrIt++;
148  if( ( RemoveIt->second - Next->first ).SquaredLength() < 1e-8 ) {
149  SegmentMap.erase(RemoveIt);
150  }
151  }
152  SegmentMap.erase(Next);
153  }
154  Vec3MapIterator Previous = SegmentMap.find(HeadFirst);
155  if( Previous != SegmentMap.end() ) {
156  FoundSomething = true;
157  CurrPath.InsertPoint(0, Previous->second);
158  HeadFirst = Previous->second;
159  Vec3MapRange Correspondants = SegmentMap.equal_range(HeadFirst);
160  for( Vec3MapIterator CorrIt = Correspondants.first ; CorrIt != Correspondants.second ; )
161  {
162  Vec3MapIterator RemoveIt = CorrIt++;
163  if( ( RemoveIt->second - Previous->first ).SquaredLength() < 1e-8 ) {
164  SegmentMap.erase(RemoveIt);
165  }
166  }
167  SegmentMap.erase(Previous);
168  }
169  }
170  // This code section is only relevant if closing of a path could be toggled without changing types.
171  if( CurrPath.GetPoint(0).SquaredDistance( CurrPath.GetPoint( CurrPath.GetSegCount() + 1 ) ) < 1e-6 ) {
172  CurrPath.GetPoints().pop_back();
173  CurrPath.Close();
174  }
175  GeneratedPaths.push_back(CurrPath);
176  }
177  }
178 
179  Mesh* Path::GenerateMesh(const String& Name, const String& Group) const
180  {
181  Ogre::ManualObject* TempMan = new Ogre::ManualObject("TempMan");
182  TempMan->begin("BaseWhiteNoLighting",Ogre::RenderOperation::OT_LINE_STRIP);
183 
184  for( ConstPoint3DIterator PointIt = this->Points.begin() ; PointIt != this->Points.end() ; ++PointIt )
185  { TempMan->position( (*PointIt).GetOgreVector3() ); }
186 
187  TempMan->end();
188  Mesh* NewMesh = MeshManager::GetSingletonPtr()->_WrapInternalMesh( TempMan->convertToMesh(Name,Group) );
189  delete TempMan;
190  return NewMesh;
191  }
192 
193  Path& Path::AppendPath(const Path& Other)
194  {
195  this->Points.insert( this->Points.end(), Other.Points.begin(), Other.Points.end() );
196  return *this;
197  }
198 
200  {
201  if( this->Points.empty() ) {
202  this->AppendPath(Other);
203  }else{
204  Vector3 refVector = *( this->Points.end() - 1 );
205  Point3DContainer Points( Other.Points.begin(), Other.Points.end() );
206  for( Point3DIterator PointIt = Points.begin() ; PointIt != Points.end() ; ++PointIt )
207  { (*PointIt) += refVector; }
208  this->Points.insert( this->Points.end(), Points.begin(), Points.end() );
209  }
210  return *this;
211  }
212 
213  Path Path::ExtractSubPath(const Whole First, const Whole Last)
214  {
215  Path Ret;
216  for( Whole Index = First ; Index < Last ; ++Index )
217  { Ret.AddPoint( this->Points[Index] ); }
218  return Ret;
219  }
220 
222  {
223  return ( this->Points.size() - 1 ) + ( this->Closed ? 1 : 0 );
224  }
225 
227  {
228  Real Length = 0;
229  for( Whole Index = 0 ; Index < this->Points.size() ; ++Index )
230  { Length += ( this->Points[ Index + 1 ] - this->Points[ Index ] ).Length(); }
231  if( this->Closed ) {
232  Length += ( this->Points.back() - *(this->Points.begin()) ).Length();
233  }
234  return Length;
235  }
236 
237  Real Path::GetLengthAtPoint(const Whole PointIndex) const
238  {
239  Real Length = 0;
240  for( Whole Index = 0 ; Index < PointIndex ; ++Index )
241  { Length += ( this->Points[ Index + 1 ] - this->Points[ Index ] ).Length(); }
242  if( this->Closed ) {
243  Length += ( this->Points.back() - *(this->Points.begin()) ).Length();
244  }
245  return Length;
246  }
247 
248  Path& Path::Reflect(const Vector3& Normal)
249  {
250  for( Point3DIterator PointIt = this->Points.begin() ; PointIt != this->Points.end() ; ++PointIt )
251  { (*PointIt) = PointIt->Reflect(Normal); }
252  return *this;
253  }
254 
256  {
257  std::reverse( this->Points.begin(), this->Points.end() );
258  return *this;
259  }
260 
262  {
263  this->Closed = true;
264  return *this;
265  }
266 
268  {
269  return this->Closed;
270  }
271 
272  ///////////////////////////////////////////////////////////////////////////////
273  // Point Management
274 
275  Path& Path::AddPoint(const Vector3& ToAdd)
276  {
277  this->Points.push_back(ToAdd);
278  return *this;
279  }
280 
281  Path& Path::AddPoint(const Real X, const Real Y, const Real Z)
282  {
283  this->Points.push_back(Vector3(X,Y,Z));
284  return *this;
285  }
286 
287  Path& Path::InsertPoint(const Whole Index, const Real X, const Real Y, const Real Z)
288  {
289  this->Points.insert( this->Points.begin() + Index, Vector3(X,Y,Z) );
290  return *this;
291  }
292 
293  Path& Path::InsertPoint(const Whole Index, const Vector3& Point)
294  {
295  this->Points.insert( this->Points.begin() + Index, Point );
296  return *this;
297  }
298 
299  const Vector3& Path::GetPoint(const Integer Index) const
300  {
301  if( this->Closed ) {
302  return this->Points.at( MathTools::WrappedModulo(Index, this->Points.size()) );
303  }else{
304  return this->Points.at( MathTools::Clamp( Index, 0, Integer(this->Points.size()) - 1 ) );
305  }
306  }
307 
309  { return this->Points; }
310 
312  { return this->Points; }
313 
314  ///////////////////////////////////////////////////////////////////////////////
315  // Transform
316 
317  Path& Path::Translate(const Vector3& Trans)
318  {
319  for( Point3DIterator PointIt = this->Points.begin() ; PointIt != this->Points.end() ; ++PointIt )
320  { (*PointIt) += Trans; }
321  return *this;
322  }
323 
324  Path& Path::Translate(const Real TransX, const Real TransY, const Real TransZ)
325  {
326  return this->Translate( Vector3(TransX,TransY,TransZ) );
327  }
328 
329  Path& Path::Scale(const Real Scaling)
330  {
331  return this->Scale(Scaling,Scaling,Scaling);
332  }
333 
334  Path& Path::Scale(const Real ScaleX, const Real ScaleY, const Real ScaleZ)
335  {
336  for( Point3DIterator PointIt = this->Points.begin() ; PointIt != this->Points.end() ; ++PointIt )
337  {
338  (*PointIt).X *= ScaleX;
339  (*PointIt).Y *= ScaleY;
340  (*PointIt).Z *= ScaleZ;
341  }
342  return *this;
343  }
344 
345  Path& Path::Scale(const Vector3& Scaling)
346  {
347  return this->Scale(Scaling.X,Scaling.Y,Scaling.Z);
348  }
349 
350  ///////////////////////////////////////////////////////////////////////////////
351  // Directions and Normals
352 
354  {
355  // If the path isn't closed, we get a different calculation at the end, because
356  // the tangent shall not be null
357  if( !this->Closed && Index == this->Points.size() - 1 && Index > 0 ) {
358  return ( this->Points[ Index ] - this->Points[ Index - 1 ] ).GetNormal();
359  }else{
360  return ( this->GetPoint( Index + 1 ) - this->GetPoint( Index ) ).GetNormal();
361  }
362  }
363 
365  {
366  // If the path isn't closed, we get a different calculation at the end, because
367  // the tangent shall not be null
368  if( !this->Closed && Index == 1 ) {
369  return ( this->Points[1] - this->Points[0] ).GetNormal();
370  }else{
371  return ( this->GetPoint( Index ) - this->GetPoint( Index - 1 ) ).GetNormal();
372  }
373  }
374 
376  {
377  return ( this->GetDirectionAfter(Index) + this->GetDirectionBefore(Index) ).GetNormal();
378  }
379 
380  ///////////////////////////////////////////////////////////////////////////////
381  // Conversion
382 
384  {
385  Shape RetShape;
386  for( ConstPoint3DIterator PointIt = this->Points.begin() ; PointIt != this->Points.end() ; ++PointIt )
387  { RetShape.AddPoint( PointIt->X, PointIt->Y ); }
388  if( this->Closed ) {
389  RetShape.Close();
390  }
391  return RetShape;
392  }
393  }//Procedural
394  }//Graphics
395 }//Mezzanine
396 
397 #endif
Path ExtractSubPath(const Whole First, const Whole Last)
Extracts a part of the path as a new path.
Definition: path.cpp:213
Mesh * GenerateMesh(const String &Name, const String &Group) const
Outputs a mesh representing this path.
Definition: path.cpp:179
Shape & AddPoint(const Vector2 &Point)
Adds a point to the shape.
Definition: shape.cpp:650
bool Boole
Generally acts a single bit, true or false.
Definition: datatypes.h:173
Vector3 GetNormal() const
This returns the normal for this relative to the origin.
Definition: vector3.cpp:363
Real GetTotalLength() const
Gets the total length of all segments in this path.
Definition: path.cpp:226
Point3DContainer & GetPoints()
Gets all of the points in this path.
Definition: path.cpp:308
std::vector< Vector3 > Point3DContainer
Basic container type for the storage of 3D points.
Real X
Coordinate on the X vector.
Definition: vector3.h:85
Real Z
Coordinate on the Z vector.
Definition: vector3.h:89
~Path()
Class destructor.
Definition: path.cpp:99
static void BuildFromSegmentSoup(const LineSeg3DVec &Segments, PathContainer &GeneratedPaths)
Generates one or more paths from a series of segments.
Definition: path.cpp:105
This class is used to check and modify the properties of a graphics mesh.
Definition: mesh.h:63
int Integer
A datatype used to represent any integer close to.
Definition: datatypes.h:154
Vector3 GetAvgDirection(const Whole Index) const
Gets the averaged direction from the specified point to both the next and previous points in the sequ...
Definition: path.cpp:375
Real GetLengthAtPoint(const Whole PointIndex) const
Gets the total length to the point in this path at an index.
Definition: path.cpp:237
Point3DContainer::iterator Point3DIterator
Iterator type for a Point3DContainer.
Shape ConvertToShape() const
Converts the path to a 2D shape, dropping the Z component.
Definition: path.cpp:383
LineSeg3DVec::const_iterator ConstLineSeg3DIterator
Const Iterator type for a LineSeg3DVec.
float Real
A Datatype used to represent a real floating point number.
Definition: datatypes.h:141
Real SquaredDistance(const Vector3 &OtherVec) const
Gets the squared distance between this and another vector.
Definition: vector3.cpp:454
Point3DContainer Points
A container storing all of the points in this path.
Definition: path.h:98
Path & AddPoint(const Vector3 &ToAdd)
Adds a point to this path.
Definition: path.cpp:275
static MeshManager * GetSingletonPtr()
Fetches a pointer to the singleton.
Definition: singleton.h:97
Shape & Close()
Makes this a closed shape, connecting the last point to the first point.
Definition: shape.cpp:623
Boole IsClosed() const
Gets whether or not the final point in this path connects to the first point.
Definition: path.cpp:267
Path & Reflect(const Vector3 &Normal)
Reflect all points in this path against a zero-origined plane with a given normal.
Definition: path.cpp:248
Boole Closed
Whether or not the end of this path connects to the beginning of this path.
Definition: path.h:101
Path & Reverse()
Reverses direction/ordering of the segments in this path.
Definition: path.cpp:255
Real Y
Coordinate on the Y vector.
Definition: vector3.h:87
std::vector< Path > PathContainer
Basic container type for the storage of Paths.
Definition: path.h:84
Path & Scale(const Real Scaling)
Applies the given scale to all the points in this path.
Definition: path.cpp:329
const Vector3 & GetPoint(const Integer Index) const
Safely gets a point in this path.
Definition: path.cpp:299
Vector3 GetDirectionBefore(const Whole Index) const
Gets the direction from a point to the previous point in the sequence.
Definition: path.cpp:364
Path & AppendPath(const Path &Other)
Appends all the points from another path to this path.
Definition: path.cpp:193
This is used to represent a point in space, or a vector through space.
Definition: vector3.h:77
The bulk of the engine components go in this namspace.
Definition: actor.cpp:56
unsigned long Whole
Whole is an unsigned integer, it will be at least 32bits in size.
Definition: datatypes.h:151
Integer GetSegCount() const
Gets the number of segments in this path.
Definition: path.cpp:221
Path & Close()
Connects the last point in this path to the first point.
Definition: path.cpp:261
Path()
Blank constructor.
Definition: path.cpp:85
std::vector< LineSegment3D > LineSeg3DVec
Basic container type for the storage of 3D line segments.
Point3DContainer::const_iterator ConstPoint3DIterator
Const Iterator type for a Point3DContainer.
Path & Translate(const Vector3 &Trans)
Applies the given translation to all the points in this path.
Definition: path.cpp:317
A collection of interconnected 2D points used to express an arbitrary 2D shape.
Definition: shape.h:95
A collection of interconnected 3D points used to express path through 3D space.
Definition: path.h:93
std::string String
A datatype used to a series of characters.
Definition: datatypes.h:159
Path & InsertPoint(const Whole Index, const Real X, const Real Y, const Real Z)
Inserts a point to the path.
Definition: path.cpp:287
Path & AppendPathRel(const Path &Other)
Appends all the points from another path to this path with their positions relative to the position o...
Definition: path.cpp:199
Vector3 GetDirectionAfter(const Whole Index) const
Gets the direction of a point to the next point in the sequence.
Definition: path.cpp:353