Salome HOME
fix: replace unordered_set/map with set/map
[tools/medcoupling.git] / src / INTERP_KERNEL / Geometric2D / InterpKernelGeo2DEdge.hxx
index 9bc9eff27cce51f798e609abc39d1db1d77c13f3..17f9ba9c65402a1ef9fa3d561c67d2e1f56d14f6 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2014  CEA/DEN, EDF R&D
+// Copyright (C) 2007-2024  CEA, EDF
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
@@ -25,6 +25,7 @@
 #include "InterpKernelException.hxx"
 #include "InterpKernelGeo2DBounds.hxx"
 #include "InterpKernelGeo2DNode.hxx"
+#include "MCIdType.hxx"
 
 #include <iostream>
 #include <vector>
 namespace INTERP_KERNEL
 {
   typedef enum
-    {
-      SEG         = 1,
-      ARC_CIRCLE  = 4,
-      ARC_PARABOL = 8
-    } TypeOfFunction;
+  {
+    SEG         = 1,
+    ARC_CIRCLE  = 4,
+    ARC_PARABOL = 8
+  } TypeOfFunction;
 
   typedef enum
-    {
-      CIRCLE  = 0 ,
-      PARABOL = 1
-    } TypeOfMod4QuadEdge;
+  {
+    CIRCLE  = 0 ,
+    PARABOL = 1
+  } TypeOfMod4QuadEdge;
 
   typedef enum
-    {
-      START       = 5,
-      END         = 1,
-      INSIDE      = 2,
-      OUT_BEFORE  = 3,
-      OUT_AFTER   = 4
-    } TypeOfLocInEdge; //see Edge::OFFSET_FOR_TYPEOFLOCINEDGE
-  
+  {
+    START       = 5,
+    END         = 1,
+    INSIDE      = 2,
+    OUT_BEFORE  = 3,
+    OUT_AFTER   = 4
+  } TypeOfLocInEdge; //see Edge::OFFSET_FOR_TYPEOFLOCINEDGE
+
   typedef enum
-    {
-      FULL_IN_1    = 1,
-      FULL_ON_1    = 4,
-      FULL_OUT_1   = 2,
-      FULL_UNKNOWN = 3
-    } TypeOfEdgeLocInPolygon;
+  {
+    FULL_IN_1    = 1,
+    FULL_ON_1    = 4,
+    FULL_OUT_1   = 2,
+    FULL_UNKNOWN = 3
+  } TypeOfEdgeLocInPolygon;
 
   class INTERPKERNEL_EXPORT MergePoints
   {
@@ -82,6 +83,9 @@ namespace INTERP_KERNEL
     bool isEnd2(unsigned rk) const;
     void clear();
     unsigned getNumberOfAssociations() const;
+    void updateMergedNodes(mcIdType e1Start, mcIdType e1End, mcIdType e2Start, mcIdType e2End, std::map<mcIdType,mcIdType>& mergedNodes);
+  private:
+    static void PushInMap(mcIdType key, mcIdType value, std::map<mcIdType,mcIdType>& mergedNodes);
   private:
     unsigned _ass1Start1  : 1;
     unsigned _ass1End1    : 1;
@@ -121,10 +125,10 @@ namespace INTERP_KERNEL
     Node *getNodeAndReleaseIt() { Node *tmp=_node; _node=0; return tmp; }
     ~IntersectElement();
   private:
-    bool _1S;
-    bool _1E;
-    bool _2S;
-    bool _2E;
+    bool _1S;  // true if starting point of edge 1 is located exactly on edge 2 (not nearby)
+    bool _1E;  // true if ending point of edge 1 is located exactly on edge 2 (not nearby)
+    bool _2S;  // true if starting point of edge 2 is located exactly on edge 1 (not nearby)
+    bool _2E;  // true if ending point of edge 2 is located exactly on edge 1 (not nearby)
     double _chararct_val_for_e1;
     double _chararct_val_for_e2;
     Node *_node;
@@ -143,26 +147,29 @@ namespace INTERP_KERNEL
   class INTERPKERNEL_EXPORT EdgeIntersector
   {
   protected:
-    //! All non symetric methods are relative to 'e1'.
-    EdgeIntersector(const Edge& e1, const Edge& e2):_e1(e1),_e2(e2) { }
+    //! All non symmetric methods are relative to 'e1'.
+    EdgeIntersector(const Edge& e1, const Edge& e2):_e1(e1),_e2(e2), _earlyInter(0) { }
   public:
-    virtual ~EdgeIntersector() { }
+    virtual ~EdgeIntersector() { if(_earlyInter) delete(_earlyInter); }
     virtual bool keepOrder() const = 0;
+    virtual bool areColinears() const = 0;
     //!to call only if 'areOverlapped' have been set to true when areOverlappedOrOnlyColinears was called
     virtual bool haveTheySameDirection() const = 0;
     //!to call only if 'areOverlapped' have been set to true when areOverlappedOrOnlyColinears was called
     virtual void getPlacements(Node *start, Node *end, TypeOfLocInEdge& whereStart, TypeOfLocInEdge& whereEnd, MergePoints& commonNode) const = 0;
     //! When true is returned, newNodes should contains at least 1 element. All merging nodes betw _e1 and _e2 extremities must be done.
-    bool intersect(const Bounds *whereToFind, std::vector<Node *>& newNodes, bool& order, MergePoints& commonNode);
+    bool intersect(std::vector<Node *>& newNodes, bool& order, MergePoints& commonNode);
     //! Should be called only once per association.
-    virtual void areOverlappedOrOnlyColinears(const Bounds *whereToFind, bool& obviousNoIntersection, bool& areOverlapped) = 0;
+    virtual void areOverlappedOrOnlyColinears(bool& obviousNoIntersection, bool& areOverlapped) = 0;
     //! The size of returned vector is equal to number of potential intersections point. The values are so that their are interpretable by virtual Edge::isIn method.
     virtual std::list< IntersectElement > getIntersectionsCharacteristicVal() const = 0;
   protected:
     void obviousCaseForCurvAbscisse(Node *node, TypeOfLocInEdge& where, MergePoints& commonNode, bool& obvious) const;
+    virtual void identifyEarlyIntersection(bool& , bool&, bool&, bool&);
   protected:
     const Edge& _e1;
     const Edge& _e2;
+    IntersectElement *_earlyInter;   // Non null if the intersection can be determined early -> see areOverlappedOrOnlyColinears()
   };
 
   class INTERPKERNEL_EXPORT SameTypeEdgeIntersector : public EdgeIntersector
@@ -208,6 +215,12 @@ namespace INTERP_KERNEL
     void declareOn() const;
     void declareIn() const;
     void declareOut() const;
+    void initHitStatus() const { _hit=false; }
+    bool getHitStatus() const { return _hit; }
+    void hitMeAlone(double xBary, double yBary, double dimChar) { _hit=true; applySimilarity(xBary,yBary,dimChar); }
+    void unHitMeAlone(double xBary, double yBary, double dimChar) { _hit=true; unApplySimilarity(xBary,yBary,dimChar); }
+    void hitMeAfter(double xBary, double yBary, double dimChar) { if(!_hit) hitMeAlone(xBary,yBary,dimChar); }
+    void unHitMeAfter(double xBary, double yBary, double dimChar) { if(!_hit) unHitMeAlone(xBary,yBary,dimChar); }
     const Bounds& getBounds() const { return _bounds; }
     void fillXfigStreamForLoc(std::ostream& stream) const;
     Node *getNode(TypeOfLocInEdge where) const { if(where==START) return _start; else if(where==END) return _end; else return 0; }
@@ -238,6 +251,10 @@ namespace INTERP_KERNEL
     virtual double getCurveLength() const = 0;
     virtual void getBarycenter(double *bary) const = 0;
     virtual void getBarycenterOfZone(double *bary) const = 0;
+    //! return the middle of two points
+    virtual void getMiddleOfPoints(const double *p1, const double *p2, double *mid) const = 0;
+    //! return the middle of two points respecting the orientation defined by this (relevant for arc of circle). By default same as getMiddleOfPoints()
+    virtual void getMiddleOfPointsOriented(const double *p1, const double *p2, double *mid) const;
     //! Retrieves a point that is owning to this, well placed for IN/OUT detection of this. Typically midlle of this is returned.
     virtual Node *buildRepresentantOfMySelf() const = 0;
     //! Given a magnitude specified by sub-type returns if in or not. See getCharactValue method.
@@ -262,24 +279,29 @@ namespace INTERP_KERNEL
     static void Interpolate1DLin(const std::vector<double>& distrib1, const std::vector<double>& distrib2,
                                  std::map<int, std::map<int,double> >& result);
     virtual void dumpInXfigFile(std::ostream& stream, bool direction, int resolution, const Bounds& box) const = 0;
+    void dumpToCout(const std::map<INTERP_KERNEL::Node *,int>& mapp, int index) const;
     bool isEqual(const Edge& other) const;
   public:
-    void sortIdsAbs(const std::vector<INTERP_KERNEL::Node *>& addNodes, const std::map<INTERP_KERNEL::Node *, int>& mapp1, const std::map<INTERP_KERNEL::Node *, int>& mapp2, std::vector<int>& edgesThis);
-    virtual void fillGlobalInfoAbs(bool direction, const std::map<INTERP_KERNEL::Node *,int>& mapThis, const std::map<INTERP_KERNEL::Node *,int>& mapOther, int offset1, int offset2, double fact, double baryX, double baryY,
-                                   std::vector<int>& edgesThis, std::vector<double>& addCoo, std::map<INTERP_KERNEL::Node *,int> mapAddCoo) const = 0;
-    virtual void fillGlobalInfoAbs2(const std::map<INTERP_KERNEL::Node *,int>& mapThis, const std::map<INTERP_KERNEL::Node *,int>& mapOther, int offset1, int offset2, double fact, double baryX, double baryY,
-                                    std::vector<int>& edgesOther, std::vector<double>& addCoo, std::map<INTERP_KERNEL::Node *,int>& mapAddCoo) const = 0;
+    bool sortSubNodesAbs(const double *coo, std::vector<mcIdType>& subNodes);
+    void sortIdsAbs(const std::vector<INTERP_KERNEL::Node *>& addNodes, const std::map<INTERP_KERNEL::Node *, mcIdType>& mapp1, const std::map<INTERP_KERNEL::Node *, mcIdType>& mapp2, std::vector<mcIdType>& edgesThis);
     virtual Edge *buildEdgeLyingOnMe(Node *start, Node *end, bool direction=true) const = 0;
+    void fillGlobalInfoAbs(bool direction, const std::map<INTERP_KERNEL::Node *,mcIdType>& mapThis, const std::map<INTERP_KERNEL::Node *,mcIdType>& mapOther, mcIdType offset1, mcIdType offset2, double fact, double baryX, double baryY,
+                           std::vector<mcIdType>& edgesThis, std::vector<double>& addCoo, std::map<INTERP_KERNEL::Node *,mcIdType> mapAddCoo) const;
+    void fillGlobalInfoAbs2(const std::map<INTERP_KERNEL::Node *,mcIdType>& mapThis, const std::map<INTERP_KERNEL::Node *,mcIdType>& mapOther, mcIdType offset1, mcIdType offset2, double fact, double baryX, double baryY,
+                            short skipStartOrEnd,
+                            std::vector<mcIdType>& edgesOther, std::vector<double>& addCoo, std::map<INTERP_KERNEL::Node *,mcIdType>& mapAddCoo) const;
+
   protected:
     Edge():_cnt(1),_loc(FULL_UNKNOWN),_start(0),_end(0) { }
     virtual ~Edge();
     static int CombineCodes(TypeOfLocInEdge code1, TypeOfLocInEdge code2);
-    static bool Intersect(const Edge *f1, const Edge *f2, EdgeIntersector *intersector, const Bounds *whereToFind, MergePoints& commonNode,
+    static bool Intersect(const Edge *f1, const Edge *f2, EdgeIntersector *intersector, MergePoints& commonNode,
                           ComposedEdge& outValForF1, ComposedEdge& outValForF2);
     //! The code 'code' is built by method combineCodes
     static bool SplitOverlappedEdges(const Edge *e1, const Edge *e2, Node *nS, Node *nE, bool direction, int code,
                                      ComposedEdge& outVal1, ComposedEdge& outVal2);
   protected:
+    mutable bool _hit;
     mutable unsigned char _cnt;
     mutable TypeOfEdgeLocInPolygon _loc;
     Bounds _bounds;