CFx SDK Documentation 2024 SP0
Loading...
Searching...
No Matches
FMImpProfile2DBool.h
Go to the documentation of this file.
1
2// Copyright (C) 2002-2022, 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 Open Design Alliance software pursuant to a license
16// agreement with Open Design Alliance.
17// Open Design Alliance Copyright (C) 2002-2022 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
33
35
36#include "FMContour2D.h"
37#include "FMProfile2D.h"
38
40
41using 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
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
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:
154 egtLines = 0x10,
156 egtRegion = 0x20,
160 //egtNegative = 0x80,
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
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
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
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 {
285 efChecked = 0x02, // finality was checked
286 efHot = 0x04, // the edge is a candidate for export
287 //efDone = 0x04,
288 efFinal = 0x10,
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
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
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
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 swap(Profile2D &rAnother)
void addNode(Node *pNode, double dParam)
const std::vector< Edge * > & getEdges() const
Locations getLocation(const OdGePoint2d &ptTest, const OdGeTol gTol) const
Contour(const IContour2D &rC, OdUInt32 uCID, OdUInt32 uGID, bool bReversed=false, bool bForceCopy=false)
const IContour2D & contour2D() const
Result createEdges(Intersector &rAI, bool bStoreEdges=false)
EdgeGroup(Edge *pFirstEdge, Edge *pSecondEdge=0)
EdgeGroup & setFlags(OdUInt32 uFlags, OdUInt32 uUnsetFirst=0)
EdgeGroup & merge(EdgeGroup *pGroup2)
EdgeGroup & addEdge(Edge *pEdge)
const OdGePoint2d & middlePoint() const
double tangentAt(int ePos, double dStep) const
const Contour & contour() const
OdUInt32 getFlag(OdUInt32 uFlag) const
Edge * getNextFinalRegional(bool bContoursCCW=true) const
Edge(const Contour &rC, double dStartP, double dEndP)
static EdgeGroup * GroupEdges(Intersector &rAI, Edge &rEdgeA, Edge &rEdgeB, bool bCoDirectional)
Edge * getNextFinalLinear(bool bStopAtJunctions=false) const
Edge * getPrevFinalRegional(bool bContoursCCW=true) const
const OdGePoint2d & middlePoint() const
Node * anotherNode(int ePos) const
Edge & setNode(OdUInt32 ePos, Node *pNode, OdUInt32 iIndex)
OdUInt32 setFlag(OdUInt32 uFlag)
static bool areCoincident(const Edge &rEdgeA, const Edge &rEdgeB, bool *pbCoDirectional=0, const OdGeTol &gTol=FMGeGbl::gTol)
OdUInt32 unsetFlag(OdUInt32 uFlag)
OdUInt32 indexInNode(int ePos) const
Edge & setEdgeGroup(EdgeGroup *pGroup, OdUInt32 iIndex)
Group(Intersector &rAI, GroupTypes eT, OdUInt32 uPri, OdUInt32 uFirst=0, OdUInt32 uSize=0)
const IContour2D & contour(OdUInt32 uIndex) const
void resize(OdUInt32 uNewSize)
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)
const Group & getGroup(OdUInt32 uGroupIdx) const
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)
EdgeGroup * addEdgeGroup(EdgeGroup *pEdgeGroup)
OdUInt32 getGroupIdxByPriority(OdUInt32 iIdx) const
static bool TryFastPerformOperation(BooleanOperation eType, const Profile2D &rArg1, const Profile2D &rArg2, Profile2D &rResult)
const Contour & getContour(OdUInt32 uContourID) const
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)
Result PerformOperation(BooleanOperation eType, const Profile2D &rArg1, const Profile2D &rArg2, Profile2D &rResult, const OdGeTol &gTol=FMGeGbl::gTol)
OdUInt32 addGroup(Group::GroupTypes eT, OdUInt32 uPriority=0, OdUInt32 uReservedSize=0)
const EdgeLink & edgeLink(OdUInt32 iIndex) const
void addEdge(int eDir, Edge *pEdge)
void reverseFinalEdge(OdUInt32 iIndex)
Edge * findFinalRegionalNeighbour(const Edge *pEdge, EdgeDirection eEdgeDir, EdgeDirection eNeighbourDir, bool bCCW=false) const
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:169