1 // Copyright (C) 2014-2015 EDF-R&D
2 // This library is free software; you can redistribute it and/or
3 // modify it under the terms of the GNU Lesser General Public
4 // License as published by the Free Software Foundation; either
5 // version 2.1 of the License, or (at your option) any later version.
7 // This library is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 // Lesser General Public License for more details.
12 // You should have received a copy of the GNU Lesser General Public
13 // License along with this library; if not, write to the Free Software
14 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #include <HYDROData_TopoCurve.h>
21 #include <Approx_Curve3d.hxx>
22 #include <BRep_Builder.hxx>
23 #include <BRepAdaptor_Curve.hxx>
24 #include <BRepAdaptor_HCurve.hxx>
25 #include <BRepBuilderAPI_MakeEdge.hxx>
26 #include <Extrema_ExtCC.hxx>
27 #include <Extrema_ExtPC.hxx>
28 #include <BRepExtrema_DistShapeShape.hxx>
29 #include <GeomAPI_Interpolate.hxx>
30 #include <Geom_BSplineCurve.hxx>
31 #include <Precision.hxx>
32 #include <ShapeAnalysis_TransferParametersProj.hxx>
33 #include <ShapeBuild_Edge.hxx>
34 #include <TColgp_Array1OfVec.hxx>
35 #include <TColgp_HArray1OfPnt.hxx>
36 #include <TColStd_HArray1OfBoolean.hxx>
37 #include <TopExp_Explorer.hxx>
39 #include <TopoDS_Wire.hxx>
40 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
41 #include <TopTools_ListOfShape.hxx>
47 #include "HYDRO_trace.hxx"
48 #include <BRepTools.hxx>
50 //! The type is intended to traverse the container
51 //! either from the begin to the end or vice versa.
52 template<typename ContainerType, typename IteratorType>
56 IteratorType myIterator; //!< The iterator.
57 IteratorType myIteratorLimit; //!< The iterator limit.
59 //! The pointer to the method to traverse the next item.
60 IteratorType& (IteratorType::*myNext)();
65 const ContainerType& theContainer,
66 const bool theIsForward)
70 myIterator = theContainer.begin();
71 myIteratorLimit = theContainer.end();
72 myNext = &IteratorType::operator++;
76 myIterator = --theContainer.end();
77 myIteratorLimit = --theContainer.begin();
78 myNext = &IteratorType::operator--;
82 //! Returna 'true' if the container contains not yet traversed item.
85 return myIterator != myIteratorLimit;
88 //! Traverses to the next item.
89 IteratorType& operator ++()
91 return (myIterator.*myNext)();
94 //! Returns the iterator.
95 IteratorType& operator *() {return myIterator;}
98 // Inserts the value after the position.
99 template<typename ItemType> static void InsertAfter(
100 const typename std::list<ItemType>::iterator& thePosition,
101 const ItemType& theValue,
102 std::list<ItemType>& theList)
104 typename std::list<ItemType>::iterator aEIt2 = thePosition;
105 if (++aEIt2 != theList.end())
107 theList.insert(aEIt2, theValue);
111 theList.push_back(theValue);
115 // Converts the curve to a smooth cubic B-spline using the deflection.
116 static Handle(Geom_BSplineCurve) BSpline(
117 const BRepAdaptor_Curve& theCurve, const double theDeflection)
119 Handle(BRepAdaptor_HCurve) aCurve = new BRepAdaptor_HCurve(theCurve);
120 Approx_Curve3d aConverter(aCurve, theDeflection, GeomAbs_C1, 4, 3);
121 Handle(Geom_BSplineCurve) aBSpline;
122 return aConverter.HasResult() ? aConverter.Curve() : aBSpline;
125 // Replaces the vertex of the edge considering the edge orientation.
126 static TopoDS_Edge ReplaceVertex(
127 const TopoDS_Edge& theEdge, const bool theIsEndVertex)
129 TopoDS_Vertex aVertices[] = {
130 TopExp::FirstVertex(theEdge, Standard_True),
131 TopExp::LastVertex(theEdge, Standard_True)};
132 aVertices[theIsEndVertex ? 1 : 0].EmptyCopy();
133 TopoDS_Edge aNewEdge = TopoDS::Edge(theEdge.Oriented(TopAbs_FORWARD));
135 ShapeBuild_Edge().CopyReplaceVertices(aNewEdge, aVertices[0], aVertices[1]);
136 aNewEdge.Orientation(theEdge.Orientation());
140 // Projects the point to the curve.
141 double ProjectPointToCurve(
142 const gp_XYZ& thePoint,
143 const Adaptor3d_Curve& theCurve,
144 double& theParameter)
146 // Calculate the nearest curve internal extremum.
147 Extrema_ExtPC aAlgo(thePoint, theCurve);
149 double aMinSqDist = DBL_MAX;
152 const int aECount = aAlgo.NbExt();
153 for (int aEN = 1; aEN <= aECount; ++aEN)
155 const gp_XYZ& aP = aAlgo.Point(aEN).Value().XYZ();
156 const double aSqDist = (thePoint - aP).SquareModulus();
157 if (aMinSqDist > aSqDist)
159 aMinSqDist = aSqDist;
165 // Calculate the nearest curve end extremum.
166 const double aParams[] =
167 {theCurve.FirstParameter(), theCurve.LastParameter()};
168 const gp_XYZ aEnds[] =
169 {theCurve.Value(aParams[0]).XYZ(), theCurve.Value(aParams[1]).XYZ()};
170 const double aSqDists[] = {
171 (thePoint - aEnds[0]).SquareModulus(),
172 (thePoint - aEnds[1]).SquareModulus()};
173 for (int aEI = 0; aEI < 2; ++aEI)
175 if (aMinSqDist > aSqDists[aEI])
177 aMinSqDist = aSqDists[aEI];
184 theParameter = aParams[-aMinEN];
188 const Extrema_POnCurv& aPOnC = aAlgo.Point(aMinEN);
189 const gp_XYZ& aP = aPOnC.Value().XYZ();
190 theParameter = aPOnC.Parameter();
191 for (int aEI = 0; aEI < 2; ++aEI)
193 if (Abs(theParameter - aParams[aEI]) < Precision::PConfusion() ||
194 (aP - aEnds[aEI]).SquareModulus() < Precision::SquareConfusion())
196 theParameter = aParams[aEI];
202 // Projects the point to the edge.
203 static double ProjectPointToEdge(
204 const gp_XYZ& thePoint, const TopoDS_Edge& theEdge, double& theParameter)
206 return ProjectPointToCurve(thePoint, BRepAdaptor_Curve(theEdge), theParameter);
209 // Adds the parameter to the curve parameter list.
210 static int AddParameter(
211 const Adaptor3d_Curve& theCurve,
212 const double theParameter,
213 std::list<double>& theParameters)
215 // Check the coincidence.
216 std::list<double> aEndParams;
217 aEndParams.push_back(theCurve.FirstParameter());
218 aEndParams.push_back(theCurve.LastParameter());
219 std::list<double>* aParams[] = {&theParameters, &aEndParams};
220 const gp_XYZ aPoint = theCurve.Value(theParameter).XYZ();
221 for (int aLI = 0; aLI < 2; ++aLI)
223 std::list<double>::iterator aPIt = aParams[aLI]->begin();
224 std::list<double>::iterator aLastPIt = aParams[aLI]->end();
225 for (int aPI = 0; aPIt != aLastPIt; ++aPI, ++aPIt)
227 const double aParam = *aPIt;
228 if (Abs(theParameter - aParam) < Precision::PConfusion() ||
229 (theCurve.Value(aParam).XYZ() - aPoint).SquareModulus() <=
230 Precision::SquareConfusion())
237 theParameters.push_front(aEndParams.front());
241 theParameters.push_back(aEndParams.back());
250 // Calculate the position to insert.
251 std::list<double>::iterator aPIt = theParameters.begin();
252 std::list<double>::iterator aLastPIt = theParameters.end();
253 if (aPIt != aLastPIt && *aPIt < theParameter)
255 for (++aPIt; aPIt != aLastPIt && *aPIt < theParameter; ++aPIt);
256 if (aPIt != aLastPIt)
258 theParameters.insert(aPIt, theParameter);
262 theParameters.push_back(theParameter);
267 theParameters.push_front(theParameter);
272 // Intersects the first curve by the second one and
273 // adds the intersection parameters to the ordered list.
274 static int IntersectCurve(
275 const Adaptor3d_Curve& theCurve1,
276 const Adaptor3d_Curve& theCurve2,
277 std::list<double>& theParameters)
281 const gp_XYZ aEndPs[] = {
282 theCurve2.Value(theCurve2.FirstParameter()).XYZ(),
283 theCurve2.Value(theCurve2.LastParameter()).XYZ()};
284 for (int aPI = 0; aPI < 2; ++aPI)
287 if (ProjectPointToCurve(aEndPs[aPI], theCurve1, aParameter) <=
288 Precision::SquareConfusion())
290 DEBTRACE("aParameter " << aParameter);
291 aIntCount += AddParameter(theCurve1, aParameter, theParameters);
295 // Process the internal extremums.
296 Extrema_ExtCC aAlgo(theCurve1, theCurve2); //, 1.e-6, 1.e-6);
299 const int aECount = aAlgo.NbExt();
300 for (int aEN = 1; aEN <= aECount; ++aEN)
302 Extrema_POnCurv aP1, aP2;
303 aAlgo.Points(aEN, aP1, aP2);
304 DEBTRACE("SquareDistance " << aP1.Value().SquareDistance(aP2.Value()));
305 if (aP1.Value().SquareDistance(aP2.Value()) <=
306 Precision::SquareConfusion())
308 DEBTRACE("aP1.Parameter() " << aP1.Parameter());
309 aIntCount += AddParameter(theCurve1, aP1.Parameter(), theParameters);
316 static int IntersectShape(
317 const TopoDS_Edge& theEdge1,
318 const TopoDS_Edge& theEdge2,
319 std::list<double>& theParameters)
321 if (theEdge1.IsSame(theEdge2))
322 Standard_ConstructionError::Raise("The lines to make intersection must be different");
324 // std::ostringstream oshp1, oshp2;
325 // BRepTools::Write(theEdge1, oshp1);
326 // BRepTools::Write(theEdge2, oshp2);
327 // BRep_Builder aBuilder;
328 // std::istringstream ishp1(oshp1.str());
329 // std::istringstream ishp2(oshp2.str());
330 // TopoDS_Shape aShape1, aShape2;
331 // DEBTRACE("oshp1.str() " << oshp1.str());
332 // DEBTRACE("oshp2.str() " << oshp2.str());
335 // BRepTools::Read(aShape1, ishp1, aBuilder);
336 // } catch (Standard_Failure)
338 // DEBTRACE("Error Brep conversion");
343 // BRepTools::Read(aShape2, ishp2, aBuilder);
344 // } catch (Standard_Failure)
346 // DEBTRACE("Error Brep conversion");
351 BRepAdaptor_Curve aCurve1 = BRepAdaptor_Curve(theEdge1);
352 //BRepAdaptor_Curve aCurve2 = BRepAdaptor_Curve(theEdge2);
354 // --- Calculate Lines Intersections Points: two times, changing the order (sometimes intersections not detected)
356 BRepExtrema_DistShapeShape dst(theEdge1, theEdge2); // first
359 DEBTRACE("nb solutions found: " << dst.NbSolution());
361 for (int i = 1; i <= dst.NbSolution(); i++)
363 P1 = dst.PointOnShape1(i);
364 P2 = dst.PointOnShape2(i);
365 Standard_Real Dist = P1.Distance(P2);
366 DEBTRACE("distance solution "<< i << " : " << Dist);
367 if (Dist <= Precision::Confusion())
370 dst.ParOnEdgeS1(i, par1);
371 DEBTRACE("parameter: " << par1);
372 nbSols += AddParameter(aCurve1, par1, theParameters); // add only new parameters
376 DEBTRACE("not an Intersection Point");
381 BRepExtrema_DistShapeShape dst2(theEdge2, theEdge1); // second
384 DEBTRACE("nb solutions found: " << dst.NbSolution());
386 for (int i = 1; i <= dst2.NbSolution(); i++)
388 P1 = dst2.PointOnShape1(i);
389 P2 = dst2.PointOnShape2(i);
390 Standard_Real Dist = P1.Distance(P2);
391 DEBTRACE("distance solution "<< i << " : " << Dist);
392 if (Dist <= Precision::Confusion())
395 dst2.ParOnEdgeS2(i, par1);
396 DEBTRACE("parameter: " << par1);
397 nbSols += AddParameter(aCurve1, par1, theParameters); // add only new parameters
401 DEBTRACE("not an Intersection Point");
408 // Intersects the first edge by the second one and
409 // adds the intersection parameters to the ordered list.
410 static int IntersectEdge(
411 const TopoDS_Edge& theEdge1,
412 const TopoDS_Edge& theEdge2,
413 std::list<double>& theParameters)
415 return IntersectShape(theEdge1, theEdge2, theParameters);
416 // BRepAdaptor_Curve aCurve1 = BRepAdaptor_Curve(theEdge1);
417 // BRepAdaptor_Curve aCurve2 = BRepAdaptor_Curve(theEdge2);
418 // return IntersectCurve(aCurve1, aCurve2, theParameters);
421 // Returns the curve tangent in the position: 0 - start, 1 - end.
422 static gp_XYZ Tangent(const Adaptor3d_Curve& theCurve, const int thePosition)
424 const Standard_Real aParam = (thePosition == 0) ?
425 theCurve.FirstParameter() : theCurve.LastParameter();
428 theCurve.D1(aParam, aP, aV);
429 Standard_Real aNorm = aV.Magnitude();
430 aNorm = (aNorm >= Precision::PConfusion()) ? aNorm : 0;
431 return ((1 / aNorm) * aV).XYZ();
434 // Returns the edge tangent in the position: 0 - start, 1 - end.
435 static gp_XYZ Tangent(const TopoDS_Edge& theEdge, const int thePosition)
437 BRepAdaptor_Curve aCurve(theEdge);
438 return Tangent(BRepAdaptor_Curve(theEdge), thePosition);
441 static bool Interpolate(
442 const gp_XYZ thePoint1,
443 const gp_XYZ thePoint2,
444 const gp_XYZ theTangent1,
445 const gp_XYZ theTangent2,
446 Handle(Geom_BSplineCurve)& theBSpline)
448 Handle(TColgp_HArray1OfPnt) aPs = new TColgp_HArray1OfPnt(1, 2);
449 TColgp_Array1OfVec aTs(1, 2);
450 Handle(TColStd_HArray1OfBoolean) aTFs = new TColStd_HArray1OfBoolean(1, 2);
451 aPs->SetValue(1, thePoint1);
452 aPs->SetValue(2, thePoint2);
453 aTs.SetValue(1, theTangent1);
454 aTs.SetValue(2, theTangent2);
455 aTFs->SetValue(1, Standard_True);
456 aTFs->SetValue(2, Standard_True);
457 GeomAPI_Interpolate aInterpolator(aPs, Standard_False, 0);
458 aInterpolator.Load(aTs, aTFs, Standard_False);
459 aInterpolator.Perform();
460 const bool aResult = (aInterpolator.IsDone() == Standard_True);
463 theBSpline = aInterpolator.Curve();
468 bool HYDROData_TopoCurve::Initialize(const TopoDS_Wire& theWire)
470 // Check for non-emptiness.
472 TopTools_IndexedDataMapOfShapeListOfShape aVertexToEdges;
473 TopExp::MapShapesAndAncestors(theWire,
474 TopAbs_VERTEX, TopAbs_EDGE, aVertexToEdges);
475 const int aVCount = aVertexToEdges.Extent(); // number of edges (an edge can be a spline with intermediate vertices)
476 DEBTRACE("initialize VCount= "<< aVCount);
482 // Check for 1 manifoldness.
483 bool isClosed = false;
486 for (int aVN = 1; aVN <= aVCount; ++aVN)
488 const int aEdgeCount = aVertexToEdges.FindFromIndex(aVN).Extent();
498 isClosed = (aEndCount == 0);
499 if (!isClosed && aEndCount != 2)
504 std::string brepName = "theWireToSplit";
506 BRepTools::Write( theWire, brepName.c_str() );
508 // Find the start, i.e. the end which is the first vertex (or just the first vertex when closed) ==> aVN
512 for (; aVertexToEdges.FindFromIndex(aVN).Extent() == 2; ++aVN);
513 if (!aVertexToEdges.FindKey(aVN).IsEqual(TopExp::FirstVertex(
514 TopoDS::Edge(aVertexToEdges.FindFromIndex(aVN).First()), Standard_True)))
516 for (; aVertexToEdges.FindFromIndex(aVN).Extent() == 2; ++aVN);
521 TopTools_ListOfShape& aEdges = aVertexToEdges.ChangeFromIndex(1);
522 if (!aVertexToEdges.FindKey(aVN).IsEqual(
523 TopExp::FirstVertex(TopoDS::Edge(aEdges.First()), Standard_True)))
525 const TopoDS_Shape aEdge = aEdges.First();
526 aEdges.First() = aEdges.Last();
527 aEdges.Last() = aEdge;
531 // Calculate the edge order ==> list in myEdges
532 TopTools_ListOfShape* aEdges = &aVertexToEdges.ChangeFromIndex(aVN); // 1 or 2 edges from first vertex
533 while (!aEdges->IsEmpty())
535 const TopoDS_Edge aEdge = TopoDS::Edge(aEdges->First());
536 aEdges->RemoveFirst();
537 myEdges.push_back(aEdge); // add an edge in the list
538 int aVN2 = aVertexToEdges.FindIndex(TopExp::FirstVertex(aEdge));
541 aVN2 = aVertexToEdges.FindIndex(TopExp::LastVertex(aEdge));
543 aVN = aVN2; // next vertex
545 aEdges = &aVertexToEdges.ChangeFromIndex(aVN2);
546 const TopoDS_Edge aEdge2 = TopoDS::Edge(aEdges->First());
547 if (aEdge2.IsEqual(aEdge))
549 aEdges->RemoveFirst();
554 aEdges->Append(aEdge2); // next edge
558 // Check for connectedness and free vertex.
559 return (aVCount - myEdges.size()) == (isClosed ? 0 : 1);
562 TopoDS_Wire HYDROData_TopoCurve::Wire() const
565 BRep_Builder aBuilder;
566 aBuilder.MakeWire(aWire);
567 std::list<TopoDS_Edge>::const_iterator aEItLast = myEdges.end();
568 std::list<TopoDS_Edge>::const_iterator aEIt = myEdges.begin();
569 for (; aEIt != aEItLast; ++aEIt)
571 aBuilder.Add(aWire, *aEIt);
576 bool HYDROData_TopoCurve::Cut(
577 const std::list<TopoDS_Edge>::iterator& theEdgePosition,
578 const double theParameter,
579 HYDROData_TopoCurve& theCurve)
581 bool aResult = false;
584 std::list<TopoDS_Edge>::iterator aFirstEIt = myEdges.begin();
585 std::list<TopoDS_Edge>::iterator aEIt = aFirstEIt;
586 for (; aEIt != theEdgePosition; ++aEIt);
589 TopoDS_Edge aEdge = *aEIt;
590 BRepAdaptor_Curve aCurve(aEdge);
592 const double aEdgeEndParams[] =
593 {aCurve.FirstParameter(), aCurve.LastParameter()};
594 if (Abs(theParameter - aEdgeEndParams[0]) < Precision::PConfusion())
598 else if (Abs(theParameter - aEdgeEndParams[1]) < Precision::PConfusion())
602 const TopAbs_Orientation aOrient = aEdge.Orientation();
603 if (aOrient == TopAbs_REVERSED)
607 const bool isClosed = IsClosed();
608 DEBTRACE("aParamI: " << aParamI << " isClosed: "<< isClosed);
611 aEdge.Orientation(TopAbs_FORWARD);
612 TopoDS_Vertex aSplitV1, aSplitV2;
613 BRep_Builder().MakeVertex(
614 aSplitV1, aCurve.Value(theParameter), Precision::Confusion());
615 BRep_Builder().MakeVertex(
616 aSplitV2, aCurve.Value(theParameter), Precision::Confusion());
617 TopoDS_Edge aEParts[] = {
618 ShapeBuild_Edge().CopyReplaceVertices(aEdge, TopoDS_Vertex(),
619 TopoDS::Vertex(aSplitV1.Oriented(TopAbs_REVERSED))),
620 ShapeBuild_Edge().CopyReplaceVertices(aEdge, aSplitV2, TopoDS_Vertex())};
621 ShapeBuild_Edge().CopyPCurves(aEParts[0], aEdge);
622 ShapeBuild_Edge().CopyPCurves(aEParts[1], aEdge);
623 BRep_Builder().SameRange(aEParts[0], Standard_False);
624 BRep_Builder().SameRange(aEParts[1], Standard_False);
625 BRep_Builder().SameParameter(aEParts[0], Standard_False);
626 BRep_Builder().SameParameter(aEParts[1], Standard_False);
627 ShapeAnalysis_TransferParametersProj aSATPP(aEdge, TopoDS_Face());
628 aSATPP.SetMaxTolerance(Precision::Confusion());
629 aSATPP.TransferRange(aEParts[0],
630 aEdgeEndParams[0], theParameter, Standard_False);
631 aSATPP.TransferRange(aEParts[1],
632 theParameter, aEdgeEndParams[1], Standard_False);
633 aEParts[0].Orientation(aOrient);
634 aEParts[1].Orientation(aOrient);
636 const int aFirstPI = (aOrient != TopAbs_REVERSED) ? 0 : 1;
637 *aEIt = aEParts[aFirstPI];
638 InsertAfter(aEIt, aEParts[1 - aFirstPI], myEdges);
645 TopoDS_Edge aNewEdge = ReplaceVertex(aEdge, (aParamI == 0) ? false : true);
651 std::list<TopoDS_Edge>::iterator aEdgePosition = theEdgePosition;
652 if (isClosed || ++aEdgePosition != myEdges.end())
659 if (isClosed || theEdgePosition != aFirstEIt)
666 // Calculate the curve parts.
667 std::list<TopoDS_Edge>::iterator aLastEIt = myEdges.end();
668 if (aEIt != aFirstEIt && aEIt != aLastEIt)
670 std::list<TopoDS_Edge>* aEdges = !isClosed ? &theCurve.myEdges : &myEdges;
671 aEdges->splice(aEdges->begin(), myEdges, aEIt, aLastEIt);
677 void HYDROData_TopoCurve::Cut(
678 const std::list<TopoDS_Edge>::const_iterator& theEdgePosition,
679 const double theParameter,
680 HYDROData_TopoCurve& theCurve1,
681 HYDROData_TopoCurve& theCurve2) const
684 std::list<TopoDS_Edge>::const_iterator aEPos = myEdges.begin();
685 std::list<TopoDS_Edge>::iterator aEPos1 = theCurve1.myEdges.begin();
686 for (; aEPos != theEdgePosition; ++aEPos1, ++aEPos);
687 theCurve1.Cut(aEPos1, theParameter, theCurve2);
690 bool HYDROData_TopoCurve::Cut(
691 const std::deque<std::list<double> >& theParameters,
692 std::deque<HYDROData_TopoCurve>& theCurves) const
694 bool aResult = false;
695 HYDROData_TopoCurve aCurves[2];
698 std::list<TopoDS_Edge>::iterator aEIt = aCurves[0].myEdges.begin();
699 std::deque<std::list<double> >::const_iterator aPLIt = theParameters.begin();
700 for (std::deque<std::list<double> >::const_iterator aLastPLIt =
701 theParameters.end(); aPLIt != aLastPLIt; ++aPLIt)
703 TopoDS_Edge aNextEdge;
705 std::list<TopoDS_Edge>::iterator aNextEIt = aEIt;
707 if (aNextEIt != aCurves[aCI].myEdges.end())
709 aNextEdge = *aNextEIt;
713 for (Iterator<std::list<double>, std::list<double>::const_iterator> aPIt(
714 *aPLIt, (aEIt->Orientation() != TopAbs_REVERSED)); aPIt.More(); ++aPIt)
716 const int aCI1 = 1 - aCI;
717 aResult |= aCurves[aCI].Cut(aEIt, **aPIt, aCurves[aCI1]);
718 if (!aCurves[aCI1].IsEmpty())
720 theCurves.push_back(HYDROData_TopoCurve());
721 theCurves.back().append(aCurves[aCI]);
722 aEIt = aCurves[aCI1].myEdges.begin();
727 aEIt = aCurves[aCI].myEdges.begin();
731 if (!aNextEdge.IsNull() && !aEIt->IsEqual(aNextEdge))
736 theCurves.push_back(aCurves[aCI]);
740 double HYDROData_TopoCurve::Project(
741 const gp_XYZ& thePoint,
742 std::list<TopoDS_Edge>::const_iterator& theEdgeIterator,
743 double& theParameter) const
745 double aMinSqDist = DBL_MAX;
746 std::list<TopoDS_Edge>::const_iterator aEIt = myEdges.begin();
747 std::list<TopoDS_Edge>::const_iterator aLastEIt = myEdges.end();
748 for (; aEIt != aLastEIt; ++aEIt)
751 const double aSqDist = ProjectPointToEdge(thePoint, *aEIt, aParam);
752 if (aMinSqDist > aSqDist)
754 aMinSqDist = aSqDist;
755 theEdgeIterator = aEIt;
756 theParameter = aParam;
762 int HYDROData_TopoCurve::Intersect(
763 const TopoDS_Wire& theWire,
764 std::deque<std::list<double> >& theParameters) const
766 std::string brepName = "theWireTool";
768 BRepTools::Write( theWire, brepName.c_str() );
771 theParameters.resize(myEdges.size());
772 DEBTRACE("myEdges.size() " << myEdges.size());
773 std::list<TopoDS_Edge>::const_iterator aEIt = myEdges.begin();
774 std::list<TopoDS_Edge>::const_iterator aLastEIt = myEdges.end();
775 std::deque<std::list<double> >::iterator aPIt = theParameters.begin();
776 for (; aEIt != aLastEIt; ++aPIt, ++aEIt)
779 const TopoDS_Edge& aEdge = *aEIt;
780 std::list<double>& aParams = *aPIt;
781 TopExp_Explorer aEIt2(theWire, TopAbs_EDGE);
782 for (; aEIt2.More(); aEIt2.Next())
784 aIntCount += IntersectEdge(aEdge,TopoDS::Edge(aEIt2.Current()), aParams);
785 DEBTRACE("aParams.size() " << aParams.size());
788 DEBTRACE("aIntCount " << aIntCount);
792 void HYDROData_TopoCurve::CloseCurve()
794 const TopoDS_Vertex aVertex = TopoDS::Vertex(TopExp::LastVertex(
795 myEdges.back(), Standard_True).Oriented(TopAbs_FORWARD));
796 TopoDS_Edge& aEdge = myEdges.front();
797 const TopoDS_Edge aForwardEdge = TopoDS::Edge(aEdge.Oriented(TopAbs_FORWARD));
798 aEdge = TopoDS::Edge(ShapeBuild_Edge().CopyReplaceVertices(
799 aForwardEdge, aVertex, TopoDS_Vertex()).Oriented(aEdge.Orientation()));
802 void HYDROData_TopoCurve::Merge(
803 const int thePosition, HYDROData_TopoCurve& theCurve)
805 if (thePosition == 0)
807 const TopoDS_Vertex aVertex = TopoDS::Vertex(TopExp::LastVertex(
808 theCurve.myEdges.back(), Standard_True).Oriented(TopAbs_FORWARD));
809 TopoDS_Edge& aEdge = myEdges.front();
810 aEdge = TopoDS::Edge(ShapeBuild_Edge().CopyReplaceVertices(
811 TopoDS::Edge(aEdge.Oriented(TopAbs_FORWARD)), aVertex, TopoDS_Vertex()).
812 Oriented(aEdge.Orientation()));
817 const TopoDS_Vertex aVertex = TopoDS::Vertex(TopExp::FirstVertex(
818 theCurve.myEdges.front(), Standard_True).Oriented(TopAbs_REVERSED));
819 TopoDS_Edge& aEdge = myEdges.back();
820 aEdge = TopoDS::Edge(ShapeBuild_Edge().CopyReplaceVertices(
821 TopoDS::Edge(aEdge.Oriented(TopAbs_FORWARD)), TopoDS_Vertex(), aVertex).
822 Oriented(aEdge.Orientation()));
827 void HYDROData_TopoCurve::Merge(
828 const double theTolerance, std::deque<HYDROData_TopoCurve>& theCurves)
830 // Process the curve closeness.
831 const double aSqTol = theTolerance * theTolerance;
832 const gp_XYZ aPs[] = {
833 BRep_Tool::Pnt(TopExp::FirstVertex(myEdges.front(), Standard_True)).XYZ(),
834 BRep_Tool::Pnt(TopExp::LastVertex(myEdges.back(), Standard_True)).XYZ()};
835 bool isClosed = IsClosed();
836 if (!isClosed && (aPs[0] - aPs[1]).SquareModulus() <= aSqTol)
842 // Find the merge places.
843 HYDROData_TopoCurve* aCurves[] = {NULL, NULL};
847 std::deque<HYDROData_TopoCurve>::iterator aCIt = theCurves.begin();
848 std::deque<HYDROData_TopoCurve>::iterator aLastCIt = theCurves.end();
849 for (; aCIt != aLastCIt; ++aCIt)
851 HYDROData_TopoCurve& aCurve = *aCIt;
852 if (aCurve.IsEmpty() || aCurve.IsClosed())
857 const gp_XYZ aP1 = BRep_Tool::Pnt(
858 TopExp::FirstVertex(aCurve.myEdges.front(), Standard_True)).XYZ();
859 if (aCurves[0] == NULL && (aPs[1] - aP1).SquareModulus() <= aSqTol)
861 aCurves[0] = &aCurve;
864 const gp_XYZ aP2 = BRep_Tool::Pnt(
865 TopExp::LastVertex(aCurve.myEdges.back(), Standard_True)).XYZ();
866 if (aCurves[1] == NULL && (aPs[0] - aP2).SquareModulus() <= aSqTol)
868 aCurves[1] = &aCurve;
869 aOrder = (aCurves[0] == NULL) ? 1 : 0;
874 if (aCurves[0] == NULL && aCurves[1] == NULL)
876 theCurves.push_back(HYDROData_TopoCurve());
877 theCurves.back().append(*this);
879 else if (aCurves[1] == NULL)
881 aCurves[0]->Merge(0, *this);
883 else if (aCurves[0] == NULL)
885 aCurves[1]->Merge(1, *this);
889 aCurves[aOrder]->Merge(aOrder, *this);
890 if (aCurves[0] != aCurves[1])
892 aCurves[aOrder]->Merge(aOrder, *aCurves[1 - aOrder]);
896 aCurves[aOrder]->CloseCurve();
901 bool HYDROData_TopoCurve::Connect(
902 const Standard_Real theTolerance, std::deque<HYDROData_TopoCurve>& theCurves)
904 const double aSqTol = theTolerance * theTolerance;
905 const gp_XYZ aPs[] = {
906 BRep_Tool::Pnt(TopExp::FirstVertex(myEdges.front(), Standard_True)).XYZ(),
907 BRep_Tool::Pnt(TopExp::LastVertex(myEdges.back(), Standard_True)).XYZ()};
908 bool isClosed = IsClosed();
909 if (!isClosed && (aPs[0] - aPs[1]).SquareModulus() <= aSqTol)
917 std::deque<HYDROData_TopoCurve>::iterator aCIt = theCurves.begin();
918 std::deque<HYDROData_TopoCurve>::iterator aLastCIt = theCurves.end();
919 for (; aCIt != aLastCIt; ++aCIt)
921 HYDROData_TopoCurve& aCurve2 = *aCIt;
922 if (aCurve2.IsEmpty() || aCurve2.IsClosed())
927 const TopoDS_Edge* aEdges2[] =
928 {&aCurve2.myEdges.front(), &aCurve2.myEdges.back()};
929 const gp_XYZ aPs2[] = {
930 BRep_Tool::Pnt(TopExp::FirstVertex(*aEdges2[0], Standard_True)).XYZ(),
931 BRep_Tool::Pnt(TopExp::LastVertex(*aEdges2[1], Standard_True)).XYZ()};
932 const double aSqDists[] =
933 {(aPs[1] - aPs2[0]).SquareModulus(), (aPs[0] - aPs2[1]).SquareModulus()};
934 const int aOrder = (aSqDists[0] <= aSqDists[1]) ? 0 : 1;
935 if (aSqDists[aOrder] > aSqTol)
937 const TopoDS_Edge& aEdge =
938 (aOrder == 0) ? myEdges.back() : myEdges.front();
939 const gp_XYZ aPs3[] = {aPs[1 - aOrder], aPs2[aOrder]};
941 {Tangent(aEdge, 1 - aOrder), Tangent(*aEdges2[aOrder], aOrder)};
942 Handle(Geom_BSplineCurve) aBSpline;
943 if (!Interpolate(aPs3[aOrder], aPs3[1 - aOrder],
944 aTs[aOrder], aTs[1 - aOrder], aBSpline))
949 HYDROData_TopoCurve aECurve = BRepBuilderAPI_MakeEdge(aBSpline).Edge();
950 aCurve2.Merge(aOrder, aECurve);
952 aCurve2.Merge(aOrder, *this);
953 if (aSqDists[1 - aOrder] <= aSqTol)
955 aCurve2.CloseCurve();
961 theCurves.push_back(HYDROData_TopoCurve());
962 theCurves.back().append(*this);
966 int HYDROData_TopoCurve::BSplinePiecewiseCurve(
967 const double theDeflection, HYDROData_TopoCurve& theCurve) const
970 std::list<TopoDS_Edge>::const_iterator aLastEIt = myEdges.end();
971 std::list<TopoDS_Edge>::const_iterator aEIt = myEdges.begin();
972 TopoDS_Vertex aEndVertex;
973 TopoDS_Edge aPrevEdge;
974 for (; aEIt != aLastEIt; ++aEIt)
976 Handle(Geom_BSplineCurve) aBSpline =
977 ::BSpline(BRepAdaptor_Curve(*aEIt), theDeflection);
978 if (aBSpline.IsNull())
983 if (aEIt->Orientation() == TopAbs_REVERSED)
989 BRep_Builder().MakeEdge(aEdge, aBSpline, Precision::Confusion());
990 TopoDS_Vertex aVertex;
991 BRep_Builder().MakeVertex(aVertex,
992 aBSpline->Value(aBSpline->FirstParameter()), Precision::Confusion());
993 if (!aPrevEdge.IsNull())
995 BRep_Builder().Add(aPrevEdge, aVertex.Oriented(TopAbs_REVERSED));
999 aEndVertex = aVertex;
1001 BRep_Builder().Add(aEdge, aVertex);
1002 theCurve.myEdges.push_back(aEdge);
1003 aPieceCount += aBSpline->NbKnots() - 1;
1009 BRepAdaptor_Curve aCurve(aPrevEdge);
1010 BRep_Builder().MakeVertex(aEndVertex,
1011 aCurve.Value(aCurve.LastParameter()), Precision::Confusion());
1013 BRep_Builder().Add(aPrevEdge, aEndVertex.Oriented(TopAbs_REVERSED));
1017 bool HYDROData_TopoCurve::ValuesInKnots(std::list<gp_XYZ>& theValues) const
1019 std::list<TopoDS_Edge>::const_iterator aLastEIt = myEdges.end();
1020 std::list<TopoDS_Edge>::const_iterator aEIt = myEdges.begin();
1021 for (; aEIt != aLastEIt; ++aEIt)
1023 Handle(Geom_BSplineCurve) aCurve;
1025 TopLoc_Location aLoc;
1027 aCurve = Handle(Geom_BSplineCurve)::
1028 DownCast(BRep_Tool::Curve(*aEIt, aLoc, aParams[0], aParams[1]));
1029 if (!aLoc.IsIdentity() || aEIt->Orientation() != TopAbs_FORWARD ||
1036 for (int aNbKnots = aCurve->NbKnots(), aKN = 1; aKN < aNbKnots; ++aKN)
1038 theValues.push_back(aCurve->Value(aCurve->Knot(aKN)).XYZ());
1044 TopLoc_Location aLoc;
1046 Handle(Geom_Curve) aCurve =
1047 BRep_Tool::Curve(myEdges.back(), aLoc, aParams[0], aParams[1]);
1048 theValues.push_back(aCurve->Value(aParams[1]).XYZ());