CFx SDK Documentation  2023 SP0
FMImpProfile2DBool.h
Go to the documentation of this file.
1 // Copyright (C) 2002-2015, Open Design Alliance (the "Alliance").
3 // All rights reserved.
4 //
5 // This software and its documentation and related materials are owned by
6 // the Alliance. The software may only be incorporated into application
7 // programs owned by members of the Alliance, subject to a signed
8 // Membership Agreement and Supplemental Software License Agreement with the
9 // Alliance. The structure and organization of this software are the valuable
10 // trade secrets of the Alliance and its suppliers. The software is also
11 // protected by copyright law and international treaty provisions. Application
12 // programs incorporating this software must include the following statement
13 // with their copyright notices:
14 //
15 // This application incorporates Teigha(R) software pursuant to a license
16 // agreement with Open Design Alliance.
17 // Teigha(R) Copyright (C) 2002-2015 by Open Design Alliance.
18 // All rights reserved.
19 //
20 // By use of this software, its documentation or related materials, you
21 // acknowledge and accept the above terms.
23 #ifndef __FM_IMP_PROFILE2D_BOOL_H__
24 #define __FM_IMP_PROFILE2D_BOOL_H__
25 
26 
27 #include "FMProfile2DBool.h"
28 
30 
32 #include "Contours/FM_IContour2D.h"
33 
35 
36 #include "FMContour2D.h"
37 #include "FMProfile2D.h"
38 
40 
41 using namespace FacetModeler;
42 
44 {
45  class Intersector;
46  class Node;
47  class Edge;
48  class EdgeGroup;
49 
51  {
57 
58  eoRegularize = (Profile2DBool::eoLastOper+1), // regularization of a single argument
59  //eoRegularizeTest, // regularization for the testing purposes
60 
61  eoFlagSetting, // set flags on the first argument WRT another args
62 
63  eoOpsMask = 0xFF,
64 
65  // Argument types
66  eoLinear = 0x100,
67  eoRegional = 0x200,
69  eoArgMask = 0xF00,
70 
71  // additional stuff
72  eoLinRegNoBoundary = 0x1000 // region boundary is not included in cutting region
73  };
74 
75 
77  {
81  //eilBySummaryArea
82  };
83 
85  {
87  erfIntersections = 0x01, // some bounds touch each other at least at one point
88  erfSticking = 0x02, // some bounds have coincident parts
89  erfCounterSticking = 0x04, // some bounds have coincident parts with opposite directions
90  erfWrongBounds = 0x08, // some bounds are not included in regularized profile
91  erfWrongNesting = 0x10, // some sub-regions have incorrect orientation
92  erfUnknownError = 0x100,// some error happened in regularization
93  erfAllFlags = 0xFFF
94  };
95 
96 #undef min
97  template< class T >
98  inline const T& min(const T& x, const T& y)
99  {
100  return (x<=y ? x : y );
101  }
102 
103 #undef max
104  template< class T >
105  inline const T& max(const T& x, const T& y)
106  {
107  return (x>=y ? x : y );
108  }
109 
110 
111 
112  class Contour
113  {
114  public:
115  Contour( const IContour2D & rC, OdUInt32 uCID, OdUInt32 uGID, bool bReversed = false, bool bForceCopy = false );
116  void Done( );
117 
118  // reset nodes and flags. Keep source contours
119  void resetNodes();
120 
121  inline const IContour2D & contour2D() const { return *pContour; };
122  inline OdUInt32 id() const { return uContourID; };
123  inline OdUInt32 groupId() const { return uGroupID; };
124 
125  inline bool isReversed () const { return m_bReversed; };
126 
127  void addNode ( Node * pNode, double dParam );
128  Result createEdges( Intersector & rAI, bool bStoreEdges = false );
129 
130  int getSign() const;
131 
132  Locations getLocation( const OdGePoint2d & ptTest, const OdGeTol gTol ) const;
133 
134  inline const std::vector< Edge* >& getEdges() const { return m_vecEdges; };
135 
136  private:
137  OdUInt32 uContourID; // ID of the contour
138  OdUInt32 uGroupID; // Group ID
139  const IContour2D * pContour; // Contour ( original or a caching copy of original )
140  const IContour2D * pOrigContour; // Original contour
141  bool m_bReversed;
142 
143  std::vector< std::pair< double, Node * > > m_vecNodes;
144 
145  // this member is not empty, if bStoreEdges was true in createEdges call
146  std::vector< Edge* > m_vecEdges;
147  };
148 
149  class Group
150  {
151  public:
152  enum GroupTypes {
153  egtUnknown = 0,
154  egtLines = 0x10,
155  egtLinesWithDirection = egtLines | 0x01,
156  egtRegion = 0x20,
157  egtRegionNormal = egtRegion,
158  egtRegionPositive = egtRegion | 0x01,
159  egtRegionOrdered = egtRegion | 0x02,
160  //egtNegative = 0x80,
161  egtLastType
162  };
163 
164 
165  Group( Intersector & rAI, GroupTypes eT, OdUInt32 uPri, OdUInt32 uFirst = 0, OdUInt32 uSize = 0 );
166 
167  inline GroupTypes type() const { return m_eType; };
168  inline OdUInt32 priority() const { return m_uPriority; };
169 
170  inline OdUInt32 size() const { return m_uSize; };
171  inline OdUInt32 firstIdx() const { return m_uFirst; };
172  inline OdUInt32 nextIdx() const { return m_uFirst + m_uSize; };
173 
174  const IContour2D & contour( OdUInt32 uIndex ) const;
175 
176  inline Intersector & intersector() const { return *m_pAI; };
177 
178  void resize( OdUInt32 uNewSize );
179 
180  // validate contours and initialize some cached values
182 
183  Locations getLocation( const OdGePoint2d & ptTest, const OdGeTol gTol ) const;
184 
185  private:
186  OdUInt32 m_uFirst;
187  OdUInt32 m_uSize;
188 
189  OdUInt32 m_uPriority;
190  GroupTypes m_eType;
191 
192  // elInside or elOutside - location of point which is not contained by the contours
193  // (i.e. "infinity" point)
194  Locations m_eInfinityLocation;
195 
196  Intersector * m_pAI;
197  };
198 
199 
200 
201  class Node
202  {
203  public:
204  Node( ) : m_uHotID(0) { };
205  Node( const OdGePoint2d & ptC )
206  : m_ptCenter( ptC ), m_uHotID(0) { };
207 
209  eOutEdge = 0,
210  eInEdge = 1,
211  eEdgeDirs
212  };
213 
214  void addEdge( int eDir, Edge * pEdge );
215 
218 
219  void updateFinalEdges( bool bReorderByAngle, double dTgStep );
220 
221  typedef std::pair< EdgeDirection, Edge * > EdgeLink;
222 
223  inline OdUInt32 edgeCount( ) const { return (OdUInt32)m_vecEdges.size(); };
224 
225  inline const EdgeLink & edgeLink ( OdUInt32 iIndex ) const { return m_vecEdges[iIndex]; };
226 
227  // HotIDs are used during export to simplify check, whether we`ve just passed the node
228  inline OdUInt32 getHotID() const { return m_uHotID; };
229  inline OdUInt32 setHotID(OdUInt32 uID) { return m_uHotID = uID; };
230 
231  //Edge * findNeighbour( const Edge * pEdge, EdgeDirection eEdgeDir, EdgeDirection eNeighbourDir, bool bCCW = false ) const;
232 
233  Edge * findFinalRegionalNeighbour( const Edge * pEdge, EdgeDirection eEdgeDir, EdgeDirection eNeighbourDir, bool bCCW = false ) const;
234  Edge * findFinalEdge( EdgeDirection eEdgeDir ) const;
235 
236  void reverseFinalEdge( OdUInt32 iIndex );
237 
238  private:
239  OdGePoint2d m_ptCenter;
240 
241  OdUInt32 m_uHotID;
242 
243  std::vector< EdgeLink > m_vecEdges;
244  };
245 
246 
247 
248  class Edge
249  {
250  public:
251  Edge( const Contour & rC, double dStartP, double dEndP );
252 
254  eStartNode = 0,
255  eEndNode = 1,
256  eNodePositions
257  };
258 
259  inline const Contour & contour( ) const { return *m_pContour; };
260  inline OdUInt32 regionId() const { return m_pContour->groupId(); };
261 
262  Edge & setNode( OdUInt32 ePos, Node * pNode, OdUInt32 iIndex );
263 
264  inline double param( int ePos ) const { return m_aParams[ePos]; };
265  inline Node * node ( int ePos ) const { return m_aNodes[ePos]; };
266  inline Node * anotherNode( int ePos ) const { return m_aNodes[ ePos^1 ]; };
267 
268  double tangentAt( int ePos, double dStep ) const;
269 
271 
272  inline OdUInt32 indexInNode( int ePos ) const { return m_aIndices[ePos]; };
273 
274  const OdGePoint2d& middlePoint() const;
275 
276  inline EdgeGroup * edgeGroup() const { return m_pEdgeGroup; };
277  Edge & setEdgeGroup( EdgeGroup * pGroup, OdUInt32 iIndex );
278 
279  static bool areCoincident( const Edge & rEdgeA, const Edge & rEdgeB, bool * pbCoDirectional = 0, const OdGeTol & gTol = FMGeGbl::gTol );
280  static EdgeGroup * GroupEdges( Intersector & rAI, Edge & rEdgeA, Edge & rEdgeB, bool bCoDirectional );
281 
282 
283  enum Flags {
284  efSourceReversed = 0x01,
285  efChecked = 0x02, // finality was checked
286  efHot = 0x04, // the edge is a candidate for export
287  //efDone = 0x04,
288  efFinal = 0x10,
289  efFinalReversed = 0x20,
290  efFinalDone = 0x40
291  };
292 
293  inline bool isFinal() const { return 0 != (m_uFlags & efFinal); };
294 
295  inline OdUInt32 setFlag( OdUInt32 uFlag ) { return m_uFlags |= uFlag; };
296  inline OdUInt32 unsetFlag( OdUInt32 uFlag ) { return m_uFlags &= ~uFlag; };
297  inline OdUInt32 getFlag( OdUInt32 uFlag ) const { return m_uFlags & uFlag; };
298 
299  Edge * getNextFinalRegional( bool bContoursCCW = true ) const;
300  Edge * getPrevFinalRegional( bool bContoursCCW = true ) const;
301 
302  Edge * getNextFinalLinear( bool bStopAtJunctions = false ) const;
303 
304  private:
305  Node * m_aNodes[ eNodePositions ];
306  OdUInt32 m_aIndices[ eNodePositions ];
307 
308  double m_aParams[ eNodePositions ];
309  const Contour * m_pContour;
310 
311  mutable OdGePoint2d m_ptMiddle;
312 
313  EdgeGroup * m_pEdgeGroup;
314 
315  OdUInt32 m_uFlags;
316  };
317 
318 
319  class EdgeGroup
320  {
321  public:
322  EdgeGroup( Edge * pFirstEdge, Edge * pSecondEdge = 0 );
323 
324  EdgeGroup & addEdge( Edge * pEdge );
325  EdgeGroup & merge( EdgeGroup * pGroup2 );
326 
327  inline OdUInt32 size() const { return (OdUInt32)m_vecEdges.size(); };
328  inline Edge * edge( OdUInt32 iIndex ) { return m_vecEdges[iIndex]; };
329 
330  EdgeGroup & setFlags( OdUInt32 uFlags, OdUInt32 uUnsetFirst = 0 );
331 
332  inline bool isHandled() const { return m_bHandled; };
333 
334  const OdGePoint2d& middlePoint() const;
335 
336  //EdgeGroup & sortByRegionNode();
337 
338  private:
339  std::vector< Edge * > m_vecEdges;
340  bool m_bHandled;
341  };
342 
343 
344 
345  // This interface updates final/checked flags in edges and edge groups.
347  {
348  public:
349  virtual ~IEdgeChecker() { };
350 
351  // this static method creates a new EdgeChecker, corresponding to eOp
352  // or returns 0, if the operation is not valid
354 
355  virtual Result CheckFinality( Edge & ) const = 0;
356 
357  virtual Result CheckFinality( EdgeGroup & ) const = 0;
358  };
359 
360 
361  class EdgeInfoImpl;
362 
363 
365  {
366  public:
369 
371  //
372  // Some simple user-friendly methods:
373  //
374 
375  Result Regularize( const Profile2D& rSource, Profile2D& rDest,
376  bool bValidateNesting = false,
378  const OdGeTol & gTol = FMGeGbl::gTol );
379 
380  // fills in riRegularityFlags
381  Result TestRegularity( const Profile2D& rSource,
382  int& riRegularityFlags,
383  int iInterestingFlags = erfAllFlags,
385  const OdGeTol & gTol = FMGeGbl::gTol );
386 
388  const Profile2D &rArg1,
389  const Profile2D &rArg2,
390  Profile2D &rResult,
391  const OdGeTol & gTol = FMGeGbl::gTol );
392 
394  const Profile2D& rArg1,
395  const Profile2D& rArg2,
396  Profile2D& rResult );
397 
399 
400  //Result InitOperation( OperationsExt eOper, const OdGeTol & gTol = FMGeGbl::gTol );
401 
402 
403 
405  //
406  // Low-level methods. Do not use if not sure WYAD.
407 
408 
410  // initialization
411 
412  void reset( const OdGeTol & gTol = FMGeGbl::gTol );
413 
414  void reserve( OdUInt32 uGroups, OdUInt32 uContours );
415 
416  // returns group index or OdUInt(-1)
417  OdUInt32 addGroup( Group::GroupTypes eT, OdUInt32 uPriority = 0, OdUInt32 uReservedSize = 0 );
418 
419  // add contours to some group ( Fails, if uGroup != last addGroup result !!! )
420  Result addContour( OdUInt32 uGroup, const IContour2D & rContour, bool bReversed = false, bool bForceCopy = false );
421 
422  // add profile to some group ( Fails, if uGroup != last addGroup result !!! )
423  Result addProfile( OdUInt32 uGroup, const Profile2D & rProfile, bool bReversed = false, bool bForceCopy = false );
424 
425  // tries to perform operation on existing groups/contours
426  // result is stored in member variable and can be obtained via getResult();
428 
429 
430  // Flag-setting operations.
431  // The result of this operation contains contours of the first group with
432  // some additional vertices and updated metadata.
433  // ToDo: more comments
434  Result evaluateFlags( const IFlagSetter& rFlagSetter );
435 
436 
437  // returns resulting profile from the last "evaluate"
438  // use moveResultTo instead to avoid contour copying
439  inline const Profile2D& getResult( ) const { return m_cDestProfile; };
440  inline void moveResultTo( Profile2D & rDest ) { rDest.clear(); m_cDestProfile.swap( rDest ); };
441 
443 
444  inline OdUInt32 numContours() const { return (OdUInt32)m_vecContours.size(); };
445  const Contour & getContour( OdUInt32 uContourID ) const;
446 
447  inline OdUInt32 numGroups() const { return (OdUInt32)m_vecGroups.size(); };
448  const Group & getGroup( OdUInt32 uGroupIdx ) const;
449 
450  // returns group indexes ordered by priority
452  { return iIdx; };
453 
454  inline const OdGeTol & getTol() const { return m_gTol; };
455  inline const OdGeTol & getPairTol() const { return m_gPairTol; };
456  inline const OdGeTol & getMergeTol() const { return m_gMergeTol; };
457  inline const OdGeTol & getExportTol() const { return m_gEdgeExportTol; };
458 
459  inline const IEdgeChecker & getChecker() const { return *m_pEdgeChecker; };
460 
462 
463  // adds node to Intersector`s node list
464  Node * addNode( Node * pNode );
465 
466  // adds edge to Intersector`s edge list
467  Edge * addEdge( Edge * pEdge );
468 
469  // adds edgegroup to Intersector`s edgegroup list
470  EdgeGroup * addEdgeGroup( EdgeGroup * pEdgeGroup );
471 
472  inline void setRegularityFlags( int iFlags ) { m_iRegularityFlags|=iFlags; };
473 
474  private:
475 
476  std::vector< Contour > m_vecContours;
477  std::vector< Group > m_vecGroups;
478 
479  std::vector< Node * > m_vecNodes;
480  std::vector< Edge * > m_vecEdges;
481  std::vector< EdgeGroup * > m_vecEdgeGroups;
482 
483  int m_iRegularityFlags;
484 
486  //
487  OperationsExt m_eCurrOper;
488 
489  //
490  Profile2D m_cDestProfile;
491 
492  IEdgeChecker * m_pEdgeChecker;
493 
494 
495  // tolerances
496  OdGeTol m_gTol;
497  OdGeTol m_gPairTol;
498  OdGeTol m_gMergeTol;
499  double m_dTgStep;
500  OdGeTol m_gEdgeExportTol;
501  void initTolerance ( const OdGeTol & gTol );
502 
503  // Reset all intermediate data. Keep source groups and contours
504  void resetIntermediate();
505 
506  // Reset resulting profile and operation code
507  void resetResult();
508 
509  // validates operation and groups/contours.
510  // Returns error, if the operation is not valid
511  Result validateArgs( OperationsExt eOper );
512 
514  private:
515 
516  // Stage 1: find all crossings using ContourIntersector
517  Result FindCrossings( std::vector< Crossing > & vecCrossings );
518 
519  // Stage 2: convert crossings to nodes and arrange the nodes on contours
520  Result CreateNodes( const std::vector< Crossing > & vecCrossings );
521 
522  // Stage 3: split contours into edges, connecting the nodes
523  Result CreateEdges( bool bStoreEdges = false, bool bStoreFirstGroupOnly = false );
524 
525  // Stage 4: find coincident edges and create groups
526  Result CreateEdgeGroups( );
527 
528  // Stage 5: find and verify final edges, depending on operation type
529  Result FindFinalEdges( );
530 
531  // Stage 6: create final contours from final edges
532  Result CreateFinalContours();
533 
534  Result CreateFinalContoursClosed( Profile2D & rDest, OdUInt32 & uHotID );
535  Result CreateFinalContoursOpen ( Profile2D & rDest, OdUInt32 & uHotID );
536 
537  Result GenerateFinalContour( const std::vector<Edge*> & vecEdges, IContour2D & rDestC2D, bool bClosed );
538 
539  // Stage 5F: create final contours with modified metadata
540  Result CreateFlaggedResult( const IFlagSetter& rFlagSetter );
541 
542  // remove empty/collapsed contours and improperly nested ones
543  // returns erOk or erWarn*, if some contours in the source profile should be removed
544  // pvecValid contains indexes of valid contours in the source profile
545  // the indexes are ordered by contour area (the first is the biggest)
546  // pvecResults contains status for each contour ( erOk for valid ones )
547  // Note: contours MUST NOT intersect. However, the contours can have common bounds
548  Result ValidateNesting( const Profile2D & rSource,
549  std::vector<OdUInt32> * pvecValid = 0,
550  std::vector<Result> * pvecResults = 0,
552  ) const;
553 
554  // remove empty/collapsed contours and improperly nested ones
555  // Note: contours MUST NOT intersect. However, the contours can have common bounds
556  // Note: rSource can be equal to *pDest
557  // Returns erOk, erWarnImproperAreas, erWarnSmallContour, erWarnEmptyContour or some
558  // error code.
559  Result RegularizeNesting( const Profile2D & rSource, Profile2D * pDest = 0, Profile2D * pRemoved = 0, InfinityLocation eIL = eilOutside );
560 
561  }; // class Intersector
562 
563 
564 
565 
566 }; // namespace FacetModelerProfile2DBool
567 
568 #endif //__FM_IMP_PROFILE2D_BOOL_H__
unsigned int OdUInt32
void addNode(Node *pNode, double dParam)
const IContour2D & contour2D() const
Locations getLocation(const OdGePoint2d &ptTest, const OdGeTol gTol) const
Contour(const IContour2D &rC, OdUInt32 uCID, OdUInt32 uGID, bool bReversed=false, bool bForceCopy=false)
Result createEdges(Intersector &rAI, bool bStoreEdges=false)
const std::vector< Edge * > & getEdges() const
EdgeGroup & addEdge(Edge *pEdge)
EdgeGroup & merge(EdgeGroup *pGroup2)
EdgeGroup(Edge *pFirstEdge, Edge *pSecondEdge=0)
EdgeGroup & setFlags(OdUInt32 uFlags, OdUInt32 uUnsetFirst=0)
const OdGePoint2d & middlePoint() const
double tangentAt(int ePos, double dStep) const
static EdgeGroup * GroupEdges(Intersector &rAI, Edge &rEdgeA, Edge &rEdgeB, bool bCoDirectional)
Edge * getNextFinalRegional(bool bContoursCCW=true) const
OdUInt32 getFlag(OdUInt32 uFlag) const
const Contour & contour() const
Edge(const Contour &rC, double dStartP, double dEndP)
Edge * getNextFinalLinear(bool bStopAtJunctions=false) const
Edge * getPrevFinalRegional(bool bContoursCCW=true) const
Node * anotherNode(int ePos) const
OdUInt32 setFlag(OdUInt32 uFlag)
Edge & setEdgeGroup(EdgeGroup *pGroup, OdUInt32 iIndex)
static bool areCoincident(const Edge &rEdgeA, const Edge &rEdgeB, bool *pbCoDirectional=0, const OdGeTol &gTol=FMGeGbl::gTol)
const OdGePoint2d & middlePoint() const
OdUInt32 unsetFlag(OdUInt32 uFlag)
OdUInt32 indexInNode(int ePos) const
Edge & setNode(OdUInt32 ePos, Node *pNode, OdUInt32 iIndex)
Group(Intersector &rAI, GroupTypes eT, OdUInt32 uPri, OdUInt32 uFirst=0, OdUInt32 uSize=0)
void resize(OdUInt32 uNewSize)
const IContour2D & contour(OdUInt32 uIndex) const
Locations getLocation(const OdGePoint2d &ptTest, const OdGeTol gTol) const
virtual Result CheckFinality(EdgeGroup &) const =0
virtual Result CheckFinality(Edge &) const =0
static IEdgeChecker * Create(OperationsExt eOp, Intersector &rAI)
void reserve(OdUInt32 uGroups, OdUInt32 uContours)
Result TestRegularity(const Profile2D &rSource, int &riRegularityFlags, int iInterestingFlags=erfAllFlags, InfinityLocation eIL=eilByBiggestArea, const OdGeTol &gTol=FMGeGbl::gTol)
Result evaluateFlags(const IFlagSetter &rFlagSetter)
Result Regularize(const Profile2D &rSource, Profile2D &rDest, bool bValidateNesting=false, InfinityLocation eIL=eilOutside, const OdGeTol &gTol=FMGeGbl::gTol)
Result evaluate(OperationsExt eOp)
OdUInt32 getGroupIdxByPriority(OdUInt32 iIdx) const
static bool TryFastPerformOperation(BooleanOperation eType, const Profile2D &rArg1, const Profile2D &rArg2, Profile2D &rResult)
const IEdgeChecker & getChecker() const
Result addContour(OdUInt32 uGroup, const IContour2D &rContour, bool bReversed=false, bool bForceCopy=false)
void reset(const OdGeTol &gTol=FMGeGbl::gTol)
Result addProfile(OdUInt32 uGroup, const Profile2D &rProfile, bool bReversed=false, bool bForceCopy=false)
const Contour & getContour(OdUInt32 uContourID) const
const Group & getGroup(OdUInt32 uGroupIdx) const
Result PerformOperation(BooleanOperation eType, const Profile2D &rArg1, const Profile2D &rArg2, Profile2D &rResult, const OdGeTol &gTol=FMGeGbl::gTol)
EdgeGroup * addEdgeGroup(EdgeGroup *pEdgeGroup)
OdUInt32 addGroup(Group::GroupTypes eT, OdUInt32 uPriority=0, OdUInt32 uReservedSize=0)
const EdgeLink & edgeLink(OdUInt32 iIndex) const
void addEdge(int eDir, Edge *pEdge)
Edge * findFinalRegionalNeighbour(const Edge *pEdge, EdgeDirection eEdgeDir, EdgeDirection eNeighbourDir, bool bCCW=false) const
void reverseFinalEdge(OdUInt32 iIndex)
void createEdgeGroups(Intersector &rAI)
void updateFinalEdges(bool bReorderByAngle, double dTgStep)
Edge * findFinalEdge(EdgeDirection eEdgeDir) const
std::pair< EdgeDirection, Edge * > EdgeLink
Definition: GeTol.h:49
GLfloat x
Definition: gles2_ext.h:314
GLfloat GLfloat y
Definition: gles2_ext.h:316
const T & min(const T &x, const T &y)
const T & max(const T &x, const T &y)
static FMGEOMETRY_API_STATIC OdGeTol gTol
Definition: FMGeometry.h:156