1 // Created on: 2014-10-14
2 // Created by: Anton POLETAEV
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <StdPrs_Isolines.hxx>
18 #include <Adaptor3d_IsoCurve.hxx>
19 #include <Bnd_Range.hxx>
20 #include <BRepTools.hxx>
21 #include <BRep_Tool.hxx>
22 #include <GCPnts_AbscissaPoint.hxx>
23 #include <GCPnts_QuasiUniformDeflection.hxx>
24 #include <Geom_BezierSurface.hxx>
25 #include <Geom_BSplineSurface.hxx>
26 #include <Geom_Plane.hxx>
27 #include <Geom_Line.hxx>
28 #include <Geom2d_Line.hxx>
29 #include <Geom2dAdaptor_Curve.hxx>
30 #include <GeomAdaptor_Curve.hxx>
31 #include <GeomLib_Tool.hxx>
32 #include <gp_Lin2d.hxx>
33 #include <Hatch_Hatcher.hxx>
34 #include <NCollection_Shared.hxx>
36 #include <Prs3d_IsoAspect.hxx>
37 #include <Poly_Array1OfTriangle.hxx>
38 #include <Poly_Triangulation.hxx>
39 #include <StdPrs_DeflectionCurve.hxx>
40 #include <StdPrs_ToolRFace.hxx>
41 #include <TColgp_SequenceOfPnt2d.hxx>
42 #include <Standard_ErrorHandler.hxx>
43 #include <Geom_Surface.hxx>
44 #include <Geom_OffsetSurface.hxx>
45 #include <Geom_RectangularTrimmedSurface.hxx>
50 const gp_Lin2d isoU (const Standard_Real theU) { return gp_Lin2d (gp_Pnt2d (theU, 0.0), gp::DY2d()); }
51 const gp_Lin2d isoV (const Standard_Real theV) { return gp_Lin2d (gp_Pnt2d (0.0, theV), gp::DX2d()); }
53 typedef NCollection_Shared< NCollection_Vector<StdPrs_Isolines::SegOnIso> > VecOfSegments;
54 typedef NCollection_Sequence<Handle(VecOfSegments)> SeqOfVecOfSegments;
56 //! Pack isoline segments into polylines.
57 static void sortSegments (const SeqOfVecOfSegments& theSegments,
58 Prs3d_NListOfSequenceOfPnt& thePolylines)
60 for (SeqOfVecOfSegments::Iterator aLineIter (theSegments); aLineIter.More(); aLineIter.Next())
62 Handle(VecOfSegments)& anIsoSegs = aLineIter.ChangeValue();
63 std::stable_sort (anIsoSegs->begin(), anIsoSegs->end());
65 Handle(TColgp_HSequenceOfPnt) aPolyline = new TColgp_HSequenceOfPnt();
66 thePolylines.Append (aPolyline);
67 Standard_Real aLast = 0.0;
68 for (VecOfSegments::Iterator aSegIter (*anIsoSegs); aSegIter.More(); aSegIter.Next())
70 if (!aPolyline->IsEmpty()
71 && Abs (aSegIter.Value()[0].Param - aLast) > Precision::PConfusion())
73 aPolyline = new TColgp_HSequenceOfPnt();
74 thePolylines.Append (aPolyline);
77 aPolyline->Append (aSegIter.Value()[0].Pnt);
78 aPolyline->Append (aSegIter.Value()[1].Pnt);
79 aLast = aSegIter.Value()[1].Param;
84 //! Reoder and adjust to the limit a curve's parameter values.
85 //! @param theCurve [in] the curve.
86 //! @param theLimit [in] the parameter limit value.
87 //! @param theFirst [in/out] the first parameter value.
88 //! @param theLast [in/out] the last parameter value.
89 static void findLimits (const Adaptor3d_Curve& theCurve,
90 const Standard_Real theLimit,
91 Standard_Real& theFirst,
92 Standard_Real& theLast)
94 theFirst = Max (theCurve.FirstParameter(), theFirst);
95 theLast = Min (theCurve.LastParameter(), theLast);
97 Standard_Boolean isFirstInf = Precision::IsNegativeInfinite (theFirst);
98 Standard_Boolean isLastInf = Precision::IsPositiveInfinite (theLast);
100 if (!isFirstInf && !isLastInf)
106 Standard_Real aDelta = 1.0;
107 if (isFirstInf && isLastInf)
114 theCurve.D0 (theFirst, aP1);
115 theCurve.D0 (theLast, aP2);
117 while (aP1.Distance (aP2) < theLimit);
121 theCurve.D0 (theLast, aP2);
125 theFirst = theLast - aDelta;
126 theCurve.D0 (theFirst, aP1);
128 while (aP1.Distance (aP2) < theLimit);
132 theCurve.D0 (theFirst, aP1);
136 theLast = theFirst + aDelta;
137 theCurve.D0 (theLast, aP2);
139 while (aP1.Distance (aP2) < theLimit);
145 //==================================================================
146 // function : AddOnTriangulation
148 //==================================================================
149 void StdPrs_Isolines::AddOnTriangulation (const Handle(Prs3d_Presentation)& thePresentation,
150 const TopoDS_Face& theFace,
151 const Handle(Prs3d_Drawer)& theDrawer)
153 Prs3d_NListOfSequenceOfPnt aUPolylines, aVPolylines;
154 AddOnTriangulation (theFace, theDrawer, aUPolylines, aVPolylines);
155 Prs3d::AddPrimitivesGroup (thePresentation, theDrawer->UIsoAspect(), aUPolylines);
156 Prs3d::AddPrimitivesGroup (thePresentation, theDrawer->VIsoAspect(), aVPolylines);
159 //==================================================================
160 // function : AddOnTriangulation
162 //==================================================================
163 void StdPrs_Isolines::AddOnTriangulation (const TopoDS_Face& theFace,
164 const Handle(Prs3d_Drawer)& theDrawer,
165 Prs3d_NListOfSequenceOfPnt& theUPolylines,
166 Prs3d_NListOfSequenceOfPnt& theVPolylines)
168 const Standard_Integer aNbIsoU = theDrawer->UIsoAspect()->Number();
169 const Standard_Integer aNbIsoV = theDrawer->VIsoAspect()->Number();
170 if (aNbIsoU < 1 && aNbIsoV < 1)
175 // Evaluate parameters for uv isolines.
176 TColStd_SequenceOfReal aUIsoParams;
177 TColStd_SequenceOfReal aVIsoParams;
178 Standard_Real aUmin = 0., aUmax = 0., aVmin = 0., aVmax = 0.;
179 UVIsoParameters (theFace, aNbIsoU, aNbIsoV, theDrawer->MaximalParameterValue(), aUIsoParams, aVIsoParams,
180 aUmin, aUmax, aVmin, aVmax);
182 // Access surface definition.
183 TopLoc_Location aLocSurface;
184 Handle(Geom_Surface) aSurface = BRep_Tool::Surface (theFace, aLocSurface);
185 if (aSurface.IsNull())
190 // Access triangulation.
191 TopLoc_Location aLocTriangulation;
192 const Handle(Poly_Triangulation)& aTriangulation = BRep_Tool::Triangulation (theFace, aLocTriangulation);
193 if (aTriangulation.IsNull())
198 // Setup equal location for surface and triangulation.
199 if (!aLocTriangulation.IsEqual (aLocSurface))
201 aSurface = Handle (Geom_Surface)::DownCast (
202 aSurface->Transformed ((aLocSurface / aLocTriangulation).Transformation()));
205 const Handle(Standard_Type)& TheType = aSurface->DynamicType();
206 if (TheType == STANDARD_TYPE(Geom_OffsetSurface))
208 Standard_Real u1, u2, v1, v2;
209 aSurface->Bounds(u1, u2, v1, v2);
210 //Isolines of Offset surfaces are calculated by approximation and
211 //cannot be calculated for infinite limits.
212 if (Precision::IsInfinite(u1) || Precision::IsInfinite(u2) ||
213 Precision::IsInfinite(v1) || Precision::IsInfinite(v2))
219 aSurface = new Geom_RectangularTrimmedSurface(aSurface, u1, u2, v1, v2);
223 addOnTriangulation (aTriangulation, aSurface, aLocTriangulation, aUIsoParams, aVIsoParams, theUPolylines, theVPolylines);
226 //==================================================================
227 // function : AddOnTriangulation
229 //==================================================================
230 void StdPrs_Isolines::AddOnTriangulation (const Handle(Prs3d_Presentation)& thePresentation,
231 const Handle(Poly_Triangulation)& theTriangulation,
232 const Handle(Geom_Surface)& theSurface,
233 const TopLoc_Location& theLocation,
234 const Handle(Prs3d_Drawer)& theDrawer,
235 const TColStd_SequenceOfReal& theUIsoParams,
236 const TColStd_SequenceOfReal& theVIsoParams)
238 Prs3d_NListOfSequenceOfPnt aUPolylines, aVPolylines;
239 addOnTriangulation (theTriangulation, theSurface, theLocation, theUIsoParams, theVIsoParams, aUPolylines, aVPolylines);
240 Prs3d::AddPrimitivesGroup (thePresentation, theDrawer->UIsoAspect(), aUPolylines);
241 Prs3d::AddPrimitivesGroup (thePresentation, theDrawer->VIsoAspect(), aVPolylines);
244 //==================================================================
245 // function : addOnTriangulation
247 //==================================================================
248 void StdPrs_Isolines::addOnTriangulation (const Handle(Poly_Triangulation)& theTriangulation,
249 const Handle(Geom_Surface)& theSurface,
250 const TopLoc_Location& theLocation,
251 const TColStd_SequenceOfReal& theUIsoParams,
252 const TColStd_SequenceOfReal& theVIsoParams,
253 Prs3d_NListOfSequenceOfPnt& theUPolylines,
254 Prs3d_NListOfSequenceOfPnt& theVPolylines)
256 const Poly_Array1OfTriangle& aTriangles = theTriangulation->Triangles();
257 const TColgp_Array1OfPnt& aNodes = theTriangulation->Nodes();
258 const TColgp_Array1OfPnt2d& aUVNodes = theTriangulation->UVNodes();
259 for (Standard_Integer anUVIter = 0; anUVIter < 2; ++anUVIter)
261 const Standard_Boolean isUIso = anUVIter == 0;
262 const TColStd_SequenceOfReal& anIsoParams = isUIso ? theUIsoParams : theVIsoParams;
263 const Standard_Integer aNbIsolines = anIsoParams.Length();
264 if (aNbIsolines == 0)
269 SeqOfVecOfSegments aPolylines;
270 TColStd_Array1OfInteger anIsoIndexes (1, aNbIsolines);
271 anIsoIndexes.Init (-1);
272 for (Standard_Integer anIsoIdx = 1; anIsoIdx <= aNbIsolines; ++anIsoIdx)
274 const gp_Lin2d anIsolineUV = isUIso ? isoU (anIsoParams.Value (anIsoIdx)) : isoV (anIsoParams.Value (anIsoIdx));
275 Handle(VecOfSegments) anIsoPnts;
276 if (anIsoIndexes.Value (anIsoIdx) != -1)
278 anIsoPnts = aPolylines.ChangeValue (anIsoIndexes.Value (anIsoIdx));
281 for (Standard_Integer aTriIter = aTriangles.Lower(); aTriIter <= aTriangles.Upper(); ++aTriIter)
283 Standard_Integer aNodeIdxs[3];
284 aTriangles.Value (aTriIter).Get (aNodeIdxs[0], aNodeIdxs[1],aNodeIdxs[2]);
285 const gp_Pnt aNodesXYZ[3] = { aNodes.Value (aNodeIdxs[0]),
286 aNodes.Value (aNodeIdxs[1]),
287 aNodes.Value (aNodeIdxs[2]) };
288 const gp_Pnt2d aNodesUV[3] = { aUVNodes.Value (aNodeIdxs[0]),
289 aUVNodes.Value (aNodeIdxs[1]),
290 aUVNodes.Value (aNodeIdxs[2]) };
292 // Find intersections with triangle in uv space and its projection on triangulation.
294 if (!findSegmentOnTriangulation (theSurface, isUIso, anIsolineUV, aNodesXYZ, aNodesUV, aSegment))
299 if (anIsoPnts.IsNull())
301 aPolylines.Append (new VecOfSegments());
302 anIsoIndexes.SetValue (anIsoIdx, aPolylines.Size());
303 anIsoPnts = aPolylines.ChangeValue (anIsoIndexes.Value (anIsoIdx));
306 if (!theLocation.IsIdentity())
308 aSegment[0].Pnt.Transform (theLocation);
309 aSegment[1].Pnt.Transform (theLocation);
311 anIsoPnts->Append (aSegment);
315 sortSegments (aPolylines, isUIso ? theUPolylines : theVPolylines);
319 //==================================================================
320 // function : AddOnSurface
322 //==================================================================
323 void StdPrs_Isolines::AddOnSurface (const Handle(Prs3d_Presentation)& thePresentation,
324 const TopoDS_Face& theFace,
325 const Handle(Prs3d_Drawer)& theDrawer,
326 const Standard_Real theDeflection)
328 Prs3d_NListOfSequenceOfPnt aUPolylines, aVPolylines;
329 AddOnSurface (theFace, theDrawer, theDeflection, aUPolylines, aVPolylines);
330 Prs3d::AddPrimitivesGroup (thePresentation, theDrawer->UIsoAspect(), aUPolylines);
331 Prs3d::AddPrimitivesGroup (thePresentation, theDrawer->VIsoAspect(), aVPolylines);
334 //==================================================================
335 // function : AddOnSurface
337 //==================================================================
338 void StdPrs_Isolines::AddOnSurface (const TopoDS_Face& theFace,
339 const Handle(Prs3d_Drawer)& theDrawer,
340 const Standard_Real theDeflection,
341 Prs3d_NListOfSequenceOfPnt& theUPolylines,
342 Prs3d_NListOfSequenceOfPnt& theVPolylines)
344 const Standard_Integer aNbIsoU = theDrawer->UIsoAspect()->Number();
345 const Standard_Integer aNbIsoV = theDrawer->VIsoAspect()->Number();
346 if (aNbIsoU < 1 && aNbIsoV < 1)
351 // Evaluate parameters for uv isolines.
352 TColStd_SequenceOfReal aUIsoParams, aVIsoParams;
353 Standard_Real aUmin = 0., aUmax = 0., aVmin = 0., aVmax = 0.;
354 UVIsoParameters (theFace, aNbIsoU, aNbIsoV, theDrawer->MaximalParameterValue(), aUIsoParams, aVIsoParams,
355 aUmin, aUmax, aVmin, aVmax);
357 BRepAdaptor_Surface aSurface (theFace);
358 addOnSurface (new BRepAdaptor_Surface (aSurface),
367 //==================================================================
368 // function : AddOnSurface
370 //==================================================================
371 void StdPrs_Isolines::AddOnSurface (const Handle(Prs3d_Presentation)& thePresentation,
372 const Handle(BRepAdaptor_Surface)& theSurface,
373 const Handle(Prs3d_Drawer)& theDrawer,
374 const Standard_Real theDeflection,
375 const TColStd_SequenceOfReal& theUIsoParams,
376 const TColStd_SequenceOfReal& theVIsoParams)
378 Prs3d_NListOfSequenceOfPnt aUPolylines, aVPolylines;
379 addOnSurface (theSurface, theDrawer, theDeflection, theUIsoParams, theVIsoParams, aUPolylines, aVPolylines);
380 Prs3d::AddPrimitivesGroup (thePresentation, theDrawer->UIsoAspect(), aUPolylines);
381 Prs3d::AddPrimitivesGroup (thePresentation, theDrawer->VIsoAspect(), aVPolylines);
384 //==================================================================
385 // function : addOnSurface
387 //==================================================================
388 void StdPrs_Isolines::addOnSurface (const Handle(BRepAdaptor_Surface)& theSurface,
389 const Handle(Prs3d_Drawer)& theDrawer,
390 const Standard_Real theDeflection,
391 const TColStd_SequenceOfReal& theUIsoParams,
392 const TColStd_SequenceOfReal& theVIsoParams,
393 Prs3d_NListOfSequenceOfPnt& theUPolylines,
394 Prs3d_NListOfSequenceOfPnt& theVPolylines)
396 // Choose a deflection for sampling edge uv curves.
397 Standard_Real aUVLimit = theDrawer->MaximalParameterValue();
398 Standard_Real aUmin = Max (theSurface->FirstUParameter(), -aUVLimit);
399 Standard_Real aUmax = Min (theSurface->LastUParameter(), aUVLimit);
400 Standard_Real aVmin = Max (theSurface->FirstVParameter(), -aUVLimit);
401 Standard_Real aVmax = Min (theSurface->LastVParameter(), aUVLimit);
402 Standard_Real aSamplerDeflection = Max (aUmax - aUmin, aVmax - aVmin) * theDrawer->DeviationCoefficient();
403 Standard_Real aHatchingTolerance = RealLast();
408 // Determine edge points for trimming uv hatch region.
409 TColgp_SequenceOfPnt2d aTrimPoints;
410 StdPrs_ToolRFace anEdgeTool (theSurface);
411 for (anEdgeTool.Init(); anEdgeTool.More(); anEdgeTool.Next())
413 TopAbs_Orientation anOrientation = anEdgeTool.Orientation();
414 const Adaptor2d_Curve2d* anEdgeCurve = &anEdgeTool.Value();
415 if (anEdgeCurve->GetType() != GeomAbs_Line)
417 GCPnts_QuasiUniformDeflection aSampler (*anEdgeCurve, aSamplerDeflection);
418 if (!aSampler.IsDone())
421 std::cout << "Cannot evaluate curve on surface" << std::endl;
426 Standard_Integer aNumberOfPoints = aSampler.NbPoints();
427 if (aNumberOfPoints < 2)
432 for (Standard_Integer anI = 1; anI < aNumberOfPoints; ++anI)
434 gp_Pnt2d aP1 (aSampler.Value (anI ).X(), aSampler.Value (anI ).Y());
435 gp_Pnt2d aP2 (aSampler.Value (anI + 1).X(), aSampler.Value (anI + 1).Y());
437 aHatchingTolerance = Min (aP1.SquareDistance (aP2), aHatchingTolerance);
439 aTrimPoints.Append (anOrientation == TopAbs_FORWARD ? aP1 : aP2);
440 aTrimPoints.Append (anOrientation == TopAbs_FORWARD ? aP2 : aP1);
445 Standard_Real aU1 = anEdgeCurve->FirstParameter();
446 Standard_Real aU2 = anEdgeCurve->LastParameter();
448 // MSV 17.08.06 OCC13144: U2 occured less than U1, to overcome it
449 // ensure that distance U2-U1 is not greater than aLimit*2,
450 // if greater then choose an origin and use aLimit to define
452 Standard_Real anOrigin = 0.0;
454 if (!Precision::IsNegativeInfinite (aU1) || !Precision::IsPositiveInfinite(aU2))
456 if (Precision::IsNegativeInfinite (aU1))
458 anOrigin = aU2 - aUVLimit;
460 else if (Precision::IsPositiveInfinite (aU2))
462 anOrigin = aU1 + aUVLimit;
466 anOrigin = (aU1 + aU2) * 0.5;
470 aU1 = Max (anOrigin - aUVLimit, aU1);
471 aU2 = Min (anOrigin + aUVLimit, aU2);
473 gp_Pnt2d aP1 = anEdgeCurve->Value (aU1);
474 gp_Pnt2d aP2 = anEdgeCurve->Value (aU2);
476 aHatchingTolerance = Min (aP1.SquareDistance(aP2), aHatchingTolerance);
478 aTrimPoints.Append (anOrientation == TopAbs_FORWARD ? aP1 : aP2);
479 aTrimPoints.Append (anOrientation == TopAbs_FORWARD ? aP2 : aP1);
483 // re-calculate UV-range basing on p-curves tessellation
484 Bnd_Range aTrimU, aTrimV;
485 for (Standard_Integer anI = 1; anI <= aTrimPoints.Length(); ++anI)
487 const gp_Pnt2d& aTrimPnt = aTrimPoints.Value (anI);
488 aTrimU.Add (aTrimPnt.X());
489 aTrimV.Add (aTrimPnt.Y());
491 // ignore p-curves tessellation under sampler deflection - it might clamp range
492 if (!aTrimU.IsVoid() && aTrimU.Delta() <= aSamplerDeflection)
496 if (!aTrimV.IsVoid() && aTrimV.Delta() <= aSamplerDeflection)
501 // Compute a hatching tolerance.
502 aHatchingTolerance *= 0.1;
503 aHatchingTolerance = Max (Precision::Confusion(), aHatchingTolerance);
504 aHatchingTolerance = Min (1.0E-5, aHatchingTolerance);
506 // Load isolines into hatcher.
507 Hatch_Hatcher aHatcher (aHatchingTolerance, anEdgeTool.IsOriented());
509 for (Standard_Integer anIso = 1; anIso <= theUIsoParams.Length(); ++anIso)
511 const Standard_Real anIsoParamU = theUIsoParams.Value (anIso);
513 || !aTrimU.IsOut (anIsoParamU))
515 aHatcher.AddXLine (anIsoParamU);
518 for (Standard_Integer anIso = 1; anIso <= theVIsoParams.Length(); ++anIso)
520 const Standard_Real anIsoParamV = theVIsoParams.Value (anIso);
522 || !aTrimV.IsOut (anIsoParamV))
524 aHatcher.AddYLine (anIsoParamV);
528 // Trim hatching region.
529 for (Standard_Integer anI = 1; anI <= aTrimPoints.Length(); anI += 2)
531 aHatcher.Trim (aTrimPoints (anI), aTrimPoints (anI + 1));
534 // Use surface definition for evaluation of Bezier, B-spline surface.
535 // Use isoline adapter for other types of surfaces.
536 GeomAbs_SurfaceType aSurfType = theSurface->GetType();
537 Handle(Geom_Surface) aBSurface;
538 GeomAdaptor_Curve aBSurfaceCurve;
539 Adaptor3d_IsoCurve aCanonicalCurve;
540 if (aSurfType == GeomAbs_BezierSurface)
542 aBSurface = theSurface->Bezier();
544 else if (aSurfType == GeomAbs_BSplineSurface)
546 aBSurface = theSurface->BSpline();
550 aCanonicalCurve.Load (theSurface);
553 // For each isoline: compute its segments.
554 for (Standard_Integer anI = 1; anI <= aHatcher.NbLines(); anI++)
556 Standard_Real anIsoParam = aHatcher.Coordinate (anI);
557 Standard_Boolean isIsoU = aHatcher.IsXLine (anI);
559 // For each isoline's segment: evaluate its points.
560 for (Standard_Integer aJ = 1; aJ <= aHatcher.NbIntervals (anI); aJ++)
562 Standard_Real aSegmentP1 = aHatcher.Start (anI, aJ);
563 Standard_Real aSegmentP2 = aHatcher.End (anI, aJ);
565 if (!aBSurface.IsNull())
567 aBSurfaceCurve.Load (isIsoU ? aBSurface->UIso (anIsoParam) : aBSurface->VIso (anIsoParam));
569 findLimits (aBSurfaceCurve, aUVLimit, aSegmentP1, aSegmentP2);
571 if (aSegmentP2 - aSegmentP1 <= Precision::Confusion())
578 aCanonicalCurve.Load (isIsoU ? GeomAbs_IsoU : GeomAbs_IsoV, anIsoParam, aSegmentP1, aSegmentP2);
580 findLimits (aCanonicalCurve, aUVLimit, aSegmentP1, aSegmentP2);
582 if (aSegmentP2 - aSegmentP1 <= Precision::Confusion())
587 Adaptor3d_Curve* aCurve = aBSurface.IsNull() ? (Adaptor3d_Curve*) &aCanonicalCurve
588 : (Adaptor3d_Curve*) &aBSurfaceCurve;
590 Handle(TColgp_HSequenceOfPnt) aPoints = new TColgp_HSequenceOfPnt();
591 StdPrs_DeflectionCurve::Add (Handle(Prs3d_Presentation)(),
596 aPoints->ChangeSequence(),
597 theDrawer->DeviationAngle(),
599 if (aPoints->IsEmpty())
606 theUPolylines.Append (aPoints);
610 theVPolylines.Append (aPoints);
615 catch (Standard_Failure const&)
621 //==================================================================
622 // function : UVIsoParameters
624 //==================================================================
625 void StdPrs_Isolines::UVIsoParameters (const TopoDS_Face& theFace,
626 const Standard_Integer theNbIsoU,
627 const Standard_Integer theNbIsoV,
628 const Standard_Real theUVLimit,
629 TColStd_SequenceOfReal& theUIsoParams,
630 TColStd_SequenceOfReal& theVIsoParams,
631 Standard_Real& theUmin,
632 Standard_Real& theUmax,
633 Standard_Real& theVmin,
634 Standard_Real& theVmax)
637 TopLoc_Location aLocation;
638 const Handle(Geom_Surface)& aSurface = BRep_Tool::Surface(theFace, aLocation);
639 if (aSurface.IsNull())
644 BRepTools::UVBounds (theFace, theUmin, theUmax, theVmin, theVmax);
646 Standard_Real aUmin = theUmin;
647 Standard_Real aUmax = theUmax;
648 Standard_Real aVmin = theVmin;
649 Standard_Real aVmax = theVmax;
651 if (Precision::IsInfinite (aUmin))
653 if (Precision::IsInfinite (aUmax))
655 if (Precision::IsInfinite (aVmin))
657 if (Precision::IsInfinite (aVmax))
661 const Standard_Boolean isUClosed = aSurface->IsUClosed();
662 const Standard_Boolean isVClosed = aSurface->IsVClosed();
666 aUmin = aUmin + (aUmax - aUmin) / 1000.0;
667 aUmax = aUmax - (aUmax - aUmin) / 1000.0;
672 aVmin = aVmin + (aVmax - aVmin) / 1000.0;
673 aVmax = aVmax - (aVmax - aVmin) / 1000.0;
676 Standard_Real aUstep = (aUmax - aUmin) / (1 + theNbIsoU);
677 Standard_Real aVstep = (aVmax - aVmin) / (1 + theNbIsoV);
679 for (Standard_Integer anIso = 1; anIso <= theNbIsoU; ++anIso)
681 theUIsoParams.Append (aUmin + aUstep * anIso);
684 for (Standard_Integer anIso = 1; anIso <= theNbIsoV; ++anIso)
686 theVIsoParams.Append (aVmin + aVstep * anIso);
690 //==================================================================
691 // function : FindSegmentOnTriangulation
693 //==================================================================
694 Standard_Boolean StdPrs_Isolines::findSegmentOnTriangulation (const Handle(Geom_Surface)& theSurface,
696 const gp_Lin2d& theIsoline,
697 const gp_Pnt* theNodesXYZ,
698 const gp_Pnt2d* theNodesUV,
699 SegOnIso& theSegment)
701 Standard_Integer aNPoints = 0;
703 for (Standard_Integer aLinkIter = 0; aLinkIter < 3 && aNPoints < 2; ++aLinkIter)
706 // Check that uv isoline crosses the triangulation link in parametric space
709 const gp_Pnt2d& aNodeUV1 = theNodesUV[aLinkIter];
710 const gp_Pnt2d& aNodeUV2 = theNodesUV[(aLinkIter + 1) % 3];
711 const gp_Pnt& aNode1 = theNodesXYZ[aLinkIter];
712 const gp_Pnt& aNode2 = theNodesXYZ[(aLinkIter + 1) % 3];
714 // Compute distance of uv points to isoline taking into consideration their relative
715 // location against the isoline (left or right). Null value for a node means that the
716 // isoline crosses the node. Both positive or negative means that the isoline does not
717 // cross the segment.
718 Standard_Boolean isLeftUV1 = (theIsoline.Direction().XY() ^ gp_Vec2d (theIsoline.Location(), aNodeUV1).XY()) > 0.0;
719 Standard_Boolean isLeftUV2 = (theIsoline.Direction().XY() ^ gp_Vec2d (theIsoline.Location(), aNodeUV2).XY()) > 0.0;
720 Standard_Real aDistanceUV1 = isLeftUV1 ? theIsoline.Distance (aNodeUV1) : -theIsoline.Distance (aNodeUV1);
721 Standard_Real aDistanceUV2 = isLeftUV2 ? theIsoline.Distance (aNodeUV2) : -theIsoline.Distance (aNodeUV2);
723 // Isoline crosses first point of an edge.
724 if (Abs (aDistanceUV1) < Precision::PConfusion())
726 theSegment[aNPoints].Param = theIsU ? aNodeUV1.Y() : aNodeUV1.X();
727 theSegment[aNPoints].Pnt = aNode1;
732 // Isoline crosses second point of an edge.
733 if (Abs (aDistanceUV2) < Precision::PConfusion())
735 theSegment[aNPoints].Param = theIsU ? aNodeUV2.Y() : aNodeUV2.X();
736 theSegment[aNPoints].Pnt = aNode2;
743 // Isoline does not cross the triangle link.
744 if (aDistanceUV1 * aDistanceUV2 > 0.0)
749 // Isoline crosses degenerated link.
750 if (aNode1.SquareDistance (aNode2) < Precision::PConfusion())
752 theSegment[aNPoints].Param = theIsU ? aNodeUV1.Y() : aNodeUV1.X();
753 theSegment[aNPoints].Pnt = aNode1;
759 // Derive cross-point from parametric coordinates
762 Standard_Real anAlpha = Abs (aDistanceUV1) / (Abs (aDistanceUV1) + Abs (aDistanceUV2));
764 gp_Pnt aCross (0.0, 0.0, 0.0);
765 Standard_Real aCrossU = aNodeUV1.X() + anAlpha * (aNodeUV2.X() - aNodeUV1.X());
766 Standard_Real aCrossV = aNodeUV1.Y() + anAlpha * (aNodeUV2.Y() - aNodeUV1.Y());
767 Standard_Real aCrossParam = theIsU ? aCrossV : aCrossU;
768 if (theSurface.IsNull())
770 // Do linear interpolation of point coordinates using triangulation nodes.
771 aCross.SetX (aNode1.X() + anAlpha * (aNode2.X() - aNode1.X()));
772 aCross.SetY (aNode1.Y() + anAlpha * (aNode2.Y() - aNode1.Y()));
773 aCross.SetZ (aNode1.Z() + anAlpha * (aNode2.Z() - aNode1.Z()));
777 // Do linear interpolation of point coordinates by triangulation nodes.
778 // Get 3d point on surface.
779 Handle(Geom_Curve) anIso1, anIso2;
780 Standard_Real aPntOnNode1Iso = 0.0;
781 Standard_Real aPntOnNode2Iso = 0.0;
782 Standard_Real aPntOnNode3Iso = 0.0;
784 if (theIsoline.Direction().X() == 0.0)
786 aPntOnNode1Iso = aNodeUV1.X();
787 aPntOnNode2Iso = aNodeUV2.X();
788 aPntOnNode3Iso = aCrossU;
789 anIso1 = theSurface->VIso (aNodeUV1.Y());
790 anIso2 = theSurface->VIso (aNodeUV2.Y());
792 else if (theIsoline.Direction().Y() == 0.0)
794 aPntOnNode1Iso = aNodeUV1.Y();
795 aPntOnNode2Iso = aNodeUV2.Y();
796 aPntOnNode3Iso = aCrossV;
797 anIso1 = theSurface->UIso (aNodeUV1.X());
798 anIso2 = theSurface->UIso (aNodeUV2.X());
801 GeomAdaptor_Curve aCurveAdaptor1 (anIso1);
802 GeomAdaptor_Curve aCurveAdaptor2 (anIso2);
803 Standard_Real aLength1 = GCPnts_AbscissaPoint::Length (aCurveAdaptor1, aPntOnNode1Iso, aPntOnNode3Iso, 1e-2);
804 Standard_Real aLength2 = GCPnts_AbscissaPoint::Length (aCurveAdaptor2, aPntOnNode2Iso, aPntOnNode3Iso, 1e-2);
805 if (Abs (aLength1) < Precision::Confusion() || Abs (aLength2) < Precision::Confusion())
807 theSegment[aNPoints].Param = aCrossParam;
808 theSegment[aNPoints].Pnt = (aNode2.XYZ() - aNode1.XYZ()) * anAlpha + aNode1.XYZ();
813 aCross = (aNode2.XYZ() - aNode1.XYZ()) * (aLength1 / (aLength1 + aLength2)) + aNode1.XYZ();
816 theSegment[aNPoints].Param = aCrossParam;
817 theSegment[aNPoints].Pnt = aCross;
822 || Abs (theSegment[1].Param - theSegment[0].Param) <= Precision::PConfusion())
827 if (theSegment[1].Param < theSegment[0].Param)
829 std::swap (theSegment[0], theSegment[1]);