--- /dev/null
+#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;
+ }
+}
--- /dev/null
+#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 * ¤t() { 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
--- /dev/null
+// 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
--- /dev/null
+#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);
+}
--- /dev/null
+#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
--- /dev/null
+#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);
+}
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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 ! ");
+ }
+}
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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;
+}
--- /dev/null
+#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
--- /dev/null
+#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));
+}
--- /dev/null
+#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
--- /dev/null
+#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]));
+}
--- /dev/null
+#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
--- /dev/null
+#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;
+}
--- /dev/null
+#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
--- /dev/null
+#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]);
+}
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+namespace INTERP_KERNEL
+{
+ namespace QUADRATIC_PLANAR
+ {
+ static double _precision=1e-14;
+ }
+}
--- /dev/null
+
+#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"
--- /dev/null
+#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);
+}
--- /dev/null
+#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
--- /dev/null
+#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;
+}
--- /dev/null
+#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();
+ }
+}
--- /dev/null
+#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();
+}
--- /dev/null
+#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;
+}
--- /dev/null
+#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
--- /dev/null
+Info for xfig outputs comes from :
+http://www.xfig.org/userman/fig-format.html
+
+
--- /dev/null
+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.
+
--- /dev/null
+#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