From abd096715b4af828af9646d2fdfe204c9e6cb150 Mon Sep 17 00:00:00 2001 From: vbd Date: Thu, 13 Mar 2008 10:51:01 +0000 Subject: [PATCH] adding Anthony Geometric intepolator for arcs and edges --- .../Geometric2D/AbstractEdge.cxx | 180 ++++ .../Geometric2D/AbstractEdge.hxx | 76 ++ .../Geometric2D/BasicMainTest.hxx | 96 +++ src/INTERP_KERNEL/Geometric2D/Bounds.cxx | 112 +++ src/INTERP_KERNEL/Geometric2D/Bounds.hxx | 43 + .../Geometric2D/ComposedEdge.cxx | 317 +++++++ .../Geometric2D/ComposedEdge.hxx | 60 ++ .../Geometric2D/ComposedEdgeWithIt.hxx | 21 + src/INTERP_KERNEL/Geometric2D/Edge.cxx | 715 +++++++++++++++ src/INTERP_KERNEL/Geometric2D/Edge.hxx | 227 +++++ src/INTERP_KERNEL/Geometric2D/Edge.txx | 12 + .../Geometric2D/EdgeArcCircle.cxx | 471 ++++++++++ .../Geometric2D/EdgeArcCircle.hxx | 94 ++ src/INTERP_KERNEL/Geometric2D/EdgeInfLin.cxx | 10 + src/INTERP_KERNEL/Geometric2D/EdgeInfLin.hxx | 22 + src/INTERP_KERNEL/Geometric2D/EdgeLin.cxx | 204 +++++ src/INTERP_KERNEL/Geometric2D/EdgeLin.hxx | 54 ++ .../Geometric2D/ElementaryEdge.cxx | 173 ++++ .../Geometric2D/ElementaryEdge.hxx | 53 ++ src/INTERP_KERNEL/Geometric2D/Node.cxx | 87 ++ src/INTERP_KERNEL/Geometric2D/Node.hxx | 65 ++ src/INTERP_KERNEL/Geometric2D/Pol1.fig | 15 + src/INTERP_KERNEL/Geometric2D/Pol2.fig | 13 + src/INTERP_KERNEL/Geometric2D/Pol3.fig | 11 + src/INTERP_KERNEL/Geometric2D/Pol4.fig | 10 + src/INTERP_KERNEL/Geometric2D/Precision.hxx | 7 + .../Geometric2D/QuadraticPlanarInterpRun.cxx | 12 + .../Geometric2D/QuadraticPlanarInterpTest.cxx | 812 ++++++++++++++++++ .../Geometric2D/QuadraticPlanarInterpTest.hxx | 60 ++ .../QuadraticPlanarInterpTest2.cxx | 639 ++++++++++++++ .../QuadraticPlanarInterpTest3.cxx | 300 +++++++ .../QuadraticPlanarInterpTest4.cxx | 327 +++++++ .../Geometric2D/QuadraticPolygon.cxx | 350 ++++++++ .../Geometric2D/QuadraticPolygon.hxx | 47 + src/INTERP_KERNEL/Geometric2D/README | 4 + src/INTERP_KERNEL/Geometric2D/TODO | 9 + .../Geometric2D/UnitTestsResult.hxx | 20 + 37 files changed, 5728 insertions(+) create mode 100644 src/INTERP_KERNEL/Geometric2D/AbstractEdge.cxx create mode 100644 src/INTERP_KERNEL/Geometric2D/AbstractEdge.hxx create mode 100644 src/INTERP_KERNEL/Geometric2D/BasicMainTest.hxx create mode 100644 src/INTERP_KERNEL/Geometric2D/Bounds.cxx create mode 100644 src/INTERP_KERNEL/Geometric2D/Bounds.hxx create mode 100644 src/INTERP_KERNEL/Geometric2D/ComposedEdge.cxx create mode 100644 src/INTERP_KERNEL/Geometric2D/ComposedEdge.hxx create mode 100644 src/INTERP_KERNEL/Geometric2D/ComposedEdgeWithIt.hxx create mode 100644 src/INTERP_KERNEL/Geometric2D/Edge.cxx create mode 100644 src/INTERP_KERNEL/Geometric2D/Edge.hxx create mode 100644 src/INTERP_KERNEL/Geometric2D/Edge.txx create mode 100644 src/INTERP_KERNEL/Geometric2D/EdgeArcCircle.cxx create mode 100644 src/INTERP_KERNEL/Geometric2D/EdgeArcCircle.hxx create mode 100644 src/INTERP_KERNEL/Geometric2D/EdgeInfLin.cxx create mode 100644 src/INTERP_KERNEL/Geometric2D/EdgeInfLin.hxx create mode 100644 src/INTERP_KERNEL/Geometric2D/EdgeLin.cxx create mode 100644 src/INTERP_KERNEL/Geometric2D/EdgeLin.hxx create mode 100644 src/INTERP_KERNEL/Geometric2D/ElementaryEdge.cxx create mode 100644 src/INTERP_KERNEL/Geometric2D/ElementaryEdge.hxx create mode 100644 src/INTERP_KERNEL/Geometric2D/Node.cxx create mode 100644 src/INTERP_KERNEL/Geometric2D/Node.hxx create mode 100644 src/INTERP_KERNEL/Geometric2D/Pol1.fig create mode 100644 src/INTERP_KERNEL/Geometric2D/Pol2.fig create mode 100644 src/INTERP_KERNEL/Geometric2D/Pol3.fig create mode 100644 src/INTERP_KERNEL/Geometric2D/Pol4.fig create mode 100644 src/INTERP_KERNEL/Geometric2D/Precision.hxx create mode 100644 src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpRun.cxx create mode 100644 src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest.cxx create mode 100644 src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest.hxx create mode 100644 src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest2.cxx create mode 100644 src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest3.cxx create mode 100644 src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest4.cxx create mode 100644 src/INTERP_KERNEL/Geometric2D/QuadraticPolygon.cxx create mode 100644 src/INTERP_KERNEL/Geometric2D/QuadraticPolygon.hxx create mode 100644 src/INTERP_KERNEL/Geometric2D/README create mode 100644 src/INTERP_KERNEL/Geometric2D/TODO create mode 100644 src/INTERP_KERNEL/Geometric2D/UnitTestsResult.hxx diff --git a/src/INTERP_KERNEL/Geometric2D/AbstractEdge.cxx b/src/INTERP_KERNEL/Geometric2D/AbstractEdge.cxx new file mode 100644 index 000000000..6bd311226 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/AbstractEdge.cxx @@ -0,0 +1,180 @@ +#include "AbstractEdge.hxx" +#include "ComposedEdge.hxx" +#include "ElementaryEdge.hxx" + +using namespace INTERP_KERNEL; + +IteratorOnComposedEdge::IteratorOnComposedEdge(ComposedEdge *cont):_container(cont) +{ + first(); +} + +void IteratorOnComposedEdge::operator=(const IteratorOnComposedEdge& other) +{ + _container=other._container; + for(ItOnFixdLev it=0;itgetLastElementary(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(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(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 && igetLoc(); + } + if(i==nbMax) + return false; + return true; + } + else + { + while(loc==FULL_OUT_1 && igetLoc(); + } + if(i==nbMax) + return false; + while(loc!=FULL_OUT_1 && igetLoc(); + } + nextLoop(); i--; + return true; + } +} diff --git a/src/INTERP_KERNEL/Geometric2D/AbstractEdge.hxx b/src/INTERP_KERNEL/Geometric2D/AbstractEdge.hxx new file mode 100644 index 000000000..a30eaf23b --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/AbstractEdge.hxx @@ -0,0 +1,76 @@ +#ifndef __ABSTRACTEDGE_HXX__ +#define __ABSTRACTEDGE_HXX__ + +#include +#include + +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& output) const = 0; + virtual ElementaryEdge* &getLastElementary(IteratorOnComposedEdge::ItOnFixdLev &delta) = 0; + virtual ElementaryEdge* &getFirstElementary(IteratorOnComposedEdge::ItOnFixdLev &delta) = 0; + virtual const AbstractEdge *&operator[](IteratorOnComposedEdge::ItOnFixdLev i) const = 0; + virtual AbstractEdge *&operator[](IteratorOnComposedEdge::ItOnFixdLev i) = 0; + virtual Node *getEndNode() const = 0; + virtual Node *getStartNode() const = 0; + virtual bool changeStartNodeWith(Node *node) const = 0; + virtual bool changeEndNodeWith(Node *node) const = 0; + virtual void dumpInXfigFile(std::ostream& stream) const = 0; + virtual bool intresicEqual(const AbstractEdge *other) const = 0; + virtual bool intresicEqualDirSensitive(const AbstractEdge *other) const = 0; + virtual bool intresincEqCoarse(const Edge *other) const = 0; + virtual bool getDirection() const = 0; + }; +} + +#endif diff --git a/src/INTERP_KERNEL/Geometric2D/BasicMainTest.hxx b/src/INTERP_KERNEL/Geometric2D/BasicMainTest.hxx new file mode 100644 index 000000000..99bc93739 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/BasicMainTest.hxx @@ -0,0 +1,96 @@ +// Copyright (C) 2005 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +#ifndef _BASICMAINTEST_HXX_ +#define _BASICMAINTEST_HXX_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +// ============================================================================ +/*! + * Main program source for Unit Tests with cppunit package does not depend + * on actual tests, so we use the same for all partial unit tests. + */ +// ============================================================================ + +#include "UnitTestsResult.hxx" + +int main(int argc, char* argv[]) +{ + // --- Create the event manager and test controller + CPPUNIT_NS::TestResult controller; + + // --- Add a listener that collects test result + CPPUNIT_NS::TestResultCollector result; + controller.addListener( &result ); + + // --- Add a listener that print dots as test run. +#ifdef WIN32 + CPPUNIT_NS::TextTestProgressListener progress; +#else + CPPUNIT_NS::BriefTestProgressListener progress; +#endif + controller.addListener( &progress ); + + // --- Get the top level suite from the registry + + CPPUNIT_NS::Test *suite = + CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest(); + + // --- Adds the test to the list of test to run + + CPPUNIT_NS::TestRunner runner; + //CPPUNIT_NS::TextTestRunner runner; + runner.addTest( suite ); + runner.run( controller); + //bool wasSucessful = runner.run(); + + // --- Print test in a compiler compatible format. + + system("mkdir -p /tmp/${USER}"); + std::ofstream testFile; + testFile.open(INTERP_KERNEL::UnitTestsResult.c_str(), std::ios::out | std::ios::app); + testFile << UNIT_TEST_HEADER << std::endl; + //CPPUNIT_NS::CompilerOutputter outputter( &result, std::cerr ); + CPPUNIT_NS::CompilerOutputter outputter( &result, testFile ); + outputter.write(); + + // --- Run the tests. + + bool wasSucessful = result.wasSuccessful(); + testFile.close(); + + // --- Return error code 1 if the one of test failed. + + return wasSucessful ? 0 : 1; +} + +#endif diff --git a/src/INTERP_KERNEL/Geometric2D/Bounds.cxx b/src/INTERP_KERNEL/Geometric2D/Bounds.cxx new file mode 100644 index 000000000..0d4f2849d --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/Bounds.cxx @@ -0,0 +1,112 @@ +#include "Bounds.hxx" +#include "Exception.hxx" +#include "Node.hxx" + +#include + +using namespace INTERP_KERNEL; + +const double& Bounds::operator[](int i) const +{ + switch(i) + { + case 0: + return _xMin; + case 1: + return _xMax; + case 2: + return _yMin; + case 3: + return _yMax; + } + throw Exception("internal error occurs !"); +} + +double &Bounds::operator[](int i) +{ + switch(i) + { + case 0: + return _xMin; + case 1: + return _xMax; + case 2: + return _yMin; + case 3: + return _yMax; + } + throw Exception("internal error occurs !"); +} + +void Bounds::prepareForAggregation() +{ + _xMin=1e200; _xMax=-1e200; _yMin=1e200; _yMax=-1e200; +} + +Bounds *Bounds::nearlyAmIIntersectingWith(const Bounds& other) const +{ + if( (other._xMin > _xMax+QUADRATIC_PLANAR::_precision) || (other._xMax < _xMin-QUADRATIC_PLANAR::_precision) || (other._yMin > _yMax+QUADRATIC_PLANAR::_precision) + || (other._yMax < _yMin-QUADRATIC_PLANAR::_precision) ) + return 0; + if( (other._xMin >= _xMax ) || (other._xMax <= _xMin) || (other._yMin >= _yMax) || (other._yMax <= _yMin) ) + return new Bounds(fmax(_xMin-QUADRATIC_PLANAR::_precision,other._xMin), + fmin(_xMax+QUADRATIC_PLANAR::_precision,other._xMax), + fmax(_yMin-QUADRATIC_PLANAR::_precision,other._yMin), + fmin(_yMax+QUADRATIC_PLANAR::_precision,other._yMax));//In approx cases. + else + return new Bounds(fmax(_xMin,other._xMin),fmin(_xMax,other._xMax),fmax(_yMin,other._yMin),fmin(_yMax,other._yMax)); +} + +Bounds *Bounds::amIIntersectingWith(const Bounds& other) const +{ + if( (other._xMin > _xMax) || (other._xMax < _xMin) || (other._yMin > _yMax) || (other._yMax < _yMin) ) + return 0; + return new Bounds(fmax(_xMin,other._xMin),fmin(_xMax,other._xMax),fmax(_yMin,other._yMin),fmin(_yMax,other._yMax)); +} + +Position Bounds::where(double x, double y) const +{ + if((x>=_xMin && x<=_xMax) && (y>=_yMin && y<=_yMax)) + return IN; + else + return OUT; +} + +Position Bounds::nearlyWhere(double x, double y) const +{ + bool thinX=Node::areDoubleEquals(_xMin,_xMax); + bool thinY=Node::areDoubleEquals(_yMin,_yMax); + if(!thinX) + { + if(Node::areDoubleEquals(x,_xMin) || Node::areDoubleEquals(x,_xMax) && (y<_yMax+QUADRATIC_PLANAR::_precision) && (y>_yMin-QUADRATIC_PLANAR::_precision)) + return ON_BOUNDARY_POS; + } + else + if(!Node::areDoubleEquals(_xMin,x) && !Node::areDoubleEquals(_xMax,x)) + return OUT; + if(!thinY) + { + if(Node::areDoubleEquals(y,_yMin) || Node::areDoubleEquals(y,_yMax) && (x<_xMax+QUADRATIC_PLANAR::_precision) && (x>_xMin-QUADRATIC_PLANAR::_precision)) + return ON_BOUNDARY_POS; + } + else + if(!Node::areDoubleEquals(_yMin,y) && !Node::areDoubleEquals(_yMax,y)) + return OUT; + if(thinX && thinY) + return ON_BOUNDARY_POS; + if((x>=_xMin && x<=_xMax) && (y>=_yMin && y<=_yMax)) + return IN; + else + return OUT; +} + +void Bounds::aggregate(const Bounds& other) +{ + _xMin=fmin(_xMin,other._xMin); _xMax=fmax(_xMax,other._xMax); + _yMin=fmin(_yMin,other._yMin); _yMax=fmax(_yMax,other._yMax); +} + +double Bounds::getCaracteristicDim() const +{ + return fmax(_xMax-_xMin,_yMax-_yMin); +} diff --git a/src/INTERP_KERNEL/Geometric2D/Bounds.hxx b/src/INTERP_KERNEL/Geometric2D/Bounds.hxx new file mode 100644 index 000000000..89ccf8242 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/Bounds.hxx @@ -0,0 +1,43 @@ +#ifndef __BOUNDS_HXX__ +#define __BOUNDS_HXX__ + +namespace INTERP_KERNEL +{ + /*! + * Relative LOC + */ + typedef enum + { + IN = 0, + OUT = 1, + ON_BOUNDARY_POS = 2, + ON_BOUNDARY_NEG = 3 + } Position; + + class Bounds + { + public: + Bounds():_xMin(0),_xMax(0.),_yMin(0.),_yMax(0.) { } + double &operator[](int i); + const double& operator[](int i) const; + Bounds& operator=(const Bounds& other) { _xMin=other._xMin; _xMax=other._xMax; _yMin=other._yMin; _yMax=other._yMax; return *this; } + Bounds(double xMin, double xMax, double yMin, double yMax):_xMin(xMin),_xMax(xMax),_yMin(yMin),_yMax(yMax) { } + void setValues(double xMin, double xMax, double yMin, double yMax) { _xMin=xMin; _xMax=xMax; _yMin=yMin; _yMax=yMax; } + void prepareForAggregation(); + Bounds *nearlyAmIIntersectingWith(const Bounds& other) const; + Bounds *amIIntersectingWith(const Bounds& other) const; + //! No approximations. + Position where(double x, double y) const; + //! Idem where method but with approximations. + Position nearlyWhere(double x, double y) const; + void aggregate(const Bounds& other); + double getCaracteristicDim() const; + protected: + double _xMin; + double _xMax; + double _yMin; + double _yMax; + }; +} + +#endif diff --git a/src/INTERP_KERNEL/Geometric2D/ComposedEdge.cxx b/src/INTERP_KERNEL/Geometric2D/ComposedEdge.cxx new file mode 100644 index 000000000..205fb8274 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/ComposedEdge.cxx @@ -0,0 +1,317 @@ +#include "ComposedEdge.hxx" +#include "ElementaryEdge.hxx" +#include "EdgeInfLin.hxx" +#include "Exception.hxx" + +#include +#include +#include + +using namespace std; +using namespace INTERP_KERNEL; + +ComposedEdge::ComposedEdge(const ComposedEdge& other) +{ + _subEdges.resize(other._subEdges.size()); + int i=0; + for(vector::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::iterator iter=_subEdges.begin();iter!=_subEdges.end();iter++) + (*iter)->reverse(); +} + +int ComposedEdge::recursiveSize() const +{ + int ret=0; + for(vector::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::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::const_iterator iter=_subEdges.begin();iter!=_subEdges.end();iter++) + ret+=(*iter)->getAreaOfZone(); + return ret; +} + +void ComposedEdge::dumpInXfigFile(std::ostream& stream) const +{ + for(std::vector::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::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::const_iterator iter=_subEdges.begin(); + for(;iter!=_subEdges.end();iter++) + (*iter)->fillBounds(output); +} + +void ComposedEdge::getAllNodes(std::set& output) const +{ + vector::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 nodes; + getAllNodes(nodes); + set radialDistributionOfNodes; + set::const_iterator iter; + for(iter=nodes.begin();iter!=nodes.end();iter++) + radialDistributionOfNodes.insert(nodeToTest->getSlope(*(*iter))); + vector radialDistrib(radialDistributionOfNodes.begin(),radialDistributionOfNodes.end()); + radialDistributionOfNodes.clear(); + vector radialDistrib2(radialDistrib.size()); + copy(radialDistrib.begin()+1,radialDistrib.end(),radialDistrib2.begin()); + radialDistrib2.back()=M_PI+radialDistrib.front(); + vector radialDistrib3(radialDistrib.size()); + transform(radialDistrib2.begin(),radialDistrib2.end(),radialDistrib.begin(),radialDistrib3.begin(),minus()); + vector::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::const_iterator iter=_subEdges.begin();iter!=_subEdges.end();iter++) + { + ElementaryEdge *val=dynamic_cast(*iter); + if(val) + { + Edge *e=val->getPtr(); + auto_ptr 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()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::const_iterator iter=_subEdges.begin();iter!=_subEdges.end();iter++) + { + ElementaryEdge *val=dynamic_cast(*iter); + if(val) + { + Edge *e=val->getPtr(); + auto_ptr 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()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::iterator startToDel) +{ + for(vector::iterator iter=startToDel;iter!=_subEdges.end();iter++) + delete (*iter); +} diff --git a/src/INTERP_KERNEL/Geometric2D/ComposedEdge.hxx b/src/INTERP_KERNEL/Geometric2D/ComposedEdge.hxx new file mode 100644 index 000000000..60c93e1e9 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/ComposedEdge.hxx @@ -0,0 +1,60 @@ +#ifndef __COMPOSEDNODE_HXX__ +#define __COMPOSEDNODE_HXX__ + +#include "AbstractEdge.hxx" + +#include + +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& 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::iterator startToDel); + protected: + std::vector _subEdges; + }; +} + +#endif diff --git a/src/INTERP_KERNEL/Geometric2D/ComposedEdgeWithIt.hxx b/src/INTERP_KERNEL/Geometric2D/ComposedEdgeWithIt.hxx new file mode 100644 index 000000000..ff31eb129 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/ComposedEdgeWithIt.hxx @@ -0,0 +1,21 @@ +#ifndef __COMPOSEDNODEWITHIT_HXX__ +#define __COMPOSEDNODEWITHIT_HXX__ + +#include "ComposedEdge.hxx" + +#include + +namespace INTERP_KERNEL +{ + class ComposedEdgeWithIt : public ComposedEdge + { + public: + ComposedEdgeWithIt():_iterator(this) { } + const IteratorOnComposedEdge& getIterator() const { return _iterator; } + void setIterator(const IteratorOnComposedEdge& it) { _iterator=it; } + protected: + IteratorOnComposedEdge _iterator; + }; +} + +#endif diff --git a/src/INTERP_KERNEL/Geometric2D/Edge.cxx b/src/INTERP_KERNEL/Geometric2D/Edge.cxx new file mode 100644 index 000000000..81cff38d4 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/Edge.cxx @@ -0,0 +1,715 @@ +#include "Edge.hxx" +#include "EdgeLin.hxx" +#include "EdgeInfLin.hxx" +//#include "EdgeParabol.hxx" +#include "EdgeArcCircle.hxx" +#include "Exception.hxx" + +using namespace std; +using namespace INTERP_KERNEL; + +MergePoints::MergePoints():_ass1Start1(0),_ass1End1(0),_ass1Start2(0),_ass1End2(0), + _ass2Start1(0),_ass2End1(0),_ass2Start2(0),_ass2End2(0) +{ +} + +void MergePoints::start1Replaced() +{ + unsigned nbOfAsso=getNumberOfAssociations(); + if(nbOfAsso==0) + _ass1Start1=1; + else + _ass2Start1=1; +} + +void MergePoints::end1Replaced() +{ + unsigned nbOfAsso=getNumberOfAssociations(); + if(nbOfAsso==0) + _ass1End1=1; + else + _ass2End1=1; +} + +void MergePoints::start1OnStart2() +{ + unsigned nbOfAsso=getNumberOfAssociations(); + if(nbOfAsso==0) + { + _ass1Start1=1; + _ass1Start2=1; + } + else + { + _ass2Start1=1; + _ass2Start2=1; + } +} + +void MergePoints::start1OnEnd2() +{ + unsigned nbOfAsso=getNumberOfAssociations(); + if(nbOfAsso==0) + { + _ass1Start1=1; + _ass1End2=1; + } + else + { + _ass2Start1=1; + _ass2End2=1; + } +} + +void MergePoints::end1OnStart2() +{ + unsigned nbOfAsso=getNumberOfAssociations(); + if(nbOfAsso==0) + { + _ass1End1=1; + _ass1Start2=1; + } + else + { + _ass2End1=1; + _ass2Start2=1; + } +} + +void MergePoints::end1OnEnd2() +{ + unsigned nbOfAsso=getNumberOfAssociations(); + if(nbOfAsso==0) + { + _ass1End1=1; + _ass1End2=1; + } + else + { + _ass2End1=1; + _ass2End2=1; + } +} + +bool MergePoints::isStart1(unsigned rk) const +{ + if(rk==0) + return _ass1Start1; + else + return _ass2Start1; +} + +bool MergePoints::isEnd1(unsigned rk) const +{ + if(rk==0) + return _ass1End1; + else + return _ass2End1; +} + +bool MergePoints::isStart2(unsigned rk) const +{ + if(rk==0) + return _ass1Start2; + else + return _ass2Start2; +} + +bool MergePoints::isEnd2(unsigned rk) const +{ + if(rk==0) + return _ass1End2; + else + return _ass2End2; +} + +void MergePoints::clear() +{ + _ass1Start1=0;_ass1End1=0;_ass1Start2=0;_ass1End2=0; + _ass2Start1=0;_ass2End1=0;_ass2Start2=0;_ass2End2=0; +} + +unsigned MergePoints::getNumberOfAssociations() const +{ + unsigned ret=0; + unsigned subTot=_ass1Start1+_ass1End1+_ass1Start2+_ass1End2; + if(subTot!=0) + ret++; + subTot=_ass2Start1+_ass2End1+_ass2Start2+_ass2End2; + if(subTot!=0) + ret++; + return ret; +} + +IntersectElement::IntersectElement(double val1, double val2, bool start1, bool end1, bool start2, bool end2, Node *node + , const Edge& e1, const Edge& e2, bool keepOrder):_1S(keepOrder?start1:start2), + _1E(keepOrder?end1:end2), + _2S(keepOrder?start2:start1), + _2E(keepOrder?end2:end1), + _chararctValForE1(keepOrder?val1:val2), + _chararctValForE2(keepOrder?val2:val1), + _node(node),_e1(keepOrder?e1:e2), + _e2(keepOrder?e2:e1) +{ +} + +IntersectElement::IntersectElement(const IntersectElement& other):_1S(other._1S),_1E(other._1E),_2S(other._2S),_2E(other._2E), + _chararctValForE1(other._chararctValForE1), + _chararctValForE2(other._chararctValForE2),_node(other._node), + _e1(other._e1), _e2(other._e2) +{ + if(_node) + _node->incrRef(); +} + +IntersectElement& IntersectElement::operator=(const IntersectElement& other) +{ + _1S=other._1S;_1E=other._1E; _2S=other._2S; _2E=other._2E; + _chararctValForE1=other._chararctValForE1; + _chararctValForE2=other._chararctValForE2; + setNode(other._node); + return *this; +} + +bool IntersectElement::operator<(const IntersectElement& other) const +{ + return _e1.isLower(_chararctValForE1,other._chararctValForE1); +} + +IntersectElement::~IntersectElement() +{ + if(_node) + _node->decrRef(); +} + +/*! + * Returns 0 or 1. + */ +bool IntersectElement::isOnMergedExtremity() const +{ + if( (_1S && _2S) || (_1S && _2E) || (_1E && _2S) || (_1E && _2E) ) + return true; + return false; +} + +/*! + * To call if isOnMergedExtremity returned true. + */ +void IntersectElement::performMerging(MergePoints& commonNode) const +{ + if(_1S && _2S) + { + if(_e1.changeStartNodeWith(_e2.getStartNode())) + { + _e2.getStartNode()->declareOnLim(); + commonNode.start1OnStart2(); + } + } + else if(_1S && _2E) + { + if(_e1.changeStartNodeWith(_e2.getEndNode())) + { + _e2.getEndNode()->declareOnLim(); + commonNode.start1OnEnd2(); + } + } + else if(_1E && _2S) + { + if(_e1.changeEndNodeWith(_e2.getStartNode())) + { + _e2.getStartNode()->declareOnLim(); + commonNode.end1OnStart2(); + } + } + else if(_1E && _2E) + { + if(_e1.changeEndNodeWith(_e2.getEndNode())) + { + _e2.getEndNode()->declareOnLim(); + commonNode.end1OnEnd2(); + } + } +} + +/*! + * This methode is const because 'node' is supposed to be equal geomitrically to _node. + */ +void IntersectElement::setNode(Node *node) const +{ + if(node!=_node) + { + if(_node) + ((Node *)_node)->decrRef(); + ((IntersectElement *)(this))->_node=node; + if(_node) + _node->incrRef(); + } +} + +bool IntersectElement::isLowerOnOther(const IntersectElement& other) const +{ + return _e2.isLower(_chararctValForE2,other._chararctValForE2); +} + +unsigned IntersectElement::isOnExtrForAnEdgeAndInForOtherEdge() const +{ + if(( _1S && !(_2S || _2E) ) || ( _1E && !(_2S || _2E) )) + { + if(_1S && !(_2S || _2E)) + setNode(_e1.getStartNode()); + else + setNode(_e1.getEndNode()); + if(_e2.isIn(_chararctValForE2)) + return LIMIT_ON; + return LIMIT_ALONE; + } + if(( _2S && !(_1S || _1E) ) || ( _2E && !(_1S || _1E))) + { + if(_2S && !(_1S || _1E)) + setNode(_e2.getStartNode()); + else + setNode(_e2.getEndNode()); + if(_e1.isIn(_chararctValForE1)) + return LIMIT_ON; + return LIMIT_ALONE; + } + return NO_LIMIT; +} + +bool IntersectElement::isIncludedByBoth() const +{ + return _e1.isIn(_chararctValForE1) && _e2.isIn(_chararctValForE2); +} + +bool Intersector::intersect(const Bounds *whereToFind, std::vector& 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 vecOfIntesc(listOfIntesc.begin(),listOfIntesc.end()); + listOfIntesc.clear(); + sort(vecOfIntesc.begin(),vecOfIntesc.end()); + for(vector::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& 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& 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 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::iterator iter=newNodes.begin(); + vector::reverse_iterator iterR=newNodes.rbegin(); + f1->addSubEdgeInVector(f1->getStartNode(),*iter,outValForF1); + f2->addSubEdgeInVector(f2->getStartNode(),*iter,outValForF2); + for(vector::iterator iter=newNodes.begin();iter!=newNodes.end();iter++,iterR++) + { + if((iter+1)==newNodes.end()) + { + f1->addSubEdgeInVector(*iter,f1->getEndNode(),outValForF1); + (*iter)->decrRef(); + f2->addSubEdgeInVector(order?*iter:*iterR,f2->getEndNode(),outValForF2); + } + else + { + f1->addSubEdgeInVector(*iter,*(iter+1),outValForF1); + (*iter)->decrRef(); + f2->addSubEdgeInVector(order?*iter:*iterR,order?*(iter+1):*(iterR+1),outValForF2); + } + } + return true; + } + else//no intersection inside whereToFind + return false; +} + +int Edge::combineCodes(TypeOfLocInEdge code1, TypeOfLocInEdge code2) +{ + int ret=(int)code1; + ret*=OFFSET_FOR_TYPEOFLOCINEDGE; + ret+=(int)code2; + return ret; +} + +/*! + * This method splits e1 and e2 into pieces as much sharable as possible. The precondition to the call of this method + * is that e1 and e2 have been declared as overlapped by corresponding intersector built from e1 and e2 type. + * + * @param nS start node of e2 with the SAME DIRECTION as e1. The pointer nS should be equal to start node of e2 or to its end node. + * @param nE end node of e2 with the SAME DIRECTION as e1. The pointer nE should be equal to start node of e2 or to its end node. + * @param direction is param that specifies if e2 and e1 have same directions (true) or opposed (false). + * @param code is the code returned by method Edge::combineCodes. + */ +bool Edge::splitOverlappedEdges(const Edge *e1, const Edge *e2, Node *nS, Node *nE, bool direction, int code, + ComposedEdge& outVal1, ComposedEdge& outVal2) +{ + Edge *tmp; + switch(code) + { + case OUT_BEFORE*OFFSET_FOR_TYPEOFLOCINEDGE+START: // OUT_BEFORE - START + case OUT_BEFORE*OFFSET_FOR_TYPEOFLOCINEDGE+OUT_BEFORE: // OUT_BEFORE - OUT_BEFORE + case OUT_AFTER*OFFSET_FOR_TYPEOFLOCINEDGE+OUT_AFTER: // OUT_AFTER - OUT_AFTER + case END*OFFSET_FOR_TYPEOFLOCINEDGE+OUT_AFTER: // END - OUT_AFTER + return false; + case INSIDE*OFFSET_FOR_TYPEOFLOCINEDGE+OUT_AFTER: // INSIDE - OUT_AFTER + outVal1.pushBack(e1->buildEdgeLyingOnMe(e1->getStartNode(),nS,true)); + tmp=e1->buildEdgeLyingOnMe(nS,e1->getEndNode()); tmp->incrRef(); + outVal1.pushBack(tmp); + outVal2.resize(2); + outVal2.setValueAt(direction?0:1,tmp,direction); tmp->declareOn(); + outVal2.setValueAt(direction?1:0,e1->buildEdgeLyingOnMe(e1->getEndNode(),nE,direction)); + return true; + case INSIDE*OFFSET_FOR_TYPEOFLOCINEDGE+INSIDE: // INSIDE - INSIDE + e2->incrRef(); e2->incrRef(); + outVal1.resize(3); + outVal1.setValueAt(0,e1->buildEdgeLyingOnMe(e1->getStartNode(),nS)); + outVal1.setValueAt(1,(Edge*)e2,direction); + outVal1.setValueAt(2,e1->buildEdgeLyingOnMe(nE,e1->getEndNode())); + outVal2.pushBack((Edge*)e2); e2->declareOn(); + return true; + case OUT_BEFORE*OFFSET_FOR_TYPEOFLOCINEDGE+INSIDE: // OUT_BEFORE - INSIDE + tmp=e1->buildEdgeLyingOnMe(e1->getStartNode(),nE); tmp->incrRef(); + outVal1.pushBack(tmp); + outVal1.pushBack(e1->buildEdgeLyingOnMe(nE,e1->getEndNode())); + outVal2.resize(2); + outVal2.setValueAt(direction?0:1,e1->buildEdgeLyingOnMe(nS,e1->getStartNode(),direction)); + outVal2.setValueAt(direction?1:0,tmp,direction); tmp->declareOn(); + return true; + case OUT_BEFORE*OFFSET_FOR_TYPEOFLOCINEDGE+OUT_AFTER: // OUT_BEFORE - OUT_AFTER + e1->incrRef(); e1->incrRef(); + outVal1.pushBack((Edge*)e1); + outVal2.resize(3); + outVal2.setValueAt(direction?0:2,e1->buildEdgeLyingOnMe(nS,e1->getStartNode(),direction)); + outVal2.setValueAt(1,(Edge*)e1,direction); e1->declareOn(); + outVal2.setValueAt(direction?2:0,e1->buildEdgeLyingOnMe(e1->getEndNode(),nE,direction)); + return true; + case START*OFFSET_FOR_TYPEOFLOCINEDGE+END: // START - END + e1->incrRef(); e1->incrRef(); + outVal1.pushBack((Edge*)e1); + outVal2.pushBack((Edge*)e1,direction); e1->declareOn(); + return true; + case START*OFFSET_FOR_TYPEOFLOCINEDGE+OUT_AFTER: // START - OUT_AFTER + e1->incrRef(); e1->incrRef(); + outVal1.pushBack((Edge*)e1); + outVal2.resize(2); + outVal2.setValueAt(direction?0:1,(Edge*)e1,direction); e1->declareOn(); + outVal2.setValueAt(direction?1:0,e1->buildEdgeLyingOnMe(e1->getEndNode(),nE,direction)); + return true; + case INSIDE*OFFSET_FOR_TYPEOFLOCINEDGE+END: // INSIDE - END + e2->incrRef(); e2->incrRef(); + outVal1.pushBack(e1->buildEdgeLyingOnMe(e1->getStartNode(),nS,true)); + outVal1.pushBack((Edge*)e2,direction); + outVal2.pushBack((Edge*)e2); e2->declareOn(); + return true; + case OUT_BEFORE*OFFSET_FOR_TYPEOFLOCINEDGE+END: // OUT_BEFORE - END + e1->incrRef(); e1->incrRef(); + outVal1.pushBack((Edge*)e1); + outVal2.resize(2); + outVal2.setValueAt(direction?0:1,e1->buildEdgeLyingOnMe(nS,e1->getStartNode(),direction)); + outVal2.setValueAt(direction?1:0,(Edge*)e1,direction); e1->declareOn(); + return true; + case START*OFFSET_FOR_TYPEOFLOCINEDGE+INSIDE: // START - INSIDE + e2->incrRef(); e2->incrRef(); + outVal1.pushBack((Edge*)e2,direction); + outVal1.pushBack(e1->buildEdgeLyingOnMe(nE,e1->getEndNode())); + outVal2.pushBack((Edge*)e2); e2->declareOn(); + return true; + default: + throw Exception("Unexpected situation of overlapping edges : internal error occurs ! "); + } +} diff --git a/src/INTERP_KERNEL/Geometric2D/Edge.hxx b/src/INTERP_KERNEL/Geometric2D/Edge.hxx new file mode 100644 index 000000000..b73c86dd0 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/Edge.hxx @@ -0,0 +1,227 @@ +#ifndef __EDGE_HXX__ +#define __EDGE_HXX__ + +#include "ComposedEdge.hxx" +#include "Exception.hxx" +#include "Bounds.hxx" +#include "Node.hxx" + +#include +#include +#include + +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& 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& track) const; + bool changeEndNodeWith(Node *otherEndNode) const; + bool changeEndNodeWithAndKeepTrack(Node *otherEndNode, std::vector& 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 + static Edge *buildEdgeFrom(Node *start, Node *middle, Node *end); + virtual void update(Node *m) = 0; + //! returns area between this and axe Ox delimited along Ox by _start and _end. + virtual double getAreaOfZone() const = 0; + virtual double getCurveLength() const = 0; + //! Retrieves a point that is owning to this, well placed for IN/OUT detection of this. Typically midlle of this is returned. + virtual Node *buildRepresentantOfMySelf() const = 0; + //! Given a magnitude specified by sub-type returns if in or not. See getCharactValue method. + virtual bool isIn(double characterVal) const = 0; + //! With the same magnitude as defined in 'isIn' method perform a compararison. Precondition : val1 and val2 are different and exactly INSIDE this. + virtual bool isLower(double val1, double val2) const = 0; + //! node is expected to lay on 'this'. It returns a characteristic magnitude usable by isIn method. + virtual double getCharactValue(const Node& node) const = 0; + virtual TypeOfFunction getTypeOfFunc() const = 0; + virtual Edge *buildEdgeLyingOnMe(Node *start, Node *end, bool direction=true) const = 0; + virtual void dynCastFunction(const EdgeLin * &seg, + const EdgeArcCircle * &arcSeg) const = 0; + bool intersectWith(const Edge *other, MergePoints& commonNode, + ComposedEdge& outVal1, ComposedEdge& outVal2) const; + virtual void dumpInXfigFile(std::ostream& stream, bool direction) const = 0; + protected: + Edge():_cnt(1),_loc(FULL_UNKNOWN),_start(0),_end(0) { } + virtual ~Edge(); + static int combineCodes(TypeOfLocInEdge code1, TypeOfLocInEdge code2); + static bool intersect(const Edge *f1, const Edge *f2, Intersector *intersector, const Bounds *whereToFind, MergePoints& commonNode, + ComposedEdge& outValForF1, ComposedEdge& outValForF2); + //! The code 'code' is built by method combineCodes + static bool splitOverlappedEdges(const Edge *e1, const Edge *e2, Node *nS, Node *nE, bool direction, int code, + ComposedEdge& outVal1, ComposedEdge& outVal2); + protected: + mutable unsigned char _cnt; + mutable TypeOfEdgeLocInPolygon _loc; + Bounds _bounds; + Node *_start; + Node *_end; + protected: + //In relation with max possible value of TypeOfLocInEdge. + static const int OFFSET_FOR_TYPEOFLOCINEDGE = 8; + }; +} + +#endif diff --git a/src/INTERP_KERNEL/Geometric2D/Edge.txx b/src/INTERP_KERNEL/Geometric2D/Edge.txx new file mode 100644 index 000000000..4b1477c09 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/Edge.txx @@ -0,0 +1,12 @@ +#ifndef __EDGE_TXX__ +#define __EDGE_TXX__ + +#include "EdgeArcCircle.hxx" + +template +INTERP_KERNEL::Edge *INTERP_KERNEL::Edge::buildEdgeFrom(Node *start, Node *middle, Node *end) +{ + return new INTERP_KERNEL::EdgeArcCircle(start,middle,end); +} + +#endif diff --git a/src/INTERP_KERNEL/Geometric2D/EdgeArcCircle.cxx b/src/INTERP_KERNEL/Geometric2D/EdgeArcCircle.cxx new file mode 100644 index 000000000..d3937bb8b --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/EdgeArcCircle.cxx @@ -0,0 +1,471 @@ +#include "EdgeArcCircle.hxx" +#include "EdgeLin.hxx" +#include "Exception.hxx" +#include "Node.hxx" + +#include + +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]radius1+radius2+QUADRATIC_PLANAR::_precision || _dist+fmin(radius1,radius2)+QUADRATIC_PLANAR::_precision 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. && myDeltadelta; + } +} + +/*! + * 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 (tmp2tmp+delta-2*M_PI); + else if(tmp+delta>=0.) + return (tmp2fmax(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> 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=0.?angle0:-angle0; + return angle0; +} + +void EdgeArcCircle::updateBounds() +{ + _bounds.setValues(fmin((*_start)[0],(*_end)[0]),fmax((*_start)[0],(*_end)[0]),fmin((*_start)[1],(*_end)[1]),fmax((*_start)[1],(*_end)[1])); + if(ArcCArcCIntersector::isIn2Pi(_angle0,_angle,M_PI/2)) + _bounds[3]=_center[1]+_radius; + if(ArcCArcCIntersector::isIn2Pi(_angle0,_angle,-M_PI/2)) + _bounds[2]=_center[1]-_radius; + if(ArcCArcCIntersector::isIn2Pi(_angle0,_angle,0.)) + _bounds[1]=_center[0]+_radius; + if(ArcCArcCIntersector::isIn2Pi(_angle0,_angle,M_PI)) + _bounds[0]=_center[0]-_radius; +} diff --git a/src/INTERP_KERNEL/Geometric2D/EdgeArcCircle.hxx b/src/INTERP_KERNEL/Geometric2D/EdgeArcCircle.hxx new file mode 100644 index 000000000..d787a6f7e --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/EdgeArcCircle.hxx @@ -0,0 +1,94 @@ +#ifndef __EDGEARCCIRCLE_HXX__ +#define __EDGEARCCIRCLE_HXX__ + +#include "Edge.hxx" + +namespace INTERP_KERNEL +{ + class ArcCArcCIntersector : public SameTypeIntersector + { + friend class EdgeArcCircle; + public: + ArcCArcCIntersector(const EdgeArcCircle& e1, const EdgeArcCircle& e2); + bool haveTheySameDirection() const; + void getPlacements(Node *start, Node *end, TypeOfLocInEdge& whereStart, TypeOfLocInEdge& whereEnd, MergePoints& commonNode) const; + void areOverlappedOrOnlyColinears(const Bounds *whereToFind, bool& obviousNoIntersection, bool& areOverlapped); + std::list< IntersectElement > getIntersectionsCharacteristicVal() const; + private: + //! return angle in ]-Pi;Pi[ - 'node' must be on curve of '_e1' + double getAngle(Node *node) const; + static bool isIn2Pi(double start, double delta, double angleIn); + //! 'delta' 'start' in ]-Pi;Pi[ + static bool isAngleNotIn(double start, double delta, double angleIn); + //! for an angle 'angle' in ]-3*Pi;3*Pi[ returns angle in ]-Pi;Pi[ + static double normalizeAngle(double angle) { if(angle>M_PI) return angle-2.*M_PI; if(angle<-M_PI) return angle+2.*M_PI; return angle; } + private: + const EdgeArcCircle& getE1() const { return (const EdgeArcCircle&)_e1; } + const EdgeArcCircle& getE2() const { return (const EdgeArcCircle&)_e2; } + private: + double _dist; + }; + + class ArcCSegIntersector : public CrossTypeIntersector + { + public: + ArcCSegIntersector(const EdgeArcCircle& e1, const EdgeLin& e2, bool reverse=true); + //virtual overloading + void getPlacements(Node *start, Node *end, TypeOfLocInEdge& whereStart, TypeOfLocInEdge& whereEnd, MergePoints& commonNode) const; + void areOverlappedOrOnlyColinears(const Bounds *whereToFind, bool& obviousNoIntersection, bool& areOverlapped); + std::list< IntersectElement > getIntersectionsCharacteristicVal() const; + private: + const EdgeArcCircle& getE1() const { return (const EdgeArcCircle&)_e1; } + const EdgeLin& getE2() const { return (const EdgeLin&)_e2; } + private: + double _dx; + double _dy; + double _drSq; + double _cross; + double _determinant; + }; + + class EdgeArcCircle : public Edge + { + public: + EdgeArcCircle(std::istream& lineInXfig); + EdgeArcCircle(Node *start, Node *middle, Node *end, bool direction = true); + EdgeArcCircle(double sX, double sY, double mX, double mY, double eX, double eY); + EdgeArcCircle(Node *start, Node *end, const double *center, double radius, double angle0, double deltaAngle, bool direction=true); + //! for tests + void changeMiddle(Node *newMiddle); + void dumpInXfigFile(std::ostream& stream, bool direction) const; + void update(Node *m); + double getAreaOfZone() const; + double getCurveLength() const; + bool isIn(double characterVal) const; + Node *buildRepresentantOfMySelf() const; + bool isLower(double val1, double val2) const; + double getCharactValue(const Node& node) const; + TypeOfFunction getTypeOfFunc() const { return ARC_CIRCLE; } + void dynCastFunction(const EdgeLin * &seg, + const EdgeArcCircle * &arcSeg) const { arcSeg=this; } + const double *getCenter() const { return _center; } + void getCenter(double *center) const { center[0]=_center[0]; center[1]=_center[1]; } + bool doIHaveSameDirectionAs(const Edge& other) const { return false; } + Edge *buildEdgeLyingOnMe(Node *start, Node *end, bool direction=true) const; + double getAngle0() const { return _angle0; } + double getRadius() const { return _radius; } + double getAngle() const { return _angle; } + static void getArcOfCirclePassingThru(const double *start, const double *middle, const double *end, + double *center, double& radius, double& angleInRad, double& angleInRad0); + //! To avoid in aggressive optimizations nan. + static double safeAcos(double cosAngle) { double ret=fmin(cosAngle,1.); ret=fmax(ret,-1.); return acos(ret); } + protected: + void updateBounds(); + protected: + //Value between -2Pi and 2Pi + double _angle; + //Value between -Pi and Pi + double _angle0; + double _radius; + double _center[2]; + }; +} + +#endif diff --git a/src/INTERP_KERNEL/Geometric2D/EdgeInfLin.cxx b/src/INTERP_KERNEL/Geometric2D/EdgeInfLin.cxx new file mode 100644 index 000000000..759c1cba6 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/EdgeInfLin.cxx @@ -0,0 +1,10 @@ +#include "EdgeInfLin.hxx" + +using namespace INTERP_KERNEL; + +EdgeInfLin::EdgeInfLin(Node *pointPassingThrough, double slope) +{ + _start=pointPassingThrough; + _start->incrRef(); + _end=new Node((*_start)[0]+cos(slope),(*_start)[1]+sin(slope)); +} diff --git a/src/INTERP_KERNEL/Geometric2D/EdgeInfLin.hxx b/src/INTERP_KERNEL/Geometric2D/EdgeInfLin.hxx new file mode 100644 index 000000000..3f47b9ade --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/EdgeInfLin.hxx @@ -0,0 +1,22 @@ +#ifndef __EDGEINFLIN_HXX__ +#define __EDGEINFLIN_HXX__ + +#include "EdgeLin.hxx" + +namespace INTERP_KERNEL +{ + class EdgeInfLin : public EdgeLin + { + public: + EdgeInfLin(Node *start, Node *end):EdgeLin(start,end,true) { } + EdgeInfLin(Node *pointPassingThrough, double slope); + bool isIn(double characterVal) const { return true; } + void dynCastFunction(const EdgeLin * &seg, + const EdgeArcCircle * &arcSeg) const { seg=this; } + void dumpInXfigFile(std::ostream& stream) const { } + private: + ~EdgeInfLin() { } + }; +} + +#endif diff --git a/src/INTERP_KERNEL/Geometric2D/EdgeLin.cxx b/src/INTERP_KERNEL/Geometric2D/EdgeLin.cxx new file mode 100644 index 000000000..2ff40f01e --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/EdgeLin.cxx @@ -0,0 +1,204 @@ +#include "EdgeLin.hxx" +#include "Node.hxx" +#include "Exception.hxx" + +using namespace std; +using namespace INTERP_KERNEL; + +namespace INTERP_KERNEL +{ + extern const unsigned MAX_SIZE_OF_LINE_XFIG_FILE=1024; +} + +SegSegIntersector::SegSegIntersector(const EdgeLin& e1, const EdgeLin& e2):SameTypeIntersector(e1,e2) +{ + _matrix[0]=(*(e2.getStartNode()))[0]-(*(e2.getEndNode()))[0]; + _matrix[1]=(*(e1.getEndNode()))[0]-(*(e1.getStartNode()))[0]; + _matrix[2]=(*(e2.getStartNode()))[1]-(*(e2.getEndNode()))[1]; + _matrix[3]=(*(e1.getEndNode()))[1]-(*(e1.getStartNode()))[1]; + _col[0]=_matrix[3]*(*(e1.getStartNode()))[0]-_matrix[1]*(*(e1.getStartNode()))[1]; + _col[1]=-_matrix[2]*(*(e2.getStartNode()))[0]+_matrix[0]*(*(e2.getStartNode()))[1]; + //Little trick to avoid problems if 'e1' and 'e2' are colinears and along Ox or Oy axes. + if(fabs(_matrix[3])>fabs(_matrix[1])) + _ind=0; + else + _ind=1; +} + +/*! + * Must be called when 'this' and 'other' have been detected to be at least colinear. Typically they are overlapped. + * Must be called after call of areOverlappedOrOnlyColinears. + */ +bool SegSegIntersector::haveTheySameDirection() const +{ + return (_matrix[_ind?1:0]>0. && _matrix[_ind?3:2]>0.) || (_matrix[_ind?1:0]<0. && _matrix[_ind?3:2]<0.); +} + +/*! + * Precondition start and end must be so that there predecessor was in the same direction than 'e1' + */ +void SegSegIntersector::getPlacements(Node *start, Node *end, TypeOfLocInEdge& whereStart, TypeOfLocInEdge& whereEnd, MergePoints& commonNode) const +{ + getCurveAbscisse(start,whereStart,commonNode); + getCurveAbscisse(end,whereEnd,commonNode); +} + +void SegSegIntersector::getCurveAbscisse(Node *node, TypeOfLocInEdge& where, MergePoints& commonNode) const +{ + bool obvious; + obviousCaseForCurvAbscisse(node,where,commonNode,obvious); + if(obvious) + return ; + double ret=((*node)[!_ind]-(*_e1.getStartNode())[!_ind])/((*_e1.getEndNode())[!_ind]-(*_e1.getStartNode())[!_ind]); + if(ret>0. && ret <1.) + where=INSIDE; + else if(ret<0.) + where=OUT_BEFORE; + else + where=OUT_AFTER; +} + +/*! + * areColinears method should be called before with a returned colinearity equal to false to avoid bad news. + */ +std::list< IntersectElement > SegSegIntersector::getIntersectionsCharacteristicVal() const +{ + std::list< IntersectElement > ret; + double x=_matrix[0]*_col[0]+_matrix[1]*_col[1]; + double y=_matrix[2]*_col[0]+_matrix[3]*_col[1]; + //Only one intersect point possible + Node *node=new Node(x,y); + node->declareOn(); + bool i_1S=_e1.getStartNode()->isEqual(*node); + bool i_1E=_e1.getEndNode()->isEqual(*node); + bool i_2S=_e2.getStartNode()->isEqual(*node); + bool i_2E=_e2.getEndNode()->isEqual(*node); + ret.push_back(IntersectElement(_e1.getCharactValue(*node), + _e2.getCharactValue(*node), + i_1S,i_1E,i_2S,i_2E,node,_e1,_e2,keepOrder())); + return ret; +} + +/*! + * Should be called \b once ! non const method. + * \param whereToFind specifies the box where final seek should be done. Essentially it is used for caracteristic reason. + * \param colinearity returns if regarding QUADRATIC_PLANAR::_precision ; e1 and e2 are colinears + * If true 'this' is modified ! So this method be called once above all if true is returned for this parameter. + * \param areOverlapped if colinearity if true, this parameter looks if e1 and e2 are overlapped. + */ +void SegSegIntersector::areOverlappedOrOnlyColinears(const Bounds *whereToFind, bool& colinearity, bool& areOverlapped) +{ + double determinant=_matrix[0]*_matrix[3]-_matrix[1]*_matrix[2]; + if(fabs(determinant)>2.*QUADRATIC_PLANAR::_precision)//2*_precision due to max of offset on _start and _end + { + colinearity=false; areOverlapped=false; + _matrix[0]/=determinant; _matrix[1]/=determinant; _matrix[2]/=determinant; _matrix[3]/=determinant; + } + else + { + colinearity=true; + //retrieving initial matrix + double tmp=_matrix[0]; _matrix[0]=_matrix[3]; _matrix[3]=tmp; + _matrix[1]=-_matrix[1]; _matrix[2]=-_matrix[2]; + // + double deno=sqrt(_matrix[0]*_matrix[0]+_matrix[1]*_matrix[1]); + double x=(*(_e1.getStartNode()))[0]-(*(_e2.getStartNode()))[0]; + double y=(*(_e1.getStartNode()))[1]-(*(_e2.getStartNode()))[1]; + areOverlapped=fabs((_matrix[1]*y+_matrix[0]*x)/deno)0. && characterVal<1.; +} + +Node *EdgeLin::buildRepresentantOfMySelf() const +{ + return new Node(((*(_start))[0]+(*(_end))[0])/2.,((*(_start))[1]+(*(_end))[1])/2.); +} + +double EdgeLin::getCharactValue(const Node& node) const +{ + double car1_1x=node[0]-(*(_start))[0]; double car1_2x=(*(_end))[0]-(*(_start))[0]; + double car1_1y=node[1]-(*(_start))[1]; double car1_2y=(*(_end))[1]-(*(_start))[1]; + return (car1_1x*car1_2x+car1_1y*car1_2y)/(car1_2x*car1_2x+car1_2y*car1_2y); +} + +void EdgeLin::dumpInXfigFile(std::ostream& stream, bool direction) const +{ + stream << "2 1 0 1 "; + fillXfigStreamForLoc(stream); + stream << " 7 50 -1 -1 0.000 0 0 -1 0 0 2" << endl; + direction?_start->dumpInXfigFile(stream):_end->dumpInXfigFile(stream); + direction?_end->dumpInXfigFile(stream):_start->dumpInXfigFile(stream); + stream << endl; +} + +void EdgeLin::update(Node *m) +{ + updateBounds(); +} + +double EdgeLin::getNormSq() const +{ + return _start->distanceWithSq(*_end); +} + +double EdgeLin::getAreaOfZone() const +{ + return ((*_start)[0]-(*_end)[0])*((*_start)[1]+(*_end)[1])/2.; +} + +double EdgeLin::getCurveLength() const +{ + double x=(*_start)[0]-(*_end)[0]; + double y=(*_start)[1]-(*_end)[1]; + return sqrt(x*x+y*y); +} + +Edge *EdgeLin::buildEdgeLyingOnMe(Node *start, Node *end, bool direction) const +{ + return new EdgeLin(start,end,direction); +} + +/*! + * No precision should be introduced here. Just think as if precision was perfect. + */ +void EdgeLin::updateBounds() +{ + _bounds.setValues(fmin((*_start)[0],(*_end)[0]),fmax((*_start)[0],(*_end)[0]),fmin((*_start)[1],(*_end)[1]),fmax((*_start)[1],(*_end)[1])); +} diff --git a/src/INTERP_KERNEL/Geometric2D/EdgeLin.hxx b/src/INTERP_KERNEL/Geometric2D/EdgeLin.hxx new file mode 100644 index 000000000..ec8d5f101 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/EdgeLin.hxx @@ -0,0 +1,54 @@ +#ifndef __EDGELIN_HXX__ +#define __EDGELIN_HXX__ + +#include "Edge.hxx" + +namespace INTERP_KERNEL +{ + class SegSegIntersector : SameTypeIntersector + { + friend class Edge; + public: + SegSegIntersector(const EdgeLin& e1, const EdgeLin& e2); + bool haveTheySameDirection() const; + void getPlacements(Node *start, Node *end, TypeOfLocInEdge& whereStart, TypeOfLocInEdge& whereEnd, MergePoints& commonNode) const; + void areOverlappedOrOnlyColinears(const Bounds *whereToFind, bool& obviousNoIntersection, bool& areOverlapped); + std::list< IntersectElement > getIntersectionsCharacteristicVal() const; + private: + void getCurveAbscisse(Node *node, TypeOfLocInEdge& where, MergePoints& commonNode) const; + private: + //! index on which all single index op will be performed. Filled in case colinearity is equal to true. + int _ind; + double _col[2]; + double _matrix[4];//SPACEDIM*SPACEDIM + }; + + class EdgeLin : public Edge + { + friend class SegSegIntersector; + public: + EdgeLin(std::istream& lineInXfig); + EdgeLin(Node *start, Node *end, bool direction=true); + EdgeLin(double sX, double sY, double eX, double eY); + ~EdgeLin(); + TypeOfFunction getTypeOfFunc() const { return SEG; } + void dumpInXfigFile(std::ostream& stream, bool direction) const; + void update(Node *m); + double getNormSq() const; + double getAreaOfZone() const; + double getCurveLength() const; + bool isIn(double characterVal) const; + Node *buildRepresentantOfMySelf() const; + double getCharactValue(const Node& node) const; + bool isLower(double val1, double val2) const { return val1incrRef(); +} + +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& output) const +{ + output.insert(_ptr->getStartNode()); + output.insert(_ptr->getEndNode()); +} + +AbstractEdge *ElementaryEdge::clone() const +{ + return new ElementaryEdge(*this); +} + +int ElementaryEdge::recursiveSize() const +{ + return 1; +} + +int ElementaryEdge::size() const +{ + throw Exception("Invalid call to ElementaryEdge::size : ElementaryEdge not splittable"); +} + +/*! + * WARNING use this method if and only if this is so that it is completely in/out/on of @param pol. + */ +TypeOfEdgeLocInPolygon ElementaryEdge::locateFullyMySelf(const ComposedEdge& pol, TypeOfEdgeLocInPolygon precEdgeLoc) const +{ + if(getLoc()!=FULL_UNKNOWN) + return getLoc(); + //obvious cases + if(precEdgeLoc==FULL_IN_1) + { + if(getStartNode()->getLoc()==ON_1) + { + declareOut(); + return getLoc(); + } + else if(getStartNode()->getLoc()==IN_1 || getStartNode()->getLoc()==ON_TANG_1) + { + declareIn(); + return getLoc(); + } + } + if(precEdgeLoc==FULL_OUT_1) + { + if(getStartNode()->getLoc()==ON_1) + { + declareIn(); + return getLoc(); + } + else if(getStartNode()->getLoc()==IN_1 || getStartNode()->getLoc()==ON_TANG_1) + { + declareOut(); + return getLoc(); + } + } + if(getStartNode()->getLoc()==IN_1 || getEndNode()->getLoc()==IN_1) + { + declareIn(); + return getLoc(); + } + if(getStartNode()->getLoc()==OUT_1 || getEndNode()->getLoc()==OUT_1) + { + declareOut(); + return getLoc(); + } + //a seek is requested + return locateFullyMySelfAbsolute(pol); +} + +TypeOfEdgeLocInPolygon ElementaryEdge::locateFullyMySelfAbsolute(const ComposedEdge& pol) const +{ + Node *node=_ptr->buildRepresentantOfMySelf(); + if(pol.isInOrOut(node)) + declareIn(); + else + declareOut(); + node->decrRef(); + return getLoc(); +} + +const AbstractEdge *&ElementaryEdge::operator[](IteratorOnComposedEdge::ItOnFixdLev i) const +{ + throw Exception("Invalid input parameter in ElementaryEdge::operator[] not splittable"); +} + +AbstractEdge *&ElementaryEdge::operator[](IteratorOnComposedEdge::ItOnFixdLev i) +{ + throw Exception("Invalid input parameter in ElementaryEdge::operator[] not splittable"); +} + +Node *ElementaryEdge::getEndNode() const +{ + if(_direction) + return _ptr->getEndNode(); + else return _ptr->getStartNode(); +} + +Node *ElementaryEdge::getStartNode() const +{ + if(_direction) + return _ptr->getStartNode(); + else + return _ptr->getEndNode(); +} + +bool ElementaryEdge::changeEndNodeWith(Node *node) const +{ + if(_direction) + return _ptr->changeEndNodeWith(node); + else + return _ptr->changeStartNodeWith(node); +} + +bool ElementaryEdge::changeStartNodeWith(Node *node) const +{ + if(_direction) + return _ptr->changeStartNodeWith(node); + else + return _ptr->changeEndNodeWith(node); +} + +void ElementaryEdge::dumpInXfigFile(std::ostream& stream) const +{ + _ptr->dumpInXfigFile(stream,_direction); +} + +bool ElementaryEdge::intresicEqual(const AbstractEdge *other) const +{ + const ElementaryEdge* otherC=dynamic_cast< const ElementaryEdge* >(other); + if(!otherC) + return false; + return (_ptr==otherC->_ptr); +} + +bool ElementaryEdge::intresicEqualDirSensitive(const AbstractEdge *other) const +{ + const ElementaryEdge* otherC=dynamic_cast< const ElementaryEdge* >(other); + if(!otherC) + return false; + return ( _direction==otherC->_direction ) && (_ptr==otherC->_ptr); +} + +bool ElementaryEdge::intresincEqCoarse(const Edge *other) const +{ + return _ptr==other; +} diff --git a/src/INTERP_KERNEL/Geometric2D/ElementaryEdge.hxx b/src/INTERP_KERNEL/Geometric2D/ElementaryEdge.hxx new file mode 100644 index 000000000..adcdca298 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/ElementaryEdge.hxx @@ -0,0 +1,53 @@ +#ifndef __ELEMENTARYEDGE_HXX__ +#define __ELEMENTARYEDGE_HXX__ + +#include "AbstractEdge.hxx" +#include "Exception.hxx" +#include "Edge.hxx" + +namespace INTERP_KERNEL +{ + class ElementaryEdge : public AbstractEdge + { + public: + ElementaryEdge(Edge *ptr, bool direction):_direction(direction),_ptr(ptr) { } + ElementaryEdge(const ElementaryEdge& other); + ~ElementaryEdge(); + bool completed() const { return false; } + void declareOn() const { _ptr->declareOn(); } + void declareIn() const { _ptr->declareIn(); } + void declareOut() const { _ptr->declareOut(); } + TypeOfEdgeLocInPolygon getLoc() const { return _ptr->getLoc(); } + Edge *getPtr() const { return _ptr; } + ElementaryEdge* &getLastElementary(IteratorOnComposedEdge::ItOnFixdLev &delta) { throw Exception("Invalid call to getLastElementary"); } + ElementaryEdge * &getFirstElementary(IteratorOnComposedEdge::ItOnFixdLev &delta) { throw Exception("Invalid call to getFirstElementary"); } + void reverse() { _direction=(!_direction); } + bool isNodeIn(Node *n) const; + double getAreaOfZone() const { return getAreaOfZoneFast(); } + void fillBounds(Bounds& output) const; + void getAllNodes(std::set& output) const; + double getAreaOfZoneFast() const { double ret=_ptr->getAreaOfZone(); return _direction?ret:-ret; } + AbstractEdge *clone() const; + int recursiveSize() const; + int size() const; + TypeOfEdgeLocInPolygon locateFullyMySelfAbsolute(const ComposedEdge& pol) const; + TypeOfEdgeLocInPolygon locateFullyMySelf(const ComposedEdge& pol, TypeOfEdgeLocInPolygon precEdgeLoc) const; + AbstractEdge *&operator[](IteratorOnComposedEdge::ItOnFixdLev i); + const AbstractEdge *&operator[](IteratorOnComposedEdge::ItOnFixdLev i) const; + Node *getEndNode() const; + Node *getStartNode() const; + double getCurveLength() const { return _ptr->getCurveLength(); } + bool changeEndNodeWith(Node *node) const; + bool changeStartNodeWith(Node *node) const; + void dumpInXfigFile(std::ostream& stream) const; + bool intresicEqual(const AbstractEdge *other) const; + bool intresicEqualDirSensitive(const AbstractEdge *other) const; + bool getDirection() const { return _direction; } + bool intresincEqCoarse(const Edge *other) const; + private: + bool _direction; + Edge *_ptr; + }; +} + +#endif diff --git a/src/INTERP_KERNEL/Geometric2D/Node.cxx b/src/INTERP_KERNEL/Geometric2D/Node.cxx new file mode 100644 index 000000000..ed60e38bf --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/Node.cxx @@ -0,0 +1,87 @@ +#include "Node.hxx" +#include "EdgeArcCircle.hxx" + +using namespace std; +using namespace INTERP_KERNEL; + +const double Node::CST_FOR_XFIG=1e4; + +Node::Node(double x, double y):_isToDel(true),_cnt(1),_loc(UNKNOWN) +{ + const unsigned SPACEDIM=2; + _coords=new double[SPACEDIM]; + _coords[0]=x; _coords[1]=y; +} + +Node::Node(const double *coords):_isToDel(false),_cnt(1),_loc(UNKNOWN),_coords((double *)coords) +{ +} + +Node::Node(std::istream& stream):_isToDel(true),_cnt(1),_loc(UNKNOWN) +{ + const unsigned SPACEDIM=2; + _coords=new double[SPACEDIM]; + for(unsigned i=0;i> 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=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& track) const +{ + bool ret=isEqual(other); + if(ret) + track.push_back((Node *)&other); + return ret; +} + +void Node::dumpInXfigFile(std::ostream& stream) const +{ + stream << (int)(_coords[0]*CST_FOR_XFIG) << " " << (int)(_coords[1]*CST_FOR_XFIG) << " "; +} + +double Node::distanceWithSq(const Node& other) const +{ + return (_coords[0]-other._coords[0])*(_coords[0]-other._coords[0])+(_coords[1]-other._coords[1])*(_coords[1]-other._coords[1]); +} diff --git a/src/INTERP_KERNEL/Geometric2D/Node.hxx b/src/INTERP_KERNEL/Geometric2D/Node.hxx new file mode 100644 index 000000000..45c4025c1 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/Node.hxx @@ -0,0 +1,65 @@ +#ifndef __NODE_HXX__ +#define __NODE_HXX__ + +#include "Precision.hxx" + +#include +#include +#include + +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& track) const; + void dumpInXfigFile(std::ostream& stream) const; + double distanceWithSq(const Node& other) const; + double operator[](int i) const { return _coords[i]; } + //!for tests only ! + void setNewCoords(double x, double y) { _coords[0]=x; _coords[1]=y; } + static double sign(double val) { if(val>=0) return 1.; else return -1.; } + static bool areDoubleEquals(double a, double b) { return fabs(a-b) < QUADRATIC_PLANAR::_precision; } + //! idem areDoubleEquals except that precision of comparison is modified. + static bool areDoubleEqualsWP(double a, double b, double k) { return fabs(a-b) < k*QUADRATIC_PLANAR::_precision; } + static double distanceBtw2Pt(const double *a, const double *b) { return sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])); } + protected: + ~Node(); + protected: + bool _isToDel; + mutable unsigned char _cnt; + mutable TypeOfLocInPolygon _loc; + double *_coords; + public: + static const double CST_FOR_XFIG; + }; +} + +#endif diff --git a/src/INTERP_KERNEL/Geometric2D/Pol1.fig b/src/INTERP_KERNEL/Geometric2D/Pol1.fig new file mode 100644 index 000000000..be55cc812 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/Pol1.fig @@ -0,0 +1,15 @@ +#FIG 3.2 Produced by xfig version 3.2.5-alpha5 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +5 1 0 1 0 7 50 -1 -1 0.000 0 1 0 0 2700.000 4800.000 3600 6000 4200 4800 3600 3600 +5 1 0 1 0 7 50 -1 -1 0.000 0 1 0 0 5400.000 1200.000 3600 3600 5400 4200 7200 3600 +5 1 0 1 0 7 50 -1 -1 0.000 0 0 0 0 5100.000 6300.000 7200 3600 7800 4200 8400 5400 +5 1 0 1 0 7 50 -1 -1 0.000 0 1 0 0 8400.000 6000.000 8400 5400 7800 6000 8400 6600 +5 1 0 1 0 7 50 -1 -1 0.000 0 1 0 0 9128.571 9642.857 8400 6600 6600 7800 6000 9600 +5 1 0 1 0 7 50 -1 -1 0.000 0 1 0 0 2820.000 9120.000 6000 9600 5400 7200 3600 6000 diff --git a/src/INTERP_KERNEL/Geometric2D/Pol2.fig b/src/INTERP_KERNEL/Geometric2D/Pol2.fig new file mode 100644 index 000000000..4778e6735 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/Pol2.fig @@ -0,0 +1,13 @@ +#FIG 3.2 Produced by xfig version 3.2.5-alpha5 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +5 1 0 1 0 7 50 -1 -1 0.000 0 0 0 0 13000.000 7200.000 6600 9000 6600 5400 8400 2400 +5 1 0 1 0 7 50 -1 -1 0.000 0 1 0 0 10500.000 -900.000 8400 2400 10800 3000 12600 2400 +5 1 0 1 0 7 50 -1 -1 0.000 0 1 0 0 16242.857 6471.429 12600 2400 10800 6000 11400 9000 +5 1 0 1 0 7 50 -1 -1 0.000 0 0 0 0 9000.000 13500.000 6600 9000 9000 8400 11400 9000 diff --git a/src/INTERP_KERNEL/Geometric2D/Pol3.fig b/src/INTERP_KERNEL/Geometric2D/Pol3.fig new file mode 100644 index 000000000..4bad14493 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/Pol3.fig @@ -0,0 +1,11 @@ +#FIG 3.2 Produced by xfig version 3.2.5-alpha5 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 +3000 7200 6600 3600 diff --git a/src/INTERP_KERNEL/Geometric2D/Pol4.fig b/src/INTERP_KERNEL/Geometric2D/Pol4.fig new file mode 100644 index 000000000..1c6cd7924 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/Pol4.fig @@ -0,0 +1,10 @@ +#FIG 3.2 Produced by xfig version 3.2.5-alpha5 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +5 1 0 1 0 7 50 -1 -1 0.000 0 0 0 0 4800.000 4837.500 4200 7200 4800 2400 5400 7200 diff --git a/src/INTERP_KERNEL/Geometric2D/Precision.hxx b/src/INTERP_KERNEL/Geometric2D/Precision.hxx new file mode 100644 index 000000000..5eb791359 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/Precision.hxx @@ -0,0 +1,7 @@ +namespace INTERP_KERNEL +{ + namespace QUADRATIC_PLANAR + { + static double _precision=1e-14; + } +} diff --git a/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpRun.cxx b/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpRun.cxx new file mode 100644 index 000000000..ffa8e9b30 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpRun.cxx @@ -0,0 +1,12 @@ + +#define UNIT_TEST_HEADER " --- TEST src/engine EngineTest" + +#include "QuadraticPlanarInterpTest.hxx" + +// --- Registers the fixture into the 'registry' + +CPPUNIT_TEST_SUITE_REGISTRATION( INTERP_KERNEL::QuadraticPlanarInterpTest ); + +// --- generic Main program from bases/Test + +#include "BasicMainTest.hxx" diff --git a/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest.cxx b/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest.cxx new file mode 100644 index 000000000..b5da3ca08 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest.cxx @@ -0,0 +1,812 @@ +#include "QuadraticPlanarInterpTest.hxx" +#include "QuadraticPolygon.hxx" +#include "EdgeArcCircle.hxx" +#include "ElementaryEdge.hxx" +#include "ComposedEdge.hxx" +#include "EdgeLin.hxx" + +#include +#include + +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(pol4[0]); + CPPUNIT_ASSERT(edge1); + Edge *edge2=edge1->getPtr(); + EdgeArcCircle *edge=dynamic_cast(edge2); + CPPUNIT_ASSERT(edge); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.24375,edge->getRadius(),ADMISSIBLE_ERROR); + CPPUNIT_ASSERT_DOUBLES_EQUAL(5.7857653289925404,edge->getAngle(),ADMISSIBLE_ERROR); + double center[2]; + edge->getCenter(center); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.48,center[0],ADMISSIBLE_ERROR); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.48375,center[1],ADMISSIBLE_ERROR); + const double *start=*edge->getStartNode(); + Node *n1=new Node(start[0]+2*(center[0]-start[0]),start[1]+2*(center[1]-start[1])); + edge->changeMiddle(n1); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.24375,edge->getRadius(),ADMISSIBLE_ERROR); + CPPUNIT_ASSERT_DOUBLES_EQUAL(5.7857653289925404,edge->getAngle(),ADMISSIBLE_ERROR); + n1->decrRef(); + n1=new Node(center[0],center[1]+0.24375); + edge->changeMiddle(n1); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.24375,edge->getRadius(),ADMISSIBLE_ERROR); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.49741997818704586,edge->getAngle(),ADMISSIBLE_ERROR);//5.7857653289925404 + 2*PI + n1->decrRef(); + //A half circle. + EdgeArcCircle *e=new EdgeArcCircle(0.84,0.54,0.78,0.6,0.84,0.66); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.06,e->getRadius(),ADMISSIBLE_ERROR); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-3.1415925921507317,e->getAngle(),1e-5); + e->decrRef(); + e=new EdgeArcCircle(0.84,0.54,0.9,0.6,0.84,0.66); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.06,e->getRadius(),ADMISSIBLE_ERROR); + CPPUNIT_ASSERT_DOUBLES_EQUAL(3.1415925921507317,e->getAngle(),1e-5); + e->decrRef(); +} + +void QuadraticPlanarInterpTest::IntersectionBasics() +{ + //Testing intersection of Bounds. + istringstream stream1("2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2\n3200 3400 4500 4800"); + EdgeLin *e1=new EdgeLin(stream1); + istringstream stream2("2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2\n3200 3400 4500 4800"); + EdgeLin *e2=new EdgeLin(stream2); + Bounds *bound=e1->getBounds().amIIntersectingWith(e2->getBounds()); CPPUNIT_ASSERT(bound); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.32,(*bound)[0],ADMISSIBLE_ERROR); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.45,(*bound)[1],ADMISSIBLE_ERROR); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.34,(*bound)[2],ADMISSIBLE_ERROR); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.48,(*bound)[3],ADMISSIBLE_ERROR); + delete bound; + e2->decrRef(); e1->decrRef(); + // + istringstream stream3("2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2\n3000 7200 6000 3700"); + EdgeLin *e3=new EdgeLin(stream3); + istringstream stream4("2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2\n4800 6600 7200 4200"); + EdgeLin *e4=new EdgeLin(stream4); + bound=e3->getBounds().amIIntersectingWith(e4->getBounds()); CPPUNIT_ASSERT(bound); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.48,(*bound)[0],ADMISSIBLE_ERROR); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.6,(*bound)[1],ADMISSIBLE_ERROR); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.42,(*bound)[2],ADMISSIBLE_ERROR); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.66,(*bound)[3],ADMISSIBLE_ERROR); + delete bound; + e3->decrRef(); e4->decrRef(); +} + +void QuadraticPlanarInterpTest::EdgeLinUnitary() +{ + EdgeLin *e1=new EdgeLin(0.5,0.5,3.7,4.1); + Node *n=new Node(2.1,2.3); + CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getCharactValue(*n),0.5,1e-8); + n->decrRef(); + n=new Node(3.7,4.1); + CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getCharactValue(*n),1.,1e-8); + n->decrRef(); + n=new Node(0.5,0.5); + CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getCharactValue(*n),0.,1e-8); + n->decrRef(); + n=new Node(-1.1,-1.3); + CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getCharactValue(*n),-0.5,1e-8); + n->decrRef(); + n=new Node(5.3,5.9); + CPPUNIT_ASSERT_DOUBLES_EQUAL(e1->getCharactValue(*n),1.5,1e-8); + n->decrRef(); e1->decrRef(); +} + +/*! + * Here two things are tested. + * 1 ) One the overlapping calculation capability of edge/edge intersector. + * 2 ) Then the capability to handle the case where 2 segs (whatever their type) are overlapped. + * All the configuration of full or part overlapping have been tested. + */ +void QuadraticPlanarInterpTest::IntersectionEdgeOverlapUnitarySegSeg() +{ + ComposedEdge& v1=*(new ComposedEdge); + ComposedEdge& v2=*(new ComposedEdge); + MergePoints v3; + //Testing merge of geometric equals seg2. + EdgeLin *e1=new EdgeLin(0.5,0.5,1.,1.); EdgeLin *e2=new EdgeLin(0.5,0.5,1.,1.); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(2,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(1,(int)v1.size()); CPPUNIT_ASSERT_EQUAL(1,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e1) && v2[0]->getDirection()); + v1.clear(); v2.clear(); v3.clear(); + // - testing by adding some noise + e1->decrRef(); e1=new EdgeLin(0.5+5.e-15,0.5-5.e-15,1.,1.+7.e-15); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(2,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(1,(int)v1.size()); CPPUNIT_ASSERT_EQUAL(1,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e1) && v2[0]->getDirection()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Testing merge of geometric equals seg2 but now with opposite direction + e1=new EdgeLin(0.5,0.5,0.7,0.7); e2=new EdgeLin(0.7+6.e-15,0.7-2.e-15,0.5+3.e-15,0.5-4.e-15); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(2,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(1,(int)v1.size()); CPPUNIT_ASSERT_EQUAL(1,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e1) && !v2[0]->getDirection());//compared 8 lines above !v2[0]->getDirection() + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 0 + //Test 1 - OUT_AFTER - OUT_AFTER | same dir. - 0° + e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(1.5,0.,2.,0.); + CPPUNIT_ASSERT(!e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(0,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(0,(int)v2.size()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 2 - INSIDE - OUT_AFTER | same dir. - 0° + e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(0.5,0.,1.5,0.); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(2,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(2,(int)v2.size()); + CPPUNIT_ASSERT(v1[1]->intresicEqualDirSensitive(v2[0])); + CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(e1->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==v1[1]->getEndNode()); + CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode()); CPPUNIT_ASSERT(e2->getStartNode()==v2[0]->getStartNode()); CPPUNIT_ASSERT(e2->getEndNode()==v2[1]->getEndNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 2 - INSIDE - OUT_AFTER | same dir. - 90° + e1=new EdgeLin(0.,0.,0.,1.); e2=new EdgeLin(0.,0.5,0.,1.5); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(2,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(2,(int)v2.size()); + CPPUNIT_ASSERT(v1[1]->intresicEqualDirSensitive(v2[0])); + CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(e1->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==v1[1]->getEndNode()); + CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode()); CPPUNIT_ASSERT(e2->getStartNode()==v2[0]->getStartNode()); CPPUNIT_ASSERT(e2->getEndNode()==v2[1]->getEndNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 2 - INSIDE - OUT_AFTER | same dir. - 45° + e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(0.5,0.5,1.5,1.5); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(2,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(2,(int)v2.size()); + CPPUNIT_ASSERT(v1[1]->intresicEqualDirSensitive(v2[0])); + CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(e1->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==v1[1]->getEndNode()); + CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode()); CPPUNIT_ASSERT(e2->getStartNode()==v2[0]->getStartNode()); CPPUNIT_ASSERT(e2->getEndNode()==v2[1]->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 2 - INSIDE - OUT_AFTER | opp. dir. - 45° + e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(1.5,1.5,0.5,0.5); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(2,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(2,(int)v2.size()); + CPPUNIT_ASSERT(!v1[1]->intresicEqualDirSensitive(v2[1]) && v1[1]->intresicEqual(v2[1])); + CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(e1->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==v1[1]->getEndNode()); + CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode()); CPPUNIT_ASSERT(e2->getStartNode()==v2[0]->getStartNode()); CPPUNIT_ASSERT(e2->getEndNode()==v2[1]->getEndNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 3 - INSIDE - INSIDE | same dir. - 0° + e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(0.25,0.,0.75,0.); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(3,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(1,(int)v2.size()); + CPPUNIT_ASSERT(v1[1]->intresincEqCoarse(e2) && v1[1]->getDirection()); + CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(v1[1]->getEndNode()==v1[2]->getStartNode()); + CPPUNIT_ASSERT(v1[0]->getStartNode()== e1->getStartNode()); CPPUNIT_ASSERT(v1[2]->getEndNode()== e1->getEndNode()); + CPPUNIT_ASSERT(v1[0]->getEndNode()==e2->getStartNode()); CPPUNIT_ASSERT(v1[1]->getEndNode()==e2->getEndNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 3 - INSIDE - INSIDE | same dir. - 90° + e1=new EdgeLin(0.,0.,0.,1.); e2=new EdgeLin(0.,0.25,0.,0.75); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(3,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(1,(int)v2.size()); + CPPUNIT_ASSERT(v1[1]->intresincEqCoarse(e2) && v1[1]->getDirection()); + CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(v1[1]->getEndNode()==v1[2]->getStartNode()); + CPPUNIT_ASSERT(v1[0]->getStartNode()== e1->getStartNode()); CPPUNIT_ASSERT(v1[2]->getEndNode()== e1->getEndNode()); + CPPUNIT_ASSERT(v1[0]->getEndNode()==e2->getStartNode()); CPPUNIT_ASSERT(v1[1]->getEndNode()==e2->getEndNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 3 - INSIDE - INSIDE | same dir. - 45° + e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(0.25,0.25,0.75,0.75); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(3,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(1,(int)v2.size()); + CPPUNIT_ASSERT(v1[1]->intresincEqCoarse(e2) && v1[1]->getDirection()); + CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(v1[1]->getEndNode()==v1[2]->getStartNode()); + CPPUNIT_ASSERT(v1[0]->getStartNode()== e1->getStartNode()); CPPUNIT_ASSERT(v1[2]->getEndNode()== e1->getEndNode()); + CPPUNIT_ASSERT(v1[0]->getEndNode()==e2->getStartNode()); CPPUNIT_ASSERT(v1[1]->getEndNode()==e2->getEndNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 3 - INSIDE - INSIDE | opp dir. - 45° + e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(0.75,0.75,0.25,0.25); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(3,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(1,(int)v2.size()); + CPPUNIT_ASSERT(v1[1]->intresincEqCoarse(e2) && !v1[1]->getDirection()); + CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(v1[1]->getEndNode()==v1[2]->getStartNode()); + CPPUNIT_ASSERT(v1[0]->getStartNode()== e1->getStartNode()); CPPUNIT_ASSERT(v1[2]->getEndNode()== e1->getEndNode()); + CPPUNIT_ASSERT(v1[0]->getEndNode()==e2->getEndNode()); CPPUNIT_ASSERT(v1[1]->getEndNode()==e2->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 4 - OUT_BEFORE - OUT_BEFORE | same dir. - 0 ° + e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(-1.,0.,-0.5,0.); + CPPUNIT_ASSERT(!e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(0,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(0,(int)v2.size()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 5 - OUT_BEFORE - INSIDE | same dir. - 0° + e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(-0.5,0.,0.5,0.); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(2,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(2,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresicEqualDirSensitive(v2[1])); + CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 5 - OUT_BEFORE - INSIDE | same dir. - 90° + e1=new EdgeLin(0.,0.,0.,1.); e2=new EdgeLin(0,-0.5,0.,0.5); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(2,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(2,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresicEqualDirSensitive(v2[1])); + CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 5 - OUT_BEFORE - INSIDE | same dir. - 45° + e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(-0.5,-0.5,0.5,0.5); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(2,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(2,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresicEqualDirSensitive(v2[1])); + CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 5 - OUT_BEFORE - INSIDE | opp dir. - 45° + e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(0.5,0.5,-0.5,-0.5); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(2,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(2,(int)v2.size()); + CPPUNIT_ASSERT(!v1[0]->intresicEqualDirSensitive(v2[0]) && v1[0]->intresicEqual(v2[0]) ); + CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 6 - OUT_BEFORE - OUT_AFTER | same dir. - 0° + e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(-0.5,0.,1.5,0.); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(1,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(3,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); + CPPUNIT_ASSERT(v2[1]->intresincEqCoarse(e1) && v2[1]->getDirection()); + CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode() && v2[1]->getEndNode()==v2[2]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 6 - OUT_BEFORE - OUT_AFTER | same dir. - 90° + e1=new EdgeLin(0.,0.,0.,1.); e2=new EdgeLin(0.,-0.5,0.,1.5); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(1,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(3,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); + CPPUNIT_ASSERT(v2[1]->intresincEqCoarse(e1) && v2[1]->getDirection()); + CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode() && v2[1]->getEndNode()==v2[2]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 6 - OUT_BEFORE - OUT_AFTER | same dir. - 45° + e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(-0.5,-0.5,1.5,1.5); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(1,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(3,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); + CPPUNIT_ASSERT(v2[1]->intresincEqCoarse(e1) && v2[1]->getDirection()); + CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode() && v2[1]->getEndNode()==v2[2]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 6 - OUT_BEFORE - OUT_AFTER | opp dir. - 45° + e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(1.5,1.5,-0.5,-0.5); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(1,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(3,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); + CPPUNIT_ASSERT(v2[1]->intresincEqCoarse(e1) && !v2[1]->getDirection()); + CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode() && v2[1]->getEndNode()==v2[2]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 7 - END - OUT_AFTER | same dir. - 0° + e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(1.,0.,1.5,0.); + CPPUNIT_ASSERT(!e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(0,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(0,(int)v2.size()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 7 - END - OUT_AFTER | opp dir. - 0° + e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(1.5,0.,1.,0.); + CPPUNIT_ASSERT(!e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(0,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(0,(int)v2.size()); + CPPUNIT_ASSERT(e1->getEndNode()==e2->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 8 - START - END | same dir. - 0° + e1=new EdgeLin(0.,0.,0.7,0.); e2=new EdgeLin(0.,0.,0.7,0.); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(2,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(1,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(1,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e1) && v2[0]->getDirection()); + CPPUNIT_ASSERT(e1->getStartNode()==e2->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==e2->getEndNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 8 - START - END | same dir. - 90° + e1=new EdgeLin(0.,0.,0.,0.7); e2=new EdgeLin(0.,0.,0.,0.7); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(2,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(1,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(1,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e1) && v2[0]->getDirection()); + CPPUNIT_ASSERT(e1->getStartNode()==e2->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==e2->getEndNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 8 - START - END | same dir. - 45° + e1=new EdgeLin(0.,0.,0.7,0.7); e2=new EdgeLin(0.,0.,0.7,0.7); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(2,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(1,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(1,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e1) && v2[0]->getDirection()); + CPPUNIT_ASSERT(e1->getStartNode()==e2->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==e2->getEndNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 8 - START - END | opp. dir. - 45° + e1=new EdgeLin(0.,0.,0.7,0.7); e2=new EdgeLin(0.7,0.7,0.,0.); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(2,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(1,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(1,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e1) && !v2[0]->getDirection()); + CPPUNIT_ASSERT(e1->getStartNode()==e2->getEndNode()); CPPUNIT_ASSERT(e1->getEndNode()==e2->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 9 - OUT_BEFORE - START | same dir. + e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(-0.5,0.,0.,0.); + CPPUNIT_ASSERT(!e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(0,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(0,(int)v2.size()); + CPPUNIT_ASSERT(e2->getEndNode()==e1->getStartNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 10 - START - OUT_AFTER | same dir. - 0° + e1=new EdgeLin(0.,0.,0.7,0.); e2=new EdgeLin(0.,0.,1.,0.); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(1,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(2,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e1) && v2[0]->getDirection()); + CPPUNIT_ASSERT(e1->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getStartNode()==e2->getStartNode()); CPPUNIT_ASSERT(v2[1]->getEndNode()==e2->getEndNode()); + CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 10 - START - OUT_AFTER | same dir. - 90° + e1=new EdgeLin(0.,0.,0.,0.7); e2=new EdgeLin(0.,0.,0.,1.); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(1,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(2,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e1) && v2[0]->getDirection()); + CPPUNIT_ASSERT(e1->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getStartNode()==e2->getStartNode()); CPPUNIT_ASSERT(v2[1]->getEndNode()==e2->getEndNode()); + CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 10 - START - OUT_AFTER | same dir. - 45° + e1=new EdgeLin(0.,0.,0.7,0.7); e2=new EdgeLin(0.,0.,1.,1.); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(1,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(2,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e1) && v2[0]->getDirection()); + CPPUNIT_ASSERT(e1->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getStartNode()==e2->getStartNode()); CPPUNIT_ASSERT(v2[1]->getEndNode()==e2->getEndNode()); + CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 10 - START - OUT_AFTER | opp dir. - 45° + e1=new EdgeLin(0.,0.,0.7,0.7); e2=new EdgeLin(1.,1.,0.,0.); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(1,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(2,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[1]->intresincEqCoarse(e1) && !v2[1]->getDirection()); + CPPUNIT_ASSERT(e1->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getStartNode()==e2->getEndNode()); CPPUNIT_ASSERT(v2[1]->getEndNode()==e2->getEndNode()); + CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 11 - INSIDE - END | same dir. - 0° + e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(0.7,0.,1.,0.); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(2,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(1,(int)v2.size()); + CPPUNIT_ASSERT(v1[1]->intresincEqCoarse(e2) && v1[1]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e2) && v2[0]->getDirection()); + CPPUNIT_ASSERT(e1->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==v1[1]->getEndNode()); CPPUNIT_ASSERT(e1->getEndNode()==e2->getEndNode()); + CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 11 - INSIDE - END | same dir. - 90° + e1=new EdgeLin(0.,0.,0.,1.); e2=new EdgeLin(0.,0.7,0.,1.); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(2,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(1,(int)v2.size()); + CPPUNIT_ASSERT(v1[1]->intresincEqCoarse(e2) && v1[1]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e2) && v2[0]->getDirection()); + CPPUNIT_ASSERT(e1->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==v1[1]->getEndNode()); CPPUNIT_ASSERT(e1->getEndNode()==e2->getEndNode()); + CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 11 - INSIDE - END | same dir. - 45° + e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(0.7,0.7,1.,1.); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(2,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(1,(int)v2.size()); + CPPUNIT_ASSERT(v1[1]->intresincEqCoarse(e2) && v1[1]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e2) && v2[0]->getDirection()); + CPPUNIT_ASSERT(e1->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==v1[1]->getEndNode()); CPPUNIT_ASSERT(e1->getEndNode()==e2->getEndNode()); + CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 11 - INSIDE - END | opp dir. - 45° + e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(1.,1.,0.7,0.7); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(2,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(1,(int)v2.size()); + CPPUNIT_ASSERT(e1->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==v1[1]->getEndNode()); CPPUNIT_ASSERT(e1->getEndNode()==e2->getStartNode()); + CPPUNIT_ASSERT(v1[1]->intresincEqCoarse(e2) && !v1[1]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e2) && v2[0]->getDirection()); + CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 12 - OUT_BEFORE - END | same dir. - 0° + e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(-0.5,0.,1.,0.); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(1,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(2,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[1]->intresincEqCoarse(e1) && v2[1]->getDirection()); + CPPUNIT_ASSERT(e2->getStartNode()==v2[0]->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==e2->getEndNode()); CPPUNIT_ASSERT(e2->getEndNode()==v2[1]->getEndNode()); + CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 12 - OUT_BEFORE - END | same dir. - 90° + e1=new EdgeLin(0.,0.,0.,1.); e2=new EdgeLin(0.,-0.5,0.,1.); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(1,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(2,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[1]->intresincEqCoarse(e1) && v2[1]->getDirection()); + CPPUNIT_ASSERT(e2->getStartNode()==v2[0]->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==e2->getEndNode()); CPPUNIT_ASSERT(e2->getEndNode()==v2[1]->getEndNode()); + CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 12 - OUT_BEFORE - END | same dir. - 45° + e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(-0.5,-0.5,1.,1.); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(1,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(2,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[1]->intresincEqCoarse(e1) && v2[1]->getDirection()); + CPPUNIT_ASSERT(e2->getStartNode()==v2[0]->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==e2->getEndNode()); CPPUNIT_ASSERT(e2->getEndNode()==v2[1]->getEndNode()); + CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 12 - OUT_BEFORE - END | opp dir. - 45° + e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(1.,1.,-0.5,-0.5); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(1,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(2,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e1) && !v2[0]->getDirection()); + CPPUNIT_ASSERT(e2->getStartNode()==v2[0]->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==e2->getStartNode()); CPPUNIT_ASSERT(e2->getEndNode()==v2[1]->getEndNode()); + CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 13 - START - INSIDE | same dir. - 0° + e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(0.,0.,0.5,0.); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(2,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(1,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e2) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e2) && v2[0]->getDirection()); + CPPUNIT_ASSERT(e2->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getStartNode()==e2->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==v1[1]->getEndNode()); + CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 13 - START - INSIDE | same dir. - 90° + e1=new EdgeLin(0.,0.,0.,1.); e2=new EdgeLin(0.,0.,0.,0.5); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(2,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(1,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e2) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e2) && v2[0]->getDirection()); + CPPUNIT_ASSERT(e2->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getStartNode()==e2->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==v1[1]->getEndNode()); + CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 13 - START - INSIDE | same dir. - 45° + e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(0.,0.,0.5,0.5); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(2,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(1,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e2) && v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e2) && v2[0]->getDirection()); + CPPUNIT_ASSERT(e2->getStartNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getStartNode()==e2->getStartNode()); CPPUNIT_ASSERT(e1->getEndNode()==v1[1]->getEndNode()); + CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 13 - START - INSIDE | opp dir. - 45° + e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(0.5,0.5,0.,0.); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(2,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(1,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e2) && !v1[0]->getDirection()); CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e2) && v2[0]->getDirection()); + CPPUNIT_ASSERT(e2->getEndNode()==v1[0]->getStartNode()); CPPUNIT_ASSERT(e1->getStartNode()==e2->getEndNode()); CPPUNIT_ASSERT(e1->getEndNode()==v1[1]->getEndNode()); + CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + ComposedEdge::Delete(&v1); + ComposedEdge::Delete(&v2); +} + +/*! + * Here there is test of cases where between 2 edges intersects only in points not on edge. + */ +void QuadraticPlanarInterpTest::IntersectionPointOnlyUnitarySegSeg() +{ + // 0° - classical + EdgeLin *e1=new EdgeLin(0.,0.,1.,0.); + EdgeLin *e2=new EdgeLin(0.3,0.3,0.5,-0.3); + ComposedEdge& v1=*(new ComposedEdge); + ComposedEdge& v2=*(new ComposedEdge); MergePoints v3; + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(2,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(2,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.4,(*v1[0]->getEndNode())[0],ADMISSIBLE_ERROR); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.,(*v1[0]->getEndNode())[1],ADMISSIBLE_ERROR); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + // 90° - classical + e1=new EdgeLin(0.,0.,0.,1.); + e2=new EdgeLin(-0.3,0.3,0.3,0.5); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_EQUAL(2,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(2,(int)v2.size()); + CPPUNIT_ASSERT(v1[0]->getEndNode()==v1[1]->getStartNode()); CPPUNIT_ASSERT(v2[0]->getEndNode()==v2[1]->getStartNode()); + CPPUNIT_ASSERT(e1->getStartNode()==v1.front()->getStartNode() && e1->getEndNode()==v1.back()->getEndNode()); + CPPUNIT_ASSERT(e2->getStartNode()==v2.front()->getStartNode() && e2->getEndNode()==v2.back()->getEndNode()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.,(*v1[0]->getEndNode())[0],ADMISSIBLE_ERROR); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.4,(*v1[0]->getEndNode())[1],ADMISSIBLE_ERROR); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 1 - 0° + e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(0.,0.,0.,1.); + CPPUNIT_ASSERT(!e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT(v3.isStart1(0)); CPPUNIT_ASSERT(v3.isStart2(0)); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 1 - 90° + e1=new EdgeLin(0.,0.,0.,1.); e2=new EdgeLin(0.,0.,1.,0.); + CPPUNIT_ASSERT(!e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT(v3.isStart1(0)); CPPUNIT_ASSERT(v3.isStart2(0)); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 1 - 45° + e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(0.,0.,1.,-1.); + CPPUNIT_ASSERT(!e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT(v3.isStart1(0)); CPPUNIT_ASSERT(v3.isStart2(0)); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 2 + e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(1.,1.,1.,0.); + CPPUNIT_ASSERT(!e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT(v3.isEnd1(0)); CPPUNIT_ASSERT(v3.isEnd2(0)); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 3 + e1=new EdgeLin(0.,0.,1.,0.); e2=new EdgeLin(1.,0.,1.,1.); + CPPUNIT_ASSERT(!e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT(v3.isEnd1(0)); CPPUNIT_ASSERT(v3.isStart2(0)); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Test 4 + e1=new EdgeLin(0.,0.,1.,1.); e2=new EdgeLin(1.,-1.,0.,0.); + CPPUNIT_ASSERT(!e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT(v3.isStart1(0)); CPPUNIT_ASSERT(v3.isEnd2(0)); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Intersection extremity of one edge and inside of other edge. 2 End. + e1=new EdgeLin(0.,0.,1.,0.); + e2=new EdgeLin(0.5,1.,0.5,0.); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(2,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(1,(int)v2.size()); + CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e2) && v2[0]->getDirection()); + CPPUNIT_ASSERT(v1[0]->getStartNode()==e1->getStartNode() && v1[0]->getEndNode()==e2->getEndNode() && v1[1]->getStartNode()==e2->getEndNode() && v1[1]->getEndNode()==e1->getEndNode()); + CPPUNIT_ASSERT(v1[0]->getDirection() && v1[1]->getDirection()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Intersection extremity of one edge and inside of other edge. 2 Start. + e1=new EdgeLin(0.,0.,1.,0.); + e2=new EdgeLin(0.5,0.,0.5,1.); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(2,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(1,(int)v2.size()); + CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT(v2[0]->intresincEqCoarse(e2) && v2[0]->getDirection()); + CPPUNIT_ASSERT(v1[0]->getStartNode()==e1->getStartNode() && v1[0]->getEndNode()==e2->getStartNode() && v1[1]->getStartNode()==e2->getStartNode() && v1[1]->getEndNode()==e1->getEndNode()); + CPPUNIT_ASSERT(v1[0]->getDirection() && v1[1]->getDirection()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Intersection extremity of one edge and inside of other edge. 1 Start. + e1=new EdgeLin(0.5,0.,0.5,1.); + e2=new EdgeLin(0.,0.,1.,0.); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(2,(int)v2.size()); + CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); + CPPUNIT_ASSERT(v2[0]->getStartNode()==e2->getStartNode() && v2[0]->getEndNode()==e1->getStartNode() && v2[1]->getStartNode()==e1->getStartNode() && v2[1]->getEndNode()==e2->getEndNode()); + CPPUNIT_ASSERT(v2[0]->getDirection() && v2[1]->getDirection()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + //Intersection extremity of one edge and inside of other edge. 1 End. + e1=new EdgeLin(0.5,1.,0.5,0.); + e2=new EdgeLin(0.,0.,1.,0.); + CPPUNIT_ASSERT(e1->intersectWith(e2,v3,v1,v2)); + CPPUNIT_ASSERT_EQUAL(1,(int)v1.size()); + CPPUNIT_ASSERT_EQUAL(2,(int)v2.size()); + CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT(v1[0]->intresincEqCoarse(e1) && v1[0]->getDirection()); + CPPUNIT_ASSERT(v2[0]->getStartNode()==e2->getStartNode() && v2[0]->getEndNode()==e1->getEndNode() && v2[1]->getStartNode()==e1->getEndNode() && v2[1]->getEndNode()==e2->getEndNode()); + CPPUNIT_ASSERT(v2[0]->getDirection() && v2[1]->getDirection()); + e2->decrRef(); e1->decrRef(); + v1.clear(); v2.clear(); v3.clear(); + ComposedEdge::Delete(&v2); + ComposedEdge::Delete(&v1); +} diff --git a/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest.hxx b/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest.hxx new file mode 100644 index 000000000..8e95387bf --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest.hxx @@ -0,0 +1,60 @@ +#ifndef _QUADRATICPLANARINTERPTEST_HXX_ +#define _QUADRATICPLANARINTERPTEST_HXX_ + +#include + +namespace INTERP_KERNEL +{ + class Node; + class EdgeArcCircle; + class QuadraticPolygon; + + class QuadraticPlanarInterpTest : public CppUnit::TestFixture + { + CPPUNIT_TEST_SUITE( QuadraticPlanarInterpTest ); + CPPUNIT_TEST( ReadWriteInXfigElementary ); + CPPUNIT_TEST( ReadWriteInXfigGlobal ); + CPPUNIT_TEST( IntersectionBasics ); + CPPUNIT_TEST( EdgeLinUnitary ); + CPPUNIT_TEST( IntersectionEdgeOverlapUnitarySegSeg ); + CPPUNIT_TEST( IntersectionPointOnlyUnitarySegSeg ); + CPPUNIT_TEST( IntersectArcCircleBase ); + CPPUNIT_TEST( IntersectArcCircleFull ); + CPPUNIT_TEST( IntersectArcCircleSegumentBase ); + CPPUNIT_TEST( checkInOutDetection ); + CPPUNIT_TEST( checkAssemblingBases1 ); + CPPUNIT_TEST( checkAssemblingBases2 ); + CPPUNIT_TEST( checkPolygonsIntersection1 ); + CPPUNIT_TEST( checkAreasCalculations ); + CPPUNIT_TEST_SUITE_END(); + public: + void setUp(); + void tearDown(); + void cleanUp(); + // + void ReadWriteInXfigElementary(); + void ReadWriteInXfigGlobal(); + void IntersectionBasics(); + void EdgeLinUnitary(); + void IntersectionEdgeOverlapUnitarySegSeg(); + void IntersectionPointOnlyUnitarySegSeg(); + // + void IntersectArcCircleBase(); + void IntersectArcCircleFull(); + void IntersectArcCircleSegumentBase(); + // + void checkInOutDetection(); + // + void checkAssemblingBases1(); + void checkAssemblingBases2(); + // + void checkPolygonsIntersection1(); + void checkAreasCalculations(); + private: + EdgeArcCircle *buildArcOfCircle(const double *center, double radius, double alphaStart, double alphaEnd); + double btw2NodesAndACenter(const Node& n1, const Node& n2, const double *center); + void checkBasicsOfPolygons(QuadraticPolygon& pol1, QuadraticPolygon& pol2, bool checkDirection); + }; +} + +#endif diff --git a/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest2.cxx b/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest2.cxx new file mode 100644 index 000000000..cb5c180f7 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest2.cxx @@ -0,0 +1,639 @@ +#include "QuadraticPlanarInterpTest.hxx" +#include "QuadraticPolygon.hxx" +#include "EdgeArcCircle.hxx" +#include "EdgeLin.hxx" + +#include +#include +#include + +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 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::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::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)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::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)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::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::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::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)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::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)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::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::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 v4; + MergePoints v3; + CPPUNIT_ASSERT(intersector->intersect(0,v4,order,v3)); CPPUNIT_ASSERT(!order); CPPUNIT_ASSERT_EQUAL(2,(int)v4.size()); CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(2.,(*v4[0])[0],1e-10); CPPUNIT_ASSERT_DOUBLES_EQUAL(4.3,(*v4[0])[1],1e-10); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.3,(*v4[1])[0],1e-10); CPPUNIT_ASSERT_DOUBLES_EQUAL(2.,(*v4[1])[1],1e-10); + v4[0]->decrRef(); v4[1]->decrRef(); e2->decrRef(); v3.clear(); v4.clear(); delete intersector; + // + e2=new EdgeLin(3.,5.3,-1.3,1.); + intersector=new ArcCSegIntersector(*e1,*e2); + intersector->areOverlappedOrOnlyColinears(0,obvious,areOverlapped); CPPUNIT_ASSERT(!obvious && !areOverlapped); + CPPUNIT_ASSERT(intersector->intersect(0,v4,order,v3)); CPPUNIT_ASSERT(order); CPPUNIT_ASSERT_EQUAL(2,(int)v4.size()); CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(2.,(*v4[0])[0],1e-10); CPPUNIT_ASSERT_DOUBLES_EQUAL(4.3,(*v4[0])[1],1e-10); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.3,(*v4[1])[0],1e-10); CPPUNIT_ASSERT_DOUBLES_EQUAL(2.,(*v4[1])[1],1e-10); + v4[0]->decrRef(); v4[1]->decrRef(); e2->decrRef(); v3.clear(); v4.clear(); delete intersector; + // tangent intersection + e2=new EdgeLin(-1.,4.3,3.,4.3); + intersector=new ArcCSegIntersector(*e1,*e2); + intersector->areOverlappedOrOnlyColinears(0,obvious,areOverlapped); CPPUNIT_ASSERT(!obvious && !areOverlapped); + CPPUNIT_ASSERT(intersector->intersect(0,v4,order,v3)); CPPUNIT_ASSERT(order); CPPUNIT_ASSERT_EQUAL(1,(int)v4.size()); CPPUNIT_ASSERT_EQUAL(0,(int)v3.getNumberOfAssociations()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(2.,(*v4[0])[0],1e-10); CPPUNIT_ASSERT_DOUBLES_EQUAL(4.3,(*v4[0])[1],1e-10); + v4[0]->decrRef(); e2->decrRef(); v3.clear(); delete intersector; + // no intersection + e2=new EdgeLin(-2.,-2.,-1.,-3.); + intersector=new ArcCSegIntersector(*e1,*e2); + intersector->areOverlappedOrOnlyColinears(0,obvious,areOverlapped); CPPUNIT_ASSERT(obvious && !areOverlapped); + e2->decrRef(); v3.clear(); delete intersector; + // + e1->decrRef(); +} + +EdgeArcCircle *QuadraticPlanarInterpTest::buildArcOfCircle(const double *center, double radius, double alphaStart, double alphaEnd) +{ + double alphaM=(alphaStart+alphaEnd)/2; + return new EdgeArcCircle(center[0]+cos(alphaStart)*radius,center[1]+sin(alphaStart)*radius, + center[0]+cos(alphaM)*radius,center[1]+sin(alphaM)*radius, + center[0]+cos(alphaEnd)*radius,center[1]+sin(alphaEnd)*radius); +} + +double QuadraticPlanarInterpTest::btw2NodesAndACenter(const Node& n1, const Node& n2, const double *center) +{ + const double *n1Pt=n1; + const double *n2Pt=n2; + double tmp1[2],tmp2[2]; + tmp1[0]=n1Pt[0]-center[0]; tmp1[1]=n1Pt[1]-center[1]; + tmp2[0]=n2Pt[0]-center[0]; tmp2[1]=n2Pt[1]-center[1]; + double distTmp1=sqrt(tmp1[0]*tmp1[0]+tmp1[1]*tmp1[1]); + double distTmp2=sqrt(tmp2[0]*tmp2[0]+tmp2[1]*tmp2[1]); + double ret=acos((tmp1[0]*tmp2[0]+tmp1[1]*tmp2[1])/(distTmp1*distTmp2)); + if(tmp1[0]*tmp2[1]-tmp1[1]*tmp2[0]<0) + ret=-ret; + return ret; +} diff --git a/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest3.cxx b/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest3.cxx new file mode 100644 index 000000000..1b3f93bbe --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest3.cxx @@ -0,0 +1,300 @@ +#include "QuadraticPlanarInterpTest.hxx" +#include "QuadraticPolygon.hxx" +#include "ElementaryEdge.hxx" +#include "EdgeArcCircle.hxx" +#include "EdgeLin.hxx" + +#include +#include +#include + +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(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((*pol2[1])[0]); CPPUNIT_ASSERT(tmp); + CPPUNIT_ASSERT(tmp->getLoc()==FULL_OUT_1); + tmp=dynamic_cast((*pol2[1])[1]); CPPUNIT_ASSERT(tmp); + CPPUNIT_ASSERT(tmp->getLoc()==FULL_IN_1); + tmp=dynamic_cast((*pol2[2])[0]); CPPUNIT_ASSERT(tmp); + CPPUNIT_ASSERT(tmp->getLoc()==FULL_IN_1); + tmp=dynamic_cast((*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(pol4[1]); CPPUNIT_ASSERT(tmp); CPPUNIT_ASSERT(tmp->getPtr()==e4_7); + CPPUNIT_ASSERT(tmp->getLoc()==FULL_OUT_1); + tmp=dynamic_cast(pol4[3]); CPPUNIT_ASSERT(tmp); CPPUNIT_ASSERT(tmp->getPtr()==e6_5); + tmp=dynamic_cast(pol4[0]); CPPUNIT_ASSERT(tmp); CPPUNIT_ASSERT(tmp->getPtr()==e5_4); + CPPUNIT_ASSERT(tmp->getLoc()==FULL_OUT_1); + tmp=dynamic_cast(pol4[2]); CPPUNIT_ASSERT(tmp); CPPUNIT_ASSERT(tmp->getPtr()==e7_6); + CPPUNIT_ASSERT(tmp->getLoc()==FULL_OUT_1); + tmp=dynamic_cast(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(pol6[0]); CPPUNIT_ASSERT(tmp); CPPUNIT_ASSERT(tmp->getPtr()==e4_5); + CPPUNIT_ASSERT(tmp->getLoc()==FULL_OUT_1); + tmp=dynamic_cast(pol6[1]); CPPUNIT_ASSERT(tmp); CPPUNIT_ASSERT(tmp->getPtr()==e5_6); + CPPUNIT_ASSERT(tmp->getLoc()==FULL_OUT_1); + tmp=dynamic_cast((*pol6[2])[0]); CPPUNIT_ASSERT(tmp); + CPPUNIT_ASSERT(tmp->getLoc()==FULL_ON_1); + tmp=dynamic_cast((*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(pol8[0]); CPPUNIT_ASSERT(tmp); CPPUNIT_ASSERT(tmp->getPtr()==e1_2); + CPPUNIT_ASSERT(tmp->getLoc()==FULL_ON_1); + tmp=dynamic_cast(pol8[1]); CPPUNIT_ASSERT(tmp); CPPUNIT_ASSERT(tmp->getPtr()==e2_3); + CPPUNIT_ASSERT(tmp->getLoc()==FULL_ON_1); + tmp=dynamic_cast(pol8[2]); CPPUNIT_ASSERT(tmp); CPPUNIT_ASSERT(tmp->getPtr()==e3_1); + CPPUNIT_ASSERT(tmp->getLoc()==FULL_ON_1); + //clean-up test4 + e1_2->decrRef(); e2_3->decrRef(); e3_1->decrRef(); e4_5->decrRef(); e5_6->decrRef(); e6_4->decrRef(); + n1->decrRef(); n2->decrRef(); n3->decrRef(); n4->decrRef(); n5->decrRef(); n6->decrRef(); +} + +void QuadraticPlanarInterpTest::checkBasicsOfPolygons(QuadraticPolygon& pol1, QuadraticPolygon& pol2, bool checkDirection) +{ + IteratorOnComposedEdge it1(&pol1),it2(&pol2); it1.previousLoop(); it2.previousLoop(); + Node *nIter1=it1.current()->getEndNode(); Node *nIter2=it2.current()->getEndNode(); + for(it2.first();!it2.finished();it2.next()) + { + CPPUNIT_ASSERT(nIter2==it2.current()->getStartNode()); + if(checkDirection) + CPPUNIT_ASSERT(it2.current()->getDirection()); + nIter2=it2.current()->getEndNode(); + } + for(it1.first();!it1.finished();it1.next()) + { + CPPUNIT_ASSERT(nIter1==it1.current()->getStartNode()); + if(checkDirection) + CPPUNIT_ASSERT(it1.current()->getDirection()); + nIter1=it1.current()->getEndNode(); + } +} diff --git a/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest4.cxx b/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest4.cxx new file mode 100644 index 000000000..9ac85aa30 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/QuadraticPlanarInterpTest4.cxx @@ -0,0 +1,327 @@ +#include "QuadraticPlanarInterpTest.hxx" +#include "QuadraticPolygon.hxx" +#include "ElementaryEdge.hxx" +#include "EdgeArcCircle.hxx" +#include "EdgeLin.hxx" + +#include +#include +#include + +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 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;i1recursiveSize()); + 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;i1recursiveSize()); + 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;i1decrRef(); 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;i1recursiveSize()); + 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;i1recursiveSize()); + 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;i1recursiveSize()); + 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;i1decrRef(); 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;i1recursiveSize()); CPPUNIT_ASSERT_EQUAL(4,result[1]->recursiveSize()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.15,result[0]->getAreaFast()+result[1]->getAreaFast(),1e-10); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.03,fabs(result[0]->getAreaFast()-result[1]->getAreaFast()),1e-10); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.15,pol15.intersectWith(pol16),1e-10); + delete result[0]; delete result[1]; + } + } + //clean-up test8 + e1_2->decrRef(); e2_3->decrRef(); e3_4->decrRef(); e4_1->decrRef(); e5_6->decrRef(); e6_7->decrRef(); e7_8->decrRef(); e8_9->decrRef(); e9_10->decrRef(); e10_11->decrRef(); e11_12->decrRef(); e12_1->decrRef(); + n1->decrRef(); n2->decrRef(); n3->decrRef(); n4->decrRef(); n5->decrRef(); n6->decrRef(); n7->decrRef(); n8->decrRef(); n9->decrRef(); n10->decrRef(); n11->decrRef(); n12->decrRef(); +} + +void QuadraticPlanarInterpTest::checkAreasCalculations() +{ + Node *n1=new Node(0.,0.); + Node *n2=new Node(1.,0.); + Node *n3=new Node(0.5,1.); + Edge *e1_2=new EdgeLin(n1,n2); + Edge *e2_3=new EdgeLin(n2,n3); + Edge *e3_1=new EdgeLin(n3,n1); + // + e1_2->incrRef(); e2_3->incrRef(); e3_1->incrRef(); + QuadraticPolygon pol1; pol1.pushBack(e1_2); pol1.pushBack(e2_3); pol1.pushBack(e3_1); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.5,pol1.getAreaFast(),1e-10); + CPPUNIT_ASSERT_DOUBLES_EQUAL(3.2360679774997898,pol1.getPerimeterFast(),1e-10); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.61803398874989479,pol1.getHydroulicDiameter(),1e-10); + pol1.reverse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.5,pol1.getAreaFast(),1e-10); + CPPUNIT_ASSERT_DOUBLES_EQUAL(3.2360679774997898,pol1.getPerimeterFast(),1e-10); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.61803398874989479,pol1.getHydroulicDiameter(),1e-10); + //clean-up + e1_2->decrRef(); e2_3->decrRef(); e3_1->decrRef(); + n1->decrRef(); n2->decrRef(); n3->decrRef(); + + //case 2 + + n1=new Node(0.,0.); + n2=new Node(1.,0.); + Node *n3m=new Node(1.5,0.5); + n3=new Node(1.,1.); + Node *n4=new Node(0.,1.); + e1_2=new EdgeLin(n1,n2); + e2_3=new EdgeArcCircle(n2,n3m,n3); + Edge *e3_4=new EdgeLin(n3,n4); + Edge *e4_1=new EdgeLin(n4,n1); + // + for(int k=0;k<8;k++) + { + n2->setNewCoords(cos(k*M_PI/4),sin(k*M_PI/4)); + n3->setNewCoords(sqrt(2.)*cos((k+1)*M_PI/4),sqrt(2.)*sin((k+1)*M_PI/4)); + n3m->setNewCoords(1.5811388300841898*cos(0.3217505543966423+k*M_PI/4),1.5811388300841898*sin(0.3217505543966423+k*M_PI/4)); + n4->setNewCoords(cos(k*M_PI/4+M_PI/2),sin(k*M_PI/4+M_PI/2)); + e1_2->update(n3m); e2_3->update(n3m); e3_4->update(n3m); e4_1->update(n3m); + e1_2->incrRef(); e2_3->incrRef(); e3_4->incrRef(); e4_1->incrRef(); + QuadraticPolygon pol2; pol2.pushBack(e1_2); pol2.pushBack(e2_3); pol2.pushBack(e3_4); pol2.pushBack(e4_1); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.3926990816987241,pol2.getAreaFast(),1e-6); + CPPUNIT_ASSERT_DOUBLES_EQUAL(4.5707963267948966,pol2.getPerimeterFast(),1e-6); + pol2.reverse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-1.3926990816987241,pol2.getAreaFast(),1e-6); + CPPUNIT_ASSERT_DOUBLES_EQUAL(4.5707963267948966,pol2.getPerimeterFast(),1e-6); + } + //clean-up case2 + e1_2->decrRef(); e2_3->decrRef(); e3_4->decrRef(); e4_1->decrRef(); + n1->decrRef(); n2->decrRef(); n3->decrRef(); n3m->decrRef(); n4->decrRef(); + + //case 3 + + const double radius1=0.7; + const double radius2=0.9; + n1=new Node(1.+radius1*cos(-2.*M_PI/3.),1.+radius1*sin(-2.*M_PI/3.)); + n2=new Node(1.+radius1*cos(-M_PI/3.),1.+radius1*sin(-M_PI/3.)); + Node *n2m=new Node(1.+radius1*cos(M_PI/2.),1.+radius1*sin(M_PI/2.)); + n3=new Node(1.+radius2*cos(-M_PI/3.),1.+radius2*sin(-M_PI/3.)); + n3m=new Node(1.+radius2*cos(M_PI/2.),1.+radius2*sin(M_PI/2.)); + n4=new Node(1.+radius2*cos(-2.*M_PI/3.),1.+radius2*sin(-2.*M_PI/3.)); + e1_2=new EdgeArcCircle(n1,n2m,n2); + e2_3=new EdgeLin(n2,n3); + e3_4=new EdgeArcCircle(n3,n3m,n4); + e4_1=new EdgeLin(n4,n1); + // + e1_2->incrRef(); e2_3->incrRef(); e3_4->incrRef(); e4_1->incrRef(); + QuadraticPolygon pol3; pol3.pushBack(e1_2); pol3.pushBack(e2_3); pol3.pushBack(e3_4); pol3.pushBack(e4_1); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.83775804095727857,pol3.getAreaFast(),1e-10); + CPPUNIT_ASSERT_DOUBLES_EQUAL(8.7775804095727832,pol3.getPerimeterFast(),1e-10); + pol3.reverse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.83775804095727857,pol3.getAreaFast(),1e-10); + CPPUNIT_ASSERT_DOUBLES_EQUAL(8.7775804095727832,pol3.getPerimeterFast(),1e-10); + //clean-up case3 + e1_2->decrRef(); e2_3->decrRef(); e3_4->decrRef(); e4_1->decrRef(); + n1->decrRef(); n2->decrRef(); n2m->decrRef(); n3->decrRef(); n3m->decrRef(); n4->decrRef(); +} diff --git a/src/INTERP_KERNEL/Geometric2D/QuadraticPolygon.cxx b/src/INTERP_KERNEL/Geometric2D/QuadraticPolygon.cxx new file mode 100644 index 000000000..99ff742f9 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/QuadraticPolygon.cxx @@ -0,0 +1,350 @@ +#include "QuadraticPolygon.hxx" +#include "ComposedEdgeWithIt.hxx" +#include "ElementaryEdge.hxx" +#include "Bounds.hxx" +#include "Edge.txx" + +#include + +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::iterator iter1=_subEdges.begin(); + vector::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::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::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 polygs=intersectMySelfWith(other); + for(vector::iterator iter=polygs.begin();iter!=polygs.end();iter++) + { + ret+=fabs((*iter)->getAreaFast()); + delete *iter; + } + return ret; +} + +std::vector 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(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::buildIntersectionPolygons(const QuadraticPolygon& pol1, const QuadraticPolygon& pol2) const +{ + vector ret; + list pol2Zip=pol2.zipConsecutiveInSegments(); + if(!pol2Zip.empty()) + closePolygons(pol2Zip,pol1,ret); + return ret; +} + +std::list QuadraticPolygon::zipConsecutiveInSegments() const +{ + list ret; + IteratorOnComposedEdge it((ComposedEdge *)this); + int nbOfTurns=recursiveSize(); + int i=0; + if(!it.goToNextInOn(false,i,nbOfTurns)) + return ret; + i=0; + // + while(igetLoc(); + while(loc!=FULL_OUT_1 && iclone(); + 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& pol2Zip, const QuadraticPolygon& pol1, + std::vector& results) const +{ + bool directionKnownInPol1=false; + bool directionInPol1; + for(list::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::iterator iter2=iter; iter2++; + list::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::iterator QuadraticPolygon::fillAsMuchAsPossibleWith(const QuadraticPolygon& pol1Splitted, + std::list::iterator iStart, + std::list::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::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::iterator QuadraticPolygon::checkInList(Node *n, std::list::iterator iStart, + std::list::iterator iEnd) +{ + for(list::iterator iter=iStart;iter!=iEnd;iter++) + if((*iter)->isNodeIn(n)) + return iter; + return iEnd; +} diff --git a/src/INTERP_KERNEL/Geometric2D/QuadraticPolygon.hxx b/src/INTERP_KERNEL/Geometric2D/QuadraticPolygon.hxx new file mode 100644 index 000000000..4c6c60bc9 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/QuadraticPolygon.hxx @@ -0,0 +1,47 @@ +#ifndef __QUADRATICPOLYGON_HXX__ +#define __QUADRATICPOLYGON_HXX__ + +#include "ComposedEdge.hxx" + +#include + +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 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 buildIntersectionPolygons(const QuadraticPolygon& pol1, const QuadraticPolygon& pol2) const; + bool amIAChanceToBeCompletedBy(const QuadraticPolygon& pol1Splitted, const QuadraticPolygon& pol2NotSplitted, bool& direction); + protected: + std::list zipConsecutiveInSegments() const; + void closePolygons(std::list& pol2Zip, const QuadraticPolygon& pol1, std::vector& results) const; + static void updateNeighbours(const MergePoints& merger, IteratorOnComposedEdge it1, IteratorOnComposedEdge it2, + const AbstractEdge *e1, const AbstractEdge *e2); + std::list::iterator fillAsMuchAsPossibleWith(const QuadraticPolygon& pol1Splitted, + std::list::iterator iStart, + std::list::iterator iEnd, + bool direction); + static std::list::iterator checkInList(Node *n, std::list::iterator iStart, + std::list::iterator iEnd); + }; +} + +#endif diff --git a/src/INTERP_KERNEL/Geometric2D/README b/src/INTERP_KERNEL/Geometric2D/README new file mode 100644 index 000000000..398f7bd1f --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/README @@ -0,0 +1,4 @@ +Info for xfig outputs comes from : +http://www.xfig.org/userman/fig-format.html + + diff --git a/src/INTERP_KERNEL/Geometric2D/TODO b/src/INTERP_KERNEL/Geometric2D/TODO new file mode 100644 index 000000000..2777c0038 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/TODO @@ -0,0 +1,9 @@ +1 ) Virer les *OFFSET_FOR... de Edge.cxx et remplacer par une méthode static à retour const int +2 ) tester le buildEdgeLyingOnMe du ArcCircle. +3 ) tester le intersectWith Lin/ArcCircle avec reverse. + + +Penser à : + +Au moment de faire les intersections Edges/Edges en cas de splitting faire le nécessaire. + diff --git a/src/INTERP_KERNEL/Geometric2D/UnitTestsResult.hxx b/src/INTERP_KERNEL/Geometric2D/UnitTestsResult.hxx new file mode 100644 index 000000000..31dfdb753 --- /dev/null +++ b/src/INTERP_KERNEL/Geometric2D/UnitTestsResult.hxx @@ -0,0 +1,20 @@ +#ifndef _UNITTESTSRESULT_HXX_ +#define _UNITTESTSRESULT_HXX_ + +#include +#include + +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 -- 2.39.2