]> SALOME platform Git repositories - tools/medcoupling.git/commitdiff
Salome HOME
adding Anthony Geometric intepolator for arcs and edges
authorvbd <vbd>
Thu, 13 Mar 2008 10:51:01 +0000 (10:51 +0000)
committervbd <vbd>
Thu, 13 Mar 2008 10:51:01 +0000 (10:51 +0000)
37 files changed:
src/INTERP_KERNEL/Geometric2D/AbstractEdge.cxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/AbstractEdge.hxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/BasicMainTest.hxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/Bounds.cxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/Bounds.hxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/ComposedEdge.cxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/ComposedEdge.hxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/ComposedEdgeWithIt.hxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/Edge.cxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/Edge.hxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/Edge.txx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/EdgeArcCircle.cxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/EdgeArcCircle.hxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/EdgeInfLin.cxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/EdgeInfLin.hxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/EdgeLin.cxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/EdgeLin.hxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/ElementaryEdge.cxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/ElementaryEdge.hxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/Node.cxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/Node.hxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/Pol1.fig [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/Pol2.fig [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/Pol3.fig [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/Pol4.fig [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/Precision.hxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpRun.cxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest.cxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest.hxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest2.cxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest3.cxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest4.cxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/QuadraticPolygon.cxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/QuadraticPolygon.hxx [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/README [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/TODO [new file with mode: 0644]
src/INTERP_KERNEL/Geometric2D/UnitTestsResult.hxx [new file with mode: 0644]

diff --git a/src/INTERP_KERNEL/Geometric2D/AbstractEdge.cxx b/src/INTERP_KERNEL/Geometric2D/AbstractEdge.cxx
new file mode 100644 (file)
index 0000000..6bd3112
--- /dev/null
@@ -0,0 +1,180 @@
+#include "AbstractEdge.hxx"
+#include "ComposedEdge.hxx"
+#include "ElementaryEdge.hxx"
+
+using namespace INTERP_KERNEL;
+
+IteratorOnComposedEdge::IteratorOnComposedEdge(ComposedEdge *cont):_container(cont) 
+{
+  first(); 
+}
+
+void IteratorOnComposedEdge::operator=(const IteratorOnComposedEdge& other)
+{
+  _container=other._container;
+  for(ItOnFixdLev it=0;it<MAX_INTERSCT_DEPH;it++)
+    _current[it]=other._current[it];
+}
+
+void IteratorOnComposedEdge::last()
+{
+  ItOnFixdLev delta=1;
+  _container->getLastElementary(delta);
+  _current[0]=delta;
+  AbstractEdge *cur=_container;
+  for(ItOnFixdLev it=1;it<=delta;it++)
+    {
+      _current[it]=cur->size()-1;
+      cur=(AbstractEdge *)(*cur)[cur->size()-1];
+    }
+}
+
+void IteratorOnComposedEdge::first()
+{
+  _current[0]=1;
+  _current[1]=0;
+}
+
+void IteratorOnComposedEdge::next()
+{
+  updateNumbering();
+  bool levelToIncr=false;
+  do
+    {
+      if(getLowestDealing()->size()-1>_current[_current[0]])
+        {
+          _current[_current[0]]++;
+          levelToIncr=true;
+        }
+      else
+       _current[0]--;
+    }
+  while(_current[0]!=0 && !levelToIncr);
+  if(levelToIncr)
+    updateNumbering();
+}
+
+void IteratorOnComposedEdge::nextLoop()
+{
+  updateNumbering();
+  bool levelToIncr=false;
+  do
+    {
+      if(getLowestDealing()->size()-1>_current[_current[0]])
+        {
+          _current[_current[0]]++;
+          levelToIncr=true;
+        }
+      else
+       _current[0]--;
+    }
+  while(_current[0]!=0 && !levelToIncr);
+  if(levelToIncr)
+    updateNumbering();
+  else
+    first();
+}
+
+void IteratorOnComposedEdge::previousLoop()
+{
+  bool levelToIncr=false;
+  do
+    {
+      if(_current[_current[0]]>0)
+        {
+          _current[_current[0]]--;
+          levelToIncr=true;
+         ItOnFixdLev delta=0;
+         AbstractEdge *curLevel=getLowestDealing();
+          AbstractEdge *coarseElem=(*curLevel)[_current[_current[0]]];
+          if(dynamic_cast<ComposedEdge *>(coarseElem))
+            {
+              ((ComposedEdge *)coarseElem)->getLastElementary(++delta);
+              for(ItOnFixdLev it=1;it<=delta;it++)
+                {
+                  _current[_current[0]+it]=coarseElem->size()-1;
+                  curLevel=(AbstractEdge *)(*coarseElem)[coarseElem->size()-1];
+                }
+              _current[0]+=delta;
+            }
+        }
+      else
+       _current[0]--;
+    }
+  while(_current[0]!=0 && !levelToIncr);
+  if(!levelToIncr)
+    last();
+}
+
+bool IteratorOnComposedEdge::finished() const
+{
+  return _current[0]==0;
+}
+
+AbstractEdge *IteratorOnComposedEdge::currentDirect() const
+{
+  return (AbstractEdge *)(*getLowestDealing())[_current[_current[0]]];
+}
+
+ElementaryEdge* &IteratorOnComposedEdge::updateNumbering()
+{
+  ItOnFixdLev delta=0;
+  AbstractEdge *& valToTest=(*getLowestDealing())[_current[_current[0]]];
+  ElementaryEdge **ret;
+  if(dynamic_cast<ElementaryEdge *>(valToTest))
+    ret=(ElementaryEdge **)&valToTest;
+  else
+    ret=&(valToTest->getFirstElementary(++delta));
+  if(delta==0)
+    return *ret;
+  else
+    {
+      for(ItOnFixdLev it=1;it<=delta;it++)
+        _current[_current[0]+it]=0;
+      _current[0]+=delta;
+    }
+  return *ret;
+}
+
+AbstractEdge *IteratorOnComposedEdge::getLowestDealing() const
+{
+  if(_current[0]==0)
+    return 0;
+  AbstractEdge *ret=(AbstractEdge *)_container;
+  for(ItOnFixdLev iter=1;iter<_current[0];iter++)
+    ret=(AbstractEdge *)(*ret)[_current[iter]];
+  return ret;
+}
+
+bool IteratorOnComposedEdge::goToNextInOn(bool direction, int& i, int nbMax)
+{
+  TypeOfEdgeLocInPolygon loc=current()->getLoc();
+  if(direction)
+    {
+      while(loc==FULL_OUT_1 && i<nbMax)
+        {
+          nextLoop(); i++;
+          loc=current()->getLoc();
+        }
+      if(i==nbMax)
+        return false;
+      return true;
+    }
+  else
+    {
+      while(loc==FULL_OUT_1 && i<nbMax)
+        {
+          previousLoop(); i++;
+          loc=current()->getLoc();
+        }
+      if(i==nbMax)
+        return false;
+      while(loc!=FULL_OUT_1 && i<nbMax)
+        {
+          previousLoop(); i++;
+          loc=current()->getLoc();
+        }
+      nextLoop(); i--;
+      return true;
+    }
+}
diff --git a/src/INTERP_KERNEL/Geometric2D/AbstractEdge.hxx b/src/INTERP_KERNEL/Geometric2D/AbstractEdge.hxx
new file mode 100644 (file)
index 0000000..a30eaf2
--- /dev/null
@@ -0,0 +1,76 @@
+#ifndef __ABSTRACTEDGE_HXX__
+#define __ABSTRACTEDGE_HXX__
+
+#include <set>
+#include <fstream>
+
+namespace INTERP_KERNEL
+{
+  class Edge;
+  class Node;
+  class Bounds;
+
+  class AbstractEdge;
+  class ComposedEdge;
+  class ElementaryEdge;
+
+  class IteratorOnComposedEdge
+  {
+    friend class AbstractEdge;
+    friend class ComposedEdge;
+    friend class ElementaryEdge;
+    friend class QuadraticPolygon;
+    //! Implicitely we suppose here that at maximum we have 256 edges on a current level.
+    typedef unsigned char ItOnFixdLev;
+  public:
+    IteratorOnComposedEdge(ComposedEdge *cont);
+    void operator=(const IteratorOnComposedEdge& other);
+    void first();
+    void next();
+    void last();
+    void nextLoop();
+    void previousLoop();
+    bool finished() const;
+    AbstractEdge *getLowestDealing() const;
+    bool goToNextInOn(bool direction, int& i, int nbMax);
+    ElementaryEdge * &current() { return updateNumbering(); }
+    AbstractEdge *currentDirect() const;
+  private:
+    ElementaryEdge* &updateNumbering();
+  private:
+    //! this number (+1) represents the maximum intersection an edge is going to have.
+    static const unsigned MAX_INTERSCT_DEPH=8;
+    ComposedEdge *_container;
+    mutable ItOnFixdLev _current[MAX_INTERSCT_DEPH];
+  };
+
+  class AbstractEdge
+  {
+  public:
+    virtual ~AbstractEdge() { }
+    virtual int size() const = 0;
+    virtual void reverse() = 0;
+    virtual bool completed() const = 0;
+    virtual int recursiveSize() const = 0;
+    virtual AbstractEdge *clone() const = 0;
+    virtual bool isNodeIn(Node *n) const = 0;
+    virtual double getAreaOfZone() const = 0;
+    virtual void fillBounds(Bounds& output) const = 0;
+    virtual void getAllNodes(std::set<Node *>& output) const = 0;
+    virtual ElementaryEdge* &getLastElementary(IteratorOnComposedEdge::ItOnFixdLev &delta) = 0;
+    virtual ElementaryEdge* &getFirstElementary(IteratorOnComposedEdge::ItOnFixdLev &delta) = 0;
+    virtual const AbstractEdge *&operator[](IteratorOnComposedEdge::ItOnFixdLev i) const = 0;
+    virtual AbstractEdge *&operator[](IteratorOnComposedEdge::ItOnFixdLev i) = 0;
+    virtual Node *getEndNode() const = 0;
+    virtual Node *getStartNode() const = 0;
+    virtual bool changeStartNodeWith(Node *node) const = 0;
+    virtual bool changeEndNodeWith(Node *node) const = 0;
+    virtual void dumpInXfigFile(std::ostream& stream) const = 0;
+    virtual bool intresicEqual(const AbstractEdge *other) const = 0;
+    virtual bool intresicEqualDirSensitive(const AbstractEdge *other) const = 0;
+    virtual bool intresincEqCoarse(const Edge *other) const = 0;
+    virtual bool getDirection() const = 0;
+  };
+}
+
+#endif
diff --git a/src/INTERP_KERNEL/Geometric2D/BasicMainTest.hxx b/src/INTERP_KERNEL/Geometric2D/BasicMainTest.hxx
new file mode 100644 (file)
index 0000000..99bc937
--- /dev/null
@@ -0,0 +1,96 @@
+// Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either 
+// version 2.1 of the License.
+// 
+// This library is distributed in the hope that it will be useful 
+// but WITHOUT ANY WARRANTY; without even the implied warranty of 
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public  
+// License along with this library; if not, write to the Free Software 
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+#ifndef _BASICMAINTEST_HXX_
+#define _BASICMAINTEST_HXX_
+
+#include <cppunit/CompilerOutputter.h>
+#include <cppunit/TestResult.h>
+#include <cppunit/TestResultCollector.h>
+#include <cppunit/TextTestProgressListener.h>
+#include <cppunit/BriefTestProgressListener.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/TestRunner.h>
+#include <cppunit/TextTestRunner.h>
+#include <stdexcept>
+
+#include <iostream>
+#include <fstream>
+#include <stdlib.h>
+
+// ============================================================================
+/*!
+ *  Main program source for Unit Tests with cppunit package does not depend
+ *  on actual tests, so we use the same for all partial unit tests.
+ */
+// ============================================================================
+
+#include "UnitTestsResult.hxx"
+
+int main(int argc, char* argv[])
+{
+  // --- Create the event manager and test controller
+  CPPUNIT_NS::TestResult controller;
+
+  // ---  Add a listener that collects test result
+  CPPUNIT_NS::TestResultCollector result;
+  controller.addListener( &result );        
+
+  // ---  Add a listener that print dots as test run.
+#ifdef WIN32
+  CPPUNIT_NS::TextTestProgressListener progress;
+#else
+  CPPUNIT_NS::BriefTestProgressListener progress;
+#endif
+  controller.addListener( &progress );      
+
+  // ---  Get the top level suite from the registry
+
+  CPPUNIT_NS::Test *suite =
+    CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest();
+
+  // ---  Adds the test to the list of test to run
+
+  CPPUNIT_NS::TestRunner runner;
+  //CPPUNIT_NS::TextTestRunner runner;
+  runner.addTest( suite );
+  runner.run( controller);
+  //bool wasSucessful = runner.run();
+
+  // ---  Print test in a compiler compatible format.
+
+  system("mkdir -p /tmp/${USER}");
+  std::ofstream testFile;
+  testFile.open(INTERP_KERNEL::UnitTestsResult.c_str(), std::ios::out | std::ios::app);
+  testFile << UNIT_TEST_HEADER << std::endl;
+  //CPPUNIT_NS::CompilerOutputter outputter( &result, std::cerr );
+  CPPUNIT_NS::CompilerOutputter outputter( &result, testFile );
+  outputter.write(); 
+
+  // ---  Run the tests.
+
+  bool wasSucessful = result.wasSuccessful();
+  testFile.close();
+
+  // ---  Return error code 1 if the one of test failed.
+
+  return wasSucessful ? 0 : 1;
+}
+
+#endif
diff --git a/src/INTERP_KERNEL/Geometric2D/Bounds.cxx b/src/INTERP_KERNEL/Geometric2D/Bounds.cxx
new file mode 100644 (file)
index 0000000..0d4f284
--- /dev/null
@@ -0,0 +1,112 @@
+#include "Bounds.hxx"
+#include "Exception.hxx"
+#include "Node.hxx"
+
+#include <cmath>
+
+using namespace INTERP_KERNEL;
+
+const double& Bounds::operator[](int i) const
+{
+  switch(i)
+    {
+    case 0:
+      return _xMin;
+    case 1:
+      return _xMax;
+    case 2:
+      return _yMin;
+    case 3:
+      return _yMax;
+    }
+  throw Exception("internal error occurs !");
+}
+
+double &Bounds::operator[](int i)
+{
+  switch(i)
+    {
+    case 0:
+      return _xMin;
+    case 1:
+      return _xMax;
+    case 2:
+      return _yMin;
+    case 3:
+      return _yMax;
+    }
+  throw Exception("internal error occurs !");
+}
+
+void Bounds::prepareForAggregation()
+{
+  _xMin=1e200; _xMax=-1e200; _yMin=1e200; _yMax=-1e200;
+}
+
+Bounds *Bounds::nearlyAmIIntersectingWith(const Bounds& other) const
+{
+  if( (other._xMin > _xMax+QUADRATIC_PLANAR::_precision) || (other._xMax < _xMin-QUADRATIC_PLANAR::_precision) || (other._yMin > _yMax+QUADRATIC_PLANAR::_precision) 
+      || (other._yMax < _yMin-QUADRATIC_PLANAR::_precision) )
+    return 0;
+  if( (other._xMin >= _xMax ) || (other._xMax <= _xMin) || (other._yMin >= _yMax) || (other._yMax <= _yMin) )
+    return new Bounds(fmax(_xMin-QUADRATIC_PLANAR::_precision,other._xMin),
+                      fmin(_xMax+QUADRATIC_PLANAR::_precision,other._xMax),
+                      fmax(_yMin-QUADRATIC_PLANAR::_precision,other._yMin),
+                      fmin(_yMax+QUADRATIC_PLANAR::_precision,other._yMax));//In approx cases.
+  else
+    return new Bounds(fmax(_xMin,other._xMin),fmin(_xMax,other._xMax),fmax(_yMin,other._yMin),fmin(_yMax,other._yMax));
+}
+
+Bounds *Bounds::amIIntersectingWith(const Bounds& other) const
+{
+  if( (other._xMin > _xMax) || (other._xMax < _xMin) || (other._yMin > _yMax) || (other._yMax < _yMin) )
+    return 0;
+  return new Bounds(fmax(_xMin,other._xMin),fmin(_xMax,other._xMax),fmax(_yMin,other._yMin),fmin(_yMax,other._yMax));
+}
+
+Position Bounds::where(double x, double y) const
+{
+  if((x>=_xMin && x<=_xMax) && (y>=_yMin && y<=_yMax))
+    return IN;
+  else
+    return OUT;
+}
+
+Position Bounds::nearlyWhere(double x, double y) const
+{
+  bool thinX=Node::areDoubleEquals(_xMin,_xMax);
+  bool thinY=Node::areDoubleEquals(_yMin,_yMax);
+  if(!thinX)
+    {
+      if(Node::areDoubleEquals(x,_xMin) || Node::areDoubleEquals(x,_xMax) && (y<_yMax+QUADRATIC_PLANAR::_precision) && (y>_yMin-QUADRATIC_PLANAR::_precision))
+        return ON_BOUNDARY_POS;
+    }
+  else
+    if(!Node::areDoubleEquals(_xMin,x) && !Node::areDoubleEquals(_xMax,x))
+      return OUT;
+  if(!thinY)
+    {
+      if(Node::areDoubleEquals(y,_yMin) || Node::areDoubleEquals(y,_yMax) && (x<_xMax+QUADRATIC_PLANAR::_precision) && (x>_xMin-QUADRATIC_PLANAR::_precision))
+        return ON_BOUNDARY_POS;
+    }
+  else
+    if(!Node::areDoubleEquals(_yMin,y) && !Node::areDoubleEquals(_yMax,y))
+      return OUT;
+  if(thinX && thinY)
+    return ON_BOUNDARY_POS;
+  if((x>=_xMin && x<=_xMax) && (y>=_yMin && y<=_yMax))
+    return IN;
+  else
+    return OUT;
+}
+
+void Bounds::aggregate(const Bounds& other)
+{
+  _xMin=fmin(_xMin,other._xMin); _xMax=fmax(_xMax,other._xMax);
+  _yMin=fmin(_yMin,other._yMin); _yMax=fmax(_yMax,other._yMax);
+}
+
+double Bounds::getCaracteristicDim() const
+{
+  return fmax(_xMax-_xMin,_yMax-_yMin);
+}
diff --git a/src/INTERP_KERNEL/Geometric2D/Bounds.hxx b/src/INTERP_KERNEL/Geometric2D/Bounds.hxx
new file mode 100644 (file)
index 0000000..89ccf82
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef __BOUNDS_HXX__
+#define __BOUNDS_HXX__
+
+namespace INTERP_KERNEL
+{
+  /*!
+   * Relative LOC
+   */
+  typedef enum
+    {
+      IN              = 0,
+      OUT             = 1,
+      ON_BOUNDARY_POS = 2,
+      ON_BOUNDARY_NEG = 3
+    } Position;
+  
+  class Bounds
+  {
+  public:
+    Bounds():_xMin(0),_xMax(0.),_yMin(0.),_yMax(0.) { }
+    double &operator[](int i);
+    const double& operator[](int i) const;
+    Bounds& operator=(const Bounds& other) { _xMin=other._xMin; _xMax=other._xMax; _yMin=other._yMin; _yMax=other._yMax; return *this; }
+    Bounds(double xMin, double xMax, double yMin, double yMax):_xMin(xMin),_xMax(xMax),_yMin(yMin),_yMax(yMax) { }
+    void setValues(double xMin, double xMax, double yMin, double yMax) { _xMin=xMin; _xMax=xMax; _yMin=yMin; _yMax=yMax; }
+    void prepareForAggregation();
+    Bounds *nearlyAmIIntersectingWith(const Bounds& other) const;
+    Bounds *amIIntersectingWith(const Bounds& other) const;
+    //! No approximations.
+    Position where(double x, double y) const;
+    //! Idem where method but with approximations.
+    Position nearlyWhere(double x, double y) const;
+    void aggregate(const Bounds& other);
+    double getCaracteristicDim() const;
+  protected:
+    double _xMin;
+    double _xMax;
+    double _yMin;
+    double _yMax;
+  };
+}
+
+#endif
diff --git a/src/INTERP_KERNEL/Geometric2D/ComposedEdge.cxx b/src/INTERP_KERNEL/Geometric2D/ComposedEdge.cxx
new file mode 100644 (file)
index 0000000..205fb82
--- /dev/null
@@ -0,0 +1,317 @@
+#include "ComposedEdge.hxx"
+#include "ElementaryEdge.hxx"
+#include "EdgeInfLin.hxx"
+#include "Exception.hxx"
+
+#include <algorithm>
+#include <iterator>
+#include <set>
+
+using namespace std;
+using namespace INTERP_KERNEL;
+
+ComposedEdge::ComposedEdge(const ComposedEdge& other)
+{
+  _subEdges.resize(other._subEdges.size());
+  int i=0;
+  for(vector<AbstractEdge *>::const_iterator iter=other._subEdges.begin();iter!=other._subEdges.end();iter++,i++)
+    _subEdges[i]=(*iter)->clone();
+}
+
+ComposedEdge::~ComposedEdge()
+{
+  clearAll(_subEdges.begin());
+}
+
+ElementaryEdge* &ComposedEdge::getLastElementary(IteratorOnComposedEdge::ItOnFixdLev &delta)
+{
+  AbstractEdge *e=_subEdges.back();
+  ElementaryEdge *eCast=dynamic_cast< ElementaryEdge* >(e);
+  if(eCast)
+    return (ElementaryEdge* &)((AbstractEdge * &) _subEdges.back());
+  delta++;
+  return _subEdges.back()->getLastElementary(delta);
+}
+
+ElementaryEdge* &ComposedEdge::getFirstElementary(IteratorOnComposedEdge::ItOnFixdLev &delta)
+{
+  AbstractEdge *e=_subEdges.front();
+  ElementaryEdge *eCast=dynamic_cast< ElementaryEdge* >(e);
+  if(eCast)
+    return (ElementaryEdge* &)((AbstractEdge * &) _subEdges.front());
+  delta++;
+  return _subEdges.front()->getFirstElementary(delta);
+}
+
+void ComposedEdge::setValueAt(int i, Edge *e, bool direction)
+{
+  delete _subEdges[i];
+  _subEdges[i]=new ElementaryEdge(e,direction);
+}
+
+void ComposedEdge::clear()
+{
+  clearAll(_subEdges.begin());
+  _subEdges.clear();
+}
+
+void ComposedEdge::pushBack(Edge *edge, bool direction)
+{
+  _subEdges.push_back(new ElementaryEdge(edge,direction));
+}
+
+void ComposedEdge::pushBack(AbstractEdge *elem)
+{
+  _subEdges.push_back(elem);
+}
+
+void ComposedEdge::reverse()
+{
+  std::reverse(_subEdges.begin(),_subEdges.end());
+  for(vector<AbstractEdge *>::iterator iter=_subEdges.begin();iter!=_subEdges.end();iter++)
+    (*iter)->reverse();
+}
+
+int ComposedEdge::recursiveSize() const
+{
+  int ret=0;
+  for(vector<AbstractEdge *>::const_iterator iter=_subEdges.begin();iter!=_subEdges.end();iter++)
+    {
+      ret+=(*iter)->recursiveSize();
+    }
+  return ret;
+}
+
+AbstractEdge *ComposedEdge::clone() const
+{
+  return new ComposedEdge(*this);
+}
+
+bool ComposedEdge::isNodeIn(Node *n) const
+{
+  bool ret=false;
+  for(std::vector<AbstractEdge *>::const_iterator iter=_subEdges.begin();iter!=_subEdges.end() && !ret;iter++)
+    ret=(*iter)->isNodeIn(n);
+  return ret;
+}
+
+double ComposedEdge::getAreaOfZone() const
+{
+  double ret=0.;
+  for(std::vector<AbstractEdge *>::const_iterator iter=_subEdges.begin();iter!=_subEdges.end();iter++)
+    ret+=(*iter)->getAreaOfZone();
+  return ret;
+}
+
+void ComposedEdge::dumpInXfigFile(std::ostream& stream) const
+{
+  for(std::vector<AbstractEdge *>::const_iterator iter=_subEdges.begin();iter!=_subEdges.end();iter++)
+    (*iter)->dumpInXfigFile(stream);
+}
+
+Node *ComposedEdge::getEndNode() const
+{
+  return _subEdges.back()->getEndNode();
+}
+
+Node *ComposedEdge::getStartNode() const
+{
+  return _subEdges.front()->getStartNode();
+}
+
+AbstractEdge *ComposedEdge::simplify()
+{
+  if(size()!=1)
+    return this;
+  else
+    {
+      vector<AbstractEdge *>::iterator iter=_subEdges.begin();
+      AbstractEdge *ret=*iter; iter++;
+      clearAll(iter);
+      _subEdges.clear();
+      delete this;
+      return ret;
+    }
+}
+
+/*!
+ * This method adds edge to this is it edge is localized as IN or ON.
+ * The returned value is true if this is not empty and that edge is not IN or ON.
+ */
+bool ComposedEdge::addEdgeIfIn(ElementaryEdge *edge)
+{
+  if(edge->getLoc()!=FULL_OUT_1)
+    {
+      _subEdges.push_back(edge->clone());
+      return false;
+    }
+  else if(!empty())
+    {
+      return true;
+    }
+  return false;
+}
+
+bool ComposedEdge::changeEndNodeWith(Node *node) const
+{
+  return _subEdges.back()->changeEndNodeWith(node);
+}
+
+bool ComposedEdge::changeStartNodeWith(Node *node) const
+{
+  return _subEdges.front()->changeStartNodeWith(node);
+}
+
+bool ComposedEdge::intresicEqual(const AbstractEdge *other) const
+{
+  throw Exception("ComposedEdge::intresicEqual : should never been called.");
+}
+
+bool ComposedEdge::intresicEqualDirSensitive(const AbstractEdge *other) const
+{
+  throw Exception("ComposedEdge::intresicEqualDirSensitive : should never been called.");
+}
+
+void ComposedEdge::fillBounds(Bounds& output) const
+{
+  vector<AbstractEdge *>::const_iterator iter=_subEdges.begin();
+  for(;iter!=_subEdges.end();iter++)
+    (*iter)->fillBounds(output);
+}
+
+void ComposedEdge::getAllNodes(std::set<Node *>& output) const
+{
+  vector<AbstractEdge *>::const_iterator iter=_subEdges.begin();
+  for(;iter!=_subEdges.end();iter++)
+    (*iter)->getAllNodes(output);
+}
+
+bool ComposedEdge::isInOrOut(Node *nodeToTest) const
+{
+  Bounds b; b.prepareForAggregation();
+  fillBounds(b);
+  if(b.nearlyWhere((*nodeToTest)[0],(*nodeToTest)[1])==OUT)
+    return false;
+  // searching for e1
+  set<Node *> nodes;
+  getAllNodes(nodes);
+  set<double> radialDistributionOfNodes;
+  set<Node *>::const_iterator iter;
+  for(iter=nodes.begin();iter!=nodes.end();iter++)
+    radialDistributionOfNodes.insert(nodeToTest->getSlope(*(*iter)));
+  vector<double> radialDistrib(radialDistributionOfNodes.begin(),radialDistributionOfNodes.end());
+  radialDistributionOfNodes.clear();
+  vector<double> radialDistrib2(radialDistrib.size());
+  copy(radialDistrib.begin()+1,radialDistrib.end(),radialDistrib2.begin());
+  radialDistrib2.back()=M_PI+radialDistrib.front();
+  vector<double> radialDistrib3(radialDistrib.size());
+  transform(radialDistrib2.begin(),radialDistrib2.end(),radialDistrib.begin(),radialDistrib3.begin(),minus<double>());
+  vector<double>::iterator iter3=max_element(radialDistrib3.begin(),radialDistrib3.end());
+  int i=iter3-radialDistrib3.begin();
+  // ok for e1 - Let's go.
+  EdgeInfLin *e1=new EdgeInfLin(nodeToTest,radialDistrib[i]+radialDistrib3[i]/2.);
+  double ref=e1->getCharactValue(*nodeToTest);
+  set< IntersectElement > inOutSwitch;
+  for(vector<AbstractEdge *>::const_iterator iter=_subEdges.begin();iter!=_subEdges.end();iter++)
+    {
+      ElementaryEdge *val=dynamic_cast<ElementaryEdge *>(*iter);
+      if(val)
+        {
+          Edge *e=val->getPtr();
+          auto_ptr<Intersector> intersc(Edge::buildIntersectorWith(e1,e));
+          bool obviousNoIntersection,areOverlapped;
+          intersc->areOverlappedOrOnlyColinears(0,obviousNoIntersection,areOverlapped);
+          if(obviousNoIntersection)
+            {
+              continue;
+            }
+          if(!areOverlapped)
+            {
+              list< IntersectElement > listOfIntesc=intersc->getIntersectionsCharacteristicVal();
+              for(list< IntersectElement >::iterator iter2=listOfIntesc.begin();iter2!=listOfIntesc.end();iter2++)
+                if((*iter2).isIncludedByBoth())
+                  inOutSwitch.insert(*iter2);
+              }
+          //if overlapped we can forget
+        }
+      else
+        throw Exception("Invalid use of ComposedEdge::isInOrOut : only one level supported !");
+    }
+  e1->decrRef();
+  bool ret=false;
+  for(set< IntersectElement >::iterator iter=inOutSwitch.begin();iter!=inOutSwitch.end();iter++)
+    {
+      if((*iter).getVal1()<ref)
+        {
+          if((*iter).getNodeOnly()->getLoc()==ON_1)
+            ret=!ret;
+        }
+      else
+        break;
+    }
+  return ret;
+}
+
+/*bool ComposedEdge::isInOrOut(Node *aNodeOn, Node *nodeToTest) const
+{
+  
+  EdgeInfLin *e1=new EdgeInfLin(aNodeOn,nodeToTest);
+  double ref=e1->getCharactValue(*nodeToTest);
+  set< IntersectElement > inOutSwitch;
+  for(vector<AbstractEdge *>::const_iterator iter=_subEdges.begin();iter!=_subEdges.end();iter++)
+    {
+      ElementaryEdge *val=dynamic_cast<ElementaryEdge *>(*iter);
+      if(val)
+        {
+          Edge *e=val->getPtr();
+          auto_ptr<Intersector> intersc(Edge::buildIntersectorWith(e1,e));
+          bool obviousNoIntersection,areOverlapped;
+          intersc->areOverlappedOrOnlyColinears(0,obviousNoIntersection,areOverlapped);
+          if(obviousNoIntersection)
+            {
+              continue;
+            }
+          if(!areOverlapped)
+            {
+              list< IntersectElement > listOfIntesc=intersc->getIntersectionsCharacteristicVal();
+              for(list< IntersectElement >::iterator iter2=listOfIntesc.begin();iter2!=listOfIntesc.end();iter2++)
+                if((*iter2).isIncludedByBoth())
+                  inOutSwitch.insert(*iter2);
+              }
+          //if overlapped we can forget
+        }
+      else
+        throw Exception("Invalid use of ComposedEdge::isInOrOut : only one level supported !");
+    }
+  e1->decrRef();
+  bool ret=false;
+  for(set< IntersectElement >::iterator iter=inOutSwitch.begin();iter!=inOutSwitch.end();iter++)
+    {
+      if((*iter).getVal1()<ref)
+        {
+          if((*iter).getNodeOnly()->getLoc()==ON_1)
+            ret=!ret;
+        }
+      else
+        break;
+    }
+  return ret;
+}*/
+
+bool ComposedEdge::getDirection() const
+{
+  throw Exception("ComposedEdge::getDirection : no sense");
+}
+
+bool ComposedEdge::intresincEqCoarse(const Edge *other) const
+{
+  if(_subEdges.size()!=1)
+    return false;
+  return _subEdges.front()->intresincEqCoarse(other);
+}
+
+void ComposedEdge::clearAll(vector<AbstractEdge *>::iterator startToDel)
+{
+  for(vector<AbstractEdge *>::iterator iter=startToDel;iter!=_subEdges.end();iter++)
+    delete (*iter);
+}
diff --git a/src/INTERP_KERNEL/Geometric2D/ComposedEdge.hxx b/src/INTERP_KERNEL/Geometric2D/ComposedEdge.hxx
new file mode 100644 (file)
index 0000000..60c93e1
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef __COMPOSEDNODE_HXX__
+#define __COMPOSEDNODE_HXX__
+
+#include "AbstractEdge.hxx"
+
+#include <vector>
+
+namespace INTERP_KERNEL
+{
+  class ComposedEdge : public AbstractEdge
+  {
+  public:
+    ComposedEdge() { }
+    ComposedEdge(const ComposedEdge& other);
+    ComposedEdge(int size):_subEdges(size) { }
+    static void Delete(ComposedEdge *pt) { delete pt; }
+    void reverse();
+    int recursiveSize() const;
+    AbstractEdge *clone() const;
+    bool isNodeIn(Node *n) const;
+    double getAreaOfZone() const;
+    void fillBounds(Bounds& output) const;
+    void getAllNodes(std::set<Node *>& output) const;
+    bool completed() const { return getEndNode()==getStartNode(); }
+    ElementaryEdge * &getLastElementary(IteratorOnComposedEdge::ItOnFixdLev &delta);
+    ElementaryEdge * &getFirstElementary(IteratorOnComposedEdge::ItOnFixdLev &delta);
+    void setValueAt(int i, AbstractEdge *val) { delete _subEdges[i]; _subEdges[i]=val; }
+    void setValueAt(int i, Edge *e, bool direction=true);
+    void clear();
+    bool empty() const { return _subEdges.empty(); }
+    AbstractEdge *front() const { return _subEdges.front(); }
+    AbstractEdge *back() const { return _subEdges.back(); }
+    void resize(int i) { _subEdges.resize(i); }
+    void pushBack(Edge *edge, bool direction=true);
+    void pushBack(AbstractEdge *elem);
+    int size() const { return _subEdges.size(); }
+    AbstractEdge *&operator[](IteratorOnComposedEdge::ItOnFixdLev i) { return (AbstractEdge *&)_subEdges[i]; }
+    const AbstractEdge *&operator[](IteratorOnComposedEdge::ItOnFixdLev i) const { return (const AbstractEdge *&)_subEdges[i]; }
+    Node *getEndNode() const;
+    Node *getStartNode() const;
+    AbstractEdge *simplify();
+    bool addEdgeIfIn(ElementaryEdge *edge);
+    bool changeEndNodeWith(Node *node) const;
+    bool changeStartNodeWith(Node *node) const;
+    void dumpInXfigFile(std::ostream& stream) const;
+    bool intresicEqual(const AbstractEdge *other) const;
+    bool intresicEqualDirSensitive(const AbstractEdge *other) const;
+    bool isInOrOut(Node *nodeToTest) const;
+    bool getDirection() const;
+    bool intresincEqCoarse(const Edge *other) const;
+  protected:
+    ~ComposedEdge();
+  private:
+    void clearAll(std::vector<AbstractEdge *>::iterator startToDel);
+  protected:
+    std::vector<AbstractEdge *> _subEdges;
+  };
+}
+
+#endif
diff --git a/src/INTERP_KERNEL/Geometric2D/ComposedEdgeWithIt.hxx b/src/INTERP_KERNEL/Geometric2D/ComposedEdgeWithIt.hxx
new file mode 100644 (file)
index 0000000..ff31eb1
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __COMPOSEDNODEWITHIT_HXX__
+#define __COMPOSEDNODEWITHIT_HXX__
+
+#include "ComposedEdge.hxx"
+
+#include <vector>
+
+namespace INTERP_KERNEL
+{
+  class ComposedEdgeWithIt : public ComposedEdge
+  {
+  public:
+    ComposedEdgeWithIt():_iterator(this) { }
+    const IteratorOnComposedEdge& getIterator() const { return _iterator; }
+    void setIterator(const IteratorOnComposedEdge& it) { _iterator=it; }
+  protected:
+    IteratorOnComposedEdge _iterator;
+  };
+}
+
+#endif
diff --git a/src/INTERP_KERNEL/Geometric2D/Edge.cxx b/src/INTERP_KERNEL/Geometric2D/Edge.cxx
new file mode 100644 (file)
index 0000000..81cff38
--- /dev/null
@@ -0,0 +1,715 @@
+#include "Edge.hxx"
+#include "EdgeLin.hxx"
+#include "EdgeInfLin.hxx"
+//#include "EdgeParabol.hxx"
+#include "EdgeArcCircle.hxx"
+#include "Exception.hxx"
+
+using namespace std;
+using namespace INTERP_KERNEL;
+
+MergePoints::MergePoints():_ass1Start1(0),_ass1End1(0),_ass1Start2(0),_ass1End2(0),
+                           _ass2Start1(0),_ass2End1(0),_ass2Start2(0),_ass2End2(0)
+{
+}
+
+void MergePoints::start1Replaced()
+{
+  unsigned nbOfAsso=getNumberOfAssociations();
+  if(nbOfAsso==0)
+    _ass1Start1=1;
+  else
+    _ass2Start1=1;
+}
+
+void MergePoints::end1Replaced()
+{
+  unsigned nbOfAsso=getNumberOfAssociations();
+  if(nbOfAsso==0)
+    _ass1End1=1;
+  else
+    _ass2End1=1;
+}
+
+void MergePoints::start1OnStart2()
+{
+  unsigned nbOfAsso=getNumberOfAssociations();
+  if(nbOfAsso==0)
+    {
+      _ass1Start1=1;
+      _ass1Start2=1;
+    }
+  else
+    {
+      _ass2Start1=1;
+      _ass2Start2=1;
+    }
+}
+
+void MergePoints::start1OnEnd2()
+{
+  unsigned nbOfAsso=getNumberOfAssociations();
+  if(nbOfAsso==0)
+    {
+      _ass1Start1=1;
+      _ass1End2=1;
+    }
+  else
+    {
+      _ass2Start1=1;
+      _ass2End2=1;
+    }
+}
+
+void MergePoints::end1OnStart2()
+{
+  unsigned nbOfAsso=getNumberOfAssociations();
+  if(nbOfAsso==0)
+    {
+      _ass1End1=1;
+      _ass1Start2=1;
+    }
+  else
+    {
+      _ass2End1=1;
+      _ass2Start2=1;
+    }
+}
+
+void MergePoints::end1OnEnd2()
+{
+  unsigned nbOfAsso=getNumberOfAssociations();
+  if(nbOfAsso==0)
+    {
+      _ass1End1=1;
+      _ass1End2=1;
+    }
+  else
+    {
+      _ass2End1=1;
+      _ass2End2=1;
+    }
+}
+
+bool MergePoints::isStart1(unsigned rk) const
+{
+  if(rk==0)
+    return _ass1Start1;
+  else
+    return _ass2Start1;
+}
+
+bool MergePoints::isEnd1(unsigned rk) const
+{
+  if(rk==0)
+    return _ass1End1;
+  else
+    return _ass2End1;
+}
+
+bool MergePoints::isStart2(unsigned rk) const
+{
+  if(rk==0)
+    return _ass1Start2;
+  else
+    return _ass2Start2;
+}
+
+bool MergePoints::isEnd2(unsigned rk) const
+{
+  if(rk==0)
+    return _ass1End2;
+  else
+    return _ass2End2;
+}
+
+void MergePoints::clear()
+{
+  _ass1Start1=0;_ass1End1=0;_ass1Start2=0;_ass1End2=0;
+  _ass2Start1=0;_ass2End1=0;_ass2Start2=0;_ass2End2=0;
+}
+
+unsigned MergePoints::getNumberOfAssociations() const
+{
+  unsigned ret=0;
+  unsigned subTot=_ass1Start1+_ass1End1+_ass1Start2+_ass1End2;
+  if(subTot!=0)
+    ret++;
+  subTot=_ass2Start1+_ass2End1+_ass2Start2+_ass2End2;
+  if(subTot!=0)
+    ret++;
+  return ret;
+}
+
+IntersectElement::IntersectElement(double val1, double val2, bool start1, bool end1, bool start2, bool end2, Node *node
+                                   , const Edge& e1, const Edge& e2, bool keepOrder):_1S(keepOrder?start1:start2),
+                                                                                     _1E(keepOrder?end1:end2),
+                                                                                     _2S(keepOrder?start2:start1),
+                                                                                     _2E(keepOrder?end2:end1),
+                                                                                     _chararctValForE1(keepOrder?val1:val2),
+                                                                                     _chararctValForE2(keepOrder?val2:val1),
+                                                                                     _node(node),_e1(keepOrder?e1:e2),
+                                                                                     _e2(keepOrder?e2:e1)
+{
+}
+
+IntersectElement::IntersectElement(const IntersectElement& other):_1S(other._1S),_1E(other._1E),_2S(other._2S),_2E(other._2E),
+                                                                  _chararctValForE1(other._chararctValForE1),
+                                                                  _chararctValForE2(other._chararctValForE2),_node(other._node),
+                                                                  _e1(other._e1), _e2(other._e2)
+{
+  if(_node)
+    _node->incrRef();
+}
+
+IntersectElement& IntersectElement::operator=(const IntersectElement& other)
+{
+  _1S=other._1S;_1E=other._1E; _2S=other._2S; _2E=other._2E;
+  _chararctValForE1=other._chararctValForE1;
+  _chararctValForE2=other._chararctValForE2;
+  setNode(other._node);
+  return *this;
+}
+
+bool IntersectElement::operator<(const IntersectElement& other) const
+{
+  return _e1.isLower(_chararctValForE1,other._chararctValForE1);
+}
+
+IntersectElement::~IntersectElement()
+{
+  if(_node)
+    _node->decrRef();
+}
+
+/*!
+ * Returns 0 or 1.
+ */
+bool IntersectElement::isOnMergedExtremity() const
+{
+  if( (_1S && _2S) || (_1S && _2E) || (_1E && _2S) || (_1E && _2E) )
+    return true;
+  return false;
+}
+
+/*!
+ * To call if isOnMergedExtremity returned true.
+ */
+void IntersectElement::performMerging(MergePoints& commonNode) const
+{
+  if(_1S && _2S)
+    {
+      if(_e1.changeStartNodeWith(_e2.getStartNode()))
+        {
+          _e2.getStartNode()->declareOnLim();
+          commonNode.start1OnStart2();
+        }
+    }
+  else if(_1S && _2E)
+    {
+      if(_e1.changeStartNodeWith(_e2.getEndNode()))
+        {
+          _e2.getEndNode()->declareOnLim();
+          commonNode.start1OnEnd2();
+        }
+    }
+  else if(_1E && _2S)
+    {
+      if(_e1.changeEndNodeWith(_e2.getStartNode()))
+        {
+          _e2.getStartNode()->declareOnLim();
+          commonNode.end1OnStart2();
+        }
+    }
+  else if(_1E && _2E)
+    {
+      if(_e1.changeEndNodeWith(_e2.getEndNode()))
+        {
+          _e2.getEndNode()->declareOnLim();
+          commonNode.end1OnEnd2();
+        }
+    }
+}
+
+/*!
+ * This methode is const because 'node' is supposed to be equal geomitrically to _node.
+ */
+void IntersectElement::setNode(Node *node) const
+{
+  if(node!=_node)
+    {
+      if(_node)
+        ((Node *)_node)->decrRef();
+      ((IntersectElement *)(this))->_node=node;
+      if(_node)
+        _node->incrRef();
+    }
+}
+
+bool IntersectElement::isLowerOnOther(const IntersectElement& other) const
+{
+  return _e2.isLower(_chararctValForE2,other._chararctValForE2);
+}
+
+unsigned IntersectElement::isOnExtrForAnEdgeAndInForOtherEdge() const
+{
+  if(( _1S && !(_2S || _2E) ) || ( _1E && !(_2S || _2E) ))
+    {
+      if(_1S && !(_2S || _2E))
+        setNode(_e1.getStartNode());
+      else
+        setNode(_e1.getEndNode());
+      if(_e2.isIn(_chararctValForE2))
+        return LIMIT_ON;
+      return LIMIT_ALONE;
+    }
+  if(( _2S && !(_1S || _1E) ) || ( _2E && !(_1S || _1E)))
+    {
+      if(_2S && !(_1S || _1E))
+        setNode(_e2.getStartNode());
+      else
+        setNode(_e2.getEndNode());
+      if(_e1.isIn(_chararctValForE1))
+        return LIMIT_ON;
+      return LIMIT_ALONE;
+    }
+  return NO_LIMIT;
+}
+
+bool IntersectElement::isIncludedByBoth() const
+{
+  return _e1.isIn(_chararctValForE1) && _e2.isIn(_chararctValForE2);
+}
+  
+bool Intersector::intersect(const Bounds *whereToFind, std::vector<Node *>& newNodes, bool& order, MergePoints& commonNode)
+{
+  list< IntersectElement > listOfIntesc=getIntersectionsCharacteristicVal();
+  list< IntersectElement >::iterator iter;
+  for(iter=listOfIntesc.begin();iter!=listOfIntesc.end();)
+    {
+      if((*iter).isOnMergedExtremity())
+        {
+          (*iter).performMerging(commonNode);
+          iter=listOfIntesc.erase(iter);
+          continue;
+        }
+      unsigned tmp=(*iter).isOnExtrForAnEdgeAndInForOtherEdge();
+      if(tmp==IntersectElement::LIMIT_ALONE)
+        {
+          iter=listOfIntesc.erase(iter);
+          continue;
+        }
+      else if(tmp==IntersectElement::LIMIT_ON)
+        {
+         iter++;
+         continue;
+       }
+      if(!(*iter).isIncludedByBoth())
+        {
+          iter=listOfIntesc.erase(iter);
+          continue;
+        }
+      iter++;
+    }
+  if(listOfIntesc.size()==0)
+    return false;
+  if(listOfIntesc.size()==1)
+    {
+      order=true;//useless
+      newNodes.push_back(listOfIntesc.front().getNodeAndReleaseIt());
+    }
+  else
+    {
+      vector<IntersectElement> vecOfIntesc(listOfIntesc.begin(),listOfIntesc.end());
+      listOfIntesc.clear();
+      sort(vecOfIntesc.begin(),vecOfIntesc.end());
+      for(vector<IntersectElement>::iterator iterV=vecOfIntesc.begin();iterV!=vecOfIntesc.end();iterV++)
+        newNodes.push_back((*iterV).getNodeAndReleaseIt());
+      order=vecOfIntesc.front().isLowerOnOther(vecOfIntesc.back());
+    }
+  return true;
+}
+
+void Intersector::obviousCaseForCurvAbscisse(Node *node, TypeOfLocInEdge& where, MergePoints& commonNode, bool& obvious) const
+{
+  obvious=true;
+  if(node->isEqual(*_e1.getStartNode()))
+    {
+      where=START;
+      if(_e1.changeStartNodeWith(node))
+       {
+         commonNode.start1Replaced();
+         node->declareOnLim();
+       }
+      return ;
+    }
+  if(node->isEqual(*_e1.getEndNode()))
+    {
+      where=END;
+      if(_e1.changeEndNodeWith(node))
+       {
+         commonNode.end1Replaced();
+         node->declareOnLim();
+       }
+      return ;
+    }
+  obvious=false;
+}
+
+Edge::Edge(double sX, double sY, double eX, double eY):_cnt(1),_loc(FULL_UNKNOWN),_start(new Node(sX,sY)),_end(new Node(eX,eY))
+{
+}
+
+Edge::~Edge()
+{
+  _start->decrRef();
+  if(_end)
+    _end->decrRef();
+}
+
+bool Edge::decrRef()
+{
+  bool ret=(--_cnt==0);
+  if(ret)
+    delete this;
+  return ret;
+}
+
+void Edge::declareOn() const
+{
+  if(_loc==FULL_UNKNOWN)
+    {
+      _loc=FULL_ON_1;
+      _start->declareOn();
+      _end->declareOn();
+    }
+}
+
+void Edge::declareIn() const
+{
+  if(_loc==FULL_UNKNOWN)
+    {
+      _loc=FULL_IN_1;
+      _start->declareIn();
+      _end->declareIn();
+    }
+}
+
+void Edge::declareOut() const
+{
+  if(_loc==FULL_UNKNOWN)
+    {
+      _loc=FULL_OUT_1;
+      _start->declareOut();
+      _end->declareOut();
+    }
+}
+
+void Edge::fillXfigStreamForLoc(std::ostream& stream) const
+{
+  switch(_loc)
+    {
+    case FULL_IN_1:
+      stream << '2';//Green
+      break;
+    case FULL_OUT_1:
+      stream << '1';//Bleue
+      break;
+    case FULL_ON_1:
+      stream << '4';//Red
+      break;
+    default:
+      stream << '0';
+    }
+}
+
+bool Edge::changeStartNodeWith(Node *otherStartNode) const
+{
+  if(_start==otherStartNode)
+    return true;
+  if(_start->isEqual(*otherStartNode))
+    {
+      (((Edge *)this)->_start)->decrRef();//un-const cast Ok thanks to 2 lines above.
+      (((Edge *)this)->_start)=otherStartNode;
+      _start->incrRef();
+      return true;
+    }
+  return false;
+}
+
+bool Edge::changeStartNodeWithAndKeepTrack(Node *otherStartNode, std::vector<Node *>& track) const
+{
+  if(_start==otherStartNode)
+    return true;
+  if(_start->isEqualAndKeepTrack(*otherStartNode,track))
+    {
+      (((Edge *)this)->_start)->decrRef();//un-const cast Ok thanks to 2 lines above.
+      (((Edge *)this)->_start)=otherStartNode;
+      otherStartNode->incrRef();
+      return true;
+    }
+  return false;
+}
+
+bool Edge::changeEndNodeWith(Node *otherEndNode) const
+{
+  if(_end==otherEndNode)
+    return true;
+  if(_end->isEqual(*otherEndNode))
+    {
+      (((Edge *)this)->_end)->decrRef();
+      (((Edge *)this)->_end)=otherEndNode;
+      _end->incrRef();
+      return true;
+    }
+  return false;
+}
+
+bool Edge::changeEndNodeWithAndKeepTrack(Node *otherEndNode, std::vector<Node *>& track) const
+{
+  if(_end==otherEndNode)
+    return true;
+  if(_end->isEqualAndKeepTrack(*otherEndNode,track))
+    {
+      (((Edge *)this)->_end)->decrRef();
+      (((Edge *)this)->_end)=otherEndNode;
+      otherEndNode->incrRef();
+      return true;
+    }
+  return false;
+}
+
+/*!
+ * Precondition : 'start' and 'end' are lying on the same curve than 'this'.
+ * Add in vec the sub edge lying on this.
+ * If 'start' is equal (by pointer) to '_end' and 'end' is equal to '_end' too nothing is added.
+ * If 'start' is equal (by pointer) to '_start' and 'end' is equal to '_start' too nothing is added.
+ * If 'start' is equal (by pointer) to '_start' and 'end' is equal to '_end' this is added in vec.
+ */
+void Edge::addSubEdgeInVector(Node *start, Node *end, ComposedEdge& vec) const
+{
+  if((start==_start && end==_start) || (start==_end && end==_end))
+    return ;
+  if(start==_start && end==_end)
+    {
+      incrRef();
+      vec.pushBack((Edge *)this);
+      return ;
+    }
+  vec.pushBack(buildEdgeLyingOnMe(start,end,true));
+}
+
+Edge *Edge::buildEdgeFrom(Node *start, Node *end)
+{
+  return new EdgeLin(start,end);
+}
+
+Edge *Edge::buildFromXfigLine(std::istream& str)
+{
+  unsigned char type;
+  str >> type;
+  if(type=='2')
+    return new EdgeLin(str);
+  else if(type=='5')
+    return new EdgeArcCircle(str);
+  else
+    {
+      std::cerr << "Unknown line found...";
+      return 0;
+    }
+}
+
+/*!
+ * \param other The Edge with which we are going to intersect.
+ * \param commonNode Output. The common nodes found during operation of intersecting.
+ * \param outVal1 Output filled in case true is returned. It specifies the new or not new edges by which 'this' is replaced after intersecting op.
+ * \param outVal2 Output filled in case true is returned. It specifies the new or not new edges by which 'other' is replaced after intersecting op.
+ * return true if the intersection between this.
+ */
+bool Edge::intersectWith(const Edge *other, MergePoints& commonNode,
+                         ComposedEdge& outVal1, ComposedEdge& outVal2) const
+{
+  bool ret=true;
+  Bounds *merge=_bounds.nearlyAmIIntersectingWith(other->getBounds());
+  if(!merge)
+    return false;
+  delete merge;
+  merge=0;
+  Intersector *intersector=buildIntersectorWith(this,other);
+  ret=intersect(this,other,intersector,merge,commonNode,outVal1,outVal2);
+  delete intersector;
+  return ret;
+}
+
+Intersector *Edge::buildIntersectorWith(const Edge *e1, const Edge *e2)
+{
+  Intersector *ret=0;
+  const EdgeLin *tmp1=0;
+  const EdgeArcCircle *tmp2=0;
+  unsigned char type1=e1->getTypeOfFunc();
+  e1->dynCastFunction(tmp1,tmp2);
+  unsigned char type2=e2->getTypeOfFunc();
+  e2->dynCastFunction(tmp1,tmp2);
+  type1|=type2;
+  switch(type1)
+    {
+    case 1:// Intersection seg/seg
+      ret=new SegSegIntersector((const EdgeLin &)(*e1),(const EdgeLin &)(*e2));
+      break;
+    case 5:// Intersection seg/arc of circle
+      ret=new ArcCSegIntersector(*tmp2,*tmp1,tmp2==e1);
+      break;
+    case 4:// Intersection arc/arc of circle
+      ret=new ArcCArcCIntersector((const EdgeArcCircle &)(*e1),(const EdgeArcCircle &)(*e2));
+      break;
+    default:
+      //Should never happen
+      throw Exception("A non managed association of edge has been detected. Go work for intersection computation implementation.");
+    }
+  return ret;
+}
+
+bool Edge::intersect(const Edge *f1, const Edge *f2, Intersector *intersector, const Bounds *whereToFind, MergePoints& commonNode,
+                     ComposedEdge& outValForF1, ComposedEdge& outValForF2)
+{
+  bool obviousNoIntersection;
+  bool areOverlapped;
+  intersector->areOverlappedOrOnlyColinears(whereToFind,obviousNoIntersection,areOverlapped);
+  if(areOverlapped)
+    {
+      bool rev=intersector->haveTheySameDirection();
+      Node *f2Start=f2->getNode(rev?START:END);
+      Node *f2End=f2->getNode(rev?END:START);
+      TypeOfLocInEdge place1, place2;
+      intersector->getPlacements(f2Start,f2End,place1,place2,commonNode);
+      int codeForIntersectionCase=combineCodes(place1,place2);
+      return splitOverlappedEdges(f1,f2,f2Start,f2End,rev,codeForIntersectionCase,outValForF1,outValForF2);
+    }
+  if(obviousNoIntersection)
+    return false;
+  vector<Node *> newNodes;
+  bool order;
+  if(intersector->intersect(whereToFind,newNodes,order,commonNode))
+    {
+      if(newNodes.empty())
+        throw Exception("Internal error occured - error in intersector implementation!");// This case should never happen
+      vector<Node *>::iterator iter=newNodes.begin();
+      vector<Node *>::reverse_iterator iterR=newNodes.rbegin();
+      f1->addSubEdgeInVector(f1->getStartNode(),*iter,outValForF1);
+      f2->addSubEdgeInVector(f2->getStartNode(),*iter,outValForF2);
+      for(vector<Node *>::iterator iter=newNodes.begin();iter!=newNodes.end();iter++,iterR++)
+        {
+          if((iter+1)==newNodes.end())
+            {
+              f1->addSubEdgeInVector(*iter,f1->getEndNode(),outValForF1);
+              (*iter)->decrRef();
+              f2->addSubEdgeInVector(order?*iter:*iterR,f2->getEndNode(),outValForF2);
+            }
+          else
+            {
+              f1->addSubEdgeInVector(*iter,*(iter+1),outValForF1);
+              (*iter)->decrRef();
+              f2->addSubEdgeInVector(order?*iter:*iterR,order?*(iter+1):*(iterR+1),outValForF2);
+            }
+        }
+      return true;
+    }
+  else//no intersection inside whereToFind
+    return false;
+}
+
+int Edge::combineCodes(TypeOfLocInEdge code1, TypeOfLocInEdge code2)
+{
+  int ret=(int)code1;
+  ret*=OFFSET_FOR_TYPEOFLOCINEDGE;
+  ret+=(int)code2;
+  return ret;
+}
+
+/*!
+ * This method splits e1 and e2 into pieces as much sharable as possible. The precondition to the call of this method
+ * is that e1 and e2 have been declared as overlapped by corresponding intersector built from e1 and e2 type.
+ *
+ * @param nS start node of e2 with the SAME DIRECTION as e1. The pointer nS should be equal to start node of e2 or to its end node.
+ * @param nE end node of e2 with the SAME DIRECTION as e1. The pointer nE should be equal to start node of e2 or to its end node.
+ * @param direction is param that specifies if e2 and e1 have same directions (true) or opposed (false).
+ * @param code is the code returned by method Edge::combineCodes.
+ */
+bool Edge::splitOverlappedEdges(const Edge *e1, const Edge *e2, Node *nS, Node *nE, bool direction, int code,
+                                ComposedEdge& outVal1, ComposedEdge& outVal2)
+{
+  Edge *tmp;
+  switch(code)
+    {
+    case OUT_BEFORE*OFFSET_FOR_TYPEOFLOCINEDGE+START:      // OUT_BEFORE - START
+    case OUT_BEFORE*OFFSET_FOR_TYPEOFLOCINEDGE+OUT_BEFORE: // OUT_BEFORE - OUT_BEFORE
+    case OUT_AFTER*OFFSET_FOR_TYPEOFLOCINEDGE+OUT_AFTER:   // OUT_AFTER - OUT_AFTER
+    case END*OFFSET_FOR_TYPEOFLOCINEDGE+OUT_AFTER:         // END - OUT_AFTER
+      return false;
+    case INSIDE*OFFSET_FOR_TYPEOFLOCINEDGE+OUT_AFTER:      // INSIDE - OUT_AFTER
+      outVal1.pushBack(e1->buildEdgeLyingOnMe(e1->getStartNode(),nS,true));
+      tmp=e1->buildEdgeLyingOnMe(nS,e1->getEndNode()); tmp->incrRef();
+      outVal1.pushBack(tmp);
+      outVal2.resize(2);
+      outVal2.setValueAt(direction?0:1,tmp,direction); tmp->declareOn();
+      outVal2.setValueAt(direction?1:0,e1->buildEdgeLyingOnMe(e1->getEndNode(),nE,direction));
+      return true;
+    case INSIDE*OFFSET_FOR_TYPEOFLOCINEDGE+INSIDE:         // INSIDE - INSIDE
+      e2->incrRef(); e2->incrRef();
+      outVal1.resize(3);
+      outVal1.setValueAt(0,e1->buildEdgeLyingOnMe(e1->getStartNode(),nS));
+      outVal1.setValueAt(1,(Edge*)e2,direction);
+      outVal1.setValueAt(2,e1->buildEdgeLyingOnMe(nE,e1->getEndNode()));
+      outVal2.pushBack((Edge*)e2); e2->declareOn();
+      return true;
+    case OUT_BEFORE*OFFSET_FOR_TYPEOFLOCINEDGE+INSIDE:     // OUT_BEFORE - INSIDE
+      tmp=e1->buildEdgeLyingOnMe(e1->getStartNode(),nE); tmp->incrRef();
+      outVal1.pushBack(tmp);
+      outVal1.pushBack(e1->buildEdgeLyingOnMe(nE,e1->getEndNode()));
+      outVal2.resize(2);
+      outVal2.setValueAt(direction?0:1,e1->buildEdgeLyingOnMe(nS,e1->getStartNode(),direction));
+      outVal2.setValueAt(direction?1:0,tmp,direction); tmp->declareOn();
+      return true;
+    case OUT_BEFORE*OFFSET_FOR_TYPEOFLOCINEDGE+OUT_AFTER:  // OUT_BEFORE - OUT_AFTER
+      e1->incrRef(); e1->incrRef();
+      outVal1.pushBack((Edge*)e1);
+      outVal2.resize(3);
+      outVal2.setValueAt(direction?0:2,e1->buildEdgeLyingOnMe(nS,e1->getStartNode(),direction));
+      outVal2.setValueAt(1,(Edge*)e1,direction); e1->declareOn();
+      outVal2.setValueAt(direction?2:0,e1->buildEdgeLyingOnMe(e1->getEndNode(),nE,direction));
+      return true;
+    case START*OFFSET_FOR_TYPEOFLOCINEDGE+END:             // START - END
+      e1->incrRef(); e1->incrRef();
+      outVal1.pushBack((Edge*)e1);
+      outVal2.pushBack((Edge*)e1,direction); e1->declareOn();
+      return true;
+    case START*OFFSET_FOR_TYPEOFLOCINEDGE+OUT_AFTER:       // START - OUT_AFTER
+      e1->incrRef(); e1->incrRef();
+      outVal1.pushBack((Edge*)e1);
+      outVal2.resize(2);
+      outVal2.setValueAt(direction?0:1,(Edge*)e1,direction); e1->declareOn();
+      outVal2.setValueAt(direction?1:0,e1->buildEdgeLyingOnMe(e1->getEndNode(),nE,direction));
+      return true;
+    case INSIDE*OFFSET_FOR_TYPEOFLOCINEDGE+END:            // INSIDE - END
+      e2->incrRef(); e2->incrRef();
+      outVal1.pushBack(e1->buildEdgeLyingOnMe(e1->getStartNode(),nS,true));
+      outVal1.pushBack((Edge*)e2,direction);
+      outVal2.pushBack((Edge*)e2); e2->declareOn();
+      return true;
+    case OUT_BEFORE*OFFSET_FOR_TYPEOFLOCINEDGE+END:        // OUT_BEFORE - END
+      e1->incrRef(); e1->incrRef();
+      outVal1.pushBack((Edge*)e1);
+      outVal2.resize(2);
+      outVal2.setValueAt(direction?0:1,e1->buildEdgeLyingOnMe(nS,e1->getStartNode(),direction));
+      outVal2.setValueAt(direction?1:0,(Edge*)e1,direction); e1->declareOn();
+      return true;
+    case START*OFFSET_FOR_TYPEOFLOCINEDGE+INSIDE:          // START - INSIDE
+      e2->incrRef(); e2->incrRef();
+      outVal1.pushBack((Edge*)e2,direction);
+      outVal1.pushBack(e1->buildEdgeLyingOnMe(nE,e1->getEndNode()));
+      outVal2.pushBack((Edge*)e2); e2->declareOn();
+      return true;
+    default:
+      throw Exception("Unexpected situation of overlapping edges : internal error occurs ! ");
+    }
+}
diff --git a/src/INTERP_KERNEL/Geometric2D/Edge.hxx b/src/INTERP_KERNEL/Geometric2D/Edge.hxx
new file mode 100644 (file)
index 0000000..b73c86d
--- /dev/null
@@ -0,0 +1,227 @@
+#ifndef __EDGE_HXX__
+#define __EDGE_HXX__
+
+#include "ComposedEdge.hxx"
+#include "Exception.hxx"
+#include "Bounds.hxx"
+#include "Node.hxx"
+
+#include <iostream>
+#include <vector>
+#include <list>
+
+namespace INTERP_KERNEL
+{
+  typedef enum
+    {
+      SEG         = 1,
+      ARC_CIRCLE  = 4,
+      ARC_PARABOL = 8
+    } TypeOfFunction;
+
+  typedef enum
+    {
+      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
+  
+  typedef enum
+    {
+      FULL_IN_1    = 1,
+      FULL_ON_1    = 4,
+      FULL_OUT_1   = 2,
+      FULL_UNKNOWN = 3
+    } TypeOfEdgeLocInPolygon;
+
+  class MergePoints
+  {
+  public:
+    MergePoints();
+    //methods called during intersection edge-edge
+    void start1Replaced();
+    void end1Replaced();
+    void start1OnStart2();
+    void start1OnEnd2();
+    void end1OnStart2();
+    void end1OnEnd2();
+    //methods to be called during aggregation
+    bool isStart1(unsigned rk) const;
+    bool isEnd1(unsigned rk) const;
+    bool isStart2(unsigned rk) const;
+    bool isEnd2(unsigned rk) const;
+    void clear();
+    unsigned getNumberOfAssociations() const;
+  private:
+    unsigned _ass1Start1  : 1;
+    unsigned _ass1End1    : 1;
+    unsigned _ass1Start2  : 1;
+    unsigned _ass1End2    : 1;
+    unsigned _ass2Start1  : 1;
+    unsigned _ass2End1    : 1;
+    unsigned _ass2Start2  : 1;
+    unsigned _ass2End2    : 1;
+  };
+
+  class IntersectElement
+  {
+  public:
+    IntersectElement(double val1, double val2, bool start1, bool end1, bool start2, bool end2, Node *node, const Edge& e1, const Edge& e2, bool keepOrder);
+    IntersectElement(const IntersectElement& other);
+    bool operator<(const IntersectElement& other) const;
+    IntersectElement& operator=(const IntersectElement& other);
+    double getVal1() const { return _chararctValForE1; }
+    double getVal2() const { return _chararctValForE2; }
+    bool isLowerOnOther(const IntersectElement& other) const;
+    unsigned isOnExtrForAnEdgeAndInForOtherEdge() const;
+    bool isOnMergedExtremity() const;
+    bool isIncludedByBoth() const;
+    void setNode(Node *node) const;
+    void performMerging(MergePoints& commonNode) const;
+    Node *getNodeOnly() const { return _node; }
+    Node *getNodeAndReleaseIt() { Node *tmp=_node; _node=0; return tmp; }
+    ~IntersectElement();
+  private:
+    bool _1S;
+    bool _1E;
+    bool _2S;
+    bool _2E;
+    double _chararctValForE1;
+    double _chararctValForE2;
+    Node *_node;
+    const Edge& _e1;
+    const Edge& _e2;
+  public:
+    static const unsigned LIMIT_ALONE = 22;
+    static const unsigned LIMIT_ON = 73;
+    static const unsigned NO_LIMIT = 19;
+  };
+
+  class Intersector
+  {
+  protected:
+    //! All non symetric methods are relative to 'e1'.
+    Intersector(const Edge& e1, const Edge& e2):_e1(e1),_e2(e2) { }
+  public:
+    virtual bool keepOrder() 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);
+    //! Should be called only once per association.
+    virtual void areOverlappedOrOnlyColinears(const Bounds *whereToFind, 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;
+  protected:
+    const Edge& _e1;
+    const Edge& _e2;
+  };
+
+  class SameTypeIntersector : public Intersector
+  {
+  protected:
+    SameTypeIntersector(const Edge& e1, const Edge& e2):Intersector(e1,e2) { }
+    bool keepOrder() const { return true; }
+  };
+
+  class CrossTypeIntersector : public Intersector
+  {
+  protected:
+    CrossTypeIntersector(const Edge& e1, const Edge& e2, bool reverse):Intersector(e1,e2),_reverse(reverse) { }
+    bool keepOrder() const { return _reverse; }
+    bool haveTheySameDirection() const { throw Exception("Cross type intersector is not supposed to deal with overlapped in cross type."); }
+    const Edge *myE1() { if(_reverse) return &_e1; else return &_e2; }
+    const Edge *myE2() { if(_reverse) return &_e2; else return &_e1; }
+  protected:
+    //! boolean to inform intersector that unsymetrics treatments reverse of e1 and e2 should be done.
+    bool _reverse;
+  };
+
+  class EdgeLin;
+  class EdgeInfLin;
+  class EdgeArcCircle;
+
+  /*!
+   * Deal with an oriented edge of a polygon.
+   */
+  class Edge
+  {
+  public:
+    Edge(Node *start, Node *end, bool direction=true):_cnt(1),_loc(FULL_UNKNOWN) { if(direction) { _start=start; _end=end; } else { _start=end; _end=start; } _start->incrRef(); _end->incrRef(); }
+    Edge(double sX, double sY, double eX, double eY);
+    TypeOfEdgeLocInPolygon getLoc() const { return _loc; }
+    void incrRef() const { _cnt++; }
+    bool decrRef();
+    void declareOn() const;
+    void declareIn() const;
+    void declareOut() const;
+    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; }
+    Node *getStartNode() const { return _start; }
+    Node *getEndNode() const { return _end; }
+    void setEndNodeWithoutChange(Node *newEnd);
+    void setStartNodeWithoutChange(Node *newStart);
+    bool changeStartNodeWith(Node *otherStartNode) const;
+    bool changeStartNodeWithAndKeepTrack(Node *otherStartNode, std::vector<Node *>& track) const;
+    bool changeEndNodeWith(Node *otherEndNode) const;
+    bool changeEndNodeWithAndKeepTrack(Node *otherEndNode, std::vector<Node *>& track) const;
+    void addSubEdgeInVector(Node *start, Node *end, ComposedEdge& vec) const;
+    static Intersector *buildIntersectorWith(const Edge *e1, const Edge *e2);
+    static Edge *buildFromXfigLine(std::istream& str);
+    static Edge *buildEdgeFrom(Node *start, Node *end);
+    template<TypeOfMod4QuadEdge type>
+    static Edge *buildEdgeFrom(Node *start, Node *middle, Node *end);
+    virtual void update(Node *m) = 0;
+    //! returns area between this and axe Ox delimited along Ox by _start and _end.
+    virtual double getAreaOfZone() const = 0;
+    virtual double getCurveLength() const = 0;
+    //! 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.
+    virtual bool isIn(double characterVal) const = 0;
+    //! With the same magnitude as defined in 'isIn' method perform a compararison. Precondition : val1 and val2 are different and exactly INSIDE this.
+    virtual bool isLower(double val1, double val2) const = 0;
+    //! node is expected to lay on 'this'. It returns a characteristic magnitude usable by isIn method.
+    virtual double getCharactValue(const Node& node) const = 0;
+    virtual TypeOfFunction getTypeOfFunc() const = 0;
+    virtual Edge *buildEdgeLyingOnMe(Node *start, Node *end, bool direction=true) const = 0;
+    virtual void dynCastFunction(const EdgeLin * &seg,
+                                 const EdgeArcCircle * &arcSeg) const = 0;
+    bool intersectWith(const Edge *other, MergePoints& commonNode,
+                       ComposedEdge& outVal1, ComposedEdge& outVal2) const;
+    virtual void dumpInXfigFile(std::ostream& stream, bool direction) const = 0;
+  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, Intersector *intersector, const Bounds *whereToFind, 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 unsigned char _cnt;
+    mutable TypeOfEdgeLocInPolygon _loc;
+    Bounds _bounds;
+    Node *_start;
+    Node *_end;
+  protected:
+    //In relation with max possible value of TypeOfLocInEdge.
+    static const int OFFSET_FOR_TYPEOFLOCINEDGE = 8;
+  };
+}
+
+#endif
diff --git a/src/INTERP_KERNEL/Geometric2D/Edge.txx b/src/INTERP_KERNEL/Geometric2D/Edge.txx
new file mode 100644 (file)
index 0000000..4b1477c
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __EDGE_TXX__
+#define __EDGE_TXX__
+
+#include "EdgeArcCircle.hxx"
+
+template<INTERP_KERNEL::TypeOfMod4QuadEdge type>
+INTERP_KERNEL::Edge *INTERP_KERNEL::Edge::buildEdgeFrom(Node *start, Node *middle, Node *end)
+{
+  return new INTERP_KERNEL::EdgeArcCircle(start,middle,end);
+}
+
+#endif
diff --git a/src/INTERP_KERNEL/Geometric2D/EdgeArcCircle.cxx b/src/INTERP_KERNEL/Geometric2D/EdgeArcCircle.cxx
new file mode 100644 (file)
index 0000000..d3937bb
--- /dev/null
@@ -0,0 +1,471 @@
+#include "EdgeArcCircle.hxx"
+#include "EdgeLin.hxx"
+#include "Exception.hxx"
+#include "Node.hxx"
+
+#include <sstream>
+
+using namespace std;
+using namespace INTERP_KERNEL;
+
+ArcCArcCIntersector::ArcCArcCIntersector(const EdgeArcCircle& e1, const EdgeArcCircle& e2):SameTypeIntersector(e1,e2),_dist(0.)
+{
+}
+
+bool ArcCArcCIntersector::haveTheySameDirection() const
+{
+  return (getE1().getAngle()>0. &&  getE2().getAngle()>0.) || (getE1().getAngle()<0. &&  getE2().getAngle()<0.);
+}
+
+/*!
+ * Precondition 'start' and 'end' are on the same curve than this.
+ */
+void ArcCArcCIntersector::getPlacements(Node *start, Node *end, TypeOfLocInEdge& whereStart, TypeOfLocInEdge& whereEnd, MergePoints& commonNode) const
+{
+  bool obvious1,obvious2;
+  obviousCaseForCurvAbscisse(start,whereStart,commonNode,obvious1);
+  obviousCaseForCurvAbscisse(end,whereEnd,commonNode,obvious2);
+  if(obvious1 && obvious2)
+    return ;
+  double angleInRadStart=getAngle(start);
+  double angleInRadEnd=getAngle(end);
+  if(obvious1 || obvious2)
+    {
+      if(obvious1)
+        {
+          if(isIn2Pi(getE1().getAngle0(),getE1().getAngle(),angleInRadEnd))
+            whereEnd=INSIDE;
+          else
+            whereEnd=OUT_AFTER;
+          return ;
+        }
+      else
+        {
+          if(isIn2Pi(getE1().getAngle0(),getE1().getAngle(),angleInRadStart))
+            whereStart=INSIDE;
+          else
+            whereStart=OUT_BEFORE;
+          return ;
+        }
+    }
+  if(isIn2Pi(getE1().getAngle0(),getE1().getAngle(),angleInRadStart))
+    {
+      whereStart=INSIDE;
+      if(isIn2Pi(getE1().getAngle0(),getE1().getAngle(),angleInRadEnd))
+        whereEnd=INSIDE;
+      else
+        whereEnd=OUT_AFTER;
+    }
+  else
+    {//we are out in start.
+      if(isIn2Pi(getE1().getAngle0(),getE1().getAngle(),angleInRadEnd))
+        {
+          whereStart=OUT_BEFORE;
+          whereEnd=INSIDE;
+        }
+      else
+        {
+          if(isIn2Pi(getE2().getAngle0(),getE2().getAngle(),getE1().getAngle0()))
+            {//_e2 contains stictly _e1
+              whereStart=OUT_BEFORE;
+              whereEnd=OUT_AFTER;
+            }
+          else
+            {//_e2 is outside from _e1
+              whereStart=OUT_BEFORE;
+              whereEnd=OUT_BEFORE;
+            }
+        }
+    }
+}
+
+/*!
+ * Return angle between ]-Pi;Pi[
+ */
+double ArcCArcCIntersector::getAngle(Node *node) const
+{
+  double ret=EdgeArcCircle::safeAcos(((*node)[0]-getE1().getCenter()[0])/getE1().getRadius());
+  if(((*node)[1]<getE1().getCenter()[1]))
+    ret=-ret;
+  return ret;
+}
+
+void ArcCArcCIntersector::areOverlappedOrOnlyColinears(const Bounds *whereToFind, bool& obviousNoIntersection, bool& areOverlapped)
+{
+  _dist=Node::distanceBtw2Pt(getE1().getCenter(),getE2().getCenter());
+  double radius1=getE1().getRadius(); double radius2=getE2().getRadius();
+  if(_dist>radius1+radius2+QUADRATIC_PLANAR::_precision || _dist+fmin(radius1,radius2)+QUADRATIC_PLANAR::_precision<fmax(radius1,radius2))
+    {
+      obviousNoIntersection=true;
+      areOverlapped=false;
+      return ;
+    }
+  if(Node::areDoubleEquals(_dist,0.) && Node::areDoubleEquals(radius1,radius2))
+    {
+      obviousNoIntersection=false;
+      areOverlapped=true;
+    }
+  else
+    {
+      obviousNoIntersection=false;
+      areOverlapped=false;
+    }
+}
+
+std::list< IntersectElement > ArcCArcCIntersector::getIntersectionsCharacteristicVal() const
+{
+  std::list< IntersectElement > ret;
+  const double *center1=getE1().getCenter();
+  const double *center2=getE2().getCenter();
+  double radius1=getE1().getRadius(); double radius2=getE2().getRadius();
+  double d1_1=(_dist*_dist-radius2*radius2+radius1*radius1)/(2.*_dist);
+  double u[2];//u is normalized vector from center1 to center2.
+  u[0]=(center2[0]-center1[0])/_dist; u[1]=(center2[1]-center1[1])/_dist;
+  double angle0_1=EdgeArcCircle::safeAcos(u[0]);
+  double angle0_2;
+  double signDeltaAngle2;
+  if(u[1]<0.)
+    angle0_1=-angle0_1;
+  if(d1_1>=0.)
+    {
+      if(_dist>radius1)
+        {
+          angle0_2=angle0_1+M_PI;
+          signDeltaAngle2=-1.;
+        }
+      else
+        {
+          angle0_2=angle0_1;
+          signDeltaAngle2=1.;
+        }
+    }
+  else
+    {
+      angle0_1+=M_PI;
+      angle0_2=angle0_1;
+      signDeltaAngle2=1.;
+    }
+  angle0_1=normalizeAngle(angle0_1);
+  angle0_2=normalizeAngle(angle0_2);
+  double angleE1=normalizeAngle(getE1().getAngle0()+getE1().getAngle());
+  double angleE2=normalizeAngle(getE2().getAngle0()+getE2().getAngle());
+  if(!(Node::areDoubleEquals(d1_1,radius1) || Node::areDoubleEquals(d1_1,-radius1)) )
+    {
+      //2 intersections
+      double d1_2=_dist-d1_1;
+      double deltaAngle1=EdgeArcCircle::safeAcos(fabs(d1_1)/radius1); //owns to 0;Pi/2 by construction
+      double deltaAngle2=EdgeArcCircle::safeAcos(fabs(d1_2)/radius2); //owns to 0;Pi/2 by construction
+      double angle1_1=normalizeAngle(angle0_1+deltaAngle1);// Intersection 1 seen for _e1
+      double angle2_1=normalizeAngle(angle0_1-deltaAngle1);// Intersection 2 seen for _e1
+      double angle1_2=normalizeAngle(angle0_2+signDeltaAngle2*deltaAngle2);// Intersection 1 seen for _e2
+      double angle2_2=normalizeAngle(angle0_2-signDeltaAngle2*deltaAngle2);// Intersection 2 seen for _e2
+      //
+      bool e1_1S=Node::areDoubleEqualsWP(angle1_1,getE1().getAngle0(),radius1);
+      bool e1_1E=Node::areDoubleEqualsWP(angle1_1,angleE1,radius1);
+      bool e1_2S=Node::areDoubleEqualsWP(angle1_2,getE2().getAngle0(),radius1);
+      bool e1_2E=Node::areDoubleEqualsWP(angle1_2,angleE2,radius1);
+      //
+      bool e2_1S=Node::areDoubleEqualsWP(angle2_1,getE1().getAngle0(),radius2);
+      bool e2_1E=Node::areDoubleEqualsWP(angle2_1,angleE1,radius2);
+      bool e2_2S=Node::areDoubleEqualsWP(angle2_2,getE2().getAngle0(),radius2);
+      bool e2_2E=Node::areDoubleEqualsWP(angle2_2,angleE2,radius2);
+      Node *node1=new Node(center1[0]+radius1*cos(angle1_1),center1[0]+radius1*sin(angle1_1)); node1->declareOn();
+      Node *node2=new Node(center1[0]+radius1*cos(angle2_1),center1[0]+radius1*sin(angle2_1)); node2->declareOn();
+      ret.push_back(IntersectElement(angle1_1,angle1_2,e1_1S,e1_1E,e1_2S,e1_2E,node1,_e1,_e2,keepOrder()));
+      ret.push_back(IntersectElement(angle2_1,angle2_2,e2_1S,e2_1E,e2_2S,e2_2E,node2,_e1,_e2,keepOrder()));
+    }
+  else
+    //tangent intersection
+    {
+      bool e0_1S=Node::areDoubleEqualsWP(angle0_1,getE1().getAngle0(),radius1);
+      bool e0_1E=Node::areDoubleEqualsWP(angle0_1,angleE1,radius1);
+      bool e0_2S=Node::areDoubleEqualsWP(angle0_2,getE2().getAngle0(),radius2);
+      bool e0_2E=Node::areDoubleEqualsWP(angle0_2,angleE2,radius2);
+      Node *node=new Node(center1[0]+radius1*cos(angle0_1),center1[0]+radius1*sin(angle0_1)); node->declareOnTangent();
+      ret.push_back(IntersectElement(angle0_1,angle0_2,e0_1S,e0_1E,e0_2S,e0_2E,node,_e1,_e2,keepOrder()));
+    }
+  return ret;
+}
+
+/*!
+ * Idem isAngleNotIn except that here 'start' in ]-Pi;Pi[ and delta in ]-2*Pi;2Pi[. 
+ * @param angleIn in ]-Pi;Pi[.
+ */
+bool ArcCArcCIntersector::isIn2Pi(double start, double delta, double angleIn)
+{
+  double myDelta=angleIn-start;
+  if(delta>0.)
+    {
+      myDelta=myDelta>=0.?myDelta:myDelta+2.*M_PI;
+      return myDelta>0. && myDelta<delta;
+    }
+  else
+    {
+      myDelta=myDelta<=0.?myDelta:myDelta-2.*M_PI;
+      return myDelta<0. && myDelta>delta;
+    }
+}
+
+/*!
+ * Given the arc 'a' defined by 'start' angle and a 'delta' [-Pi;Pi] states for the angle 'angleIn' [-Pi;Pi] if it owns or not 'a'.
+ */
+bool ArcCArcCIntersector::isAngleNotIn(double start, double delta, double angleIn)
+{
+  double tmp=start;
+  if(tmp<0.)
+    tmp+=2*M_PI;
+  double tmp2=angleIn;
+  if(tmp2<0.)
+    tmp2+=2*M_PI;
+  if(tmp+delta>=2.*M_PI)
+    return (tmp2<tmp) && (tmp2>tmp+delta-2*M_PI);
+  else if(tmp+delta>=0.)
+    return (tmp2<fmin(tmp,tmp+delta) || tmp2>fmax(tmp,tmp+delta));
+  else
+    return (tmp2>tmp) && (tmp2<(tmp+delta+2.*M_PI));
+}
+
+ArcCSegIntersector::ArcCSegIntersector(const EdgeArcCircle& e1, const EdgeLin& e2, bool reverse):CrossTypeIntersector(e1,e2,reverse)
+{
+}
+
+void ArcCSegIntersector::areOverlappedOrOnlyColinears(const Bounds *whereToFind, bool& obviousNoIntersection, bool& areOverlapped)
+{
+  areOverlapped=false;//No overlapping by contruction
+  const double *center=getE1().getCenter();
+  _dx=(*(_e2.getEndNode()))[0]-(*(_e2.getStartNode()))[0];
+  _dy=(*(_e2.getEndNode()))[1]-(*(_e2.getStartNode()))[1];
+  _drSq=_dx*_dx+_dy*_dy;
+  _cross=
+    ((*(_e2.getStartNode()))[0]-center[0])*((*(_e2.getEndNode()))[1]-center[1])-
+    ((*(_e2.getStartNode()))[1]-center[1])*((*(_e2.getEndNode()))[0]-center[0]);
+  _determinant=getE1().getRadius()*getE1().getRadius()*_drSq-_cross*_cross;
+  if(_determinant>-QUADRATIC_PLANAR::_precision*10.)//QUADRATIC_PLANAR::_precision*QUADRATIC_PLANAR::_precision*_drSq*_drSq/(2.*_dx*_dx))
+    obviousNoIntersection=false;
+  else
+    obviousNoIntersection=true;   
+}
+
+void ArcCSegIntersector::getPlacements(Node *start, Node *end, TypeOfLocInEdge& whereStart, TypeOfLocInEdge& whereEnd, MergePoints& commonNode) const
+{
+  throw Exception("Internal error. Should never been called : no overlapping possible between arc of circle and a segment.");
+}
+
+std::list< IntersectElement > ArcCSegIntersector::getIntersectionsCharacteristicVal() const
+{
+  std::list< IntersectElement > ret;
+  const double *center=getE1().getCenter();
+  if(!(fabs(_determinant)<(QUADRATIC_PLANAR::_precision*10.)))//QUADRATIC_PLANAR::_precision*QUADRATIC_PLANAR::_precision*_drSq*_drSq/(2.*_dx*_dx))
+    {
+      double determinant=fmax(_determinant,0.);
+      determinant=sqrt(_determinant);
+      double x1=(_cross*_dy+Node::sign(_dy)*_dx*determinant)/_drSq+center[0];
+      double y1=(-_cross*_dx+fabs(_dy)*determinant)/_drSq+center[1];
+      Node *intersect1=new Node(x1,y1); intersect1->declareOn();
+      bool i1_1S=_e1.getStartNode()->isEqual(*intersect1);
+      bool i1_1E=_e1.getEndNode()->isEqual(*intersect1);
+      bool i1_2S=_e2.getStartNode()->isEqual(*intersect1);
+      bool i1_2E=_e2.getEndNode()->isEqual(*intersect1);
+      ret.push_back(IntersectElement(getE1().getCharactValue(*intersect1),getE2().getCharactValue(*intersect1),i1_1S,i1_1E,i1_2S,i1_2E,intersect1,_e1,_e2,keepOrder()));
+      //
+      double x2=(_cross*_dy-Node::sign(_dy)*_dx*determinant)/_drSq+center[0];
+      double y2=(-_cross*_dx-fabs(_dy)*determinant)/_drSq+center[1];
+      Node *intersect2=new Node(x2,y2); intersect2->declareOn();
+      bool i2_1S=_e1.getStartNode()->isEqual(*intersect2);
+      bool i2_1E=_e1.getEndNode()->isEqual(*intersect2);
+      bool i2_2S=_e2.getStartNode()->isEqual(*intersect2);
+      bool i2_2E=_e2.getEndNode()->isEqual(*intersect2);
+      ret.push_back(IntersectElement(getE1().getCharactValue(*intersect2),getE2().getCharactValue(*intersect2),i2_1S,i2_1E,i2_2S,i2_2E,intersect2,_e1,_e2,keepOrder()));
+    }
+  else//tangent intersection
+    {
+      double x=(_cross*_dy)/_drSq+center[0];
+      double y=(-_cross*_dx)/_drSq+center[1];
+      Node *intersect=new Node(x,y); intersect->declareOnTangent();
+      bool i_1S=_e1.getStartNode()->isEqual(*intersect);
+      bool i_1E=_e1.getEndNode()->isEqual(*intersect);
+      bool i_2S=_e2.getStartNode()->isEqual(*intersect);
+      bool i_2E=_e2.getEndNode()->isEqual(*intersect);
+      ret.push_back(IntersectElement(_e1.getCharactValue(*intersect),_e2.getCharactValue(*intersect),i_1S,i_1E,i_2S,i_2E,intersect,_e1,_e2,keepOrder()));
+    }
+  return ret;
+}
+
+EdgeArcCircle::EdgeArcCircle(std::istream& lineInXfig)
+{
+  const unsigned NB_OF_SKIP_FIELDS=15;
+  std::string tmpS;
+  for(unsigned i=0;i<NB_OF_SKIP_FIELDS;i++)
+    lineInXfig >> tmpS;
+  _start=new Node(lineInXfig);
+  Node *middle=new Node(lineInXfig);
+  _end=new Node(lineInXfig);
+  getArcOfCirclePassingThru(*_start,*middle,*_end,_center,_radius,_angle,_angle0);
+  middle->decrRef();
+  updateBounds();
+}
+
+EdgeArcCircle::EdgeArcCircle(Node *start, Node *middle, Node *end, bool direction):Edge(start,end, direction)
+{
+  getArcOfCirclePassingThru(*_start,*middle,*_end,_center,_radius,_angle,_angle0);
+  updateBounds();
+}
+
+EdgeArcCircle::EdgeArcCircle(double sX, double sY, double mX, double mY, double eX, double eY):Edge(sX,sY,eX,eY)
+{
+  double middle[2]; middle[0]=mX; middle[1]=mY;
+  getArcOfCirclePassingThru(*_start,middle,*_end,_center,_radius,_angle,_angle0);
+  updateBounds();
+}
+
+/*!
+ * @param angle0 in ]-Pi;Pi[
+ * @param deltaAngle in ]-2.*Pi;2.*Pi[
+ */
+EdgeArcCircle::EdgeArcCircle(Node *start, Node *end, const double *center, double radius, double angle0, double deltaAngle, bool direction):Edge(start,end,direction),_angle(deltaAngle),
+                                                                                                                                      _angle0(angle0),_radius(radius)
+{
+  _center[0]=center[0];
+  _center[1]=center[1];
+}
+
+void EdgeArcCircle::changeMiddle(Node *newMiddle)
+{
+  getArcOfCirclePassingThru(*_start,*newMiddle,*_end,_center,_radius,_angle,_angle0);
+  updateBounds();
+}
+
+Edge *EdgeArcCircle::buildEdgeLyingOnMe(Node *start, Node *end, bool direction) const
+{
+  double sx=((*start)[0]-_center[0])/_radius;
+  double sy=((*start)[1]-_center[1])/_radius;
+  double ex=((*end)[0]-_center[0])/_radius;
+  double ey=((*end)[1]-_center[1])/_radius;
+  double angle0=safeAcos(direction?sx:ex);
+  angle0=direction?sy:ey>0.?angle0:-angle0;
+  double deltaAngle=safeAcos(sx*ex+sy*ey);
+  deltaAngle=sx*ey-sy*ex>0.?deltaAngle:-deltaAngle;
+  if(deltaAngle>0. && _angle<0.)
+    deltaAngle-=2.*M_PI;
+  else if(deltaAngle<0. && _angle>0.)
+    deltaAngle+=2.*M_PI;
+  deltaAngle=direction?deltaAngle:-deltaAngle;
+  return new EdgeArcCircle(start,end,_center,_radius,angle0,deltaAngle,direction);
+}
+
+void EdgeArcCircle::getArcOfCirclePassingThru(const double *start, const double *middle, const double *end, 
+                                              double *center, double& radius, double& angleInRad, double& angleInRad0)
+{
+  double delta=(middle[0]-start[0])*(end[1]-middle[1])-(end[0]-middle[0])*(middle[1]-start[1]);
+  double b1=(middle[1]*middle[1]+middle[0]*middle[0]-start[0]*start[0]-start[1]*start[1])/2;
+  double b2=(end[1]*end[1]+end[0]*end[0]-middle[0]*middle[0]-middle[1]*middle[1])/2;
+  center[0]=((end[1]-middle[1])*b1+(start[1]-middle[1])*b2)/delta;
+  center[1]=((middle[0]-end[0])*b1+(middle[0]-start[0])*b2)/delta;
+  radius=sqrt((start[0]-center[0])*(start[0]-center[0])+(start[1]-center[1])*(start[1]-center[1]));
+  angleInRad0=safeAcos((start[0]-center[0])/radius);
+  if((start[1]-center[1])<0.)
+    angleInRad0=-angleInRad0;
+  double angleInRadM=safeAcos((middle[0]-center[0])/radius);
+  if((middle[1]-center[1])<0.)
+    angleInRadM=-angleInRadM;
+  angleInRad=safeAcos(((start[0]-center[0])*(end[0]-center[0])+(start[1]-center[1])*(end[1]-center[1]))/(radius*radius));
+  bool signOfAngle=((start[0]-center[0])*(end[1]-center[1])-(start[1]-center[1])*(end[0]-center[0]))>0.;
+  angleInRad=signOfAngle?angleInRad:-angleInRad;
+  if(ArcCArcCIntersector::isAngleNotIn(angleInRad0,angleInRad,angleInRadM))
+    angleInRad=angleInRad<0?2*M_PI+angleInRad:angleInRad-2*M_PI;
+}
+
+void EdgeArcCircle::dumpInXfigFile(std::ostream& stream, bool direction) const
+{
+  stream << "5 1 0 1 ";
+  fillXfigStreamForLoc(stream);
+  stream << " 7 50 -1 -1 0.000 0 ";
+  if( (direction && _angle>=0) || (!direction && _angle<0))
+    stream << '0';//'0'
+  else
+    stream << '1';//'1'
+  stream << " 0 0 ";
+  stream << (int)(_center[0]*Node::CST_FOR_XFIG) << " " << (int)(_center[1]*Node::CST_FOR_XFIG) << " ";
+  direction?_start->dumpInXfigFile(stream):_end->dumpInXfigFile(stream);
+  Node *middle=buildRepresentantOfMySelf();
+  middle->dumpInXfigFile(stream);
+  middle->decrRef();
+  direction?_end->dumpInXfigFile(stream):_start->dumpInXfigFile(stream);
+  stream << endl;
+}
+
+void EdgeArcCircle::update(Node *m)
+{
+  getArcOfCirclePassingThru(*_start,*m,*_end,_center,_radius,_angle,_angle0);
+  updateBounds();
+}
+
+double EdgeArcCircle::getAreaOfZone() const
+{
+  return -_radius*_radius*(sin(_angle)-_angle)/2.+((*_start)[0]-(*_end)[0])*((*_start)[1]+(*_end)[1])/2.;
+}
+
+double EdgeArcCircle::getCurveLength() const
+{
+  return fabs(_angle*_radius);
+}
+
+/*!
+ * Characteristic value used is angle in ]_Pi;Pi[ from axe 0x.
+ */
+bool EdgeArcCircle::isIn(double characterVal) const
+{
+  return ArcCArcCIntersector::isIn2Pi(_angle0,_angle,characterVal);
+}
+
+Node *EdgeArcCircle::buildRepresentantOfMySelf() const
+{
+  return new Node(_center[0]+_radius*cos(_angle0+_angle/2.),_center[1]+_radius*sin(_angle0+_angle/2.));
+}
+
+/*!
+ * Characteristic value used is angle in ]_Pi;Pi[ from axe 0x.
+ * 'val1' and 'val2' have been detected previously as owning to this.
+ */
+bool EdgeArcCircle::isLower(double val1, double val2) const
+{
+  double myDelta1=val1-_angle0;
+  double myDelta2=val2-_angle0;
+  if(_angle>0.)
+    {
+      myDelta1=myDelta1>-(_radius*QUADRATIC_PLANAR::_precision)?myDelta1:myDelta1+2.*M_PI;//in some cases val1 or val2 are so close to angle0 that myDelta is close to 0. but negative.
+      myDelta2=myDelta2>-(_radius*QUADRATIC_PLANAR::_precision)?myDelta2:myDelta2+2.*M_PI;
+      return myDelta1<myDelta2;
+    }
+  else
+    {
+      myDelta1=myDelta1<(_radius*QUADRATIC_PLANAR::_precision)?myDelta1:myDelta1-2.*M_PI;
+      myDelta2=myDelta2<(_radius*QUADRATIC_PLANAR::_precision)?myDelta2:myDelta2-2.*M_PI;
+      return myDelta2<myDelta1;
+    }
+}
+
+/*!
+ * For Arc circle the caract value is angle with Ox between -Pi and Pi.
+ */
+double EdgeArcCircle::getCharactValue(const Node& node) const
+{
+  double dx=(node[0]-_center[0])/_radius;
+  double dy=(node[1]-_center[1])/_radius;
+  double angle0=safeAcos(dx);
+  angle0=dy>=0.?angle0:-angle0;
+  return angle0;
+}
+
+void EdgeArcCircle::updateBounds()
+{
+  _bounds.setValues(fmin((*_start)[0],(*_end)[0]),fmax((*_start)[0],(*_end)[0]),fmin((*_start)[1],(*_end)[1]),fmax((*_start)[1],(*_end)[1]));
+  if(ArcCArcCIntersector::isIn2Pi(_angle0,_angle,M_PI/2))
+    _bounds[3]=_center[1]+_radius;
+  if(ArcCArcCIntersector::isIn2Pi(_angle0,_angle,-M_PI/2))
+    _bounds[2]=_center[1]-_radius;
+  if(ArcCArcCIntersector::isIn2Pi(_angle0,_angle,0.))
+    _bounds[1]=_center[0]+_radius;
+  if(ArcCArcCIntersector::isIn2Pi(_angle0,_angle,M_PI))
+  _bounds[0]=_center[0]-_radius;
+}
diff --git a/src/INTERP_KERNEL/Geometric2D/EdgeArcCircle.hxx b/src/INTERP_KERNEL/Geometric2D/EdgeArcCircle.hxx
new file mode 100644 (file)
index 0000000..d787a6f
--- /dev/null
@@ -0,0 +1,94 @@
+#ifndef __EDGEARCCIRCLE_HXX__
+#define __EDGEARCCIRCLE_HXX__
+
+#include "Edge.hxx"
+
+namespace INTERP_KERNEL
+{
+  class ArcCArcCIntersector : public SameTypeIntersector
+  {
+    friend class EdgeArcCircle;
+  public:
+    ArcCArcCIntersector(const EdgeArcCircle& e1, const EdgeArcCircle& e2);
+    bool haveTheySameDirection() const;
+    void getPlacements(Node *start, Node *end, TypeOfLocInEdge& whereStart, TypeOfLocInEdge& whereEnd, MergePoints& commonNode) const;
+    void areOverlappedOrOnlyColinears(const Bounds *whereToFind, bool& obviousNoIntersection, bool& areOverlapped);
+    std::list< IntersectElement > getIntersectionsCharacteristicVal() const;
+  private:
+    //! return angle in ]-Pi;Pi[ - 'node' must be on curve of '_e1'
+    double getAngle(Node *node) const;
+    static bool isIn2Pi(double start, double delta, double angleIn);
+    //! 'delta' 'start' in ]-Pi;Pi[
+    static bool isAngleNotIn(double start, double delta, double angleIn);
+    //! for an angle 'angle' in ]-3*Pi;3*Pi[ returns angle in ]-Pi;Pi[
+    static double normalizeAngle(double angle) { if(angle>M_PI) return angle-2.*M_PI; if(angle<-M_PI) return angle+2.*M_PI; return angle; }
+  private:
+    const EdgeArcCircle& getE1() const { return (const EdgeArcCircle&)_e1; }
+    const EdgeArcCircle& getE2() const { return (const EdgeArcCircle&)_e2; }
+  private:
+    double _dist;
+  };
+
+  class ArcCSegIntersector : public CrossTypeIntersector
+  {
+  public:
+    ArcCSegIntersector(const EdgeArcCircle& e1, const EdgeLin& e2, bool reverse=true);
+    //virtual overloading
+    void getPlacements(Node *start, Node *end, TypeOfLocInEdge& whereStart, TypeOfLocInEdge& whereEnd, MergePoints& commonNode) const;
+    void areOverlappedOrOnlyColinears(const Bounds *whereToFind, bool& obviousNoIntersection, bool& areOverlapped);
+    std::list< IntersectElement > getIntersectionsCharacteristicVal() const;
+  private:
+    const EdgeArcCircle& getE1() const { return (const EdgeArcCircle&)_e1; }
+    const EdgeLin& getE2() const { return (const EdgeLin&)_e2; }
+  private:
+    double _dx;
+    double _dy;
+    double _drSq;
+    double _cross;
+    double _determinant;
+  };
+  
+  class EdgeArcCircle : public Edge
+  {
+  public:
+    EdgeArcCircle(std::istream& lineInXfig);
+    EdgeArcCircle(Node *start, Node *middle, Node *end, bool direction = true);
+    EdgeArcCircle(double sX, double sY, double mX, double mY, double eX, double eY);
+    EdgeArcCircle(Node *start, Node *end, const double *center, double radius, double angle0, double deltaAngle, bool direction=true);
+    //! for tests
+    void changeMiddle(Node *newMiddle);
+    void dumpInXfigFile(std::ostream& stream, bool direction) const;
+    void update(Node *m);
+    double getAreaOfZone() const;
+    double getCurveLength() const;
+    bool isIn(double characterVal) const;
+    Node *buildRepresentantOfMySelf() const;
+    bool isLower(double val1, double val2) const;
+    double getCharactValue(const Node& node) const;
+    TypeOfFunction getTypeOfFunc() const { return ARC_CIRCLE; }
+    void dynCastFunction(const EdgeLin * &seg,
+                         const EdgeArcCircle * &arcSeg) const { arcSeg=this; }
+    const double *getCenter() const { return _center; }
+    void getCenter(double *center) const { center[0]=_center[0]; center[1]=_center[1]; }
+    bool doIHaveSameDirectionAs(const Edge& other) const { return false; }
+    Edge *buildEdgeLyingOnMe(Node *start, Node *end, bool direction=true) const;
+    double getAngle0() const { return _angle0; }
+    double getRadius() const { return _radius; }
+    double getAngle() const { return _angle; }
+    static void getArcOfCirclePassingThru(const double *start, const double *middle, const double *end, 
+                                          double *center, double& radius, double& angleInRad, double& angleInRad0);
+    //! To avoid in aggressive optimizations nan.
+    static double safeAcos(double cosAngle) { double ret=fmin(cosAngle,1.); ret=fmax(ret,-1.); return acos(ret); }
+  protected:
+    void updateBounds();
+  protected:
+    //Value between -2Pi and 2Pi
+    double _angle;
+    //Value between -Pi and Pi
+    double _angle0;
+    double _radius;
+    double _center[2];
+  };
+}
+
+#endif
diff --git a/src/INTERP_KERNEL/Geometric2D/EdgeInfLin.cxx b/src/INTERP_KERNEL/Geometric2D/EdgeInfLin.cxx
new file mode 100644 (file)
index 0000000..759c1cb
--- /dev/null
@@ -0,0 +1,10 @@
+#include "EdgeInfLin.hxx"
+
+using namespace INTERP_KERNEL;
+
+EdgeInfLin::EdgeInfLin(Node *pointPassingThrough, double slope)
+{
+  _start=pointPassingThrough;
+  _start->incrRef();
+  _end=new Node((*_start)[0]+cos(slope),(*_start)[1]+sin(slope));
+}
diff --git a/src/INTERP_KERNEL/Geometric2D/EdgeInfLin.hxx b/src/INTERP_KERNEL/Geometric2D/EdgeInfLin.hxx
new file mode 100644 (file)
index 0000000..3f47b9a
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef __EDGEINFLIN_HXX__
+#define __EDGEINFLIN_HXX__
+
+#include "EdgeLin.hxx"
+
+namespace INTERP_KERNEL
+{
+  class EdgeInfLin : public EdgeLin
+  {
+  public:
+    EdgeInfLin(Node *start, Node *end):EdgeLin(start,end,true) { }
+    EdgeInfLin(Node *pointPassingThrough, double slope);
+    bool isIn(double characterVal) const { return true; }
+    void dynCastFunction(const EdgeLin * &seg,
+                         const EdgeArcCircle * &arcSeg) const { seg=this; }
+    void dumpInXfigFile(std::ostream& stream) const { }
+  private:
+    ~EdgeInfLin() { }
+  };
+}
+
+#endif
diff --git a/src/INTERP_KERNEL/Geometric2D/EdgeLin.cxx b/src/INTERP_KERNEL/Geometric2D/EdgeLin.cxx
new file mode 100644 (file)
index 0000000..2ff40f0
--- /dev/null
@@ -0,0 +1,204 @@
+#include "EdgeLin.hxx"
+#include "Node.hxx"
+#include "Exception.hxx"
+
+using namespace std;
+using namespace INTERP_KERNEL;
+
+namespace INTERP_KERNEL
+{
+  extern const unsigned MAX_SIZE_OF_LINE_XFIG_FILE=1024;
+}
+
+SegSegIntersector::SegSegIntersector(const EdgeLin& e1, const EdgeLin& e2):SameTypeIntersector(e1,e2)
+{
+  _matrix[0]=(*(e2.getStartNode()))[0]-(*(e2.getEndNode()))[0];
+  _matrix[1]=(*(e1.getEndNode()))[0]-(*(e1.getStartNode()))[0];
+  _matrix[2]=(*(e2.getStartNode()))[1]-(*(e2.getEndNode()))[1];
+  _matrix[3]=(*(e1.getEndNode()))[1]-(*(e1.getStartNode()))[1];
+  _col[0]=_matrix[3]*(*(e1.getStartNode()))[0]-_matrix[1]*(*(e1.getStartNode()))[1];
+  _col[1]=-_matrix[2]*(*(e2.getStartNode()))[0]+_matrix[0]*(*(e2.getStartNode()))[1];
+  //Little trick to avoid problems if 'e1' and 'e2' are colinears and along Ox or Oy axes.
+  if(fabs(_matrix[3])>fabs(_matrix[1]))
+    _ind=0;
+  else
+    _ind=1;
+}
+
+/*!
+ * Must be called when 'this' and 'other' have been detected to be at least colinear. Typically they are overlapped.
+ * Must be called after call of areOverlappedOrOnlyColinears.
+ */
+bool SegSegIntersector::haveTheySameDirection() const
+{
+  return (_matrix[_ind?1:0]>0. && _matrix[_ind?3:2]>0.) || (_matrix[_ind?1:0]<0. && _matrix[_ind?3:2]<0.);
+}
+
+/*!
+ * Precondition start and end must be so that there predecessor was in the same direction than 'e1'
+ */
+void SegSegIntersector::getPlacements(Node *start, Node *end, TypeOfLocInEdge& whereStart, TypeOfLocInEdge& whereEnd, MergePoints& commonNode) const
+{
+  getCurveAbscisse(start,whereStart,commonNode);
+  getCurveAbscisse(end,whereEnd,commonNode);
+}
+
+void SegSegIntersector::getCurveAbscisse(Node *node, TypeOfLocInEdge& where, MergePoints& commonNode) const
+{
+  bool obvious;
+  obviousCaseForCurvAbscisse(node,where,commonNode,obvious);
+  if(obvious)
+    return ;
+  double ret=((*node)[!_ind]-(*_e1.getStartNode())[!_ind])/((*_e1.getEndNode())[!_ind]-(*_e1.getStartNode())[!_ind]);
+  if(ret>0. && ret <1.)
+    where=INSIDE;
+  else if(ret<0.)
+    where=OUT_BEFORE;
+  else
+    where=OUT_AFTER;
+}
+
+/*!
+ * areColinears method should be called before with a returned colinearity equal to false to avoid bad news.
+ */
+std::list< IntersectElement > SegSegIntersector::getIntersectionsCharacteristicVal() const
+{
+  std::list< IntersectElement > ret;
+  double x=_matrix[0]*_col[0]+_matrix[1]*_col[1];
+  double y=_matrix[2]*_col[0]+_matrix[3]*_col[1];
+  //Only one intersect point possible
+  Node *node=new Node(x,y);
+  node->declareOn();
+  bool i_1S=_e1.getStartNode()->isEqual(*node);
+  bool i_1E=_e1.getEndNode()->isEqual(*node);
+  bool i_2S=_e2.getStartNode()->isEqual(*node);
+  bool i_2E=_e2.getEndNode()->isEqual(*node);
+  ret.push_back(IntersectElement(_e1.getCharactValue(*node),
+                                 _e2.getCharactValue(*node),
+                                 i_1S,i_1E,i_2S,i_2E,node,_e1,_e2,keepOrder()));
+  return ret;
+}
+
+/*!
+ * Should be called \b once ! non const method.
+ * \param whereToFind specifies the box where final seek should be done. Essentially it is used for caracteristic reason.
+ * \param colinearity returns if regarding QUADRATIC_PLANAR::_precision ; e1 and e2 are colinears
+ *                    If true 'this' is modified ! So this method be called once above all if true is returned for this parameter.
+ * \param areOverlapped if colinearity if true, this parameter looks if e1 and e2 are overlapped.
+ */
+void SegSegIntersector::areOverlappedOrOnlyColinears(const Bounds *whereToFind, bool& colinearity, bool& areOverlapped)
+{
+  double determinant=_matrix[0]*_matrix[3]-_matrix[1]*_matrix[2];
+  if(fabs(determinant)>2.*QUADRATIC_PLANAR::_precision)//2*_precision due to max of offset on _start and _end
+    {
+      colinearity=false; areOverlapped=false;
+      _matrix[0]/=determinant; _matrix[1]/=determinant; _matrix[2]/=determinant; _matrix[3]/=determinant;
+    }
+  else
+    {
+      colinearity=true;
+      //retrieving initial matrix
+      double tmp=_matrix[0]; _matrix[0]=_matrix[3]; _matrix[3]=tmp;
+      _matrix[1]=-_matrix[1]; _matrix[2]=-_matrix[2];
+      //
+      double deno=sqrt(_matrix[0]*_matrix[0]+_matrix[1]*_matrix[1]);
+      double x=(*(_e1.getStartNode()))[0]-(*(_e2.getStartNode()))[0];
+      double y=(*(_e1.getStartNode()))[1]-(*(_e2.getStartNode()))[1];
+      areOverlapped=fabs((_matrix[1]*y+_matrix[0]*x)/deno)<QUADRATIC_PLANAR::_precision;
+      /*double tmp=_matrix[0]; _matrix[0]=_matrix[3]; _matrix[3]=tmp;
+      _matrix[1]=-_matrix[1]; _matrix[2]=-_matrix[2];
+      double dist1=(_col[0]-(*whereToFind)[2*(_ind)]*_matrix[!_ind])/_matrix[_ind];
+      double dist2=(_col[1]-(*whereToFind)[2*(_ind)]*_matrix[!_ind+2])/_matrix[_ind+2];
+      double dist3=(_col[0]-(*whereToFind)[2*(_ind)+1]*_matrix[!_ind])/_matrix[_ind];
+      double dist4=(_col[1]-(*whereToFind)[2*(_ind)+1]*_matrix[!_ind+2])/_matrix[_ind+2];
+      areOverlapped=(fmax(fabs(dist1-dist2),fabs(dist3-dist4))<1.4142135623730951*QUADRATIC_PLANAR::_precision);*/
+    }
+}
+
+EdgeLin::EdgeLin(std::istream& lineInXfig)
+{
+  char currentLine[MAX_SIZE_OF_LINE_XFIG_FILE];
+  lineInXfig.getline(currentLine,MAX_SIZE_OF_LINE_XFIG_FILE);
+  _start=new Node(lineInXfig);
+  _end=new Node(lineInXfig);
+  updateBounds();
+}
+
+EdgeLin::EdgeLin(Node *start, Node *end, bool direction):Edge(start,end,direction)
+{
+  updateBounds();
+}
+
+EdgeLin::EdgeLin(double sX, double sY, double eX, double eY):Edge(sX,sY,eX,eY)
+{
+  updateBounds();
+}
+
+EdgeLin::~EdgeLin()
+{
+}
+
+/*!
+ * Characteristic for edges is relative position btw 0.;1.
+ */
+bool EdgeLin::isIn(double characterVal) const
+{
+  return characterVal>0. && characterVal<1.;
+}
+
+Node *EdgeLin::buildRepresentantOfMySelf() const
+{
+  return new Node(((*(_start))[0]+(*(_end))[0])/2.,((*(_start))[1]+(*(_end))[1])/2.);
+}
+
+double EdgeLin::getCharactValue(const Node& node) const
+{
+  double car1_1x=node[0]-(*(_start))[0]; double car1_2x=(*(_end))[0]-(*(_start))[0];
+  double car1_1y=node[1]-(*(_start))[1]; double car1_2y=(*(_end))[1]-(*(_start))[1];
+  return (car1_1x*car1_2x+car1_1y*car1_2y)/(car1_2x*car1_2x+car1_2y*car1_2y);
+}
+
+void EdgeLin::dumpInXfigFile(std::ostream& stream, bool direction) const
+{
+  stream << "2 1 0 1 ";
+  fillXfigStreamForLoc(stream);
+  stream << " 7 50 -1 -1 0.000 0 0 -1 0 0 2" << endl;
+  direction?_start->dumpInXfigFile(stream):_end->dumpInXfigFile(stream);
+  direction?_end->dumpInXfigFile(stream):_start->dumpInXfigFile(stream);
+  stream << endl;
+}
+
+void EdgeLin::update(Node *m)
+{
+  updateBounds();
+}
+
+double EdgeLin::getNormSq() const
+{
+  return _start->distanceWithSq(*_end);
+}
+
+double EdgeLin::getAreaOfZone() const
+{
+  return ((*_start)[0]-(*_end)[0])*((*_start)[1]+(*_end)[1])/2.;
+}
+
+double EdgeLin::getCurveLength() const
+{
+  double x=(*_start)[0]-(*_end)[0];
+  double y=(*_start)[1]-(*_end)[1];
+  return sqrt(x*x+y*y);
+}
+
+Edge *EdgeLin::buildEdgeLyingOnMe(Node *start, Node *end, bool direction) const
+{
+  return new EdgeLin(start,end,direction);
+}
+
+/*!
+ * No precision should be introduced here. Just think as if precision was perfect.
+ */
+void EdgeLin::updateBounds()
+{
+  _bounds.setValues(fmin((*_start)[0],(*_end)[0]),fmax((*_start)[0],(*_end)[0]),fmin((*_start)[1],(*_end)[1]),fmax((*_start)[1],(*_end)[1]));
+}
diff --git a/src/INTERP_KERNEL/Geometric2D/EdgeLin.hxx b/src/INTERP_KERNEL/Geometric2D/EdgeLin.hxx
new file mode 100644 (file)
index 0000000..ec8d5f1
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef __EDGELIN_HXX__
+#define __EDGELIN_HXX__
+
+#include "Edge.hxx"
+
+namespace INTERP_KERNEL
+{
+  class SegSegIntersector : SameTypeIntersector
+    {
+      friend class Edge;
+    public:
+      SegSegIntersector(const EdgeLin& e1, const EdgeLin& e2);
+      bool haveTheySameDirection() const;
+      void getPlacements(Node *start, Node *end, TypeOfLocInEdge& whereStart, TypeOfLocInEdge& whereEnd, MergePoints& commonNode) const;
+      void areOverlappedOrOnlyColinears(const Bounds *whereToFind, bool& obviousNoIntersection, bool& areOverlapped);
+      std::list< IntersectElement > getIntersectionsCharacteristicVal() const;
+    private:
+      void getCurveAbscisse(Node *node, TypeOfLocInEdge& where, MergePoints& commonNode) const;
+    private:
+      //! index on which all single index op will be performed. Filled in case colinearity is equal to true.
+      int _ind;
+      double _col[2];
+      double _matrix[4];//SPACEDIM*SPACEDIM
+    };
+
+  class EdgeLin : public Edge
+  {
+    friend class SegSegIntersector;
+  public:
+    EdgeLin(std::istream& lineInXfig);
+    EdgeLin(Node *start, Node *end, bool direction=true);
+    EdgeLin(double sX, double sY, double eX, double eY);
+    ~EdgeLin();
+    TypeOfFunction getTypeOfFunc() const { return SEG; }
+    void dumpInXfigFile(std::ostream& stream, bool direction) const;
+    void update(Node *m);
+    double getNormSq() const;
+    double getAreaOfZone() const;
+    double getCurveLength() const;
+    bool isIn(double characterVal) const;
+    Node *buildRepresentantOfMySelf() const;
+    double getCharactValue(const Node& node) const;
+    bool isLower(double val1, double val2) const { return val1<val2; }
+    bool doIHaveSameDirectionAs(const Edge& other) const;
+    Edge *buildEdgeLyingOnMe(Node *start, Node *end, bool direction=true) const;
+    void dynCastFunction(const EdgeLin * &seg,
+                         const EdgeArcCircle * &arcSeg) const { seg=this; }
+  protected:
+    EdgeLin() { }
+    void updateBounds();
+  };
+}
+
+#endif
diff --git a/src/INTERP_KERNEL/Geometric2D/ElementaryEdge.cxx b/src/INTERP_KERNEL/Geometric2D/ElementaryEdge.cxx
new file mode 100644 (file)
index 0000000..af97833
--- /dev/null
@@ -0,0 +1,173 @@
+#include "ElementaryEdge.hxx"
+#include "Exception.hxx"
+#include "Edge.hxx"
+
+using namespace INTERP_KERNEL;
+
+ElementaryEdge::ElementaryEdge(const ElementaryEdge& other):_direction(other._direction),_ptr(other._ptr)
+{
+  _ptr->incrRef(); 
+}
+
+ElementaryEdge::~ElementaryEdge()
+{
+  if(_ptr)
+    _ptr->decrRef();
+}
+
+bool ElementaryEdge::isNodeIn(Node *n) const
+{
+  return _ptr->getStartNode()==n || _ptr->getEndNode()==n;
+}
+
+void ElementaryEdge::fillBounds(Bounds& output) const
+{
+  output.aggregate(_ptr->getBounds());
+}
+
+void ElementaryEdge::getAllNodes(std::set<Node *>& output) const
+{
+  output.insert(_ptr->getStartNode());
+  output.insert(_ptr->getEndNode());
+}
+
+AbstractEdge *ElementaryEdge::clone() const
+{
+  return new ElementaryEdge(*this);
+}
+
+int ElementaryEdge::recursiveSize() const
+{
+  return 1;
+}
+
+int ElementaryEdge::size() const
+{
+  throw Exception("Invalid call to ElementaryEdge::size : ElementaryEdge not splittable");
+}
+
+/*!
+ * WARNING use this method if and only if this is so that it is completely in/out/on of @param pol.
+ */
+TypeOfEdgeLocInPolygon ElementaryEdge::locateFullyMySelf(const ComposedEdge& pol, TypeOfEdgeLocInPolygon precEdgeLoc) const
+{
+  if(getLoc()!=FULL_UNKNOWN)
+    return getLoc();
+  //obvious cases
+  if(precEdgeLoc==FULL_IN_1)
+    {
+      if(getStartNode()->getLoc()==ON_1)
+        {
+          declareOut();
+          return getLoc();
+        }
+      else if(getStartNode()->getLoc()==IN_1 || getStartNode()->getLoc()==ON_TANG_1)
+        {
+          declareIn();
+          return getLoc();
+        }
+    }
+  if(precEdgeLoc==FULL_OUT_1)
+    {
+      if(getStartNode()->getLoc()==ON_1)
+        {
+          declareIn();
+          return getLoc();
+        }
+      else if(getStartNode()->getLoc()==IN_1 || getStartNode()->getLoc()==ON_TANG_1)
+        {
+          declareOut();
+          return getLoc();
+        }
+    }
+  if(getStartNode()->getLoc()==IN_1 || getEndNode()->getLoc()==IN_1)
+    {
+      declareIn();
+      return getLoc();
+    }
+  if(getStartNode()->getLoc()==OUT_1 || getEndNode()->getLoc()==OUT_1)
+    {
+      declareOut();
+      return getLoc();
+    }
+  //a seek is requested
+  return locateFullyMySelfAbsolute(pol);
+}
+
+TypeOfEdgeLocInPolygon ElementaryEdge::locateFullyMySelfAbsolute(const ComposedEdge& pol) const
+{
+  Node *node=_ptr->buildRepresentantOfMySelf();
+  if(pol.isInOrOut(node))
+    declareIn(); 
+  else
+    declareOut();
+  node->decrRef();
+  return getLoc();
+}
+
+const AbstractEdge *&ElementaryEdge::operator[](IteratorOnComposedEdge::ItOnFixdLev i) const
+{
+  throw Exception("Invalid input parameter in ElementaryEdge::operator[] not splittable");
+}
+
+AbstractEdge *&ElementaryEdge::operator[](IteratorOnComposedEdge::ItOnFixdLev i)
+{
+  throw Exception("Invalid input parameter in ElementaryEdge::operator[] not splittable");
+}
+
+Node *ElementaryEdge::getEndNode() const
+{ 
+  if(_direction)
+    return _ptr->getEndNode();
+  else return _ptr->getStartNode();
+}
+
+Node *ElementaryEdge::getStartNode() const
+{
+  if(_direction)
+    return _ptr->getStartNode();
+  else 
+    return _ptr->getEndNode();
+}
+
+bool ElementaryEdge::changeEndNodeWith(Node *node) const
+{
+  if(_direction)
+    return _ptr->changeEndNodeWith(node);
+  else 
+    return _ptr->changeStartNodeWith(node);
+}
+
+bool ElementaryEdge::changeStartNodeWith(Node *node) const
+{
+  if(_direction)
+    return _ptr->changeStartNodeWith(node);
+  else 
+    return _ptr->changeEndNodeWith(node);
+}
+
+void ElementaryEdge::dumpInXfigFile(std::ostream& stream) const
+{
+  _ptr->dumpInXfigFile(stream,_direction);
+}
+
+bool ElementaryEdge::intresicEqual(const AbstractEdge *other) const
+{
+  const ElementaryEdge* otherC=dynamic_cast< const ElementaryEdge* >(other);
+  if(!otherC)
+    return false;
+  return (_ptr==otherC->_ptr);
+}
+
+bool ElementaryEdge::intresicEqualDirSensitive(const AbstractEdge *other) const
+{
+  const ElementaryEdge* otherC=dynamic_cast< const ElementaryEdge* >(other);
+  if(!otherC)
+    return false;
+  return ( _direction==otherC->_direction ) && (_ptr==otherC->_ptr);
+}
+
+bool ElementaryEdge::intresincEqCoarse(const Edge *other) const
+{
+  return _ptr==other;
+}
diff --git a/src/INTERP_KERNEL/Geometric2D/ElementaryEdge.hxx b/src/INTERP_KERNEL/Geometric2D/ElementaryEdge.hxx
new file mode 100644 (file)
index 0000000..adcdca2
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef __ELEMENTARYEDGE_HXX__
+#define __ELEMENTARYEDGE_HXX__
+
+#include "AbstractEdge.hxx"
+#include "Exception.hxx"
+#include "Edge.hxx"
+
+namespace INTERP_KERNEL
+{
+  class ElementaryEdge : public AbstractEdge
+  {
+  public:
+    ElementaryEdge(Edge *ptr, bool direction):_direction(direction),_ptr(ptr) { }
+    ElementaryEdge(const ElementaryEdge& other);
+    ~ElementaryEdge();
+    bool completed() const { return false; }
+    void declareOn() const { _ptr->declareOn(); }
+    void declareIn() const { _ptr->declareIn(); }
+    void declareOut() const { _ptr->declareOut(); }
+    TypeOfEdgeLocInPolygon getLoc() const { return _ptr->getLoc(); }
+    Edge *getPtr() const { return _ptr; }
+    ElementaryEdge* &getLastElementary(IteratorOnComposedEdge::ItOnFixdLev &delta)  { throw Exception("Invalid call to getLastElementary"); }
+    ElementaryEdge * &getFirstElementary(IteratorOnComposedEdge::ItOnFixdLev &delta)  { throw Exception("Invalid call to getFirstElementary"); }
+    void reverse() { _direction=(!_direction); }
+    bool isNodeIn(Node *n) const;
+    double getAreaOfZone() const { return getAreaOfZoneFast(); }
+    void fillBounds(Bounds& output) const;
+    void getAllNodes(std::set<Node *>& output) const;
+    double getAreaOfZoneFast() const { double ret=_ptr->getAreaOfZone(); return _direction?ret:-ret; }
+    AbstractEdge *clone() const;
+    int recursiveSize() const;
+    int size() const;
+    TypeOfEdgeLocInPolygon locateFullyMySelfAbsolute(const ComposedEdge& pol) const;
+    TypeOfEdgeLocInPolygon locateFullyMySelf(const ComposedEdge& pol, TypeOfEdgeLocInPolygon precEdgeLoc) const;
+    AbstractEdge *&operator[](IteratorOnComposedEdge::ItOnFixdLev i);
+    const AbstractEdge *&operator[](IteratorOnComposedEdge::ItOnFixdLev i) const;
+    Node *getEndNode() const;
+    Node *getStartNode() const;
+    double getCurveLength() const { return _ptr->getCurveLength(); }
+    bool changeEndNodeWith(Node *node) const;
+    bool changeStartNodeWith(Node *node) const;
+    void dumpInXfigFile(std::ostream& stream) const;
+    bool intresicEqual(const AbstractEdge *other) const;
+    bool intresicEqualDirSensitive(const AbstractEdge *other) const;
+    bool getDirection() const { return _direction; }
+    bool intresincEqCoarse(const Edge *other) const;
+  private:
+    bool _direction;
+    Edge *_ptr;
+  };
+}
+
+#endif
diff --git a/src/INTERP_KERNEL/Geometric2D/Node.cxx b/src/INTERP_KERNEL/Geometric2D/Node.cxx
new file mode 100644 (file)
index 0000000..ed60e38
--- /dev/null
@@ -0,0 +1,87 @@
+#include "Node.hxx"
+#include "EdgeArcCircle.hxx"
+
+using namespace std;
+using namespace INTERP_KERNEL;
+
+const double Node::CST_FOR_XFIG=1e4;
+
+Node::Node(double x, double y):_isToDel(true),_cnt(1),_loc(UNKNOWN)
+{
+  const unsigned SPACEDIM=2;
+  _coords=new double[SPACEDIM];
+  _coords[0]=x; _coords[1]=y;
+}
+
+Node::Node(const double *coords):_isToDel(false),_cnt(1),_loc(UNKNOWN),_coords((double *)coords)
+{
+}
+
+Node::Node(std::istream& stream):_isToDel(true),_cnt(1),_loc(UNKNOWN)
+{
+  const unsigned SPACEDIM=2;
+  _coords=new double[SPACEDIM];
+  for(unsigned i=0;i<SPACEDIM;i++)
+    {
+      int tmp;
+      stream >> tmp;
+      _coords[i]=((double) tmp)/CST_FOR_XFIG;
+    }
+}
+
+Node::~Node()
+{
+  if(_isToDel)
+    delete [] _coords;
+}
+
+bool Node::decrRef()
+{
+  bool ret=(--_cnt==0);
+  if(ret)
+    delete this;
+  return ret;
+}
+
+bool Node::isEqual(const Node& other) const
+{
+  const unsigned SPACEDIM=2;
+  bool ret=true;
+  for(unsigned i=0;i<SPACEDIM;i++)
+    ret&=areDoubleEquals((*this)[i],other[i]);
+  return ret;
+}
+
+double Node::getSlope(const Node& other) const
+{
+  double x=other[0]-(*this)[0];
+  double y=other[1]-(*this)[1];
+  double norm=sqrt(x*x+y*y);
+  double ret=EdgeArcCircle::safeAcos(fabs(x)/norm);
+  if( (x>=0. && y>=0.) || (x<0. && y<0.) )
+    return ret;
+  else
+    return M_PI-ret;
+}
+
+/*!
+ * Convenient method. Equivalent to isEqual method. In case of true is returned, '&other' is
+ * added in 'track' container.
+ */
+bool Node::isEqualAndKeepTrack(const Node& other, std::vector<Node *>& track) const
+{
+  bool ret=isEqual(other);
+  if(ret)
+    track.push_back((Node *)&other);
+  return ret;
+}
+
+void Node::dumpInXfigFile(std::ostream& stream) const
+{
+  stream << (int)(_coords[0]*CST_FOR_XFIG) << " " << (int)(_coords[1]*CST_FOR_XFIG) << " ";
+}
+
+double Node::distanceWithSq(const Node& other) const
+{
+  return (_coords[0]-other._coords[0])*(_coords[0]-other._coords[0])+(_coords[1]-other._coords[1])*(_coords[1]-other._coords[1]);
+}
diff --git a/src/INTERP_KERNEL/Geometric2D/Node.hxx b/src/INTERP_KERNEL/Geometric2D/Node.hxx
new file mode 100644 (file)
index 0000000..45c4025
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef __NODE_HXX__
+#define __NODE_HXX__
+
+#include "Precision.hxx"
+
+#include <cmath>
+#include <vector>
+#include <iostream>
+
+namespace INTERP_KERNEL
+{
+  typedef enum
+    {
+      IN_1      =  7,
+      ON_1      =  8,
+      ON_LIM_1  = 12,
+      ON_TANG_1 =  9,
+      OUT_1     = 10,
+      UNKNOWN   = 11
+    } TypeOfLocInPolygon;
+  
+  /*!
+   * As nodes can be shared between edges it is dealed with ref counting.
+   */
+  class Node
+  {
+  public:
+    Node(double x, double y);
+    Node(const double *coords);
+    Node(std::istream& stream);
+    void incrRef() const { _cnt++; }
+    bool decrRef();
+    TypeOfLocInPolygon getLoc() const { return _loc; }
+    void declareIn() const { if(_loc==UNKNOWN) _loc=IN_1; }
+    void declareOn() const { if(_loc==UNKNOWN) _loc=ON_1; }
+    void declareOnLim() const { if(_loc==UNKNOWN || _loc==ON_1) _loc=ON_LIM_1; }
+    void declareOut() { if(_loc==UNKNOWN) _loc=OUT_1; }
+    void declareOnTangent() { _loc=ON_TANG_1; }
+    operator const double*() const { return _coords; }
+    bool isEqual(const Node& other) const;
+    double getSlope(const Node& other) const;
+    bool isEqualAndKeepTrack(const Node& other, std::vector<Node *>& track) const;
+    void dumpInXfigFile(std::ostream& stream) const;
+    double distanceWithSq(const Node& other) const;
+    double operator[](int i) const { return _coords[i]; }
+    //!for tests only !
+    void setNewCoords(double x, double y) { _coords[0]=x; _coords[1]=y; }
+    static double sign(double val) { if(val>=0) return 1.; else return -1.; }
+    static bool areDoubleEquals(double a, double b) { return fabs(a-b) < QUADRATIC_PLANAR::_precision; }
+    //! idem areDoubleEquals except that precision of comparison is modified.
+    static bool areDoubleEqualsWP(double a, double b, double k) { return fabs(a-b) < k*QUADRATIC_PLANAR::_precision; }
+    static double distanceBtw2Pt(const double *a, const double *b) { return sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])); }
+  protected:
+    ~Node();
+  protected:
+    bool _isToDel;
+    mutable unsigned char _cnt;
+    mutable TypeOfLocInPolygon _loc;
+    double *_coords;
+  public:
+    static const double CST_FOR_XFIG;
+  };
+}
+
+#endif
diff --git a/src/INTERP_KERNEL/Geometric2D/Pol1.fig b/src/INTERP_KERNEL/Geometric2D/Pol1.fig
new file mode 100644 (file)
index 0000000..be55cc8
--- /dev/null
@@ -0,0 +1,15 @@
+#FIG 3.2  Produced by xfig version 3.2.5-alpha5
+Landscape
+Center
+Inches
+Letter  
+100.00
+Single
+-2
+1200 2
+5 1 0 1 0 7 50 -1 -1 0.000 0 1 0 0 2700.000 4800.000 3600 6000 4200 4800 3600 3600
+5 1 0 1 0 7 50 -1 -1 0.000 0 1 0 0 5400.000 1200.000 3600 3600 5400 4200 7200 3600
+5 1 0 1 0 7 50 -1 -1 0.000 0 0 0 0 5100.000 6300.000 7200 3600 7800 4200 8400 5400
+5 1 0 1 0 7 50 -1 -1 0.000 0 1 0 0 8400.000 6000.000 8400 5400 7800 6000 8400 6600
+5 1 0 1 0 7 50 -1 -1 0.000 0 1 0 0 9128.571 9642.857 8400 6600 6600 7800 6000 9600
+5 1 0 1 0 7 50 -1 -1 0.000 0 1 0 0 2820.000 9120.000 6000 9600 5400 7200 3600 6000
diff --git a/src/INTERP_KERNEL/Geometric2D/Pol2.fig b/src/INTERP_KERNEL/Geometric2D/Pol2.fig
new file mode 100644 (file)
index 0000000..4778e67
--- /dev/null
@@ -0,0 +1,13 @@
+#FIG 3.2  Produced by xfig version 3.2.5-alpha5
+Landscape
+Center
+Inches
+Letter  
+100.00
+Single
+-2
+1200 2
+5 1 0 1 0 7 50 -1 -1 0.000 0 0 0 0 13000.000 7200.000 6600 9000 6600 5400 8400 2400
+5 1 0 1 0 7 50 -1 -1 0.000 0 1 0 0 10500.000 -900.000 8400 2400 10800 3000 12600 2400
+5 1 0 1 0 7 50 -1 -1 0.000 0 1 0 0 16242.857 6471.429 12600 2400 10800 6000 11400 9000
+5 1 0 1 0 7 50 -1 -1 0.000 0 0 0 0 9000.000 13500.000 6600 9000 9000 8400 11400 9000
diff --git a/src/INTERP_KERNEL/Geometric2D/Pol3.fig b/src/INTERP_KERNEL/Geometric2D/Pol3.fig
new file mode 100644 (file)
index 0000000..4bad144
--- /dev/null
@@ -0,0 +1,11 @@
+#FIG 3.2  Produced by xfig version 3.2.5-alpha5
+Landscape
+Center
+Inches
+Letter  
+100.00
+Single
+-2
+1200 2
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+3000 7200 6600 3600
diff --git a/src/INTERP_KERNEL/Geometric2D/Pol4.fig b/src/INTERP_KERNEL/Geometric2D/Pol4.fig
new file mode 100644 (file)
index 0000000..1c6cd79
--- /dev/null
@@ -0,0 +1,10 @@
+#FIG 3.2  Produced by xfig version 3.2.5-alpha5
+Landscape
+Center
+Inches
+Letter  
+100.00
+Single
+-2
+1200 2
+5 1 0 1 0 7 50 -1 -1 0.000 0 0 0 0 4800.000 4837.500 4200 7200 4800 2400 5400 7200
diff --git a/src/INTERP_KERNEL/Geometric2D/Precision.hxx b/src/INTERP_KERNEL/Geometric2D/Precision.hxx
new file mode 100644 (file)
index 0000000..5eb7913
--- /dev/null
@@ -0,0 +1,7 @@
+namespace INTERP_KERNEL
+{
+  namespace QUADRATIC_PLANAR
+  {
+    static double _precision=1e-14;
+  }
+}
diff --git a/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpRun.cxx b/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpRun.cxx
new file mode 100644 (file)
index 0000000..ffa8e9b
--- /dev/null
@@ -0,0 +1,12 @@
+
+#define UNIT_TEST_HEADER " --- TEST src/engine EngineTest"
+
+#include "QuadraticPlanarInterpTest.hxx"
+
+// --- Registers the fixture into the 'registry'
+
+CPPUNIT_TEST_SUITE_REGISTRATION( INTERP_KERNEL::QuadraticPlanarInterpTest );
+
+// --- generic Main program from bases/Test
+
+#include "BasicMainTest.hxx"
diff --git a/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest.cxx b/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest.cxx
new file mode 100644 (file)
index 0000000..b5da3ca
--- /dev/null
@@ -0,0 +1,812 @@
+#include "QuadraticPlanarInterpTest.hxx"
+#include "QuadraticPolygon.hxx"
+#include "EdgeArcCircle.hxx"
+#include "ElementaryEdge.hxx"
+#include "ComposedEdge.hxx"
+#include "EdgeLin.hxx"
+
+#include <sstream>
+#include <iostream>
+
+using namespace std;
+using namespace INTERP_KERNEL;
+
+static const double ADMISSIBLE_ERROR = 1.e-14;
+
+void QuadraticPlanarInterpTest::setUp()
+{
+}
+
+void QuadraticPlanarInterpTest::tearDown()
+{
+}
+
+void QuadraticPlanarInterpTest::cleanUp()
+{
+}
+
+void QuadraticPlanarInterpTest::ReadWriteInXfigElementary()
+{
+  //Testing bounds calculation. For Seg2
+  istringstream stream("2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2\n3200 3400 4500 4700");
+  EdgeLin *e1=new EdgeLin(stream);
+  Bounds bound=e1->getBounds();
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.32,bound[0],ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.45,bound[1],ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.34,bound[2],ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.47,bound[3],ADMISSIBLE_ERROR);
+  e1->decrRef();
+  istringstream stream2("2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2\n4500 4700 3200 3400");
+  e1=new EdgeLin(stream2);
+  bound=e1->getBounds();
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.32,bound[0],ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.45,bound[1],ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.34,bound[2],ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.47,bound[3],ADMISSIBLE_ERROR);
+  e1->decrRef();
+  //Testing bounds calculation For Arc of circle.
+  
+}
+
+void QuadraticPlanarInterpTest::ReadWriteInXfigGlobal()
+{
+  QuadraticPolygon pol1("Pol1.fig");
+  pol1.dumpInXfigFile("Pol1_gen.fig");
+  QuadraticPolygon pol2("Pol2.fig");
+  pol2.dumpInXfigFile("Pol2_gen.fig");
+  QuadraticPolygon pol3("Pol3.fig");
+  pol3.dumpInXfigFile("Pol3_gen.fig");
+  QuadraticPolygon pol4("Pol4.fig");
+  CPPUNIT_ASSERT_EQUAL(1,pol4.size());
+  ElementaryEdge *edge1=dynamic_cast<ElementaryEdge *>(pol4[0]);
+  CPPUNIT_ASSERT(edge1);
+  Edge *edge2=edge1->getPtr();
+  EdgeArcCircle *edge=dynamic_cast<EdgeArcCircle *>(edge2);
+  CPPUNIT_ASSERT(edge);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.24375,edge->getRadius(),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(5.7857653289925404,edge->getAngle(),ADMISSIBLE_ERROR);
+  double center[2];
+  edge->getCenter(center);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.48,center[0],ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.48375,center[1],ADMISSIBLE_ERROR);
+  const double *start=*edge->getStartNode();
+  Node *n1=new Node(start[0]+2*(center[0]-start[0]),start[1]+2*(center[1]-start[1]));
+  edge->changeMiddle(n1);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.24375,edge->getRadius(),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(5.7857653289925404,edge->getAngle(),ADMISSIBLE_ERROR);
+  n1->decrRef();
+  n1=new Node(center[0],center[1]+0.24375);
+  edge->changeMiddle(n1);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.24375,edge->getRadius(),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.49741997818704586,edge->getAngle(),ADMISSIBLE_ERROR);//5.7857653289925404 + 2*PI
+  n1->decrRef();
+  //A half circle.
+  EdgeArcCircle *e=new EdgeArcCircle(0.84,0.54,0.78,0.6,0.84,0.66);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.06,e->getRadius(),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(-3.1415925921507317,e->getAngle(),1e-5);
+  e->decrRef();
+  e=new EdgeArcCircle(0.84,0.54,0.9,0.6,0.84,0.66);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.06,e->getRadius(),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(3.1415925921507317,e->getAngle(),1e-5);
+  e->decrRef();
+}
+
+void QuadraticPlanarInterpTest::IntersectionBasics()
+{
+  //Testing intersection of Bounds.
+  istringstream stream1("2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2\n3200 3400 4500 4800");
+  EdgeLin *e1=new EdgeLin(stream1);
+  istringstream stream2("2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2\n3200 3400 4500 4800");
+  EdgeLin *e2=new EdgeLin(stream2);
+  Bounds *bound=e1->getBounds().amIIntersectingWith(e2->getBounds()); CPPUNIT_ASSERT(bound);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.32,(*bound)[0],ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.45,(*bound)[1],ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.34,(*bound)[2],ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.48,(*bound)[3],ADMISSIBLE_ERROR);
+  delete bound;
+  e2->decrRef(); e1->decrRef();
+  //
+  istringstream stream3("2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2\n3000 7200 6000 3700");
+  EdgeLin *e3=new EdgeLin(stream3);
+  istringstream stream4("2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2\n4800 6600 7200 4200");
+  EdgeLin *e4=new EdgeLin(stream4);
+  bound=e3->getBounds().amIIntersectingWith(e4->getBounds()); CPPUNIT_ASSERT(bound);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.48,(*bound)[0],ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.6,(*bound)[1],ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.42,(*bound)[2],ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.66,(*bound)[3],ADMISSIBLE_ERROR);
+  delete bound;
+  e3->decrRef(); e4->decrRef();
+}
+
+void QuadraticPlanarInterpTest::EdgeLinUnitary()
+{
+  EdgeLin *e1=new EdgeLin(0.5,0.5,3.7,4.1);
+  Node *n=new Node(2.1,2.3);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getCharactValue(*n),0.5,1e-8);
+  n->decrRef();
+  n=new Node(3.7,4.1);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getCharactValue(*n),1.,1e-8);
+  n->decrRef();
+  n=new Node(0.5,0.5);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getCharactValue(*n),0.,1e-8);
+  n->decrRef();
+  n=new Node(-1.1,-1.3);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getCharactValue(*n),-0.5,1e-8);
+  n->decrRef();
+  n=new Node(5.3,5.9);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getCharactValue(*n),1.5,1e-8);
+  n->decrRef(); e1->decrRef();
+}
+
+/*!
+ * Here two things are tested. 
+ * 1 ) One the overlapping calculation capability of edge/edge intersector.
+ * 2 ) Then the capability to handle the case where 2 segs (whatever their type) are overlapped.
+ * All the configuration of full or part overlapping have been tested.
+ */
+void QuadraticPlanarInterpTest::IntersectionEdgeOverlapUnitarySegSeg()
+{
+  ComposedEdge& v1=*(new ComposedEdge);
+  ComposedEdge& v2=*(new ComposedEdge);
+  MergePoints v3;
+  //Testing merge of geometric equals seg2.
+  EdgeLin *e1=new EdgeLin(0.5,0.5,1.,1.); EdgeLin *e2=new EdgeLin(0.5,0.5,1.,1.);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(2,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v1.size()); CPPUNIT_ASSERT_EQUAL(1,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e1) && v2[0]->getDirection());
+  v1.clear(); v2.clear(); v3.clear();
+  //  - testing by adding some noise
+  e1->decrRef(); e1=new EdgeLin(0.5+5.e-15,0.5-5.e-15,1.,1.+7.e-15);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(2,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v1.size()); CPPUNIT_ASSERT_EQUAL(1,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e1) && v2[0]->getDirection());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Testing merge of geometric equals seg2 but now with opposite direction
+  e1=new EdgeLin(0.5,0.5,0.7,0.7); e2=new EdgeLin(0.7+6.e-15,0.7-2.e-15,0.5+3.e-15,0.5-4.e-15);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(2,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v1.size()); CPPUNIT_ASSERT_EQUAL(1,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e1) && !v2[0]->getDirection());//compared 8 lines above !v2[0]->getDirection()
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 0
+  //Test 1 - OUT_AFTER - OUT_AFTER | same dir. - 0°
+  e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(1.5,0.,2.,0.);
+  CPPUNIT_ASSERT(!e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(0,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(0,(int)v2.size());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 2 - INSIDE - OUT_AFTER | same dir. - 0°
+  e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(0.5,0.,1.5,0.);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v2.size());
+  CPPUNIT_ASSERT(v1[1]->intresicEqualDirSensitive(v2[0]));
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(e1->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==v1[1]->getEndNode());
+  CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode()); CPPUNIT_ASSERT(e2->getStartNode()==v2[0]->getStartNode()); CPPUNIT_ASSERT(e2->getEndNode()==v2[1]->getEndNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 2 - INSIDE - OUT_AFTER | same dir. - 90°
+  e1=new EdgeLin(0.,0.,0.,1.); e2=new EdgeLin(0.,0.5,0.,1.5);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v2.size());
+  CPPUNIT_ASSERT(v1[1]->intresicEqualDirSensitive(v2[0]));
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(e1->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==v1[1]->getEndNode());
+  CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode()); CPPUNIT_ASSERT(e2->getStartNode()==v2[0]->getStartNode()); CPPUNIT_ASSERT(e2->getEndNode()==v2[1]->getEndNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 2 - INSIDE - OUT_AFTER | same dir. - 45°
+  e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(0.5,0.5,1.5,1.5);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v2.size());
+  CPPUNIT_ASSERT(v1[1]->intresicEqualDirSensitive(v2[0]));
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(e1->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==v1[1]->getEndNode());
+  CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode()); CPPUNIT_ASSERT(e2->getStartNode()==v2[0]->getStartNode()); CPPUNIT_ASSERT(e2->getEndNode()==v2[1]->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 2 - INSIDE - OUT_AFTER | opp. dir. - 45°
+  e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(1.5,1.5,0.5,0.5);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v2.size());
+  CPPUNIT_ASSERT(!v1[1]->intresicEqualDirSensitive(v2[1]) && v1[1]->intresicEqual(v2[1]));
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(e1->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==v1[1]->getEndNode());
+  CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode()); CPPUNIT_ASSERT(e2->getStartNode()==v2[0]->getStartNode()); CPPUNIT_ASSERT(e2->getEndNode()==v2[1]->getEndNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 3 - INSIDE - INSIDE | same dir. - 0°
+  e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(0.25,0.,0.75,0.);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(3,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v2.size());
+  CPPUNIT_ASSERT(v1[1]->intresincEqCoarse(e2) && v1[1]->getDirection());
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(v1[1]->getEndNode()==v1[2]->getStartNode());
+  CPPUNIT_ASSERT(v1[0]->getStartNode()== e1->getStartNode()); CPPUNIT_ASSERT(v1[2]->getEndNode()== e1->getEndNode());
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==e2->getStartNode()); CPPUNIT_ASSERT(v1[1]->getEndNode()==e2->getEndNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 3 - INSIDE - INSIDE | same dir. - 90°
+  e1=new EdgeLin(0.,0.,0.,1.); e2=new EdgeLin(0.,0.25,0.,0.75);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(3,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v2.size());
+  CPPUNIT_ASSERT(v1[1]->intresincEqCoarse(e2) && v1[1]->getDirection());
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(v1[1]->getEndNode()==v1[2]->getStartNode());
+  CPPUNIT_ASSERT(v1[0]->getStartNode()== e1->getStartNode()); CPPUNIT_ASSERT(v1[2]->getEndNode()== e1->getEndNode());
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==e2->getStartNode()); CPPUNIT_ASSERT(v1[1]->getEndNode()==e2->getEndNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 3 - INSIDE - INSIDE | same dir. - 45°
+  e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(0.25,0.25,0.75,0.75);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(3,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v2.size());
+  CPPUNIT_ASSERT(v1[1]->intresincEqCoarse(e2) && v1[1]->getDirection());
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(v1[1]->getEndNode()==v1[2]->getStartNode());
+  CPPUNIT_ASSERT(v1[0]->getStartNode()== e1->getStartNode()); CPPUNIT_ASSERT(v1[2]->getEndNode()== e1->getEndNode());
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==e2->getStartNode()); CPPUNIT_ASSERT(v1[1]->getEndNode()==e2->getEndNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 3 - INSIDE - INSIDE | opp dir. - 45°
+  e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(0.75,0.75,0.25,0.25);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(3,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v2.size());
+  CPPUNIT_ASSERT(v1[1]->intresincEqCoarse(e2) && !v1[1]->getDirection());
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(v1[1]->getEndNode()==v1[2]->getStartNode());
+  CPPUNIT_ASSERT(v1[0]->getStartNode()== e1->getStartNode()); CPPUNIT_ASSERT(v1[2]->getEndNode()== e1->getEndNode());
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==e2->getEndNode()); CPPUNIT_ASSERT(v1[1]->getEndNode()==e2->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 4 - OUT_BEFORE - OUT_BEFORE | same dir. - 0 °
+  e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(-1.,0.,-0.5,0.);
+  CPPUNIT_ASSERT(!e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(0,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(0,(int)v2.size());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 5 - OUT_BEFORE - INSIDE | same dir. - 0°
+  e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(-0.5,0.,0.5,0.);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresicEqualDirSensitive(v2[1]));
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 5 - OUT_BEFORE - INSIDE | same dir. - 90°
+  e1=new EdgeLin(0.,0.,0.,1.); e2=new EdgeLin(0,-0.5,0.,0.5);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresicEqualDirSensitive(v2[1]));
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 5 - OUT_BEFORE - INSIDE | same dir. - 45°
+  e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(-0.5,-0.5,0.5,0.5);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresicEqualDirSensitive(v2[1]));
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 5 - OUT_BEFORE - INSIDE | opp dir. - 45°
+  e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(0.5,0.5,-0.5,-0.5);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v2.size());
+  CPPUNIT_ASSERT(!v1[0]->intresicEqualDirSensitive(v2[0]) && v1[0]->intresicEqual(v2[0]) );
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 6 - OUT_BEFORE - OUT_AFTER | same dir. - 0°
+  e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(-0.5,0.,1.5,0.);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(3,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection());
+  CPPUNIT_ASSERT(v2[1]->intresincEqCoarse(e1) && v2[1]->getDirection());
+  CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode() && v2[1]->getEndNode()==v2[2]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 6 - OUT_BEFORE - OUT_AFTER | same dir. - 90°
+  e1=new EdgeLin(0.,0.,0.,1.); e2=new EdgeLin(0.,-0.5,0.,1.5);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(3,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection());
+  CPPUNIT_ASSERT(v2[1]->intresincEqCoarse(e1) && v2[1]->getDirection());
+  CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode() && v2[1]->getEndNode()==v2[2]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 6 - OUT_BEFORE - OUT_AFTER | same dir. - 45°
+  e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(-0.5,-0.5,1.5,1.5);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(3,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection());
+  CPPUNIT_ASSERT(v2[1]->intresincEqCoarse(e1) && v2[1]->getDirection());
+  CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode() && v2[1]->getEndNode()==v2[2]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 6 - OUT_BEFORE - OUT_AFTER | opp dir. - 45°
+  e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(1.5,1.5,-0.5,-0.5);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(3,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection());
+  CPPUNIT_ASSERT(v2[1]->intresincEqCoarse(e1) && !v2[1]->getDirection());
+  CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode() && v2[1]->getEndNode()==v2[2]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 7 - END - OUT_AFTER | same dir. - 0°
+  e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(1.,0.,1.5,0.);
+  CPPUNIT_ASSERT(!e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(0,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(0,(int)v2.size());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 7 - END - OUT_AFTER | opp dir. - 0°
+  e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(1.5,0.,1.,0.);
+  CPPUNIT_ASSERT(!e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(0,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(0,(int)v2.size());
+  CPPUNIT_ASSERT(e1->getEndNode()==e2->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 8 - START - END | same dir. - 0°
+  e1=new EdgeLin(0.,0.,0.7,0.); e2=new EdgeLin(0.,0.,0.7,0.);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(2,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e1) && v2[0]->getDirection());
+  CPPUNIT_ASSERT(e1->getStartNode()==e2->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==e2->getEndNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 8 - START - END | same dir. - 90°
+  e1=new EdgeLin(0.,0.,0.,0.7); e2=new EdgeLin(0.,0.,0.,0.7);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(2,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e1) && v2[0]->getDirection());
+  CPPUNIT_ASSERT(e1->getStartNode()==e2->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==e2->getEndNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 8 - START - END | same dir. - 45°
+  e1=new EdgeLin(0.,0.,0.7,0.7); e2=new EdgeLin(0.,0.,0.7,0.7);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(2,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e1) && v2[0]->getDirection());
+  CPPUNIT_ASSERT(e1->getStartNode()==e2->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==e2->getEndNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 8 - START - END | opp. dir. - 45°
+  e1=new EdgeLin(0.,0.,0.7,0.7); e2=new EdgeLin(0.7,0.7,0.,0.);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(2,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e1) && !v2[0]->getDirection());
+  CPPUNIT_ASSERT(e1->getStartNode()==e2->getEndNode()); CPPUNIT_ASSERT(e1->getEndNode()==e2->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 9 - OUT_BEFORE - START | same dir.
+  e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(-0.5,0.,0.,0.);
+  CPPUNIT_ASSERT(!e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(0,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(0,(int)v2.size());
+  CPPUNIT_ASSERT(e2->getEndNode()==e1->getStartNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 10 - START - OUT_AFTER | same dir. - 0°
+  e1=new EdgeLin(0.,0.,0.7,0.); e2=new EdgeLin(0.,0.,1.,0.);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e1) && v2[0]->getDirection()); 
+  CPPUNIT_ASSERT(e1->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getStartNode()==e2->getStartNode()); CPPUNIT_ASSERT(v2[1]->getEndNode()==e2->getEndNode());
+  CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 10 - START - OUT_AFTER | same dir. - 90°
+  e1=new EdgeLin(0.,0.,0.,0.7); e2=new EdgeLin(0.,0.,0.,1.);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e1) && v2[0]->getDirection()); 
+  CPPUNIT_ASSERT(e1->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getStartNode()==e2->getStartNode()); CPPUNIT_ASSERT(v2[1]->getEndNode()==e2->getEndNode());
+  CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 10 - START - OUT_AFTER | same dir. - 45°
+  e1=new EdgeLin(0.,0.,0.7,0.7); e2=new EdgeLin(0.,0.,1.,1.);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e1) && v2[0]->getDirection()); 
+  CPPUNIT_ASSERT(e1->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getStartNode()==e2->getStartNode()); CPPUNIT_ASSERT(v2[1]->getEndNode()==e2->getEndNode());
+  CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 10 - START - OUT_AFTER | opp dir. - 45°
+  e1=new EdgeLin(0.,0.,0.7,0.7); e2=new EdgeLin(1.,1.,0.,0.);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[1]->intresincEqCoarse(e1) && !v2[1]->getDirection()); 
+  CPPUNIT_ASSERT(e1->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getStartNode()==e2->getEndNode()); CPPUNIT_ASSERT(v2[1]->getEndNode()==e2->getEndNode());
+  CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 11 - INSIDE - END | same dir. - 0°
+  e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(0.7,0.,1.,0.);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v2.size());
+  CPPUNIT_ASSERT(v1[1]->intresincEqCoarse(e2) && v1[1]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e2) && v2[0]->getDirection()); 
+  CPPUNIT_ASSERT(e1->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==v1[1]->getEndNode()); CPPUNIT_ASSERT(e1->getEndNode()==e2->getEndNode());
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 11 - INSIDE - END | same dir. - 90°
+  e1=new EdgeLin(0.,0.,0.,1.); e2=new EdgeLin(0.,0.7,0.,1.);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v2.size());
+  CPPUNIT_ASSERT(v1[1]->intresincEqCoarse(e2) && v1[1]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e2) && v2[0]->getDirection()); 
+  CPPUNIT_ASSERT(e1->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==v1[1]->getEndNode()); CPPUNIT_ASSERT(e1->getEndNode()==e2->getEndNode());
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 11 - INSIDE - END | same dir. - 45°
+  e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(0.7,0.7,1.,1.);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v2.size());
+  CPPUNIT_ASSERT(v1[1]->intresincEqCoarse(e2) && v1[1]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e2) && v2[0]->getDirection()); 
+  CPPUNIT_ASSERT(e1->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==v1[1]->getEndNode()); CPPUNIT_ASSERT(e1->getEndNode()==e2->getEndNode());
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 11 - INSIDE - END | opp dir. - 45°
+  e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(1.,1.,0.7,0.7);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v2.size());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==v1[1]->getEndNode()); CPPUNIT_ASSERT(e1->getEndNode()==e2->getStartNode());
+  CPPUNIT_ASSERT(v1[1]->intresincEqCoarse(e2) && !v1[1]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e2) && v2[0]->getDirection()); 
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 12 - OUT_BEFORE - END | same dir. - 0°
+  e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(-0.5,0.,1.,0.);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[1]->intresincEqCoarse(e1) && v2[1]->getDirection());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2[0]->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==e2->getEndNode()); CPPUNIT_ASSERT(e2->getEndNode()==v2[1]->getEndNode());
+  CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 12 - OUT_BEFORE - END | same dir. - 90°
+  e1=new EdgeLin(0.,0.,0.,1.); e2=new EdgeLin(0.,-0.5,0.,1.);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[1]->intresincEqCoarse(e1) && v2[1]->getDirection());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2[0]->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==e2->getEndNode()); CPPUNIT_ASSERT(e2->getEndNode()==v2[1]->getEndNode());
+  CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 12 - OUT_BEFORE - END | same dir. - 45°
+  e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(-0.5,-0.5,1.,1.);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[1]->intresincEqCoarse(e1) && v2[1]->getDirection());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2[0]->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==e2->getEndNode()); CPPUNIT_ASSERT(e2->getEndNode()==v2[1]->getEndNode());
+  CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 12 - OUT_BEFORE - END | opp dir. - 45°
+  e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(1.,1.,-0.5,-0.5);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e1) && !v2[0]->getDirection());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2[0]->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==e2->getStartNode()); CPPUNIT_ASSERT(e2->getEndNode()==v2[1]->getEndNode());
+  CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 13 - START - INSIDE | same dir. - 0°
+  e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(0.,0.,0.5,0.);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e2) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e2) && v2[0]->getDirection());
+  CPPUNIT_ASSERT(e2->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getStartNode()==e2->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==v1[1]->getEndNode());
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 13 - START - INSIDE | same dir. - 90°
+  e1=new EdgeLin(0.,0.,0.,1.); e2=new EdgeLin(0.,0.,0.,0.5);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e2) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e2) && v2[0]->getDirection());
+  CPPUNIT_ASSERT(e2->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getStartNode()==e2->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==v1[1]->getEndNode());
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 13 - START - INSIDE | same dir. - 45°
+  e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(0.,0.,0.5,0.5);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e2) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e2) && v2[0]->getDirection());
+  CPPUNIT_ASSERT(e2->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getStartNode()==e2->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==v1[1]->getEndNode());
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 13 - START - INSIDE | opp dir. - 45°
+  e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(0.5,0.5,0.,0.);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e2) && !v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e2) && v2[0]->getDirection());
+  CPPUNIT_ASSERT(e2->getEndNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getStartNode()==e2->getEndNode()); CPPUNIT_ASSERT(e1->getEndNode()==v1[1]->getEndNode());
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  ComposedEdge::Delete(&v1);
+  ComposedEdge::Delete(&v2);
+}
+
+/*!
+ * Here there is test of cases where between 2 edges intersects only in points not on edge.
+ */
+void QuadraticPlanarInterpTest::IntersectionPointOnlyUnitarySegSeg()
+{
+  // 0° - classical
+  EdgeLin *e1=new EdgeLin(0.,0.,1.,0.);
+  EdgeLin *e2=new EdgeLin(0.3,0.3,0.5,-0.3);
+  ComposedEdge& v1=*(new ComposedEdge);
+  ComposedEdge& v2=*(new ComposedEdge); MergePoints v3;
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.4,(*v1[0]->getEndNode())[0],ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.,(*v1[0]->getEndNode())[1],ADMISSIBLE_ERROR);
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  // 90° - classical
+  e1=new EdgeLin(0.,0.,0.,1.);
+  e2=new EdgeLin(-0.3,0.3,0.3,0.5);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v2.size());
+  CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode());
+  CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode());
+  CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode());
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.,(*v1[0]->getEndNode())[0],ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.4,(*v1[0]->getEndNode())[1],ADMISSIBLE_ERROR);
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 1 - 0°
+  e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(0.,0.,0.,1.);
+  CPPUNIT_ASSERT(!e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT(v3.isStart1(0)); CPPUNIT_ASSERT(v3.isStart2(0));
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 1 - 90°
+  e1=new EdgeLin(0.,0.,0.,1.); e2=new EdgeLin(0.,0.,1.,0.);
+  CPPUNIT_ASSERT(!e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT(v3.isStart1(0)); CPPUNIT_ASSERT(v3.isStart2(0));
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 1 - 45°
+  e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(0.,0.,1.,-1.);
+  CPPUNIT_ASSERT(!e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT(v3.isStart1(0)); CPPUNIT_ASSERT(v3.isStart2(0));
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 2
+  e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(1.,1.,1.,0.);
+  CPPUNIT_ASSERT(!e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT(v3.isEnd1(0)); CPPUNIT_ASSERT(v3.isEnd2(0));
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 3
+  e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(1.,0.,1.,1.);
+  CPPUNIT_ASSERT(!e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT(v3.isEnd1(0)); CPPUNIT_ASSERT(v3.isStart2(0));
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Test 4
+  e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(1.,-1.,0.,0.);
+  CPPUNIT_ASSERT(!e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT(v3.isStart1(0)); CPPUNIT_ASSERT(v3.isEnd2(0));
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Intersection extremity of one edge and inside of other edge. 2 End.
+  e1=new EdgeLin(0.,0.,1.,0.);
+  e2=new EdgeLin(0.5,1.,0.5,0.);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(2,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v2.size());
+  CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e2) && v2[0]->getDirection());
+  CPPUNIT_ASSERT(v1[0]->getStartNode()==e1->getStartNode() && v1[0]->getEndNode()==e2->getEndNode() && v1[1]->getStartNode()==e2->getEndNode() && v1[1]->getEndNode()==e1->getEndNode());
+  CPPUNIT_ASSERT(v1[0]->getDirection() && v1[1]->getDirection());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Intersection extremity of one edge and inside of other edge. 2 Start.
+  e1=new EdgeLin(0.,0.,1.,0.);
+  e2=new EdgeLin(0.5,0.,0.5,1.);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(2,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(1,(int)v2.size());
+  CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e2) && v2[0]->getDirection());
+  CPPUNIT_ASSERT(v1[0]->getStartNode()==e1->getStartNode() && v1[0]->getEndNode()==e2->getStartNode() && v1[1]->getStartNode()==e2->getStartNode() && v1[1]->getEndNode()==e1->getEndNode());
+  CPPUNIT_ASSERT(v1[0]->getDirection() && v1[1]->getDirection());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Intersection extremity of one edge and inside of other edge. 1 Start.
+  e1=new EdgeLin(0.5,0.,0.5,1.);
+  e2=new EdgeLin(0.,0.,1.,0.);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v2.size());
+  CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection());
+  CPPUNIT_ASSERT(v2[0]->getStartNode()==e2->getStartNode() && v2[0]->getEndNode()==e1->getStartNode() && v2[1]->getStartNode()==e1->getStartNode() && v2[1]->getEndNode()==e2->getEndNode());
+  CPPUNIT_ASSERT(v2[0]->getDirection() && v2[1]->getDirection());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  //Intersection extremity of one edge and inside of other edge. 1 End.
+  e1=new EdgeLin(0.5,1.,0.5,0.);
+  e2=new EdgeLin(0.,0.,1.,0.);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2));
+  CPPUNIT_ASSERT_EQUAL(1,(int)v1.size());
+  CPPUNIT_ASSERT_EQUAL(2,(int)v2.size());
+  CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection());
+  CPPUNIT_ASSERT(v2[0]->getStartNode()==e2->getStartNode() && v2[0]->getEndNode()==e1->getEndNode() && v2[1]->getStartNode()==e1->getEndNode() && v2[1]->getEndNode()==e2->getEndNode());
+  CPPUNIT_ASSERT(v2[0]->getDirection() && v2[1]->getDirection());
+  e2->decrRef(); e1->decrRef();
+  v1.clear(); v2.clear(); v3.clear();
+  ComposedEdge::Delete(&v2);
+  ComposedEdge::Delete(&v1);
+}
diff --git a/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest.hxx b/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest.hxx
new file mode 100644 (file)
index 0000000..8e95387
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef _QUADRATICPLANARINTERPTEST_HXX_
+#define _QUADRATICPLANARINTERPTEST_HXX_
+
+#include <cppunit/extensions/HelperMacros.h>
+
+namespace INTERP_KERNEL
+{
+  class Node;
+  class EdgeArcCircle;
+  class QuadraticPolygon;
+
+  class QuadraticPlanarInterpTest : public CppUnit::TestFixture
+  {
+    CPPUNIT_TEST_SUITE( QuadraticPlanarInterpTest );
+    CPPUNIT_TEST( ReadWriteInXfigElementary );
+    CPPUNIT_TEST( ReadWriteInXfigGlobal );
+    CPPUNIT_TEST( IntersectionBasics );
+    CPPUNIT_TEST( EdgeLinUnitary );
+    CPPUNIT_TEST( IntersectionEdgeOverlapUnitarySegSeg );
+    CPPUNIT_TEST( IntersectionPointOnlyUnitarySegSeg );
+    CPPUNIT_TEST( IntersectArcCircleBase );
+    CPPUNIT_TEST( IntersectArcCircleFull );
+    CPPUNIT_TEST( IntersectArcCircleSegumentBase );
+    CPPUNIT_TEST( checkInOutDetection );
+    CPPUNIT_TEST( checkAssemblingBases1 );
+    CPPUNIT_TEST( checkAssemblingBases2 );
+    CPPUNIT_TEST( checkPolygonsIntersection1 );
+    CPPUNIT_TEST( checkAreasCalculations );
+    CPPUNIT_TEST_SUITE_END();
+  public:  
+    void setUp();
+    void tearDown();
+    void cleanUp();
+    //
+    void ReadWriteInXfigElementary();
+    void ReadWriteInXfigGlobal();
+    void IntersectionBasics();
+    void EdgeLinUnitary();
+    void IntersectionEdgeOverlapUnitarySegSeg();
+    void IntersectionPointOnlyUnitarySegSeg();
+    //
+    void IntersectArcCircleBase();
+    void IntersectArcCircleFull();
+    void IntersectArcCircleSegumentBase();
+    //
+    void checkInOutDetection();
+    //
+    void checkAssemblingBases1();
+    void checkAssemblingBases2();
+    //
+    void checkPolygonsIntersection1();
+    void checkAreasCalculations();
+  private:
+    EdgeArcCircle *buildArcOfCircle(const double *center, double radius, double alphaStart, double alphaEnd);
+    double btw2NodesAndACenter(const Node& n1, const Node& n2, const double *center);
+    void checkBasicsOfPolygons(QuadraticPolygon& pol1, QuadraticPolygon& pol2, bool checkDirection);
+  };
+}
+
+#endif
diff --git a/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest2.cxx b/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest2.cxx
new file mode 100644 (file)
index 0000000..cb5c180
--- /dev/null
@@ -0,0 +1,639 @@
+#include "QuadraticPlanarInterpTest.hxx"
+#include "QuadraticPolygon.hxx"
+#include "EdgeArcCircle.hxx"
+#include "EdgeLin.hxx"
+
+#include <cmath>
+#include <sstream>
+#include <iostream>
+
+using namespace std;
+using namespace INTERP_KERNEL;
+
+static const double ADMISSIBLE_ERROR = 1.e-14;
+
+void QuadraticPlanarInterpTest::IntersectArcCircleBase()
+{
+  double center[2]={0.5,0.5};
+  double radius=0.3;
+  EdgeArcCircle *e1=buildArcOfCircle(center,radius,M_PI/4.,M_PI/3.);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[0],center[0]+radius*cos(M_PI/3),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[1],center[0]+radius*cos(M_PI/4),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[2],center[1]+radius*sin(M_PI/4),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[3],center[1]+radius*sin(M_PI/3),ADMISSIBLE_ERROR);
+  e1->decrRef();
+  //
+  e1=buildArcOfCircle(center,radius,M_PI/3.,M_PI/2.);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[0],center[0]+radius*cos(M_PI/2),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[1],center[0]+radius*cos(M_PI/3),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[2],center[1]+radius*sin(M_PI/3),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[3],center[1]+radius*sin(M_PI/2),ADMISSIBLE_ERROR);
+  e1->decrRef();
+  //
+  e1=buildArcOfCircle(center,radius,M_PI/3.,3.*M_PI/4.);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[0],center[0]+radius*cos(3*M_PI/4),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[1],center[0]+radius*cos(M_PI/3),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[2],center[1]+radius*sin(3*M_PI/4),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[3],center[1]+radius*sin(M_PI/2),ADMISSIBLE_ERROR);//<<
+  e1->decrRef();
+  //
+  e1=buildArcOfCircle(center,radius,3*M_PI/4,7*M_PI/8);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[0],center[0]+radius*cos(7*M_PI/8),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[1],center[0]+radius*cos(3*M_PI/4),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[2],center[1]+radius*sin(7*M_PI/8),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[3],center[1]+radius*sin(3*M_PI/4),ADMISSIBLE_ERROR);
+  e1->decrRef();
+  //
+  e1=buildArcOfCircle(center,radius,7.*M_PI/8.,9.*M_PI/8.);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[0],center[0]+radius*cos(M_PI),ADMISSIBLE_ERROR);//<<
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[1],center[0]+radius*cos(7*M_PI/8),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[2],center[1]+radius*sin(9*M_PI/8),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[3],center[1]+radius*sin(7*M_PI/8),ADMISSIBLE_ERROR);
+  e1->decrRef();
+  //
+  e1=buildArcOfCircle(center,radius,9.*M_PI/8.,11.*M_PI/8.);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[0],center[0]+radius*cos(9*M_PI/8),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[1],center[0]+radius*cos(11*M_PI/8),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[2],center[1]+radius*sin(11*M_PI/8),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[3],center[1]+radius*sin(9*M_PI/8),ADMISSIBLE_ERROR);
+  e1->decrRef();
+  //
+  e1=buildArcOfCircle(center,radius,11.*M_PI/8.,7.*M_PI/4.);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[0],center[0]+radius*cos(11*M_PI/8),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[1],center[0]+radius*cos(7*M_PI/4),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[2],center[1]+radius*sin(3*M_PI/2),ADMISSIBLE_ERROR);//<<
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[3],center[1]+radius*sin(7*M_PI/4),ADMISSIBLE_ERROR);
+  e1->decrRef();
+  //
+   e1=buildArcOfCircle(center,radius,7.*M_PI/4.,15.*M_PI/8.);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[0],center[0]+radius*cos(7*M_PI/4),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[1],center[0]+radius*cos(15*M_PI/8),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[2],center[1]+radius*sin(7*M_PI/4),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[3],center[1]+radius*sin(15*M_PI/8),ADMISSIBLE_ERROR);
+  e1->decrRef();
+  //
+  e1=buildArcOfCircle(center,radius,-M_PI/8.,M_PI/4.);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[0],center[0]+radius*cos(M_PI/4),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[1],center[0]+radius*cos(0.),ADMISSIBLE_ERROR);      //<<
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[2],center[1]+radius*sin(15*M_PI/8),ADMISSIBLE_ERROR);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getBounds()[3],center[1]+radius*sin(M_PI/4),ADMISSIBLE_ERROR);
+  e1->decrRef();
+  //
+  // ArcCArcCIntersector
+  //
+  TypeOfLocInEdge where1,where2;
+  vector<Node *> v4;
+  MergePoints v3;
+  EdgeArcCircle *e2;
+  ArcCArcCIntersector *intersector=0;
+  for(unsigned k=0;k<8;k++)
+    {
+      e1=buildArcOfCircle(center,radius,M_PI/4.+k*M_PI/4.,M_PI/3.+k*M_PI/4.);
+      e2=buildArcOfCircle(center,radius,M_PI/4.+k*M_PI/4.,M_PI/3.+k*M_PI/4.);
+      intersector=new ArcCArcCIntersector(*e1,*e2);
+      intersector->getPlacements(e2->getStartNode(),e2->getEndNode(),where1,where2,v3);
+      CPPUNIT_ASSERT(where1==START && where2==END);
+      delete intersector; v3.clear(); e2->decrRef();
+      //
+      e2=buildArcOfCircle(center,radius,7*M_PI/24.+k*M_PI/4.,M_PI/3.+k*M_PI/4.);
+      intersector=new ArcCArcCIntersector(*e1,*e2);
+      intersector->getPlacements(e2->getStartNode(),e2->getEndNode(),where1,where2,v3);
+      CPPUNIT_ASSERT(where1==INSIDE && where2==END);
+      delete intersector; v3.clear(); e2->decrRef();
+      //
+      e2=buildArcOfCircle(center,radius,M_PI/4.+k*M_PI/4.,7*M_PI/24.+k*M_PI/4.);
+      intersector=new ArcCArcCIntersector(*e1,*e2);
+      intersector->getPlacements(e2->getStartNode(),e2->getEndNode(),where1,where2,v3);
+      CPPUNIT_ASSERT(where1==START && where2==INSIDE);
+      delete intersector; v3.clear(); e2->decrRef();
+      //
+      e2=buildArcOfCircle(center,radius,13.*M_PI/48.+k*M_PI/4.,15*M_PI/48.+k*M_PI/4.);
+      intersector=new ArcCArcCIntersector(*e1,*e2);
+      intersector->getPlacements(e2->getStartNode(),e2->getEndNode(),where1,where2,v3);
+      CPPUNIT_ASSERT(where1==INSIDE && where2==INSIDE);
+      delete intersector; v3.clear(); e2->decrRef();
+      //
+      e2=buildArcOfCircle(center,radius,-M_PI/4.+k*M_PI/4.,M_PI/6.+k*M_PI/4.);
+      intersector=new ArcCArcCIntersector(*e1,*e2);
+      intersector->getPlacements(e2->getStartNode(),e2->getEndNode(),where1,where2,v3);
+      CPPUNIT_ASSERT(where1==OUT_BEFORE && where2==OUT_BEFORE);
+      delete intersector; v3.clear(); e2->decrRef();
+      //
+      e2=buildArcOfCircle(center,radius,0+k*M_PI/4.,5*M_PI/6.+k*M_PI/4.);
+      intersector=new ArcCArcCIntersector(*e1,*e2);
+      intersector->getPlacements(e2->getStartNode(),e2->getEndNode(),where1,where2,v3);
+      CPPUNIT_ASSERT(where1==OUT_BEFORE && where2==OUT_AFTER);
+      delete intersector; v3.clear(); e2->decrRef();
+      e1->decrRef();
+    }
+  // Ok now let's see intersection only. 2 intersections R1 > R2 ; dist(circle1,circle2)>R1; Opposite order.
+  for(unsigned k=0;k<8;k++)
+    {
+      center[0]=0.; center[1]=0.;
+      double center2[2]; center2[0]=3.8*cos(k*M_PI/4.); center2[1]=3.8*sin(k*M_PI/4.);
+      e1=buildArcOfCircle(center,3.,(k-1)*M_PI/4.,(k+1)*M_PI/4.);
+      e2=buildArcOfCircle(center2,1.,M_PI+(k-1)*M_PI/4.,M_PI+(k+1)*M_PI/4.);
+      intersector=new ArcCArcCIntersector(*e1,*e2);
+      bool order;
+      bool obvious,areOverlapped;
+      intersector->areOverlappedOrOnlyColinears(0,obvious,areOverlapped);
+      CPPUNIT_ASSERT(!obvious && !areOverlapped);
+      CPPUNIT_ASSERT(intersector->intersect(0,v4,order,v3)); CPPUNIT_ASSERT(!order);
+      CPPUNIT_ASSERT_EQUAL(2,(int)v4.size()); CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getRadius(),Node::distanceBtw2Pt(e1->getCenter(),(*(v4[0]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e2->getRadius(),Node::distanceBtw2Pt(e2->getCenter(),(*(v4[0]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getRadius(),Node::distanceBtw2Pt(e1->getCenter(),(*(v4[1]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e2->getRadius(),Node::distanceBtw2Pt(e2->getCenter(),(*(v4[1]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT(!v4[0]->isEqual(*v4[1]));
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(btw2NodesAndACenter(*v4[0],*v4[1],e1->getCenter()),0.35587863972199624,1e-10);
+      for(vector<Node *>::iterator iter=v4.begin();iter!=v4.end();iter++)
+        (*iter)->decrRef();
+      v4.clear(); v3.clear();
+      delete intersector; e2->decrRef(); e1->decrRef();
+    }
+  // Ok now let's see intersection only. 2 intersections R1 > R2 ; dist(circle1,circle2)>R1; Same order.
+  for(unsigned k=0;k<7;k++)
+    {
+      center[0]=0.; center[1]=0.;
+      double center2[2]; center2[0]=3.8*cos(k*M_PI/4.); center2[1]=3.8*sin(k*M_PI/4.);
+      e1=buildArcOfCircle(center,3.,(k-1)*M_PI/4.,(k+1)*M_PI/4.);
+      e2=buildArcOfCircle(center2,1.,M_PI+(k+1)*M_PI/4.,M_PI+(k-1)*M_PI/4.);
+      intersector=new ArcCArcCIntersector(*e1,*e2);
+      bool order;
+      bool obvious,areOverlapped;
+      intersector->areOverlappedOrOnlyColinears(0,obvious,areOverlapped);
+      CPPUNIT_ASSERT(!obvious && !areOverlapped);
+      CPPUNIT_ASSERT(intersector->intersect(0,v4,order,v3)); CPPUNIT_ASSERT(order);
+      CPPUNIT_ASSERT_EQUAL(2,(int)v4.size()); CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getRadius(),Node::distanceBtw2Pt(e1->getCenter(),(*(v4[0]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e2->getRadius(),Node::distanceBtw2Pt(e2->getCenter(),(*(v4[0]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getRadius(),Node::distanceBtw2Pt(e1->getCenter(),(*(v4[1]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e2->getRadius(),Node::distanceBtw2Pt(e2->getCenter(),(*(v4[1]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT(!v4[0]->isEqual(*v4[1]));
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(btw2NodesAndACenter(*v4[0],*v4[1],e1->getCenter()),0.35587863972199624,1e-10);
+      for(vector<Node *>::iterator iter=v4.begin();iter!=v4.end();iter++)
+        (*iter)->decrRef();
+      v4.clear(); v3.clear();
+      delete intersector; e2->decrRef(); e1->decrRef();
+    }
+  // 2 intersections R1>R2 ; dist(circle1,circle2)<R1; Same order.
+  for(unsigned k=0;k<8;k++)
+    {
+      center[0]=0.; center[1]=0.;
+      double center2[2]; center2[0]=2.8*cos(k*M_PI/4.); center2[1]=2.8*sin(k*M_PI/4.);
+      e1=buildArcOfCircle(center,3.,(k-1)*M_PI/4.,(k+1)*M_PI/4.);
+      e2=buildArcOfCircle(center2,1.,(k)*M_PI/4.-M_PI/2.,(k)*M_PI/4.+M_PI/2.);
+      intersector=new ArcCArcCIntersector(*e1,*e2);
+      bool order;
+      bool obvious,areOverlapped;
+      intersector->areOverlappedOrOnlyColinears(0,obvious,areOverlapped);
+      CPPUNIT_ASSERT(!obvious && !areOverlapped);
+      CPPUNIT_ASSERT(intersector->intersect(0,v4,order,v3)); CPPUNIT_ASSERT(order);
+      CPPUNIT_ASSERT_EQUAL(2,(int)v4.size()); CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getRadius(),Node::distanceBtw2Pt(e1->getCenter(),(*(v4[0]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e2->getRadius(),Node::distanceBtw2Pt(e2->getCenter(),(*(v4[0]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getRadius(),Node::distanceBtw2Pt(e1->getCenter(),(*(v4[1]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e2->getRadius(),Node::distanceBtw2Pt(e2->getCenter(),(*(v4[1]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT(!v4[0]->isEqual(*v4[1]));
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(btw2NodesAndACenter(*v4[0],*v4[1],e1->getCenter()),0.6793851523346941,1e-10);
+      for(vector<Node *>::iterator iter=v4.begin();iter!=v4.end();iter++)
+        (*iter)->decrRef();
+      v4.clear(); v3.clear();
+      delete intersector; e2->decrRef(); e1->decrRef();
+    }
+  // 2 intersections R1>R2 ; dist(circle1,circle2)<R1; Opp order.
+  for(unsigned k=0;k<8;k++)
+    {
+      center[0]=0.; center[1]=0.;
+      double center2[2]; center2[0]=2.8*cos(k*M_PI/4.); center2[1]=2.8*sin(k*M_PI/4.);
+      e1=buildArcOfCircle(center,3.,(k-1)*M_PI/4.,(k+1)*M_PI/4.);
+      e2=buildArcOfCircle(center2,1.,(k)*M_PI/4.+M_PI/2.,(k)*M_PI/4.-M_PI/2.);
+      intersector=new ArcCArcCIntersector(*e1,*e2);
+      bool order;
+      bool obvious,areOverlapped;
+      intersector->areOverlappedOrOnlyColinears(0,obvious,areOverlapped);
+      CPPUNIT_ASSERT(!obvious && !areOverlapped);
+      CPPUNIT_ASSERT(intersector->intersect(0,v4,order,v3)); CPPUNIT_ASSERT(!order);
+      CPPUNIT_ASSERT_EQUAL(2,(int)v4.size()); CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getRadius(),Node::distanceBtw2Pt(e1->getCenter(),(*(v4[0]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e2->getRadius(),Node::distanceBtw2Pt(e2->getCenter(),(*(v4[0]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getRadius(),Node::distanceBtw2Pt(e1->getCenter(),(*(v4[1]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e2->getRadius(),Node::distanceBtw2Pt(e2->getCenter(),(*(v4[1]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT(!v4[0]->isEqual(*v4[1]));
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(btw2NodesAndACenter(*v4[0],*v4[1],e1->getCenter()),0.6793851523346941,1e-10);
+      for(vector<Node *>::iterator iter=v4.begin();iter!=v4.end();iter++)
+       (*iter)->decrRef();
+      v4.clear(); v3.clear();
+      delete intersector; e2->decrRef(); e1->decrRef();
+    }
+  // Ok now let's see intersection only. 2 intersections R1 < R2 ; dist(circle1,circle2)>R2; Opposite order.
+  for(unsigned k=0;k<1;k++)
+    {
+      double center2[2]; center[0]=0.; center[1]=0.;
+      center2[0]=3.8*cos(k*M_PI/4.); center2[1]=3.8*sin(k*M_PI/4.);
+      e1=buildArcOfCircle(center,1.,(k-1)*M_PI/4.,(k+1)*M_PI/4.);
+      e2=buildArcOfCircle(center2,3.,M_PI+(k-1)*M_PI/4.,M_PI+(k+1)*M_PI/4.);
+      intersector=new ArcCArcCIntersector(*e1,*e2);
+      bool order;
+      bool obvious,areOverlapped;
+      intersector->areOverlappedOrOnlyColinears(0,obvious,areOverlapped);
+      CPPUNIT_ASSERT(!obvious && !areOverlapped);
+      CPPUNIT_ASSERT(intersector->intersect(0,v4,order,v3)); CPPUNIT_ASSERT(!order);
+      CPPUNIT_ASSERT_EQUAL(2,(int)v4.size()); CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getRadius(),Node::distanceBtw2Pt(e1->getCenter(),(*(v4[0]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e2->getRadius(),Node::distanceBtw2Pt(e2->getCenter(),(*(v4[0]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getRadius(),Node::distanceBtw2Pt(e1->getCenter(),(*(v4[1]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e2->getRadius(),Node::distanceBtw2Pt(e2->getCenter(),(*(v4[1]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT(!v4[0]->isEqual(*v4[1]));
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(1.1195732971845034,btw2NodesAndACenter(*v4[0],*v4[1],e1->getCenter()),1e-10);
+      for(vector<Node *>::iterator iter=v4.begin();iter!=v4.end();iter++)
+        (*iter)->decrRef();
+      v4.clear(); v3.clear();
+      delete intersector; e2->decrRef(); e1->decrRef();
+    }
+  // Ok now let's see intersection only. 2 intersections R1 < R2 ; dist(circle1,circle2)>R2; same order.
+  for(unsigned k=0;k<8;k++)
+    {
+      double center2[2]; center[0]=0.; center[1]=0.;
+      center2[0]=3.8*cos(k*M_PI/4.); center2[1]=3.8*sin(k*M_PI/4.);
+      e1=buildArcOfCircle(center,1.,(k+1)*M_PI/4.,(k-1)*M_PI/4.);
+      e2=buildArcOfCircle(center2,3.,M_PI+(k-1)*M_PI/4.,M_PI+(k+1)*M_PI/4.);
+      intersector=new ArcCArcCIntersector(*e1,*e2);
+      bool order;
+      bool obvious,areOverlapped;
+      intersector->areOverlappedOrOnlyColinears(0,obvious,areOverlapped);
+      CPPUNIT_ASSERT(!obvious && !areOverlapped);
+      CPPUNIT_ASSERT(intersector->intersect(0,v4,order,v3)); CPPUNIT_ASSERT(order);
+      CPPUNIT_ASSERT_EQUAL(2,(int)v4.size()); CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getRadius(),Node::distanceBtw2Pt(e1->getCenter(),(*(v4[0]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e2->getRadius(),Node::distanceBtw2Pt(e2->getCenter(),(*(v4[0]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getRadius(),Node::distanceBtw2Pt(e1->getCenter(),(*(v4[1]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e2->getRadius(),Node::distanceBtw2Pt(e2->getCenter(),(*(v4[1]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT(!v4[0]->isEqual(*v4[1]));
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(-1.1195732971845034,btw2NodesAndACenter(*v4[0],*v4[1],e1->getCenter()),1e-10);
+      for(vector<Node *>::iterator iter=v4.begin();iter!=v4.end();iter++)
+        (*iter)->decrRef();
+      v4.clear(); v3.clear();
+      delete intersector; e2->decrRef(); e1->decrRef();
+    }
+  // Ok now let's see intersection only. 2 intersections R1 < R2 ; dist(circle1,circle2)<R2; same order.
+  for(unsigned k=0;k<8;k++)
+    {
+      double center2[2]; center[0]=0.; center[1]=0.;
+      center2[0]=-2.8*cos(k*M_PI/4.); center2[1]=-2.8*sin(k*M_PI/4.);
+      e1=buildArcOfCircle(center,1.,(k)*M_PI/4.+M_PI/2.,(k)*M_PI/4.-M_PI/2.);
+      e2=buildArcOfCircle(center2,3.,(k+1)*M_PI/4.,(k-1)*M_PI/4.);
+      intersector=new ArcCArcCIntersector(*e1,*e2);
+      bool order;
+      bool obvious,areOverlapped;
+      intersector->areOverlappedOrOnlyColinears(0,obvious,areOverlapped);
+      CPPUNIT_ASSERT(!obvious && !areOverlapped);
+      CPPUNIT_ASSERT(intersector->intersect(0,v4,order,v3)); CPPUNIT_ASSERT(order);
+      CPPUNIT_ASSERT_EQUAL(2,(int)v4.size()); CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getRadius(),Node::distanceBtw2Pt(e1->getCenter(),(*(v4[0]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e2->getRadius(),Node::distanceBtw2Pt(e2->getCenter(),(*(v4[0]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getRadius(),Node::distanceBtw2Pt(e1->getCenter(),(*(v4[1]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e2->getRadius(),Node::distanceBtw2Pt(e2->getCenter(),(*(v4[1]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT(!v4[0]->isEqual(*v4[1]));
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(-3.0844420190512074,btw2NodesAndACenter(*v4[0],*v4[1],e1->getCenter()),1e-10);
+      for(vector<Node *>::iterator iter=v4.begin();iter!=v4.end();iter++)
+        (*iter)->decrRef();
+      v4.clear(); v3.clear();
+      delete intersector; e2->decrRef(); e1->decrRef();
+    }
+  // Ok now let's see intersection only. 2 intersections R1 < R2 ; dist(circle1,circle2)<R2; opp. order.
+  for(unsigned k=0;k<8;k++)
+    {
+      double center2[2]; center[0]=0.; center[1]=0.;
+      center2[0]=-2.8*cos(k*M_PI/4.); center2[1]=-2.8*sin(k*M_PI/4.);
+      e1=buildArcOfCircle(center,1.,(k)*M_PI/4.+M_PI/2.,(k)*M_PI/4.-M_PI/2.);
+      e2=buildArcOfCircle(center2,3.,(k-1)*M_PI/4.,(k+1)*M_PI/4.);
+      intersector=new ArcCArcCIntersector(*e1,*e2);
+      bool order;
+      bool obvious,areOverlapped;
+      intersector->areOverlappedOrOnlyColinears(0,obvious,areOverlapped);
+      CPPUNIT_ASSERT(!obvious && !areOverlapped);
+      CPPUNIT_ASSERT(intersector->intersect(0,v4,order,v3)); CPPUNIT_ASSERT(!order);
+      CPPUNIT_ASSERT_EQUAL(2,(int)v4.size()); CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getRadius(),Node::distanceBtw2Pt(e1->getCenter(),(*(v4[0]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e2->getRadius(),Node::distanceBtw2Pt(e2->getCenter(),(*(v4[0]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getRadius(),Node::distanceBtw2Pt(e1->getCenter(),(*(v4[1]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e2->getRadius(),Node::distanceBtw2Pt(e2->getCenter(),(*(v4[1]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT(!v4[0]->isEqual(*v4[1]));
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(-3.0844420190512074,btw2NodesAndACenter(*v4[0],*v4[1],e1->getCenter()),1e-10);
+      for(vector<Node *>::iterator iter=v4.begin();iter!=v4.end();iter++)
+        (*iter)->decrRef();
+      v4.clear(); v3.clear();
+      delete intersector; e2->decrRef(); e1->decrRef();
+    }
+  // Tangent intersection
+  for(unsigned k=0;k<8;k++)
+    {
+      double center2[2]; center[0]=0.; center[1]=0.;
+      center2[0]=4.*cos(k*M_PI/4.); center2[1]=4.*sin(k*M_PI/4.);
+      e1=buildArcOfCircle(center,1.,(k+1)*M_PI/4.,(k-1)*M_PI/4.);
+      e2=buildArcOfCircle(center2,3.,M_PI+(k-1)*M_PI/4.,M_PI+(k+1)*M_PI/4.);
+      intersector=new ArcCArcCIntersector(*e1,*e2);
+      bool order;
+      bool obvious,areOverlapped;
+      intersector->areOverlappedOrOnlyColinears(0,obvious,areOverlapped);
+      CPPUNIT_ASSERT(!obvious && !areOverlapped);
+      CPPUNIT_ASSERT(intersector->intersect(0,v4,order,v3)); CPPUNIT_ASSERT(order); // order has no sence here because v4.size() expected to 1 but for valgrind serenity test.
+      CPPUNIT_ASSERT_EQUAL(1,(int)v4.size()); CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getRadius(),Node::distanceBtw2Pt(e1->getCenter(),(*(v4[0]))),ADMISSIBLE_ERROR);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(e2->getRadius(),Node::distanceBtw2Pt(e2->getCenter(),(*(v4[0]))),ADMISSIBLE_ERROR);
+      for(vector<Node *>::iterator iter=v4.begin();iter!=v4.end();iter++)
+        (*iter)->decrRef();
+      v4.clear(); v4.clear();
+      delete intersector; e2->decrRef(); e1->decrRef();
+    }
+  // Extremities # 1
+  for(unsigned k=0;k<8;k++)
+    {
+      center[0]=0.; center[1]=0.;
+      double center2[2]; center2[0]=3.8*cos(k*M_PI/4.); center2[1]=3.8*sin(k*M_PI/4.);
+      e1=buildArcOfCircle(center,3.,k*M_PI/4.-0.17793931986099812,k*M_PI/4.+0.17793931986099812);
+      e2=buildArcOfCircle(center2,1.,M_PI+k*M_PI/4.-0.55978664859225125,M_PI+k*M_PI/4.+0.55978664859225125);
+      intersector=new ArcCArcCIntersector(*e1,*e2);
+      bool order;
+      bool obvious,areOverlapped;
+      intersector->areOverlappedOrOnlyColinears(0,obvious,areOverlapped);
+      CPPUNIT_ASSERT(!obvious && !areOverlapped);
+      CPPUNIT_ASSERT(!intersector->intersect(0,v4,order,v3)); CPPUNIT_ASSERT_EQUAL(0,(int)v4.size()); CPPUNIT_ASSERT_EQUAL(2,(int)v3.getNumberOfAssociations());
+      CPPUNIT_ASSERT(e1->getStartNode()==e2->getEndNode()); CPPUNIT_ASSERT(e2->getStartNode()==e1->getEndNode());
+      v4.clear(); v3.clear();
+      delete intersector; e2->decrRef(); e1->decrRef();
+    }
+  for(unsigned k=0;k<8;k++)
+    {
+      center[0]=0.; center[1]=0.;
+      double center2[2]; center2[0]=3.8*cos(k*M_PI/4.); center2[1]=3.8*sin(k*M_PI/4.);
+      e1=buildArcOfCircle(center,3.,k*M_PI/4.-0.17793931986099812,k*M_PI/4.+0.17793931986099812);
+      e2=buildArcOfCircle(center2,1.,M_PI+k*M_PI/4.+0.55978664859225125,M_PI+k*M_PI/4.-0.55978664859225125);
+      intersector=new ArcCArcCIntersector(*e1,*e2);
+      bool order;
+      bool obvious,areOverlapped;
+      intersector->areOverlappedOrOnlyColinears(0,obvious,areOverlapped);
+      CPPUNIT_ASSERT(!obvious && !areOverlapped);
+      CPPUNIT_ASSERT(!intersector->intersect(0,v4,order,v3)); CPPUNIT_ASSERT_EQUAL(0,(int)v4.size()); CPPUNIT_ASSERT_EQUAL(2,(int)v3.getNumberOfAssociations());
+      CPPUNIT_ASSERT(e1->getStartNode()==e2->getStartNode()); CPPUNIT_ASSERT(e2->getEndNode()==e1->getEndNode());
+      v4.clear(); v3.clear();
+      delete intersector; e2->decrRef(); e1->decrRef();
+    }
+  // Extremities # 2
+  for(unsigned k=0;k<8;k++)
+    {
+      center[0]=0.; center[1]=0.;
+      double center2[2]; center2[0]=3.8*cos(k*M_PI/4.); center2[1]=3.8*sin(k*M_PI/4.);
+      e1=buildArcOfCircle(center,3.,k*M_PI/4.-0.17793931986099812,k*M_PI/4.+0.17793931986099812);
+      e2=buildArcOfCircle(center2,1.,M_PI+k*M_PI/4.+0.55978664859225125,M_PI+k*M_PI/4.-0.7);
+      intersector=new ArcCArcCIntersector(*e1,*e2);
+      bool order;
+      bool obvious,areOverlapped;
+      intersector->areOverlappedOrOnlyColinears(0,obvious,areOverlapped);
+      CPPUNIT_ASSERT(!obvious && !areOverlapped);
+      CPPUNIT_ASSERT(intersector->intersect(0,v4,order,v3));
+      CPPUNIT_ASSERT(order); CPPUNIT_ASSERT_EQUAL(1,(int)v4.size()); CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations());
+      CPPUNIT_ASSERT(e1->getStartNode()==e2->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==v4[0]);
+      v4[0]->decrRef();
+      v4.clear(); v3.clear();
+      delete intersector; e2->decrRef(); e1->decrRef();
+      }
+  // Extremities # 3
+  for(unsigned k=0;k<8;k++)
+    {
+      center[0]=0.; center[1]=0.;
+      double center2[2]; center2[0]=3.8*cos(k*M_PI/4.); center2[1]=3.8*sin(k*M_PI/4.);
+      e1=buildArcOfCircle(center,3.,k*M_PI/4.-0.17793931986099812,k*M_PI/4.+0.17793931986099812);
+      e2=buildArcOfCircle(center2,1.,M_PI+k*M_PI/4.+0.7,M_PI+k*M_PI/4.-0.7);
+      intersector=new ArcCArcCIntersector(*e1,*e2);
+      bool order;
+      bool obvious,areOverlapped;
+      intersector->areOverlappedOrOnlyColinears(0,obvious,areOverlapped);
+      CPPUNIT_ASSERT(!obvious && !areOverlapped);
+      CPPUNIT_ASSERT(intersector->intersect(0,v4,order,v3)); CPPUNIT_ASSERT(order); CPPUNIT_ASSERT_EQUAL(2,(int)v4.size()); CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+      CPPUNIT_ASSERT(e1->getStartNode()==v4[0]); CPPUNIT_ASSERT(e1->getEndNode()==v4[1]);
+      v4[0]->decrRef(); v4[1]->decrRef();
+      v4.clear(); v3.clear();
+      delete intersector; e2->decrRef(); e1->decrRef();
+    }
+  // Extremities # 4
+  for(unsigned k=0;k<8;k++)
+    {
+      center[0]=0.; center[1]=0.;
+      double center2[2]; center2[0]=3.8*cos(k*M_PI/4.); center2[1]=3.8*sin(k*M_PI/4.);
+      Node *nodeS=new Node(center[0]+3.*cos(k*M_PI/4.-0.17793931986099812),center[1]+3.*sin(k*M_PI/4.-0.17793931986099812));
+      Node *nodeE=new Node(center[0]+3.*cos(k*M_PI/4.),center[1]+3.*sin(k*M_PI/4.));
+      double angle=k*M_PI/4.-0.17793931986099812;
+      angle=angle>M_PI?angle-2.*M_PI:angle;
+      e1=new EdgeArcCircle(nodeS,nodeE,//Problem of precision 1e-14 to easily reached.
+                          center,3.,angle,0.17793931986099812);
+      nodeS->decrRef(); nodeE->decrRef();
+      e2=buildArcOfCircle(center2,1.,M_PI+k*M_PI/4.+0.7,M_PI+k*M_PI/4.-0.7);
+      intersector=new ArcCArcCIntersector(*e1,*e2);
+      bool order;
+      bool obvious,areOverlapped;
+      intersector->areOverlappedOrOnlyColinears(0,obvious,areOverlapped);
+      CPPUNIT_ASSERT(!obvious && !areOverlapped);
+      CPPUNIT_ASSERT(intersector->intersect(0,v4,order,v3)); CPPUNIT_ASSERT(order); CPPUNIT_ASSERT_EQUAL(1,(int)v4.size()); CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+      CPPUNIT_ASSERT(e1->getStartNode()==v4[0]);
+      v4[0]->decrRef();
+      v4.clear(); v3.clear();
+      delete intersector; e2->decrRef(); e1->decrRef();
+    }
+  //Extremities # 5
+  for(unsigned k=0;k<8;k++)
+    {
+      center[0]=0.; center[1]=0.;
+      double center2[2]; center2[0]=3.8*cos(k*M_PI/4.); center2[1]=3.8*sin(k*M_PI/4.);
+      Node *nodeS=new Node(center[0]+3.*cos(k*M_PI/4.-0.17793931986099812),center[1]+3.*sin(k*M_PI/4.-0.17793931986099812));
+      Node *nodeE=new Node(center[0]+3.*cos(k*M_PI/4.)+0.5,center[1]+3.*sin(k*M_PI/4.));
+      double angle=k*M_PI/4.-0.17793931986099812;
+      angle=angle>M_PI?angle-2.*M_PI:angle;
+      e1=new EdgeArcCircle(nodeS,nodeE,//Problem of precision 1e-14 to easily reached.
+                          center,3.,angle,0.67793931986099812);
+      nodeS->decrRef(); nodeE->decrRef();
+      e2=buildArcOfCircle(center2,1.,M_PI+k*M_PI/4.+0.7,M_PI+k*M_PI/4.-0.7);
+      intersector=new ArcCArcCIntersector(*e1,*e2);
+      bool order;
+      bool obvious,areOverlapped;
+      intersector->areOverlappedOrOnlyColinears(0,obvious,areOverlapped);
+      CPPUNIT_ASSERT(!obvious && !areOverlapped);
+      CPPUNIT_ASSERT(intersector->intersect(0,v4,order,v3)); CPPUNIT_ASSERT(order); CPPUNIT_ASSERT_EQUAL(2,(int)v4.size()); CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+      CPPUNIT_ASSERT(e1->getStartNode()==v4[0]);
+      v4[0]->decrRef(); v4[1]->decrRef();
+      v4.clear(); v3.clear();
+      delete intersector; e2->decrRef(); e1->decrRef();
+    }
+}
+
+void QuadraticPlanarInterpTest::IntersectArcCircleFull()
+{
+  double center1[2]; center1[0]=0.;   center1[1]=0.;   double radius1=3.;
+  double center2[2]; center2[0]=0.75; center2[1]=-2.6; double radius2=1.;
+  EdgeArcCircle *e1=buildArcOfCircle(center1,radius1,-M_PI/3.,4.*M_PI/3.);
+  EdgeArcCircle *e2=buildArcOfCircle(center2,radius2,0.,M_PI/2.);
+  MergePoints commonNode;
+  QuadraticPolygon pol1; QuadraticPolygon pol2;
+  QuadraticPolygon pol3; QuadraticPolygon pol4;
+  pol3.pushBack(e1); pol4.pushBack(e2);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(15.707963267948966,pol3.getPerimeterFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(1.5707963267949,pol4.getPerimeterFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(19.6648305849,pol3.getAreaFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(-1.8146018366,pol4.getAreaFast(),1e-6);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,commonNode,pol1,pol2));
+  CPPUNIT_ASSERT_EQUAL(2,pol1.size());
+  CPPUNIT_ASSERT_EQUAL(2,pol2.size());
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(19.6648305849,pol1.getAreaFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(-1.8146018366,pol2.getAreaFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(15.707963267948966,pol1.getPerimeterFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(1.5707963267949,pol2.getPerimeterFast(),1e-6);
+  //
+  e1=buildArcOfCircle(center1,radius1,-2*M_PI/3.,-7.*M_PI/3.);
+  e2=buildArcOfCircle(center2,radius2,0.,M_PI/2.);
+  commonNode.clear();
+  QuadraticPolygon pol5; QuadraticPolygon pol6;
+  QuadraticPolygon pol7; QuadraticPolygon pol8;
+  pol7.pushBack(e1); pol8.pushBack(e2);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(15.707963267948966,pol7.getPerimeterFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(1.5707963267949,pol8.getPerimeterFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(-19.6648305849,pol7.getAreaFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(-1.8146018366,pol8.getAreaFast(),1e-6);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,commonNode,pol5,pol6));
+  CPPUNIT_ASSERT_EQUAL(2,pol5.size());
+  CPPUNIT_ASSERT_EQUAL(2,pol6.size());
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(-19.6648305849,pol5.getAreaFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(-1.8146018366,pol6.getAreaFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(15.707963267948966,pol5.getPerimeterFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(1.5707963267949,pol6.getPerimeterFast(),1e-6);
+  //
+  center2[0]=3.5; center2[1]=0.;
+  e1=buildArcOfCircle(center1,radius1,-2*M_PI/3.,-7.*M_PI/3.);
+  e2=buildArcOfCircle(center2,radius2,M_PI/2.,3*M_PI/2.);
+  commonNode.clear();
+  QuadraticPolygon pol9; QuadraticPolygon pol10;
+  QuadraticPolygon pol11; QuadraticPolygon pol12;
+  pol11.pushBack(e1); pol12.pushBack(e2);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(15.707963267948966,pol11.getPerimeterFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(3.1415926535897931,pol12.getPerimeterFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(-19.6648305849,pol11.getAreaFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(1.5707963267949,pol12.getAreaFast(),1e-6);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,commonNode,pol9,pol10));
+  CPPUNIT_ASSERT_EQUAL(3,pol9.size());
+  CPPUNIT_ASSERT_EQUAL(3,pol10.size());
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(15.707963267948966,pol9.getPerimeterFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(3.1415926535897931,pol10.getPerimeterFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(-19.6648305849,pol9.getAreaFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(1.5707963267949,pol10.getAreaFast(),1e-6);
+  //
+  center2[0]=0.; center2[1]=0.; radius2=radius1;
+  e1=buildArcOfCircle(center1,radius1,-2*M_PI/3.,-7.*M_PI/3.);
+  e2=buildArcOfCircle(center2,radius2,M_PI/3.,2*M_PI/3.);
+  commonNode.clear();
+  QuadraticPolygon pol13; QuadraticPolygon pol14;
+  QuadraticPolygon pol15; QuadraticPolygon pol16;
+  pol15.pushBack(e1); pol16.pushBack(e2);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(15.707963267948966,pol15.getPerimeterFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(3.1415926535897931,pol16.getPerimeterFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(-19.6648305849,pol15.getAreaFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(8.6095032974147,pol16.getAreaFast(),1e-6);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,commonNode,pol13,pol14));
+  CPPUNIT_ASSERT_EQUAL(3,pol13.size());
+  CPPUNIT_ASSERT_EQUAL(1,pol14.size());
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(15.707963267948966,pol13.getPerimeterFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(-19.6648305849,pol13.getAreaFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(3.1415926535897931,pol14.getPerimeterFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(8.6095032974147,pol14.getAreaFast(),1e-6);
+  //
+  e1=buildArcOfCircle(center1,radius1,-2*M_PI/3.,-7.*M_PI/3.);
+  e2=buildArcOfCircle(center2,radius2,2*M_PI/3.,M_PI/3.);
+  commonNode.clear();
+  QuadraticPolygon pol17; QuadraticPolygon pol18;
+  QuadraticPolygon pol19; QuadraticPolygon pol20;
+  pol19.pushBack(e1); pol20.pushBack(e2);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(15.707963267948966,pol19.getPerimeterFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(3.1415926535897931,pol20.getPerimeterFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(-19.6648305849,pol19.getAreaFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(-8.6095032974147,pol20.getAreaFast(),1e-6);
+  CPPUNIT_ASSERT(e1->intersectWith(e2,commonNode,pol17,pol18));
+  CPPUNIT_ASSERT_EQUAL(3,pol17.size());
+  CPPUNIT_ASSERT_EQUAL(1,pol18.size());
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(15.707963267948966,pol17.getPerimeterFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(-19.6648305849,pol17.getAreaFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(3.1415926535897931,pol18.getPerimeterFast(),1e-6);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(-8.6095032974147,pol18.getAreaFast(),1e-6);
+  //no intersection #1
+  center2[0]=4.277; center2[1]=-4.277;
+  e1=buildArcOfCircle(center1,radius1,-2*M_PI/3.,-7.*M_PI/3.);
+  e2=buildArcOfCircle(center2,radius2,M_PI/4.,5*M_PI/4.);
+  QuadraticPolygon polTemp1; QuadraticPolygon polTemp2;
+  CPPUNIT_ASSERT(!e1->intersectWith(e2,commonNode,polTemp1,polTemp2));
+  //no intersection #2
+  center2[0]=1.; center2[1]=-1.; radius2=0.2;
+  e1=buildArcOfCircle(center1,radius1,-2*M_PI/3.,-7.*M_PI/3.);
+  e2=buildArcOfCircle(center2,radius2,M_PI/4.,5*M_PI/4.);
+  CPPUNIT_ASSERT(!e1->intersectWith(e2,commonNode,polTemp1,polTemp2));
+}
+
+void QuadraticPlanarInterpTest::IntersectArcCircleSegumentBase()
+{
+  double center[2]={2.,2.};
+  EdgeArcCircle *e1=buildArcOfCircle(center,2.3,M_PI/4.,5.*M_PI/4.);
+  EdgeLin *e2=new EdgeLin(-1.3,1.,3.,5.3);
+  Intersector *intersector=new ArcCSegIntersector(*e1,*e2);
+  bool order;
+  bool obvious,areOverlapped;
+  intersector->areOverlappedOrOnlyColinears(0,obvious,areOverlapped);
+  CPPUNIT_ASSERT(!obvious && !areOverlapped);
+  vector<Node *> v4;
+  MergePoints v3;
+  CPPUNIT_ASSERT(intersector->intersect(0,v4,order,v3)); CPPUNIT_ASSERT(!order); CPPUNIT_ASSERT_EQUAL(2,(int)v4.size()); CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(2.,(*v4[0])[0],1e-10); CPPUNIT_ASSERT_DOUBLES_EQUAL(4.3,(*v4[0])[1],1e-10);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.3,(*v4[1])[0],1e-10); CPPUNIT_ASSERT_DOUBLES_EQUAL(2.,(*v4[1])[1],1e-10);
+  v4[0]->decrRef(); v4[1]->decrRef(); e2->decrRef(); v3.clear(); v4.clear(); delete intersector;
+  //
+  e2=new EdgeLin(3.,5.3,-1.3,1.);
+  intersector=new ArcCSegIntersector(*e1,*e2);
+  intersector->areOverlappedOrOnlyColinears(0,obvious,areOverlapped); CPPUNIT_ASSERT(!obvious && !areOverlapped);
+  CPPUNIT_ASSERT(intersector->intersect(0,v4,order,v3)); CPPUNIT_ASSERT(order); CPPUNIT_ASSERT_EQUAL(2,(int)v4.size()); CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(2.,(*v4[0])[0],1e-10); CPPUNIT_ASSERT_DOUBLES_EQUAL(4.3,(*v4[0])[1],1e-10);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.3,(*v4[1])[0],1e-10); CPPUNIT_ASSERT_DOUBLES_EQUAL(2.,(*v4[1])[1],1e-10);
+  v4[0]->decrRef(); v4[1]->decrRef(); e2->decrRef(); v3.clear(); v4.clear(); delete intersector;
+  // tangent intersection
+  e2=new EdgeLin(-1.,4.3,3.,4.3);
+  intersector=new ArcCSegIntersector(*e1,*e2);
+  intersector->areOverlappedOrOnlyColinears(0,obvious,areOverlapped); CPPUNIT_ASSERT(!obvious && !areOverlapped);
+  CPPUNIT_ASSERT(intersector->intersect(0,v4,order,v3)); CPPUNIT_ASSERT(order); CPPUNIT_ASSERT_EQUAL(1,(int)v4.size()); CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations());
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(2.,(*v4[0])[0],1e-10); CPPUNIT_ASSERT_DOUBLES_EQUAL(4.3,(*v4[0])[1],1e-10);
+  v4[0]->decrRef(); e2->decrRef(); v3.clear(); delete intersector;
+  // no intersection
+  e2=new EdgeLin(-2.,-2.,-1.,-3.);
+  intersector=new ArcCSegIntersector(*e1,*e2);
+  intersector->areOverlappedOrOnlyColinears(0,obvious,areOverlapped); CPPUNIT_ASSERT(obvious && !areOverlapped);
+  e2->decrRef(); v3.clear(); delete intersector;
+  //
+  e1->decrRef();
+}
+
+EdgeArcCircle *QuadraticPlanarInterpTest::buildArcOfCircle(const double *center, double radius, double alphaStart, double alphaEnd)
+{
+  double alphaM=(alphaStart+alphaEnd)/2;
+  return new EdgeArcCircle(center[0]+cos(alphaStart)*radius,center[1]+sin(alphaStart)*radius,
+                          center[0]+cos(alphaM)*radius,center[1]+sin(alphaM)*radius,
+                          center[0]+cos(alphaEnd)*radius,center[1]+sin(alphaEnd)*radius);
+}
+
+double QuadraticPlanarInterpTest::btw2NodesAndACenter(const Node& n1, const Node& n2, const double *center)
+{
+  const double *n1Pt=n1;
+  const double *n2Pt=n2;
+  double tmp1[2],tmp2[2];
+  tmp1[0]=n1Pt[0]-center[0]; tmp1[1]=n1Pt[1]-center[1];
+  tmp2[0]=n2Pt[0]-center[0]; tmp2[1]=n2Pt[1]-center[1];
+  double distTmp1=sqrt(tmp1[0]*tmp1[0]+tmp1[1]*tmp1[1]);
+  double distTmp2=sqrt(tmp2[0]*tmp2[0]+tmp2[1]*tmp2[1]);
+  double ret=acos((tmp1[0]*tmp2[0]+tmp1[1]*tmp2[1])/(distTmp1*distTmp2));
+  if(tmp1[0]*tmp2[1]-tmp1[1]*tmp2[0]<0)
+    ret=-ret;
+  return ret;
+}
diff --git a/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest3.cxx b/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest3.cxx
new file mode 100644 (file)
index 0000000..1b3f93b
--- /dev/null
@@ -0,0 +1,300 @@
+#include "QuadraticPlanarInterpTest.hxx"
+#include "QuadraticPolygon.hxx"
+#include "ElementaryEdge.hxx"
+#include "EdgeArcCircle.hxx"
+#include "EdgeLin.hxx"
+
+#include <cmath>
+#include <sstream>
+#include <iostream>
+
+using namespace std;
+using namespace INTERP_KERNEL;
+
+
+void QuadraticPlanarInterpTest::checkInOutDetection()
+{
+  Node *n1=new Node(0.,0.);
+  Node *n2=new Node(1.,0.);
+  Node *n3=new Node(0.5,1.);
+  EdgeLin *e1=new EdgeLin(n1,n2);
+  EdgeLin *e2=new EdgeLin(n2,n3);
+  EdgeLin *e3=new EdgeLin(n3,n1);
+  ComposedEdge *tri=new ComposedEdge;
+  tri->pushBack(e1); tri->pushBack(e2); tri->pushBack(e3);
+  //
+  Node *where=new Node(0.4,0.1);
+  CPPUNIT_ASSERT(tri->isInOrOut(where)); where->decrRef();
+  where=new Node(-0.1,1.);
+  CPPUNIT_ASSERT(!tri->isInOrOut(where)); where->decrRef();
+  where=new Node(0.6,-0.1);
+  CPPUNIT_ASSERT(!tri->isInOrOut(where)); where->decrRef();
+  //Clean-up
+  n1->decrRef(); n2->decrRef(); n3->decrRef();
+  ComposedEdge::Delete(tri);
+}
+
+/*!
+ * Check Iterators mechanism.
+ */
+void QuadraticPlanarInterpTest::checkAssemblingBases1()
+{
+  Node *n1=new Node(0.,0.);
+  Node *n2=new Node(0.1,0.); EdgeLin *e1_2=new EdgeLin(n1,n2);
+  Node *n3=new Node(0.2,0.); EdgeLin *e2_3=new EdgeLin(n2,n3);
+  Node *n4=new Node(0.3,0.); EdgeLin *e3_4=new EdgeLin(n3,n4);
+  Node *n5=new Node(0.4,0.); EdgeLin *e4_5=new EdgeLin(n4,n5);
+  Node *n6=new Node(0.5,0.); EdgeLin *e5_6=new EdgeLin(n5,n6);
+  Node *n7=new Node(0.6,0.); EdgeLin *e6_7=new EdgeLin(n6,n7);
+  Node *n8=new Node(0.7,0.); EdgeLin *e7_8=new EdgeLin(n7,n8);
+  Node *n9=new Node(0.8,0.); EdgeLin *e8_9=new EdgeLin(n8,n9);
+  Node *n10=new Node(0.9,0.); EdgeLin *e9_10=new EdgeLin(n9,n10);
+  Node *n11=new Node(1.,0.); EdgeLin *e10_11=new EdgeLin(n10,n11);
+  Node *n12=new Node(0.5,1.); EdgeLin *e11_12=new EdgeLin(n11,n12);
+  EdgeLin *e12_1=new EdgeLin(n12,n1);
+  //Only one level
+  e1_2->incrRef(); e2_3->incrRef(); e3_4->incrRef(); e4_5->incrRef(); e5_6->incrRef(); e6_7->incrRef(); 
+  e7_8->incrRef(); e8_9->incrRef(); e9_10->incrRef(); e10_11->incrRef(); e11_12->incrRef(); e12_1->incrRef();
+  ComposedEdge *c=new ComposedEdge;
+  c->pushBack(e1_2); c->pushBack(e2_3); c->pushBack(e3_4); c->pushBack(e4_5); c->pushBack(e5_6); c->pushBack(e6_7);
+  c->pushBack(e7_8); c->pushBack(e8_9); c->pushBack(e9_10); c->pushBack(e10_11); c->pushBack(e11_12); c->pushBack(e12_1);
+  CPPUNIT_ASSERT_EQUAL(12,c->recursiveSize());
+  IteratorOnComposedEdge it(c);
+  CPPUNIT_ASSERT(it.current()->getPtr()==e1_2); CPPUNIT_ASSERT(!it.finished());
+  it.next(); CPPUNIT_ASSERT(it.current()->getPtr()==e2_3); CPPUNIT_ASSERT(!it.finished());
+  it.next(); it.next(); CPPUNIT_ASSERT(it.current()->getPtr()==e4_5); CPPUNIT_ASSERT(!it.finished());
+  it.previousLoop(); CPPUNIT_ASSERT(it.current()->getPtr()==e3_4); CPPUNIT_ASSERT(!it.finished());
+  it.previousLoop(); CPPUNIT_ASSERT(it.current()->getPtr()==e2_3); CPPUNIT_ASSERT(!it.finished());
+  it.previousLoop(); CPPUNIT_ASSERT(it.current()->getPtr()==e1_2); CPPUNIT_ASSERT(!it.finished());
+  it.previousLoop(); CPPUNIT_ASSERT(it.current()->getPtr()==e12_1); CPPUNIT_ASSERT(!it.finished());
+  it.next(); CPPUNIT_ASSERT(it.finished());
+  it.first(); CPPUNIT_ASSERT(it.current()->getPtr()==e1_2); CPPUNIT_ASSERT(!it.finished());
+  it.previousLoop(); CPPUNIT_ASSERT(it.current()->getPtr()==e12_1); CPPUNIT_ASSERT(!it.finished());
+  it.nextLoop(); CPPUNIT_ASSERT(it.current()->getPtr()==e1_2); CPPUNIT_ASSERT(!it.finished());
+  it.last(); CPPUNIT_ASSERT(it.current()->getPtr()==e12_1); CPPUNIT_ASSERT(!it.finished());
+  //Multi-Level
+  ComposedEdge::Delete(c);
+  //(e1_2, (e2_3,(e3_4, e4_5, e5_6, e6_7, (e7_8, e8_9 ), ( e9_10 , e10_11 ), e11_12 ),e12_1 ) )
+  e1_2->incrRef(); e2_3->incrRef(); e3_4->incrRef(); e4_5->incrRef(); e5_6->incrRef(); e6_7->incrRef(); 
+  e7_8->incrRef(); e8_9->incrRef(); e9_10->incrRef(); e10_11->incrRef(); e11_12->incrRef(); e12_1->incrRef();
+  ComposedEdge *c2_2_4=new ComposedEdge; c2_2_4->pushBack(e7_8); c2_2_4->pushBack(e8_9);
+  ComposedEdge *c2_2_5=new ComposedEdge; c2_2_5->pushBack(e9_10); c2_2_5->pushBack(e10_11);
+  ComposedEdge *c2_2=new ComposedEdge; c2_2->pushBack(e3_4); c2_2->pushBack(e4_5); c2_2->pushBack(e5_6);  c2_2->pushBack(e6_7); c2_2->pushBack(c2_2_4); c2_2->pushBack(c2_2_5); c2_2->pushBack(e11_12);
+  ComposedEdge *c2=new ComposedEdge; c2->pushBack(e2_3); c2->pushBack(c2_2); c2->pushBack(e12_1);
+  c=new ComposedEdge; c->pushBack(e1_2); c->pushBack(c2); CPPUNIT_ASSERT_EQUAL(12,c->recursiveSize());
+  IteratorOnComposedEdge it2(c);
+  CPPUNIT_ASSERT(it2.current()->getPtr()==e1_2);
+  it2.next(); CPPUNIT_ASSERT(it2.current()->getPtr()==e2_3); CPPUNIT_ASSERT(!it2.finished());
+  it2.next(); CPPUNIT_ASSERT(it2.current()->getPtr()==e3_4); CPPUNIT_ASSERT(!it2.finished());
+  it2.next(); CPPUNIT_ASSERT(it2.current()->getPtr()==e4_5); CPPUNIT_ASSERT(!it2.finished());
+  it2.previousLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e3_4); CPPUNIT_ASSERT(!it2.finished());
+  it2.previousLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e2_3); CPPUNIT_ASSERT(!it2.finished());
+  it2.previousLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e1_2); CPPUNIT_ASSERT(!it2.finished());
+  it2.previousLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e12_1); CPPUNIT_ASSERT(!it2.finished());
+  it2.next(); CPPUNIT_ASSERT(it2.finished());
+  it2.first(); CPPUNIT_ASSERT(it2.current()->getPtr()==e1_2); CPPUNIT_ASSERT(!it2.finished());
+  it2.previousLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e12_1); CPPUNIT_ASSERT(!it2.finished());
+  it2.nextLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e1_2); CPPUNIT_ASSERT(!it2.finished());
+  it2.last(); CPPUNIT_ASSERT(it2.current()->getPtr()==e12_1); CPPUNIT_ASSERT(!it2.finished());
+  it2.first(); CPPUNIT_ASSERT(it2.current()->getPtr()==e1_2); CPPUNIT_ASSERT(!it2.finished());
+  it2.nextLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e2_3); CPPUNIT_ASSERT(!it2.finished());
+  it2.nextLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e3_4); CPPUNIT_ASSERT(!it2.finished());
+  it2.nextLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e4_5); CPPUNIT_ASSERT(!it2.finished());
+  //  substitutions.
+  it2.first(); CPPUNIT_ASSERT(it2.current()->getPtr()==e1_2); CPPUNIT_ASSERT(!it2.finished());
+  ElementaryEdge *&tmp=it2.current(); CPPUNIT_ASSERT(it2.current()->getPtr()==e1_2); CPPUNIT_ASSERT(!it2.finished());
+  ComposedEdge *c1=new ComposedEdge;  Node *n1_bis=new Node(0.,0.05); EdgeLin *e1_1bis=new EdgeLin(n1,n1_bis); EdgeLin *e1bis_2=new EdgeLin(n1_bis,n2); e1_1bis->incrRef(); e1bis_2->incrRef();
+  c1->pushBack(e1_1bis); c1->pushBack(e1bis_2); delete tmp; tmp=(ElementaryEdge *)c1; CPPUNIT_ASSERT_EQUAL(13,c->recursiveSize());
+  CPPUNIT_ASSERT(it2.current()->getPtr()==e1_1bis); CPPUNIT_ASSERT(!it2.finished());// here testing capability of Iterator.'current' method to deal with change of hierarchy.
+  it2.next(); CPPUNIT_ASSERT(it2.current()->getPtr()==e1bis_2); CPPUNIT_ASSERT(!it2.finished());
+  it2.next(); CPPUNIT_ASSERT(it2.current()->getPtr()==e2_3); CPPUNIT_ASSERT(!it2.finished());
+  it2.previousLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e1bis_2); CPPUNIT_ASSERT(!it2.finished());
+  it2.previousLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e1_1bis); CPPUNIT_ASSERT(!it2.finished());
+  it2.previousLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e12_1); CPPUNIT_ASSERT(!it2.finished());
+  it2.previousLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e11_12); CPPUNIT_ASSERT(!it2.finished());
+  it2.previousLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e10_11); CPPUNIT_ASSERT(!it2.finished());
+  it2.previousLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e9_10); CPPUNIT_ASSERT(!it2.finished());
+  it2.previousLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e8_9); CPPUNIT_ASSERT(!it2.finished());
+  it2.previousLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e7_8); CPPUNIT_ASSERT(!it2.finished());
+  it2.previousLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e6_7); CPPUNIT_ASSERT(!it2.finished());
+  it2.previousLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e5_6); CPPUNIT_ASSERT(!it2.finished());
+  it2.previousLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e4_5); CPPUNIT_ASSERT(!it2.finished());
+  it2.previousLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e3_4); CPPUNIT_ASSERT(!it2.finished());
+  it2.previousLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e2_3); CPPUNIT_ASSERT(!it2.finished());
+  it2.previousLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e1bis_2); CPPUNIT_ASSERT(!it2.finished());
+  it2.previousLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e1_1bis); CPPUNIT_ASSERT(!it2.finished());
+  it2.previousLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e12_1); CPPUNIT_ASSERT(!it2.finished());
+  //go forward
+  it2.nextLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e1_1bis); CPPUNIT_ASSERT(!it2.finished());
+  it2.nextLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e1bis_2); CPPUNIT_ASSERT(!it2.finished());
+  it2.nextLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e2_3); CPPUNIT_ASSERT(!it2.finished());
+  it2.nextLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e3_4); CPPUNIT_ASSERT(!it2.finished());
+  it2.nextLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e4_5); CPPUNIT_ASSERT(!it2.finished());
+  it2.nextLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e5_6); CPPUNIT_ASSERT(!it2.finished());
+  it2.nextLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e6_7); CPPUNIT_ASSERT(!it2.finished());
+  it2.nextLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e7_8); CPPUNIT_ASSERT(!it2.finished());
+  it2.nextLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e8_9); CPPUNIT_ASSERT(!it2.finished());
+  it2.nextLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e9_10); CPPUNIT_ASSERT(!it2.finished());
+  it2.nextLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e10_11); CPPUNIT_ASSERT(!it2.finished());
+  it2.nextLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e11_12); CPPUNIT_ASSERT(!it2.finished());
+  it2.nextLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e12_1); CPPUNIT_ASSERT(!it2.finished());
+  it2.nextLoop(); CPPUNIT_ASSERT(it2.current()->getPtr()==e1_1bis); CPPUNIT_ASSERT(!it2.finished());
+  ComposedEdge::Delete(c);
+  //clean-up
+  e1_1bis->decrRef(); e1bis_2->decrRef();
+  e1_2->decrRef(); e2_3->decrRef(); e3_4->decrRef(); e4_5->decrRef(); e5_6->decrRef(); e6_7->decrRef(); 
+  e7_8->decrRef(); e8_9->decrRef(); e9_10->decrRef(); e10_11->decrRef(); e11_12->decrRef(); e12_1->decrRef(); 
+  n1_bis->decrRef();
+  n1->decrRef(); n2->decrRef(); n3->decrRef(); n4->decrRef(); n5->decrRef(); n6->decrRef();
+  n7->decrRef(); n8->decrRef(); n9->decrRef(); n10->decrRef(); n11->decrRef(); n12->decrRef();
+}
+
+/*!
+ * Check splitting of 2 polygons. After this operation, all ElementaryEdge are either in/out/on.
+ */
+void QuadraticPlanarInterpTest::checkAssemblingBases2()
+{
+  //The "most" basic test1
+  Node *n1=new Node(0.,0.);                Node *n4=new Node(0.,-0.3);   
+  Node *n2=new Node(1.,0.);                Node *n5=new Node(1.,-0.3);
+  Node *n3=new Node(0.5,1.);               Node *n6=new Node(0.5,0.7);
+  EdgeLin *e1_2=new EdgeLin(n1,n2);        EdgeLin *e4_5=new EdgeLin(n4,n5);
+  EdgeLin *e2_3=new EdgeLin(n2,n3);        EdgeLin *e5_6=new EdgeLin(n5,n6);
+  EdgeLin *e3_1=new EdgeLin(n3,n1);        EdgeLin *e6_4=new EdgeLin(n6,n4);
+  //
+  e1_2->incrRef(); e2_3->incrRef(); e3_1->incrRef(); e4_5->incrRef(); e5_6->incrRef(); e6_4->incrRef(); 
+  QuadraticPolygon pol1; pol1.pushBack(e1_2); pol1.pushBack(e2_3); pol1.pushBack(e3_1);
+  QuadraticPolygon pol2; pol2.pushBack(e4_5); pol2.pushBack(e5_6); pol2.pushBack(e6_4);
+  QuadraticPolygon cpyPol1(pol1); int nbOfSplits=0;
+  cpyPol1.splitPolygonsEachOther(pol1,pol2,nbOfSplits);
+  CPPUNIT_ASSERT_EQUAL(5,pol1.recursiveSize());
+  CPPUNIT_ASSERT_EQUAL(5,pol2.recursiveSize());CPPUNIT_ASSERT_EQUAL(15,nbOfSplits);
+  checkBasicsOfPolygons(pol1,pol2,true);
+  CPPUNIT_ASSERT((*pol2[1])[0]->getEndNode()==(*(*pol1[0])[0])[1]->getEndNode());
+  CPPUNIT_ASSERT((*pol2[1])[0]->getEndNode()->getLoc()==ON_1);
+  CPPUNIT_ASSERT((*pol2[2])[0]->getEndNode()==(*(*pol1[0])[0])[0]->getEndNode());
+  CPPUNIT_ASSERT((*pol2[2])[0]->getEndNode()->getLoc()==ON_1);
+  cpyPol1.performLocatingOperation(pol2);
+  ElementaryEdge *tmp=dynamic_cast<ElementaryEdge *>(pol2[0]); CPPUNIT_ASSERT(tmp); CPPUNIT_ASSERT(tmp->getPtr()==e4_5);
+  CPPUNIT_ASSERT(tmp->getLoc()==FULL_OUT_1);
+  CPPUNIT_ASSERT(tmp->getLoc()==FULL_OUT_1);
+  tmp=dynamic_cast<ElementaryEdge *>((*pol2[1])[0]); CPPUNIT_ASSERT(tmp);
+  CPPUNIT_ASSERT(tmp->getLoc()==FULL_OUT_1);
+  tmp=dynamic_cast<ElementaryEdge *>((*pol2[1])[1]); CPPUNIT_ASSERT(tmp);
+  CPPUNIT_ASSERT(tmp->getLoc()==FULL_IN_1);
+  tmp=dynamic_cast<ElementaryEdge *>((*pol2[2])[0]); CPPUNIT_ASSERT(tmp);
+  CPPUNIT_ASSERT(tmp->getLoc()==FULL_IN_1);
+  tmp=dynamic_cast<ElementaryEdge *>((*pol2[2])[1]); CPPUNIT_ASSERT(tmp);
+  CPPUNIT_ASSERT(tmp->getLoc()==FULL_OUT_1);
+  //clean-up for test1
+  e1_2->decrRef(); e2_3->decrRef(); e3_1->decrRef(); e4_5->decrRef(); e5_6->decrRef(); e6_4->decrRef();
+  n1->decrRef(); n2->decrRef(); n3->decrRef(); n4->decrRef(); n5->decrRef(); n6->decrRef();
+
+  //Deeper test some extremities of pol2 are on edges of pol1.
+
+  n1=new Node(0.,0.);                n4=new Node(1.5,-0.5);   
+  n2=new Node(1.,0.);                n5=new Node(0.5,0.);
+  n3=new Node(0.5,1.);               n6=new Node(0.75,0.5); Node *n7=new Node(2.,0.5);
+  e1_2=new EdgeLin(n1,n2); e2_3=new EdgeLin(n2,n3); e3_1=new EdgeLin(n3,n1);
+  EdgeLin *e5_4=new EdgeLin(n5,n4); EdgeLin *e4_7=new EdgeLin(n4,n7); EdgeLin *e7_6=new EdgeLin(n7,n6); EdgeLin *e6_5=new EdgeLin(n6,n5);
+  //
+  e1_2->incrRef(); e2_3->incrRef(); e3_1->incrRef(); e5_4->incrRef(); e4_7->incrRef(); e7_6->incrRef(); e6_5->incrRef();
+  QuadraticPolygon pol3; pol3.pushBack(e1_2); pol3.pushBack(e2_3); pol3.pushBack(e3_1);
+  QuadraticPolygon pol4; pol4.pushBack(e5_4); pol4.pushBack(e4_7); pol4.pushBack(e7_6); pol4.pushBack(e6_5);
+  QuadraticPolygon cpyPol3(pol3); nbOfSplits=0;
+  cpyPol3.splitPolygonsEachOther(pol3,pol4,nbOfSplits);
+  CPPUNIT_ASSERT_EQUAL(5,pol3.recursiveSize());
+  CPPUNIT_ASSERT_EQUAL(4,pol4.recursiveSize());CPPUNIT_ASSERT_EQUAL(16,nbOfSplits);
+  checkBasicsOfPolygons(pol3,pol4,true);
+  CPPUNIT_ASSERT(pol4[0]->getStartNode()==(*pol3[0])[0]->getEndNode()); CPPUNIT_ASSERT(pol4[0]->getStartNode()==n5);
+  CPPUNIT_ASSERT(n5->getLoc()==ON_LIM_1);
+  CPPUNIT_ASSERT(pol4[2]->getEndNode()==(*pol3[1])[0]->getEndNode()); CPPUNIT_ASSERT(pol4[2]->getEndNode()==n6);
+  CPPUNIT_ASSERT(n6->getLoc()==ON_LIM_1);
+  cpyPol3.performLocatingOperation(pol4);
+  tmp=dynamic_cast<ElementaryEdge *>(pol4[1]); CPPUNIT_ASSERT(tmp); CPPUNIT_ASSERT(tmp->getPtr()==e4_7);
+  CPPUNIT_ASSERT(tmp->getLoc()==FULL_OUT_1);
+  tmp=dynamic_cast<ElementaryEdge *>(pol4[3]); CPPUNIT_ASSERT(tmp); CPPUNIT_ASSERT(tmp->getPtr()==e6_5);
+  tmp=dynamic_cast<ElementaryEdge *>(pol4[0]); CPPUNIT_ASSERT(tmp); CPPUNIT_ASSERT(tmp->getPtr()==e5_4);
+  CPPUNIT_ASSERT(tmp->getLoc()==FULL_OUT_1);
+  tmp=dynamic_cast<ElementaryEdge *>(pol4[2]); CPPUNIT_ASSERT(tmp); CPPUNIT_ASSERT(tmp->getPtr()==e7_6);
+  CPPUNIT_ASSERT(tmp->getLoc()==FULL_OUT_1);
+  tmp=dynamic_cast<ElementaryEdge *>(pol4[3]); CPPUNIT_ASSERT(tmp); CPPUNIT_ASSERT(tmp->getPtr()==e6_5);
+  CPPUNIT_ASSERT(tmp->getLoc()==FULL_IN_1);
+  //clean-up for test2
+  e1_2->decrRef(); e2_3->decrRef(); e3_1->decrRef(); e5_4->decrRef(); e4_7->decrRef(); e7_6->decrRef(); e6_5->decrRef();
+  n1->decrRef(); n2->decrRef(); n3->decrRef(); n4->decrRef(); n5->decrRef(); n6->decrRef(); n7->decrRef();
+
+  //Test with one edge of pol2 is included in pol1.
+
+  n1=new Node(0.,0.);                n4=new Node(-0.5,0.);   
+  n2=new Node(1.,0.);                n5=new Node(0.,-1.);
+  n3=new Node(0.5,1.);               n6=new Node(0.5,0.);
+  e1_2=new EdgeLin(n1,n2); e2_3=new EdgeLin(n2,n3); e3_1=new EdgeLin(n3,n1);
+  e4_5=new EdgeLin(n4,n5); e5_6=new EdgeLin(n5,n6); e6_4=new EdgeLin(n6,n4);
+  e1_2->incrRef(); e2_3->incrRef(); e3_1->incrRef(); e4_5->incrRef(); e5_6->incrRef(); e6_4->incrRef();
+  QuadraticPolygon pol5; pol5.pushBack(e1_2); pol5.pushBack(e2_3); pol5.pushBack(e3_1);
+  QuadraticPolygon pol6; pol6.pushBack(e4_5); pol6.pushBack(e5_6); pol6.pushBack(e6_4);
+  QuadraticPolygon cpyPol5(pol5); nbOfSplits=0;
+  cpyPol5.splitPolygonsEachOther(pol5,pol6,nbOfSplits);
+  CPPUNIT_ASSERT_EQUAL(4,pol5.recursiveSize());
+  CPPUNIT_ASSERT_EQUAL(4,pol6.recursiveSize()); CPPUNIT_ASSERT_EQUAL(13,nbOfSplits);
+  checkBasicsOfPolygons(pol5,pol6,false);
+  CPPUNIT_ASSERT((*pol6[2])[0]->getStartNode()==(*pol5[0])[0]->getEndNode()); CPPUNIT_ASSERT((*pol6[2])[0]->getStartNode()==n6);
+  CPPUNIT_ASSERT(n6->getLoc()==ON_LIM_1);
+  CPPUNIT_ASSERT((*pol6[2])[0]->getEndNode()==(*pol5[0])[0]->getStartNode()); CPPUNIT_ASSERT((*pol5[0])[0]->getStartNode()==n1);
+  CPPUNIT_ASSERT(n1->getLoc()==ON_LIM_1);
+  cpyPol5.performLocatingOperation(pol6);
+  tmp=dynamic_cast<ElementaryEdge *>(pol6[0]); CPPUNIT_ASSERT(tmp); CPPUNIT_ASSERT(tmp->getPtr()==e4_5);
+  CPPUNIT_ASSERT(tmp->getLoc()==FULL_OUT_1);
+  tmp=dynamic_cast<ElementaryEdge *>(pol6[1]); CPPUNIT_ASSERT(tmp); CPPUNIT_ASSERT(tmp->getPtr()==e5_6);
+  CPPUNIT_ASSERT(tmp->getLoc()==FULL_OUT_1);
+  tmp=dynamic_cast<ElementaryEdge *>((*pol6[2])[0]); CPPUNIT_ASSERT(tmp);
+  CPPUNIT_ASSERT(tmp->getLoc()==FULL_ON_1);
+  tmp=dynamic_cast<ElementaryEdge *>((*pol6[2])[1]); CPPUNIT_ASSERT(tmp);
+  CPPUNIT_ASSERT(tmp->getLoc()==FULL_OUT_1);
+  //clean-up test3
+  e1_2->decrRef(); e2_3->decrRef(); e3_1->decrRef(); e4_5->decrRef(); e5_6->decrRef(); e6_4->decrRef();
+  n1->decrRef(); n2->decrRef(); n3->decrRef(); n4->decrRef(); n5->decrRef(); n6->decrRef();
+
+  //Test of full overlapped polygons.
+
+  n1=new Node(0.,0.);                n4=new Node(0.,0.);   
+  n2=new Node(1.,0.);                n5=new Node(1.,0.);
+  n3=new Node(0.5,1.);               n6=new Node(0.5,1.);
+  e1_2=new EdgeLin(n1,n2); e2_3=new EdgeLin(n2,n3); e3_1=new EdgeLin(n3,n1);
+  e4_5=new EdgeLin(n4,n5); e5_6=new EdgeLin(n5,n6); e6_4=new EdgeLin(n6,n4);
+  e1_2->incrRef(); e2_3->incrRef(); e3_1->incrRef(); e4_5->incrRef(); e5_6->incrRef(); e6_4->incrRef();
+  QuadraticPolygon pol7; pol7.pushBack(e1_2); pol7.pushBack(e2_3); pol7.pushBack(e3_1);
+  QuadraticPolygon pol8; pol8.pushBack(e4_5); pol8.pushBack(e5_6); pol8.pushBack(e6_4);
+  QuadraticPolygon cpyPol7(pol7); nbOfSplits=0;
+  cpyPol7.splitPolygonsEachOther(pol7,pol8,nbOfSplits);
+  tmp=dynamic_cast<ElementaryEdge *>(pol8[0]); CPPUNIT_ASSERT(tmp); CPPUNIT_ASSERT(tmp->getPtr()==e1_2);
+  CPPUNIT_ASSERT(tmp->getLoc()==FULL_ON_1);
+  tmp=dynamic_cast<ElementaryEdge *>(pol8[1]); CPPUNIT_ASSERT(tmp); CPPUNIT_ASSERT(tmp->getPtr()==e2_3);
+  CPPUNIT_ASSERT(tmp->getLoc()==FULL_ON_1);
+  tmp=dynamic_cast<ElementaryEdge *>(pol8[2]); CPPUNIT_ASSERT(tmp); CPPUNIT_ASSERT(tmp->getPtr()==e3_1);
+  CPPUNIT_ASSERT(tmp->getLoc()==FULL_ON_1);
+  //clean-up test4
+  e1_2->decrRef(); e2_3->decrRef(); e3_1->decrRef(); e4_5->decrRef(); e5_6->decrRef(); e6_4->decrRef();
+  n1->decrRef(); n2->decrRef(); n3->decrRef(); n4->decrRef(); n5->decrRef(); n6->decrRef();
+}
+
+void QuadraticPlanarInterpTest::checkBasicsOfPolygons(QuadraticPolygon& pol1, QuadraticPolygon& pol2, bool checkDirection)
+{
+  IteratorOnComposedEdge it1(&pol1),it2(&pol2); it1.previousLoop(); it2.previousLoop();
+  Node *nIter1=it1.current()->getEndNode(); Node *nIter2=it2.current()->getEndNode();
+  for(it2.first();!it2.finished();it2.next())
+    {
+      CPPUNIT_ASSERT(nIter2==it2.current()->getStartNode());
+      if(checkDirection)
+        CPPUNIT_ASSERT(it2.current()->getDirection());
+      nIter2=it2.current()->getEndNode();
+    }
+  for(it1.first();!it1.finished();it1.next())
+    {
+      CPPUNIT_ASSERT(nIter1==it1.current()->getStartNode());
+      if(checkDirection)
+        CPPUNIT_ASSERT(it1.current()->getDirection());
+      nIter1=it1.current()->getEndNode();
+    }
+}
diff --git a/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest4.cxx b/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest4.cxx
new file mode 100644 (file)
index 0000000..9ac85aa
--- /dev/null
@@ -0,0 +1,327 @@
+#include "QuadraticPlanarInterpTest.hxx"
+#include "QuadraticPolygon.hxx"
+#include "ElementaryEdge.hxx"
+#include "EdgeArcCircle.hxx"
+#include "EdgeLin.hxx"
+
+#include <cmath>
+#include <sstream>
+#include <iostream>
+
+using namespace std;
+using namespace INTERP_KERNEL;
+
+void QuadraticPlanarInterpTest::checkPolygonsIntersection1()
+{
+   //The "most" basic test1
+  Node *n1=new Node(0.,0.);                Node *n4=new Node(0.,-0.3);   
+  Node *n2=new Node(1.,0.);                Node *n5=new Node(1.,-0.3);
+  Node *n3=new Node(0.5,1.);               Node *n6=new Node(0.5,0.7);
+  EdgeLin *e1_2=new EdgeLin(n1,n2);        EdgeLin *e4_5=new EdgeLin(n4,n5);
+  EdgeLin *e2_3=new EdgeLin(n2,n3);        EdgeLin *e5_6=new EdgeLin(n5,n6);
+  EdgeLin *e3_1=new EdgeLin(n3,n1);        EdgeLin *e6_4=new EdgeLin(n6,n4);
+  //
+  vector<QuadraticPolygon *> result;
+  for(int k=0;k<2;k++)
+    for(int i=0;i<1;i++)
+      {
+        for(int j=0;j<1;j++)
+          {
+            e1_2->incrRef(); e2_3->incrRef(); e3_1->incrRef(); e4_5->incrRef(); e5_6->incrRef(); e6_4->incrRef(); 
+            QuadraticPolygon pol1; pol1.circularPermute(); pol1.pushBack(e1_2); pol1.pushBack(e2_3); pol1.pushBack(e3_1);
+            for(int i1=0;i1<i;i1++) pol1.circularPermute(); if(k==1) pol1.reverse();
+            QuadraticPolygon pol2; pol2.pushBack(e4_5); pol2.pushBack(e5_6); pol2.pushBack(e6_4);
+            for(int j1=0;j1<j;j1++) pol2.circularPermute();
+            result=pol1.intersectMySelfWith(pol2);
+            CPPUNIT_ASSERT_EQUAL(1,(int)result.size()); checkBasicsOfPolygons(*result[0],*result[0],false);
+            CPPUNIT_ASSERT_EQUAL(3,result[0]->recursiveSize());
+            delete result[0];
+          }
+      }
+  //clean-up for test1
+  e1_2->decrRef(); e2_3->decrRef(); e3_1->decrRef(); e4_5->decrRef(); e5_6->decrRef(); e6_4->decrRef();
+  n1->decrRef(); n2->decrRef(); n3->decrRef(); n4->decrRef(); n5->decrRef(); n6->decrRef();
+
+  //Deeper test some extremities of pol2 are on edges of pol1.
+
+  n1=new Node(0.,0.);                n4=new Node(1.5,-0.5);   
+  n2=new Node(1.,0.);                n5=new Node(0.5,0.);
+  n3=new Node(0.5,1.);               n6=new Node(0.75,0.5); Node *n7=new Node(2.,0.5);
+  e1_2=new EdgeLin(n1,n2); e2_3=new EdgeLin(n2,n3); e3_1=new EdgeLin(n3,n1);
+  EdgeLin *e5_4=new EdgeLin(n5,n4); EdgeLin *e4_7=new EdgeLin(n4,n7); EdgeLin *e7_6=new EdgeLin(n7,n6); EdgeLin *e6_5=new EdgeLin(n6,n5);
+  //
+  for(int k=0;k<2;k++)
+    for(int i=0;i<3;i++)
+      {
+        for(int j=0;j<4;j++)
+          {
+            e1_2->incrRef(); e2_3->incrRef(); e3_1->incrRef(); e5_4->incrRef(); e4_7->incrRef(); e7_6->incrRef(); e6_5->incrRef();
+            QuadraticPolygon pol3; pol3.pushBack(e1_2); pol3.pushBack(e2_3); pol3.pushBack(e3_1);
+            for(int i1=0;i1<i;i1++) pol3.circularPermute(); if(k==1) pol3.reverse();
+            QuadraticPolygon pol4; pol4.pushBack(e5_4); pol4.pushBack(e4_7); pol4.pushBack(e7_6); pol4.pushBack(e6_5);
+            for(int j1=0;j1<j;j1++) pol4.circularPermute();
+            result=pol3.intersectMySelfWith(pol4);
+            CPPUNIT_ASSERT_EQUAL(1,(int)result.size()); checkBasicsOfPolygons(*result[0],*result[0],false);
+            CPPUNIT_ASSERT_EQUAL(3,result[0]->recursiveSize());
+            delete result[0];          
+          }
+      }
+  //clean-up for test2
+  e1_2->decrRef(); e2_3->decrRef(); e3_1->decrRef(); e5_4->decrRef(); e4_7->decrRef(); e7_6->decrRef(); e6_5->decrRef();
+  n1->decrRef(); n2->decrRef(); n3->decrRef(); n4->decrRef(); n5->decrRef(); n6->decrRef(); n7->decrRef();
+
+  //Test with one edge of pol2 is included in pol1.
+
+  n1=new Node(0.,0.);                n4=new Node(-0.5,0.);   
+  n2=new Node(1.,0.);                n5=new Node(0.,-1.);
+  n3=new Node(0.5,1.);               n6=new Node(0.5,0.);
+  e1_2=new EdgeLin(n1,n2); e2_3=new EdgeLin(n2,n3); e3_1=new EdgeLin(n3,n1);
+  e4_5=new EdgeLin(n4,n5); e5_6=new EdgeLin(n5,n6); e6_4=new EdgeLin(n6,n4);
+  for(int k=0;k<2;k++)
+    for(int i=0;i<3;i++)
+      {
+        for(int j=0;j<3;j++)
+          {
+            e1_2->incrRef(); e2_3->incrRef(); e3_1->incrRef(); e4_5->incrRef(); e5_6->incrRef(); e6_4->incrRef();
+            QuadraticPolygon pol5; pol5.pushBack(e1_2); pol5.pushBack(e2_3); pol5.pushBack(e3_1);
+            for(int i1=0;i1<i;i1++) pol5.circularPermute(); if(k==1) pol5.reverse();
+            QuadraticPolygon pol6; pol6.pushBack(e4_5); pol6.pushBack(e5_6); pol6.pushBack(e6_4);
+            for(int j1=0;j1<j;j1++) pol6.circularPermute();
+            result=pol5.intersectMySelfWith(pol6);
+            CPPUNIT_ASSERT_EQUAL(0,(int)result.size());
+          }
+      }
+  //clean-up test3
+  e1_2->decrRef(); e2_3->decrRef(); e3_1->decrRef(); e4_5->decrRef(); e5_6->decrRef(); e6_4->decrRef();
+  n1->decrRef(); n2->decrRef(); n3->decrRef(); n4->decrRef(); n5->decrRef(); n6->decrRef();
+
+  //Test of full overlapped polygons.
+
+  n1=new Node(0.,0.);                n4=new Node(0.,0.);   
+  n2=new Node(1.,0.);                n5=new Node(1.,0.);
+  n3=new Node(0.5,1.);               n6=new Node(0.5,1.);
+  e1_2=new EdgeLin(n1,n2); e2_3=new EdgeLin(n2,n3); e3_1=new EdgeLin(n3,n1);
+  e4_5=new EdgeLin(n4,n5); e5_6=new EdgeLin(n5,n6); e6_4=new EdgeLin(n6,n4);
+  for(int k=0;k<2;k++)
+    for(int i=0;i<3;i++)
+      {
+        for(int j=0;j<3;j++)
+          {
+            e1_2->incrRef(); e2_3->incrRef(); e3_1->incrRef(); e4_5->incrRef(); e5_6->incrRef(); e6_4->incrRef();
+            QuadraticPolygon pol7; pol7.pushBack(e1_2); pol7.pushBack(e2_3); pol7.pushBack(e3_1);
+            for(int i1=0;i1<i;i1++) pol7.circularPermute(); if(k==1) pol7.reverse();
+            QuadraticPolygon pol8; pol8.pushBack(e4_5); pol8.pushBack(e5_6); pol8.pushBack(e6_4);
+            for(int j1=0;j1<j;j1++) pol8.circularPermute();
+            result=pol7.intersectMySelfWith(pol8);
+            CPPUNIT_ASSERT_EQUAL(1,(int)result.size()); checkBasicsOfPolygons(*result[0],*result[0],false);
+            CPPUNIT_ASSERT_EQUAL(3,result[0]->recursiveSize());
+            delete result[0];
+          }
+      }
+  //clean-up test4
+  e1_2->decrRef(); e2_3->decrRef(); e3_1->decrRef(); e4_5->decrRef(); e5_6->decrRef(); e6_4->decrRef();
+  n1->decrRef(); n2->decrRef(); n3->decrRef(); n4->decrRef(); n5->decrRef(); n6->decrRef();
+
+  //Test of closing process
+  
+  n1=new Node(0.,0.);                n4=new Node(0.539,-0.266);   
+  n2=new Node(1.,0.);                n5=new Node(1.039,0.6);
+  n3=new Node(0.5,1.);               n6=new Node(-0.077,0.667);
+  e1_2=new EdgeLin(n1,n2); e2_3=new EdgeLin(n2,n3); e3_1=new EdgeLin(n3,n1);
+  e4_5=new EdgeLin(n4,n5); e5_6=new EdgeLin(n5,n6); e6_4=new EdgeLin(n6,n4);
+  for(int k=0;k<2;k++)
+    for(int i=0;i<3;i++)
+      {
+        for(int j=0;j<3;j++)
+          {
+            e1_2->incrRef(); e2_3->incrRef(); e3_1->incrRef(); e4_5->incrRef(); e5_6->incrRef(); e6_4->incrRef();
+            QuadraticPolygon pol9; pol9.pushBack(e1_2); pol9.pushBack(e2_3); pol9.pushBack(e3_1);
+            for(int i1=0;i1<i;i1++) pol9.circularPermute(); if(k==1) pol9.reverse();
+            QuadraticPolygon pol10; pol10.pushBack(e5_6); pol10.pushBack(e6_4); pol10.pushBack(e4_5);
+            for(int j1=0;j1<j;j1++) pol10.circularPermute();
+            result=pol9.intersectMySelfWith(pol10);
+            CPPUNIT_ASSERT_EQUAL(1,(int)result.size()); checkBasicsOfPolygons(*result[0],*result[0],false);
+            CPPUNIT_ASSERT_EQUAL(6,result[0]->recursiveSize());
+            delete result[0];
+          }
+      }
+  //clean-up test5
+  e1_2->decrRef(); e2_3->decrRef(); e3_1->decrRef(); e4_5->decrRef(); e5_6->decrRef(); e6_4->decrRef();
+  n1->decrRef(); n2->decrRef(); n3->decrRef(); n4->decrRef(); n5->decrRef(); n6->decrRef();
+
+  // Full in case
+
+  n1=new Node(0.,0.);                n4=new Node(0.3,0.1);   
+  n2=new Node(1.,0.);                n5=new Node(0.7,0.1);
+  n3=new Node(0.5,1.);               n6=new Node(0.5,0.7);
+  e1_2=new EdgeLin(n1,n2); e2_3=new EdgeLin(n2,n3); e3_1=new EdgeLin(n3,n1);
+  e4_5=new EdgeLin(n4,n5); e5_6=new EdgeLin(n5,n6); e6_4=new EdgeLin(n6,n4);
+  for(int k=0;k<2;k++)
+    for(int i=0;i<3;i++)
+      {
+        for(int j=0;j<3;j++)
+          {
+            e1_2->incrRef(); e2_3->incrRef(); e3_1->incrRef(); e4_5->incrRef(); e5_6->incrRef(); e6_4->incrRef();
+            QuadraticPolygon pol11; pol11.pushBack(e1_2); pol11.pushBack(e2_3); pol11.pushBack(e3_1);
+            for(int i1=0;i1<i;i1++) pol11.circularPermute(); if(k==1) pol11.reverse();
+            QuadraticPolygon pol12; pol12.pushBack(e5_6); pol12.pushBack(e6_4); pol12.pushBack(e4_5);
+            for(int j1=0;j1<j;j1++) pol12.circularPermute();
+            result=pol11.intersectMySelfWith(pol12);
+            CPPUNIT_ASSERT_EQUAL(1,(int)result.size()); checkBasicsOfPolygons(*result[0],*result[0],false);
+            CPPUNIT_ASSERT_EQUAL(3,result[0]->recursiveSize());
+            delete result[0];
+          }
+      }
+  //clean-up test6
+  e1_2->decrRef(); e2_3->decrRef(); e3_1->decrRef(); e4_5->decrRef(); e5_6->decrRef(); e6_4->decrRef();
+  n1->decrRef(); n2->decrRef(); n3->decrRef(); n4->decrRef(); n5->decrRef(); n6->decrRef();
+
+  // Full out case
+
+  n1=new Node(0.,0.);                n4=new Node(-2,0.);   
+  n2=new Node(1.,0.);                n5=new Node(-1.,0.);
+  n3=new Node(0.5,1.);               n6=new Node(-1.5,1.);
+  e1_2=new EdgeLin(n1,n2); e2_3=new EdgeLin(n2,n3); e3_1=new EdgeLin(n3,n1);
+  e4_5=new EdgeLin(n4,n5); e5_6=new EdgeLin(n5,n6); e6_4=new EdgeLin(n6,n4);
+  for(int k=0;k<2;k++)
+    for(int i=0;i<3;i++)
+      {
+        for(int j=0;j<3;j++)
+          {
+            e1_2->incrRef(); e2_3->incrRef(); e3_1->incrRef(); e4_5->incrRef(); e5_6->incrRef(); e6_4->incrRef();
+            QuadraticPolygon pol13; pol13.pushBack(e1_2); pol13.pushBack(e2_3); pol13.pushBack(e3_1);
+            for(int i1=0;i1<i;i1++) pol13.circularPermute(); if(k==1) pol13.reverse();
+            QuadraticPolygon pol14; pol14.pushBack(e5_6); pol14.pushBack(e6_4); pol14.pushBack(e4_5);
+            for(int j1=0;j1<j;j1++) pol14.circularPermute();
+            result=pol13.intersectMySelfWith(pol14);
+            CPPUNIT_ASSERT_EQUAL(0,(int)result.size());
+          }
+      }
+  //clean-up test7
+  e1_2->decrRef(); e2_3->decrRef(); e3_1->decrRef(); e4_5->decrRef(); e5_6->decrRef(); e6_4->decrRef();
+  n1->decrRef(); n2->decrRef(); n3->decrRef(); n4->decrRef(); n5->decrRef(); n6->decrRef();
+
+  //Multi polygons
+  
+   n1=new Node(0.,0.);
+   n2=new Node(1.,0.);
+   n3=new Node(1.,1.);
+   n4=new Node(0.,1.);
+   //
+   n5=new Node(0.2,0.7);
+   n6=new Node(0.4,0.7);
+   n7=new Node(0.4,1.3);
+   Node *n8=new Node(0.6,1.3);
+   Node *n9=new Node(0.6,0.7);
+   Node *n10=new Node(0.9,0.7);
+   Node *n11=new Node(0.9,2.);
+   Node *n12=new Node(0.2,2.);
+   //
+   e1_2=new EdgeLin(n1,n2); e2_3=new EdgeLin(n2,n3); Edge *e3_4=new EdgeLin(n3,n4); Edge *e4_1=new EdgeLin(n4,n1);
+   e5_6=new EdgeLin(n5,n6); Edge *e6_7=new EdgeLin(n6,n7); Edge *e7_8=new EdgeLin(n7,n8); Edge *e8_9=new EdgeLin(n8,n9); Edge *e9_10=new EdgeLin(n9,n10); Edge *e10_11=new EdgeLin(n10,n11);
+   Edge *e11_12=new EdgeLin(n11,n12); Edge *e12_1=new EdgeLin(n12,n5);
+   //
+   for(int k=0;k<2;k++)
+     for(int i=0;i<4;i++)
+       {
+         for(int j=0;j<8;j++)
+           {
+             e1_2->incrRef(); e2_3->incrRef(); e3_4->incrRef(); e4_1->incrRef(); e5_6->incrRef(); e6_7->incrRef(); e7_8->incrRef(); e8_9->incrRef(); e9_10->incrRef(); e10_11->incrRef(); e11_12->incrRef(); e12_1->incrRef();
+             QuadraticPolygon pol15; pol15.pushBack(e1_2); pol15.pushBack(e2_3); pol15.pushBack(e3_4); pol15.pushBack(e4_1);
+             for(int i1=0;i1<i;i1++) pol15.circularPermute(); if(k==1) pol15.reverse();
+             QuadraticPolygon pol16; pol16.pushBack(e5_6); pol16.pushBack(e6_7); pol16.pushBack(e7_8); pol16.pushBack(e8_9); pol16.pushBack(e9_10); pol16.pushBack(e10_11); pol16.pushBack(e11_12); pol16.pushBack(e12_1);
+             for(int j1=0;j1<j;j1++) pol16.circularPermute();
+             result=pol15.intersectMySelfWith(pol16);
+             CPPUNIT_ASSERT_EQUAL(2,(int)result.size());
+             checkBasicsOfPolygons(*result[0],*result[1],false);
+             CPPUNIT_ASSERT_EQUAL(4,result[0]->recursiveSize()); CPPUNIT_ASSERT_EQUAL(4,result[1]->recursiveSize());
+             CPPUNIT_ASSERT_DOUBLES_EQUAL(0.15,result[0]->getAreaFast()+result[1]->getAreaFast(),1e-10);
+             CPPUNIT_ASSERT_DOUBLES_EQUAL(0.03,fabs(result[0]->getAreaFast()-result[1]->getAreaFast()),1e-10);
+             CPPUNIT_ASSERT_DOUBLES_EQUAL(0.15,pol15.intersectWith(pol16),1e-10);
+             delete result[0]; delete result[1];
+           }
+       }
+   //clean-up test8
+   e1_2->decrRef(); e2_3->decrRef(); e3_4->decrRef(); e4_1->decrRef(); e5_6->decrRef(); e6_7->decrRef(); e7_8->decrRef(); e8_9->decrRef(); e9_10->decrRef(); e10_11->decrRef(); e11_12->decrRef(); e12_1->decrRef();
+   n1->decrRef(); n2->decrRef(); n3->decrRef(); n4->decrRef(); n5->decrRef(); n6->decrRef(); n7->decrRef(); n8->decrRef(); n9->decrRef(); n10->decrRef(); n11->decrRef(); n12->decrRef();
+}
+
+void QuadraticPlanarInterpTest::checkAreasCalculations()
+{
+  Node *n1=new Node(0.,0.);
+  Node *n2=new Node(1.,0.);
+  Node *n3=new Node(0.5,1.);
+  Edge *e1_2=new EdgeLin(n1,n2);
+  Edge *e2_3=new EdgeLin(n2,n3);
+  Edge *e3_1=new EdgeLin(n3,n1);
+  //
+  e1_2->incrRef(); e2_3->incrRef(); e3_1->incrRef();
+  QuadraticPolygon pol1; pol1.pushBack(e1_2); pol1.pushBack(e2_3); pol1.pushBack(e3_1);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.5,pol1.getAreaFast(),1e-10);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(3.2360679774997898,pol1.getPerimeterFast(),1e-10);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.61803398874989479,pol1.getHydroulicDiameter(),1e-10);
+  pol1.reverse();
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.5,pol1.getAreaFast(),1e-10);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(3.2360679774997898,pol1.getPerimeterFast(),1e-10);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.61803398874989479,pol1.getHydroulicDiameter(),1e-10);
+  //clean-up
+  e1_2->decrRef(); e2_3->decrRef(); e3_1->decrRef();
+  n1->decrRef(); n2->decrRef(); n3->decrRef();
+
+  //case 2
+
+  n1=new Node(0.,0.);
+  n2=new Node(1.,0.);
+  Node *n3m=new Node(1.5,0.5);
+  n3=new Node(1.,1.);
+  Node *n4=new Node(0.,1.);
+  e1_2=new EdgeLin(n1,n2);
+  e2_3=new EdgeArcCircle(n2,n3m,n3);
+  Edge *e3_4=new EdgeLin(n3,n4);
+  Edge *e4_1=new EdgeLin(n4,n1);
+  //
+  for(int k=0;k<8;k++)
+    {
+      n2->setNewCoords(cos(k*M_PI/4),sin(k*M_PI/4));
+      n3->setNewCoords(sqrt(2.)*cos((k+1)*M_PI/4),sqrt(2.)*sin((k+1)*M_PI/4));
+      n3m->setNewCoords(1.5811388300841898*cos(0.3217505543966423+k*M_PI/4),1.5811388300841898*sin(0.3217505543966423+k*M_PI/4));
+      n4->setNewCoords(cos(k*M_PI/4+M_PI/2),sin(k*M_PI/4+M_PI/2));
+      e1_2->update(n3m); e2_3->update(n3m); e3_4->update(n3m); e4_1->update(n3m);
+      e1_2->incrRef(); e2_3->incrRef(); e3_4->incrRef(); e4_1->incrRef();
+      QuadraticPolygon pol2; pol2.pushBack(e1_2); pol2.pushBack(e2_3); pol2.pushBack(e3_4); pol2.pushBack(e4_1);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(1.3926990816987241,pol2.getAreaFast(),1e-6);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(4.5707963267948966,pol2.getPerimeterFast(),1e-6);
+      pol2.reverse();
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(-1.3926990816987241,pol2.getAreaFast(),1e-6);
+      CPPUNIT_ASSERT_DOUBLES_EQUAL(4.5707963267948966,pol2.getPerimeterFast(),1e-6);
+    }
+  //clean-up case2
+  e1_2->decrRef(); e2_3->decrRef(); e3_4->decrRef(); e4_1->decrRef(); 
+  n1->decrRef(); n2->decrRef(); n3->decrRef(); n3m->decrRef(); n4->decrRef();
+  
+  //case 3
+
+  const double radius1=0.7;
+  const double radius2=0.9;
+  n1=new Node(1.+radius1*cos(-2.*M_PI/3.),1.+radius1*sin(-2.*M_PI/3.));
+  n2=new Node(1.+radius1*cos(-M_PI/3.),1.+radius1*sin(-M_PI/3.));
+  Node *n2m=new Node(1.+radius1*cos(M_PI/2.),1.+radius1*sin(M_PI/2.));
+  n3=new Node(1.+radius2*cos(-M_PI/3.),1.+radius2*sin(-M_PI/3.));
+  n3m=new Node(1.+radius2*cos(M_PI/2.),1.+radius2*sin(M_PI/2.));
+  n4=new Node(1.+radius2*cos(-2.*M_PI/3.),1.+radius2*sin(-2.*M_PI/3.));
+  e1_2=new EdgeArcCircle(n1,n2m,n2);
+  e2_3=new EdgeLin(n2,n3);
+  e3_4=new EdgeArcCircle(n3,n3m,n4);
+  e4_1=new EdgeLin(n4,n1);
+  //
+  e1_2->incrRef(); e2_3->incrRef(); e3_4->incrRef(); e4_1->incrRef();
+  QuadraticPolygon pol3; pol3.pushBack(e1_2); pol3.pushBack(e2_3); pol3.pushBack(e3_4); pol3.pushBack(e4_1);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(0.83775804095727857,pol3.getAreaFast(),1e-10);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(8.7775804095727832,pol3.getPerimeterFast(),1e-10);
+  pol3.reverse();
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.83775804095727857,pol3.getAreaFast(),1e-10);
+  CPPUNIT_ASSERT_DOUBLES_EQUAL(8.7775804095727832,pol3.getPerimeterFast(),1e-10);
+  //clean-up case3
+  e1_2->decrRef(); e2_3->decrRef(); e3_4->decrRef(); e4_1->decrRef(); 
+  n1->decrRef(); n2->decrRef(); n2m->decrRef(); n3->decrRef(); n3m->decrRef(); n4->decrRef();
+}
diff --git a/src/INTERP_KERNEL/Geometric2D/QuadraticPolygon.cxx b/src/INTERP_KERNEL/Geometric2D/QuadraticPolygon.cxx
new file mode 100644 (file)
index 0000000..99ff742
--- /dev/null
@@ -0,0 +1,350 @@
+#include "QuadraticPolygon.hxx"
+#include "ComposedEdgeWithIt.hxx"
+#include "ElementaryEdge.hxx"
+#include "Bounds.hxx"
+#include "Edge.txx"
+
+#include <fstream>
+
+using namespace std;
+using namespace INTERP_KERNEL;
+
+namespace INTERP_KERNEL
+{
+  const unsigned MAX_SIZE_OF_LINE_XFIG_FILE=1024;
+}
+
+QuadraticPolygon::QuadraticPolygon(const char *file)
+{
+  char currentLine[MAX_SIZE_OF_LINE_XFIG_FILE];
+  ifstream stream(file);
+  stream.exceptions(ios_base::eofbit);
+  try
+    {
+      do
+       stream.getline(currentLine,MAX_SIZE_OF_LINE_XFIG_FILE);
+      while(strcmp(currentLine,"1200 2")!=0);
+      do
+       {
+          Edge *newEdge=Edge::buildFromXfigLine(stream);
+          if(!empty())
+            newEdge->changeStartNodeWith(back()->getEndNode());
+         pushBack(newEdge);
+       }
+      while(1);
+    }
+  catch(ifstream::failure& e)
+    {
+    }
+  front()->changeStartNodeWith(back()->getEndNode());
+}
+
+QuadraticPolygon::~QuadraticPolygon()
+{
+}
+
+void QuadraticPolygon::circularPermute()
+{
+  vector<AbstractEdge *>::iterator iter1=_subEdges.begin();
+  vector<AbstractEdge *>::iterator iter2=_subEdges.begin();
+  if(iter2!=_subEdges.end())
+    iter2++;
+  else
+    return ;
+  for(;iter2!=_subEdges.end();iter1++,iter2++)
+    iter_swap(iter1,iter2);
+}
+
+double QuadraticPolygon::getAreaFast() const
+{
+  double ret=0.;
+  for(vector<AbstractEdge *>::const_iterator iter=_subEdges.begin();iter!=_subEdges.end();iter++)
+    {
+      ElementaryEdge *tmp=(ElementaryEdge *)(*iter);
+      ret+=tmp->getAreaOfZoneFast();
+    }
+  return ret;
+}
+
+double QuadraticPolygon::getPerimeterFast() const
+{
+  double ret=0.;
+  for(vector<AbstractEdge *>::const_iterator iter=_subEdges.begin();iter!=_subEdges.end();iter++)
+    {
+      ElementaryEdge *tmp=(ElementaryEdge *)(*iter);
+      ret+=tmp->getCurveLength();
+    }
+  return ret;
+}
+
+double QuadraticPolygon::getHydroulicDiameter() const
+{
+  return 4*fabs(getAreaFast())/getPerimeterFast();
+}
+
+void QuadraticPolygon::dumpInXfigFile(const char *fileName) const
+{
+  ofstream file(fileName);
+  file << "#FIG 3.2  Produced by xfig version 3.2.5-alpha5" << endl;
+  file << "Landscape" << endl;
+  file << "Center" << endl;
+  file << "Inches" << endl;
+  file << "Letter" << endl;
+  file << "100.00" << endl;
+  file << "Single" << endl;
+  file << "-2" << endl;
+  file << "1200 2" << endl;
+  ComposedEdge::dumpInXfigFile(file);
+}
+
+double QuadraticPolygon::intersectWith(const QuadraticPolygon& other) const
+{
+  double ret=0;
+  vector<QuadraticPolygon *> polygs=intersectMySelfWith(other);
+  for(vector<QuadraticPolygon *>::iterator iter=polygs.begin();iter!=polygs.end();iter++)
+    {
+      ret+=fabs((*iter)->getAreaFast());
+      delete *iter;
+    }
+  return ret;
+}
+
+std::vector<QuadraticPolygon *> QuadraticPolygon::intersectMySelfWith(const QuadraticPolygon& other) const
+{
+  QuadraticPolygon cpyOfThis(*this);
+  QuadraticPolygon cpyOfOther(other); int nbOfSplits=0;
+  splitPolygonsEachOther(cpyOfThis,cpyOfOther,nbOfSplits);
+  //At this point cpyOfThis and cpyOfOther have been splited at maximum edge so that in/out can been done.
+  performLocatingOperation(cpyOfOther);
+  return other.buildIntersectionPolygons(cpyOfThis,cpyOfOther);
+}
+
+/*!
+ * This method is typically the first step of boolean operations between pol1 and pol2.
+ * This method perform the minimal splitting so that at the end each edges constituting pol1 are fully either IN or OUT or ON.
+ * @param pol1 IN/OUT param that is equal to 'this' when called.
+ */
+void QuadraticPolygon::splitPolygonsEachOther(QuadraticPolygon& pol1, QuadraticPolygon& pol2, int& nbOfSplits) const
+{
+  IteratorOnComposedEdge it1(&pol1),it2(&pol2);
+  MergePoints merge;
+  ComposedEdge *c1=new ComposedEdge;
+  ComposedEdgeWithIt *c2=new ComposedEdgeWithIt;
+  for(it2.first();!it2.finished();it2.next())
+    {
+      ComposedEdgeWithIt *dealer=dynamic_cast<ComposedEdgeWithIt *>(it2.getLowestDealing());
+      if(!dealer)
+        it1.first();
+      else
+        it1=dealer->getIterator();
+      for(;!it1.finished();)
+        {
+          ElementaryEdge* &curE2=it2.current();
+          ElementaryEdge* &curE1=it1.current();
+          merge.clear(); nbOfSplits++;
+          if(curE1->getPtr()->intersectWith(curE2->getPtr(),merge,*c1,*c2))
+            {
+              if(!curE1->getDirection()) c1->reverse();
+              if(!curE2->getDirection()) c2->reverse();
+              AbstractEdge *c1s=c1->simplify();
+              AbstractEdge *c2s=c2->simplify();
+              updateNeighbours(merge,it1,it2,c1s,c2s);
+              it1.next();//to do before
+              //Substitution of simple edge by sub-edges.
+              AbstractEdge **tmp1=(AbstractEdge**)&curE1; delete *tmp1; // <-- destroying simple edge coming from pol1
+              AbstractEdge **tmp2=(AbstractEdge**)&curE2; delete *tmp2; // <-- destroying simple edge coming from pol2
+              *tmp1=c1s;
+              *tmp2=c2s;
+              //
+              if(c2s==c2)//in this case, all elts of c2s(ComposedEdges) should start to be intersected by starting to it1.
+                c2->setIterator(it1);//c2s==c2 implies that c2s is a composed edge so sub iterations requested.
+              c1=new ComposedEdge;
+              c2=new ComposedEdgeWithIt;
+            }
+          else
+                                               {
+                                                       updateNeighbours(merge,it1,it2,curE1,curE2);
+                                                       it1.next();
+                                               }
+        }
+    }
+  ComposedEdge::Delete(c1); delete c2;
+}
+
+void QuadraticPolygon::performLocatingOperation(QuadraticPolygon& pol2) const
+{
+  IteratorOnComposedEdge it(&pol2);
+  TypeOfEdgeLocInPolygon loc=FULL_ON_1;
+  for(it.first();!it.finished();it.next())
+    {
+      ElementaryEdge *cur=it.current();
+      loc=cur->locateFullyMySelf(*this,loc);
+    }
+}
+
+std::vector<QuadraticPolygon *> QuadraticPolygon::buildIntersectionPolygons(const QuadraticPolygon& pol1, const QuadraticPolygon& pol2) const
+{
+  vector<QuadraticPolygon *> ret;
+  list<QuadraticPolygon *> pol2Zip=pol2.zipConsecutiveInSegments();
+  if(!pol2Zip.empty())
+    closePolygons(pol2Zip,pol1,ret);
+  return ret;
+}
+
+std::list<QuadraticPolygon *> QuadraticPolygon::zipConsecutiveInSegments() const
+{
+  list<QuadraticPolygon *> ret;
+  IteratorOnComposedEdge it((ComposedEdge *)this);
+  int nbOfTurns=recursiveSize();
+  int i=0;
+  if(!it.goToNextInOn(false,i,nbOfTurns))
+    return ret;
+  i=0;
+  //
+  while(i<nbOfTurns)
+    {
+      QuadraticPolygon *tmp1=new QuadraticPolygon;
+      TypeOfEdgeLocInPolygon loc=it.current()->getLoc();
+      while(loc!=FULL_OUT_1 && i<nbOfTurns)
+        {
+         AbstractEdge *tmp3=it.current()->clone();
+          tmp1->pushBack(tmp3);
+          it.nextLoop(); i++;
+          loc=it.current()->getLoc();
+        }
+      if(tmp1->empty())
+        {
+          delete tmp1;
+          continue;
+        }
+      ret.push_back(tmp1);
+      it.goToNextInOn(true,i,nbOfTurns);
+    }
+  return ret;
+}
+
+/*!
+ * 'this' should be considered as pol2Simplified.
+ */
+void QuadraticPolygon::closePolygons(std::list<QuadraticPolygon *>& pol2Zip, const QuadraticPolygon& pol1,
+                                     std::vector<QuadraticPolygon *>& results) const
+{
+  bool directionKnownInPol1=false;
+  bool directionInPol1;
+  for(list<QuadraticPolygon *>::iterator iter=pol2Zip.begin();iter!=pol2Zip.end();)
+    {
+      if((*iter)->completed())
+        {
+          results.push_back(*iter);
+          directionKnownInPol1=false;
+          iter=pol2Zip.erase(iter);
+          continue;
+        }
+      if(!directionKnownInPol1)
+        if(!(*iter)->amIAChanceToBeCompletedBy(pol1,*this,directionInPol1))
+          { delete *iter; iter=pol2Zip.erase(iter); continue; }
+       else
+         directionKnownInPol1=true;
+      list<QuadraticPolygon *>::iterator iter2=iter; iter2++;
+      list<QuadraticPolygon *>::iterator iter3=(*iter)->fillAsMuchAsPossibleWith(pol1,iter2,pol2Zip.end(),directionInPol1);
+      if(iter3!=pol2Zip.end())
+        {
+          (*iter)->pushBack(*iter3);
+          pol2Zip.erase(iter3);
+        }
+    }
+}
+
+void QuadraticPolygon::updateNeighbours(const MergePoints& merger, IteratorOnComposedEdge it1, IteratorOnComposedEdge it2,
+                                       const AbstractEdge *e1, const AbstractEdge *e2)
+{
+  it1.previousLoop(); it2.previousLoop();
+  ElementaryEdge *curE1=it1.current(); ElementaryEdge *curE2=it2.current();
+  curE1->changeEndNodeWith(e1->getStartNode()); curE2->changeEndNodeWith(e2->getStartNode());
+  it1.nextLoop(); it1.nextLoop(); it2.nextLoop(); it2.nextLoop();
+  curE1->changeStartNodeWith(e1->getEndNode()); curE2->changeStartNodeWith(e2->getEndNode());
+}
+
+bool QuadraticPolygon::amIAChanceToBeCompletedBy(const QuadraticPolygon& pol1Splitted,const QuadraticPolygon& pol2NotSplitted, bool& direction)
+{
+  IteratorOnComposedEdge it((QuadraticPolygon *)&pol1Splitted);
+  bool found=false;
+  Node *n=getEndNode();
+  ElementaryEdge *cur=it.current();
+  for(it.first();!it.finished() && !found;)
+    {
+      cur=it.current();
+      found=(cur->getStartNode()==n);
+      if(!found)
+        it.next();
+    }
+  if(!found)
+    throw Exception("Internal error : polygons uncompatible each others. Should never happend");
+  //Ok we found correspondance between this and pol1. Searching for right direction to close polygon.
+  IteratorOnComposedEdge::ItOnFixdLev tmp;
+  ElementaryEdge *e=getLastElementary(tmp);
+  if(e->getLoc()==FULL_ON_1)
+    {
+      if(e->getPtr()==cur->getPtr())
+        {
+          direction=false;
+          it.previousLoop();
+          cur=it.current();
+          return pol2NotSplitted.isInOrOut(cur->getStartNode());
+        }
+      else
+        {
+          direction=true;
+          return pol2NotSplitted.isInOrOut(cur->getEndNode());
+        }
+    }
+  else
+    direction=cur->locateFullyMySelfAbsolute(pol2NotSplitted)==FULL_IN_1;
+  return true;
+}
+
+std::list<QuadraticPolygon *>::iterator QuadraticPolygon::fillAsMuchAsPossibleWith(const QuadraticPolygon& pol1Splitted,
+                                                                                   std::list<QuadraticPolygon *>::iterator iStart,
+                                                                                   std::list<QuadraticPolygon *>::iterator iEnd,
+                                                                                   bool direction)
+{
+  IteratorOnComposedEdge it((QuadraticPolygon *)&pol1Splitted);
+  bool found=false;
+  Node *n=getEndNode();
+  ElementaryEdge *cur;
+  for(it.first();!it.finished() && !found;)
+    {
+      cur=it.current();
+      found=(cur->getStartNode()==n);
+      if(!found)
+        it.next();
+    }
+  if(!direction)
+    it.previousLoop();
+  Node *nodeToTest;
+  std::list<QuadraticPolygon *>::iterator ret;
+  do
+    {
+      cur=it.current();
+      AbstractEdge *tmp=cur->clone();
+      if(!direction)
+        tmp->reverse();
+      pushBack(tmp);
+      nodeToTest=tmp->getEndNode();
+      direction?it.nextLoop():it.previousLoop();
+      ret=checkInList(nodeToTest,iStart,iEnd);
+      if(completed())
+        return iEnd;
+    }
+  while(ret==iEnd);
+  return ret;
+}
+
+std::list<QuadraticPolygon *>::iterator QuadraticPolygon::checkInList(Node *n, std::list<QuadraticPolygon *>::iterator iStart,
+                                                                      std::list<QuadraticPolygon *>::iterator iEnd)
+{
+  for(list<QuadraticPolygon *>::iterator iter=iStart;iter!=iEnd;iter++)
+    if((*iter)->isNodeIn(n))
+      return iter;
+  return iEnd;
+}
diff --git a/src/INTERP_KERNEL/Geometric2D/QuadraticPolygon.hxx b/src/INTERP_KERNEL/Geometric2D/QuadraticPolygon.hxx
new file mode 100644 (file)
index 0000000..4c6c60b
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef __QUADRATICPOLYGON_HXX__
+#define __QUADRATICPOLYGON_HXX__
+
+#include "ComposedEdge.hxx"
+
+#include <list>
+
+namespace INTERP_KERNEL
+{
+  class Edge;
+  class MergePoints;
+
+  class QuadraticPolygon : public ComposedEdge
+  {
+  public:
+    QuadraticPolygon() { }
+    QuadraticPolygon(const QuadraticPolygon& other):ComposedEdge(other) { }
+    QuadraticPolygon(const char *fileName);
+    ~QuadraticPolygon();
+    void circularPermute();
+    //! warning : use it if and only if this is composed of ElementaryEdges only : typical case.
+    double getAreaFast() const;
+    double getPerimeterFast() const;
+    double getHydroulicDiameter() const;
+    void dumpInXfigFile(const char *fileName) const;
+    double intersectWith(const QuadraticPolygon& other) const;
+    std::vector<QuadraticPolygon *> intersectMySelfWith(const QuadraticPolygon& other) const;
+  public://Only public for tests reasons
+    void performLocatingOperation(QuadraticPolygon& pol2) const;
+    void splitPolygonsEachOther(QuadraticPolygon& pol1, QuadraticPolygon& pol2, int& nbOfSplits) const;
+    std::vector<QuadraticPolygon *> buildIntersectionPolygons(const QuadraticPolygon& pol1, const QuadraticPolygon& pol2) const;
+    bool amIAChanceToBeCompletedBy(const QuadraticPolygon& pol1Splitted, const QuadraticPolygon& pol2NotSplitted, bool& direction);
+  protected:
+    std::list<QuadraticPolygon *> zipConsecutiveInSegments() const;
+    void closePolygons(std::list<QuadraticPolygon *>& pol2Zip, const QuadraticPolygon& pol1, std::vector<QuadraticPolygon *>& results) const;
+    static void updateNeighbours(const MergePoints& merger, IteratorOnComposedEdge it1, IteratorOnComposedEdge it2,
+                                const AbstractEdge *e1, const AbstractEdge *e2);
+    std::list<QuadraticPolygon *>::iterator fillAsMuchAsPossibleWith(const QuadraticPolygon& pol1Splitted,
+                                                                     std::list<QuadraticPolygon *>::iterator iStart,
+                                                                     std::list<QuadraticPolygon *>::iterator iEnd,
+                                                                     bool direction);
+    static std::list<QuadraticPolygon *>::iterator checkInList(Node *n, std::list<QuadraticPolygon *>::iterator iStart,
+                                                               std::list<QuadraticPolygon *>::iterator iEnd);
+  };
+}
+
+#endif
diff --git a/src/INTERP_KERNEL/Geometric2D/README b/src/INTERP_KERNEL/Geometric2D/README
new file mode 100644 (file)
index 0000000..398f7bd
--- /dev/null
@@ -0,0 +1,4 @@
+Info for xfig outputs comes from : 
+http://www.xfig.org/userman/fig-format.html
+
+
diff --git a/src/INTERP_KERNEL/Geometric2D/TODO b/src/INTERP_KERNEL/Geometric2D/TODO
new file mode 100644 (file)
index 0000000..2777c00
--- /dev/null
@@ -0,0 +1,9 @@
+1 ) Virer les *OFFSET_FOR... de Edge.cxx et remplacer par une méthode static à retour const int
+2 ) tester le buildEdgeLyingOnMe du ArcCircle.
+3 ) tester le intersectWith Lin/ArcCircle avec reverse.
+
+Penser à :
+
+Au moment de faire les intersections Edges/Edges en cas de splitting faire le nécessaire.
+
diff --git a/src/INTERP_KERNEL/Geometric2D/UnitTestsResult.hxx b/src/INTERP_KERNEL/Geometric2D/UnitTestsResult.hxx
new file mode 100644 (file)
index 0000000..31dfdb7
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _UNITTESTSRESULT_HXX_
+#define _UNITTESTSRESULT_HXX_
+
+#include <fstream>
+#include <cstdlib>
+
+namespace INTERP_KERNEL
+{
+  static inline std::string getResultFile() 
+    {
+      std::string s = "/tmp/";
+      s += std::getenv("USER");
+      s += "/UnitTestsResult";
+      return s;
+    }
+
+  std::string UnitTestsResult = getResultFile();
+}
+
+#endif