// // Copyright (C) : Please refer to the COPYRIGHT file distributed // with this source distribution. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // /////////////////////////////////////////////////////////////////////////////// #include "Curve.h" #include "CurveIterators.h" #include "CurveAdvancedIterators.h" /**********************************/ /* */ /* */ /* CurvePoint */ /* */ /* */ /**********************************/ CurvePoint::CurvePoint() { __A=0; __B=0; _t2d=0; } CurvePoint::CurvePoint(SVertex *iA, SVertex *iB, float t) { __A=iA; __B=iB; _t2d=t; if((iA == 0) && (t == 1.f)) { _Point2d=__B->point2d(); _Point3d=__B->point3d(); } else if((iB == 0) && (t == 0.f)) { _Point2d=__A->point2d(); _Point3d=__A->point3d(); } else { _Point2d=__A->point2d()+_t2d*(__B->point2d()-__A->point2d()); _Point3d=__A->point3d()+_t2d*(__B->point3d()-__A->point3d()); } } CurvePoint::CurvePoint(CurvePoint *iA, CurvePoint *iB, float t3) { float t1=iA->t2d(); float t2=iB->t2d(); if((iA->A() == iB->A()) && (iA->B() == iB->B()) && (iA->A() != 0) && (iA->B() != 0) && (iB->A() != 0) && (iB->B() != 0)) { __A=iA->A(); __B=iB->B(); _t2d=t1+t2*t3-t1*t3; } else if((iA->B() == 0) && (iB->B() == 0)) { __A = iA->A(); __B = iB->A(); _t2d = t3; } else if((iA->t2d() == 0) && (iB->t2d() == 0)) { __A = iA->A(); __B = iB->A(); _t2d = t3; } else if(iA->A() == iB->A()){ if(iA->t2d() == 0){ __A = iB->A(); __B = iB->B(); _t2d = t3; }else if(iB->t2d() == 0){ __A = iA->A(); __B = iA->B(); _t2d = t3; } }else if(iA->B() == iB->B()){ if(iA->t2d() == 1){ __A = iB->A(); __B = iB->B(); _t2d = t3; }else if(iB->t2d() == 1){ __A = iA->A(); __B = iA->B(); _t2d = t3; } } else if(iA->B() == iB->A()) { if((iA->t2d() != 1.f) && (iB->t2d() == 0.f)) { __A = iA->A(); __B = iA->B(); _t2d=t1+t3-t1*t3; //_t2d = t3; } else if((iA->t2d() == 1.f) && (iB->t2d() != 0.f)) { __A = iB->A(); __B = iB->B(); //_t2d = t3; _t2d=t2*t3; } } //_Point2d=__A->point2d()+_t2d*(__B->point2d()-__A->point2d()); //_Point3d=__A->point3d()+_t2d*(__B->point3d()-__A->point3d()); _Point2d= iA->point2d()+t3*(iB->point2d()-iA->point2d()); _Point3d=__A->point3d()+_t2d*(__B->point3d()-__A->point3d()); } CurvePoint::CurvePoint(const CurvePoint& iBrother) { __A=iBrother.__A; __B=iBrother.__B; _t2d=iBrother._t2d; _Point2d=iBrother._Point2d; _Point3d=iBrother._Point3d; } CurvePoint& CurvePoint::operator=(const CurvePoint& iBrother) { __A=iBrother.__A; __B=iBrother.__B; _t2d=iBrother._t2d; _Point2d=iBrother._Point2d; _Point3d=iBrother._Point3d; return *this; } FEdge *CurvePoint::fedge() { if(getNature() & Nature::T_VERTEX) return 0; return __A->fedge(); } FEdge* CurvePoint::getFEdge(Interface0D& inter) { CurvePoint* iVertexB = dynamic_cast(&inter); if (!iVertexB) return 0; if(((__A == iVertexB->__A) && (__B == iVertexB->__B)) || ((__A == iVertexB->__B) && (__B == iVertexB->__A))) return __A->getFEdge(*__B); else if(__B == 0) { if(iVertexB->__B == 0) return __A->getFEdge(*(iVertexB->__A)); else if(iVertexB->__A == __A) return __A->getFEdge(*(iVertexB->__B)); else if(iVertexB->__B == __A) return __A->getFEdge(*(iVertexB->__A)); } else if(iVertexB->__B == 0) { if(iVertexB->__A == __A) return __B->getFEdge(*(iVertexB->__A)); else if(iVertexB->__A == __B) return __A->getFEdge(*(iVertexB->__A)); } else if(__B == iVertexB->__A) { if((_t2d != 1) && (iVertexB->_t2d == 0)) return __A->getFEdge(*__B); if((_t2d == 1) && (iVertexB->_t2d != 0)) return iVertexB->__A->getFEdge(*(iVertexB->__B)); } else if(__B == iVertexB->__B) { if((_t2d != 1) && (iVertexB->_t2d == 1)) return __A->getFEdge(*__B); if((_t2d == 1) && (iVertexB->_t2d != 1)) return iVertexB->__A->getFEdge(*(iVertexB->__B)); } else if(__A == iVertexB->__A) { if((_t2d == 0) && (iVertexB->_t2d != 0)) return iVertexB->__A->getFEdge(*(iVertexB->__B)); if((_t2d != 0) && (iVertexB->_t2d == 0)) return __A->getFEdge(*__B); } else if(__A == iVertexB->__B) { if((_t2d == 0) && (iVertexB->_t2d != 1)) return iVertexB->__A->getFEdge(*(iVertexB->__B)); if((_t2d != 0) && (iVertexB->_t2d == 1)) return __A->getFEdge(*__B); } cerr << "Warning: you should not be there..." << endl; return 0; } Vec3r CurvePoint::normal() const { if(__B == 0) return __A->normal(); if(__A == 0) return __B->normal(); Vec3r Na = __A->normal(); if(Exception::getException()) Na = Vec3r(0,0,0); Vec3r Nb = __B->normal(); if(Exception::getException()) Nb = Vec3r(0,0,0); // compute t3d: real t3d = SilhouetteGeomEngine::ImageToWorldParameter(__A->getFEdge(*__B),_t2d); return ((1-t3d)*Na+t3d*Nb); } // Material CurvePoint::material() const //{ // if(__A == 0) // return __B->material(); // return __A->material(); //} // Id CurvePoint::shape_id() const // { // if(__A == 0) // return __B->shape_id(); // return __A->shape_id(); // } const SShape * CurvePoint::shape() const { if(__A == 0) return __B->shape(); return __A->shape(); } // float CurvePoint::shape_importance() const // { // if(__A == 0) // return __B->shape_importance(); // return __A->shape_importance(); // } // const unsigned CurvePoint::qi() const //{ // if(__A == 0) // return __B->qi(); // if(__B == 0) // return __A->qi(); // return __A->getFEdge(*__B)->qi(); //} occluder_container::const_iterator CurvePoint::occluders_begin() const { if(__A == 0) return __B->occluders_begin(); if(__B == 0) return __A->occluders_begin(); return __A->getFEdge(*__B)->occluders_begin(); } occluder_container::const_iterator CurvePoint::occluders_end() const { if(__A == 0) return __B->occluders_end(); if(__B == 0) return __A->occluders_end(); return __A->getFEdge(*__B)->occluders_end(); } bool CurvePoint::occluders_empty() const { if(__A == 0) return __B->occluders_empty(); if(__B == 0) return __A->occluders_empty(); return __A->getFEdge(*__B)->occluders_empty(); } int CurvePoint::occluders_size() const { if(__A == 0) return __B->occluders_size(); if(__B == 0) return __A->occluders_size(); return __A->getFEdge(*__B)->occluders_size(); } const SShape * CurvePoint::occluded_shape() const { if(__A == 0) return __B->occluded_shape(); if(__B == 0) return __A->occluded_shape(); return __A->getFEdge(*__B)->occluded_shape(); } const Polygon3r& CurvePoint::occludee() const { if(__A == 0) return __B->occludee(); if(__B == 0) return __A->occludee(); return __A->getFEdge(*__B)->occludee(); } const bool CurvePoint::occludee_empty() const { if(__A == 0) return __B->occludee_empty(); if(__B == 0) return __A->occludee_empty(); return __A->getFEdge(*__B)->occludee_empty(); } real CurvePoint::z_discontinuity() const { if(__A == 0) return __B->z_discontinuity(); if(__B == 0) return __A->z_discontinuity(); if(__A->getFEdge(*__B) == 0) return 0.0; return __A->getFEdge(*__B)->z_discontinuity(); } // // float CurvePoint::local_average_depth() const //{ // return local_average_depth_function(this); //} // // float CurvePoint::local_depth_variance() const //{ // return local_depth_variance_function(this); //} // // real CurvePoint::local_average_density(float sigma) const //{ // //return local_average_density(this); // // return density_function(this); //} // Vec3r shaded_color() const ; // // Vec3r CurvePoint::orientation2d() const // { // if(__A == 0) // return __B->orientation2d(); // if(__B == 0) // return __A->orientation2d(); // return __B->point2d()-__A->point2d(); // } // // Vec3r CurvePoint::orientation3d() const // { // if(__A == 0) // return __B->orientation3d(); // if(__B == 0) // return __A->orientation3d(); // return __B->point3d()-__A->point3d(); // } // real curvature2d() const {return viewedge()->curvature2d((_VertexA->point2d()+_VertexB->point2d())/2.0);} // // Vec3r CurvePoint::curvature2d_as_vector() const //{ // // Vec3r edgeA = (_FEdges[0])->orientation2d().normalize(); // // Vec3r edgeB = (_FEdges[1])->orientation2d().normalize(); // // return edgeA+edgeB; // // // if(__A == 0) // return __B->curvature2d_as_vector(); // if(__B == 0) // return __A->curvature2d_as_vector(); // return ((1-_t2d)*__A->curvature2d_as_vector()+_t2d*__B->curvature2d_as_vector()); //} // // real CurvePoint::curvature2d_as_angle() const //{ // // Vec3r edgeA = (_FEdges[0])->orientation2d(); // // Vec3r edgeB = (_FEdges[1])->orientation2d(); // // Vec2d N1(-edgeA.y(), edgeA.x());N1.normalize(); // // Vec2d N2(-edgeB.y(), edgeB.x());N2.normalize(); // // return acos((N1*N2)); // // if(__A == 0) // return __B->curvature2d_as_angle(); // if(__B == 0) // return __A->curvature2d_as_angle(); // return ((1-_t2d)*__A->curvature2d_as_angle()+_t2d*__B->curvature2d_as_angle()); //} real CurvePoint::curvatureFredo() const { if(__A == 0) return __B->curvatureFredo(); if(__B == 0) return __A->curvatureFredo(); return ((1-_t2d)*__A->curvatureFredo()+_t2d*__B->curvatureFredo()); } Vec2d CurvePoint::directionFredo () const { if(__A == 0) return __B->directionFredo(); if(__B == 0) return __A->directionFredo(); return ((1-_t2d)*__A->directionFredo()+_t2d*__B->directionFredo()); } /**********************************/ /* */ /* */ /* Curve */ /* */ /* */ /**********************************/ /* for functions */ Curve::~Curve() { if(!_Vertices.empty()) { for(vertex_container::iterator it=_Vertices.begin(), itend =_Vertices.end(); it!=itend; ++it) { delete (*it); } _Vertices.clear(); } } /*! iterators access */ Curve::point_iterator Curve::points_begin(float step) { vertex_container::iterator second = _Vertices.begin();++second; return point_iterator(_Vertices.begin(), second, _Vertices.begin(), _Vertices.end(), _nSegments, step, 0.f, 0.f); //return point_iterator(_Vertices.begin(), second, _nSegments, step, 0.f, 0.f); } Curve::const_point_iterator Curve::points_begin(float step) const { vertex_container::const_iterator second = _Vertices.begin();++second; return const_point_iterator(_Vertices.begin(), second, _Vertices.begin(), _Vertices.end(), _nSegments, step, 0.f, 0.f); //return const_point_iterator(_Vertices.begin(), second, _nSegments, step, 0.f, 0.f); } Curve::point_iterator Curve::points_end(float step) { return point_iterator(_Vertices.end(), _Vertices.end(), _Vertices.begin(), _Vertices.end(), _nSegments, step, 1.f, _Length); //return point_iterator(_Vertices.end(), _Vertices.end(), _nSegments, step, 1.f, _Length); } Curve::const_point_iterator Curve::points_end(float step) const { return const_point_iterator(_Vertices.end(), _Vertices.end(), _Vertices.begin(), _Vertices.end(), _nSegments, step, 1.f, _Length); //return const_point_iterator(_Vertices.end(), _Vertices.end(), _nSegments, step, 1.f, _Length); } // Adavnced Iterators access Curve::point_iterator Curve::vertices_begin(){return points_begin(0);} Curve::const_point_iterator Curve::vertices_begin() const {return points_begin(0);} Curve::point_iterator Curve::vertices_end(){return points_end(0);} Curve::const_point_iterator Curve::vertices_end() const {return points_end(0);} // specialized iterators access CurveInternal::CurvePointIterator Curve::curvePointsBegin(float t){ vertex_container::iterator second = _Vertices.begin();++second; return CurveInternal::CurvePointIterator(_Vertices.begin(), second, _Vertices.begin(), _Vertices.end(), 0, _nSegments, _Length, t, 0.f, 0.f); } CurveInternal::CurvePointIterator Curve::curvePointsEnd(float t){ vertex_container::iterator last = _Vertices.end();--last; return CurveInternal::CurvePointIterator(last, _Vertices.end(), _Vertices.begin(), _Vertices.end(), _nSegments, _nSegments, _Length, t, 0.f, _Length); } CurveInternal::CurvePointIterator Curve::curveVerticesBegin(){ return curvePointsBegin(0); } CurveInternal::CurvePointIterator Curve::curveVerticesEnd(){ return curvePointsEnd(0); } Interface0DIterator Curve::pointsBegin(float t){ vertex_container::iterator second = _Vertices.begin();++second; Interface0DIterator ret(new CurveInternal::CurvePointIterator(_Vertices.begin(), second, _Vertices.begin(), _Vertices.end(), 0, _nSegments, _Length, t, 0.f, 0.f)); return ret; } Interface0DIterator Curve::pointsEnd(float t){ vertex_container::iterator last = _Vertices.end();--last; Interface0DIterator ret(new CurveInternal::CurvePointIterator(last, _Vertices.end(), _Vertices.begin(), _Vertices.end(), _nSegments, _nSegments, _Length, t, 0.f, _Length)); return ret; } Interface0DIterator Curve::verticesBegin(){ return pointsBegin(0); } Interface0DIterator Curve::verticesEnd(){ return pointsEnd(0); } // Vec3r shaded_color(int iCombination = 0) const ; // // Vec3r Curve::orientation2d(point_iterator it) const //{ // return (*it)->orientation2d(); //} /* template */ /* Vec3r Curve::orientation2d(int iCombination) const */ /* { */ /* return edge_orientation2d_function(this, iCombination); */ /* } */ // // Vec3r Curve::orientation3d(point_iterator it) const //{ // return (*it)->orientation3d(); //} /* */ /* Vec3r Curve::orientation3d(int iCombination) const */ /* { */ /* return edge_orientation3d_function(this, iCombination); */ /* } */ // real curvature2d(point_iterator it) const {return (*it)->curvature2d();} // real curvature2d(int iCombination = 0) const ; // Material Curve::material() const //{ // const_vertex_iterator v=vertices_begin(), vend=vertices_end(); // const Material& mat = (*v)->material(); // for(;v!=vend;++v) // { // if((*v)->material() != mat) // Exception::raiseException(); // } // return mat; //} // int Curve::qi() const //{ // const_vertex_iterator v=vertices_begin(), vend=vertices_end(); // int qi_= (*v)->qi(); // for(;v!=vend;++v) // { // if((*v)->qi() != qi_) // Exception::raiseException(); // } // return qi_; //} // occluder_container::const_iterator occluders_begin() const {return _FEdgeA->occluders().begin();} // occluder_container::const_iterator occluders_end() const {return _FEdgeA->occluders().end();} //int Curve::occluders_size() const //{ // return qi(); //} // bool Curve::occluders_empty() const //{ // const_vertex_iterator v=vertices_begin(), vend=vertices_end(); // bool empty = (*v)->occluders_empty(); // for(;v!=vend;++v) // { // if((*v)->occluders_empty() != empty) // Exception::raiseException(); // } // return empty; //} // const Polygon3r& occludee() const {return *(_FEdgeA->aFace());} // const SShape * Curve::occluded_shape() const //{ // const_vertex_iterator v=vertices_begin(), vend=vertices_end(); // const SShape *sshape = (*v)->occluded_shape(); // for(;v!=vend;++v) // { // if((*v)->occluded_shape() != sshape) // Exception::raiseException(); // } // return sshape; //} // const bool Curve::occludee_empty() const //{ // const_vertex_iterator v=vertices_begin(), vend=vertices_end(); // bool empty = (*v)->occludee_empty(); // for(;v!=vend;++v) // { // if((*v)->occludee_empty() != empty) // Exception::raiseException(); // } // return empty; //} /* */ /* real Curve::z_discontinuity(int iCombination) const */ /* { */ /* return z_discontinuity_edge_function(this, iCombination); */ /* } */ // int Curve::shape_id() const // { // const_vertex_iterator v=vertices_begin(), vend=vertices_end(); // Id id = (*v)->shape_id(); // for(;v!=vend;++v) // { // if((*v)->shape_id() != id) // Exception::raiseException(); // } // return id.first; // } // const SShape * Curve::shape() const //{ // const_vertex_iterator v=vertices_begin(), vend=vertices_end(); // const SShape *sshape = (*v)->shape(); // for(;v!=vend;++v) // { // if((*v)->shape() != sshape) // Exception::raiseException(); // } // return sshape; //} // occluder_container::const_iterator Curve::occluders_begin() const //{ // const_vertex_iterator v=vertices_begin(); // return (*v)->occluders_begin(); //} // // // occluder_container::const_iterator Curve::occluders_end() const //{ // const_vertex_iterator v=vertices_end(); // return (*v)->occluders_end(); //} /* */ /* Vec3r Curve::curvature2d_as_vector(int iCombination) const */ /* { */ /* return curvature2d_as_vector_edge_function(this, iCombination); */ /* } */ /* */ /* real Curve::curvature2d_as_angle(int iCombination) const */ /* { */ /* return curvature2d_as_angle_edge_function(this, iCombination); */ /* } */ /* */ /* float Curve::shape_importance(int iCombination) const */ /* { */ /* return shape_importance_edge_function(this, iCombination); */ /* } */ /* */ /* float Curve::local_average_depth(int iCombination) const */ /* { */ /* return local_average_depth_edge_function(this, iCombination); */ /* } */ /* */ /* float Curve::local_depth_variance(int iCombination ) const */ /* { */ /* return local_depth_variance_edge_function(this, iCombination); */ /* // local_depth_variance_functor functor; */ /* // float result; */ /* // Evaluate >(&functor, iCombination, result); */ /* // return result; */ /* } */ /* */ /* real Curve::local_average_density(float sigma, int iCombination ) const */ /* { */ /* return density_edge_function(this, iCombination); */ /* // density_functor functor; */ /* // real result; */ /* // Evaluate >(&functor, iCombination, result); */ /* // return result; */ /* } */ #define EPS_CURVA_DIR 0.01 void Curve::computeCurvatureAndOrientation () { // const_vertex_iterator v=vertices_begin(), vend=vertices_end(), v2, prevV, v0; // Vec2d p0, p1, p2; // Vec3r p; // p=(*v)->point2d(); // p0=Vec2d(p[0], p[1]); // prevV=v; ++v; // p=(*v)->point2d(); // p1=Vec2d(p[0], p[1]); // Vec2d prevDir(p1-p0); // for(;v!=vend;++v) // { // v2=v; ++v2; // if (v2==vend) break; // Vec3r p2=(*v2)->point2d(); // Vec2d BA=p0-p1; // Vec2d BC=p2-p1; // real lba=BA.norm(), lbc=BC.norm(); // BA.normalizeSafe(); // BC.normalizeSafe(); // Vec2d normalCurvature=BA+BC; // Vec2d dir=Vec2d(BC-BA); // Vec2d normal=Vec2d(-dir[1], dir[0]); // normal.normalizeSafe(); // real curvature=normalCurvature*normal; // if (lba+lbc > MY_EPSILON) // curvature/=(0.5*lba+lbc); // if (dir.norm() < MY_EPSILON) // dir=0.1*prevDir; // (*v)->setCurvatureFredo(curvature); // (*v)->setDirectionFredo(dir); // prevV=v; p0=p1; p1=p2; prevDir=dir; prevDir.normalize(); // } // (*v)->setCurvatureFredo((*prevV)->curvatureFredo()); // (*v)->setDirectionFredo((*v)->point2d()-(*prevV)->point2d()); // v0=vertices_begin(); v2=v0; ++v2; // (*v0)->setCurvatureFredo((*v2)->curvatureFredo()); // (*v0)->setDirectionFredo((*v2)->point2d()-(*v0)->point2d()); // //closed curve case one day... // // // return; // //numerical degeneracy verification.. we'll see later // const_vertex_iterator vLastReliable=vertices_begin(); // v=vertices_begin(); // p=(*v)->point2d(); // p0=Vec2d(p[0], p[1]); // prevV=v; ++v; // p=(*v)->point2d(); // p1=Vec2d(p[0], p[1]); // bool isReliable=false; // if ((p1-p0).norm>EPS_CURVA) // { // vLastReliable=v; // isReliable=true; // } // for(;v!=vend;++v) // { // v2=v; ++v2; // if (v2==vend) break; // Vec3r p2=(*v2)->point2d(); // Vec2d BA=p0-p1; // Vec2d BC=p2-p1; // real lba=BA.norm(), lbc=BC.norm(); // if ((lba+lbc)setCurvatureFredo((*v)->curvatureFredo()); // (*vfix)->setDirectionFredo((*v)->directionFredo()); // } // } // isReliable=true; // vLastReliable=v; // } // prevV=v; p0=p1; p1=p2; // } }