0032351: Visualization, PrsDim_LengthDimension - add NULL checks for handling non...
authorkgv <kgv@opencascade.com>
Mon, 10 May 2021 06:05:11 +0000 (09:05 +0300)
committerbugmaster <bugmaster@opencascade.com>
Tue, 11 May 2021 16:24:10 +0000 (19:24 +0300)
Added several missing NULL-checks.
Reduced restrictions on building Edge-Edge and Edge-Vertex length dimension.
Added empty constructor for more straightforward initialization from vdimension command.

src/PrsDim/PrsDim.cxx
src/PrsDim/PrsDim_LengthDimension.cxx
src/PrsDim/PrsDim_LengthDimension.hxx
src/ViewerTest/ViewerTest_RelationCommands.cxx
tests/v3d/dimensions/bug26317
tests/v3d/dimensions/bug32351 [new file with mode: 0644]

index 013b644..e923502 100644 (file)
@@ -233,21 +233,15 @@ Standard_Boolean PrsDim::ComputeGeometry (const TopoDS_Edge& theEdge,
                                           gp_Pnt& theLastPnt,
                                           Standard_Boolean& theIsInfinite)
 {
-  Standard_Real aFirst, aLast;
-
   BRepAdaptor_Curve anAdaptor (theEdge);
-
-  theCurve = Handle(Geom_Curve)::DownCast
-    (anAdaptor.Curve().Curve()->Transformed (anAdaptor.Trsf()));
-
+  theCurve = Handle(Geom_Curve)::DownCast (anAdaptor.Curve().Curve()->Transformed (anAdaptor.Trsf()));
   if (theCurve.IsNull())
   {
     return Standard_False;
   }
 
-  aFirst = anAdaptor.FirstParameter();
-  aLast = anAdaptor.LastParameter();
-
+  const Standard_Real aFirst = anAdaptor.FirstParameter();
+  const Standard_Real aLast  = anAdaptor.LastParameter();
   theIsInfinite = (Precision::IsInfinite (aFirst) || Precision::IsInfinite (aLast));
 
   if (theCurve->IsInstance (STANDARD_TYPE (Geom_TrimmedCurve)))
@@ -288,18 +282,16 @@ Standard_Boolean PrsDim::ComputeGeometry (const TopoDS_Edge& theEdge,
     return Standard_False;
   }
 
-  Standard_Real aFirst, aLast;
   BRepAdaptor_Curve aCurveAdaptor (theEdge);
   theCurve = Handle(Geom_Curve)::DownCast (aCurveAdaptor.Curve().Curve()->Transformed (aCurveAdaptor.Trsf()));
-  aFirst = aCurveAdaptor.FirstParameter();
-  aLast = aCurveAdaptor.LastParameter();
-
   if (theCurve.IsNull())
   {
     return Standard_False;
   }
   
   theExtCurve = theCurve;
+  const Standard_Real aFirst = aCurveAdaptor.FirstParameter();
+  const Standard_Real aLast  = aCurveAdaptor.LastParameter();
   theIsInfinite = (Precision::IsInfinite (aFirst) || Precision::IsInfinite (aLast));
 
   // Checks that the projected curve is not in the plane.
@@ -309,17 +301,14 @@ Standard_Boolean PrsDim::ComputeGeometry (const TopoDS_Edge& theEdge,
     theExtCurve = Handle(Geom_TrimmedCurve)::DownCast (theExtCurve)->BasisCurve();
   }
 
-  if (theExtCurve->IsInstance (STANDARD_TYPE (Geom_Line)))
+  if (Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast (theExtCurve))
   {
-    Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast (theExtCurve);
     theIsOnPlane = thePlane->Pln().Contains (aLine->Lin(),
                                              Precision::Confusion(),
                                              Precision::Angular());
   }
-  else if (theExtCurve->IsInstance (STANDARD_TYPE (Geom_Circle)))
+  else if (Handle(Geom_Circle) aCircle = Handle(Geom_Circle)::DownCast (theExtCurve))
   {
-    Handle(Geom_Circle) aCircle = Handle(Geom_Circle)::DownCast (theExtCurve);
-
     gp_Ax3 aCircPos (aCircle->Position());
     theIsOnPlane = aCircPos.IsCoplanar (thePlane->Pln().Position(),
                                                 Precision::Confusion(),
@@ -335,29 +324,24 @@ Standard_Boolean PrsDim::ComputeGeometry (const TopoDS_Edge& theEdge,
                                           thePlane->Pln().Axis().Direction(),
                                           Standard_False);
 
-  if (theCurve->IsInstance (STANDARD_TYPE (Geom_Line)))
+  if (Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast (theCurve))
   {
-    Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast (theCurve);
     if (!theIsInfinite)
     {
       theFirstPnt = ElCLib::Value (aFirst, aLine->Lin());
       theLastPnt = ElCLib::Value (aLast, aLine->Lin());
     }
   }
-  else if (theCurve->IsInstance (STANDARD_TYPE (Geom_Circle)))
+  else if (Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast (theCurve))
   {
-    Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast (theCurve);
-
     theFirstPnt = ElCLib::Value (aFirst, aCirc->Circ());
     theLastPnt = ElCLib::Value (aLast, aCirc->Circ());
   }
-  else if (theCurve->IsInstance (STANDARD_TYPE (Geom_Ellipse)))
-    {
-      Handle(Geom_Ellipse) anEllipse = Handle(Geom_Ellipse)::DownCast (theCurve);
-
-      theFirstPnt = ElCLib::Value (aFirst, anEllipse->Elips());
-      theLastPnt = ElCLib::Value (aLast, anEllipse->Elips());
-    }
+  else if (Handle(Geom_Ellipse) anEllipse = Handle(Geom_Ellipse)::DownCast (theCurve))
+  {
+    theFirstPnt = ElCLib::Value (aFirst, anEllipse->Elips());
+    theLastPnt = ElCLib::Value (aLast, anEllipse->Elips());
+  }
   else
   {
     return Standard_False;
@@ -390,13 +374,8 @@ Standard_Boolean PrsDim::ComputeGeometry (const TopoDS_Edge& theFirstEdge,
   
   theFirstCurve = BRep_Tool::Curve (theFirstEdge, aFirstEdgeLoc, aFirst1, aLast1);
   theSecondCurve = BRep_Tool::Curve (theSecondEdge, aSecondEdgeLoc, aFirst2, aLast2);
-
-  if (theFirstCurve.IsNull())
-  {
-    return Standard_False;
-  }
-    
-  if (theSecondCurve.IsNull())
+  if (theFirstCurve.IsNull()
+   || theSecondCurve.IsNull())
   {
     return Standard_False;
   }
@@ -417,33 +396,25 @@ Standard_Boolean PrsDim::ComputeGeometry (const TopoDS_Edge& theFirstEdge,
                                                thePlane->Pln().Axis().Direction(),
                                                Standard_False);
 
-
   theSecondCurve = GeomProjLib::ProjectOnPlane (theSecondCurve, thePlane,
                                                 thePlane->Pln().Axis().Direction(),
                                                 Standard_False);
-
-
   if (theFirstCurve->IsInstance (STANDARD_TYPE(Geom_TrimmedCurve)))
   {
     theFirstCurve = Handle(Geom_TrimmedCurve)::DownCast (theFirstCurve)->BasisCurve();
   }
-    
   if (theSecondCurve->IsInstance (STANDARD_TYPE (Geom_TrimmedCurve)))
   {
     theSecondCurve = Handle(Geom_TrimmedCurve)::DownCast (theSecondCurve)->BasisCurve();
   }
 
-  if (theFirstCurve->IsInstance(STANDARD_TYPE(Geom_Line)))
+  if (Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast (theFirstCurve))
   {
-    Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast (theFirstCurve);
-
     theFirstPnt1 = ElCLib::Value (aFirst1, aLine->Lin());
     theLastPnt1 = ElCLib::Value (aLast1, aLine->Lin());
   }
-  else if (theFirstCurve->IsInstance(STANDARD_TYPE(Geom_Circle)))
+  else if (Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast (theFirstCurve))
   {
-    Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast (theFirstCurve);
-      
     theFirstPnt1 = ElCLib::Value (aFirst1, aCirc->Circ());
     theLastPnt1 = ElCLib::Value (aLast1, aCirc->Circ());
   }
@@ -452,17 +423,13 @@ Standard_Boolean PrsDim::ComputeGeometry (const TopoDS_Edge& theFirstEdge,
     return Standard_False;
   }
 
-  if (theSecondCurve->IsInstance (STANDARD_TYPE (Geom_Line)))
-{
-    Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast (theSecondCurve);
-
+  if (Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast (theSecondCurve))
+  {
     theFirstPnt2 = ElCLib::Value (aFirst2, aLine->Lin());
     theLastPnt2 = ElCLib::Value (aLast2, aLine->Lin());
   }
-  else if (theSecondCurve->IsInstance (STANDARD_TYPE (Geom_Circle)))
+  else if (Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast (theSecondCurve))
   {
-    Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast (theSecondCurve);
-
     theFirstPnt2 = ElCLib::Value (aFirst2, aCirc->Circ());
     theLastPnt2 = ElCLib::Value (aLast2, aCirc->Circ());
   }
@@ -489,62 +456,60 @@ Standard_Boolean PrsDim::ComputeGeometry (const TopoDS_Edge& theFirstEdge,
                                           Standard_Boolean& theIsInfinite1,
                                           Standard_Boolean& theIsInfinite2)
 {
-    theIsInfinite1 = theIsInfinite2 = Standard_False;
-
-   if (!PrsDim::ComputeGeometry (theFirstEdge, theFirstCurve,theFirstPnt1, theLastPnt1, theIsInfinite1))
-   {
-     return Standard_False;
-   }
-
-   if (!PrsDim::ComputeGeometry (theSecondEdge, theSecondCurve,theFirstPnt2, theLastPnt2, theIsInfinite2))
-   {
-     return Standard_False;
-   }
+  theIsInfinite1 = theIsInfinite2 = Standard_False;
+  if (!PrsDim::ComputeGeometry (theFirstEdge, theFirstCurve, theFirstPnt1, theLastPnt1, theIsInfinite1))
+  {
+    return Standard_False;
+  }
+  if (!PrsDim::ComputeGeometry (theSecondEdge, theSecondCurve, theFirstPnt2, theLastPnt2, theIsInfinite2))
+  {
+    return Standard_False;
+  }
 
   if (theIsInfinite1 || theIsInfinite2)
   {
-      if (theFirstCurve->DynamicType() == theSecondCurve->DynamicType())
+    if (theFirstCurve->DynamicType() == theSecondCurve->DynamicType()
+     && theFirstCurve->IsInstance (STANDARD_TYPE (Geom_Line)))
+    {
+      gp_Lin aLin1 = Handle(Geom_Line)::DownCast (theFirstCurve)->Lin();
+      gp_Lin aLin2 = Handle(Geom_Line)::DownCast (theSecondCurve)->Lin();
+      if (theIsInfinite1)
       {
-          gp_Lin aLin1 = Handle(Geom_Line)::DownCast (theFirstCurve)->Lin();
-          gp_Lin aLin2 = Handle(Geom_Line)::DownCast (theSecondCurve)->Lin();
-
-          if (theIsInfinite1)
-          {
-              theFirstPnt1 = ElCLib::Value (ElCLib::Parameter (aLin2, theFirstPnt2), aLin1);
-              theLastPnt1 = ElCLib::Value (ElCLib::Parameter (aLin2, theLastPnt2), aLin1);
-          }
-          else if (theIsInfinite2)
-          {
-              theFirstPnt2 = ElCLib::Value (ElCLib::Parameter (aLin1, theFirstPnt1), aLin2);
-              theLastPnt2 = ElCLib::Value (ElCLib::Parameter (aLin1, theLastPnt1), aLin2);
-          }
+        theFirstPnt1 = ElCLib::Value (ElCLib::Parameter (aLin2, theFirstPnt2), aLin1);
+        theLastPnt1 = ElCLib::Value (ElCLib::Parameter (aLin2, theLastPnt2), aLin1);
       }
-      else
+      else if (theIsInfinite2)
       {
-        if (theIsInfinite1 && !theIsInfinite2)
-        {
-          GeomAPI_ProjectPointOnCurve aProjector (theFirstPnt2, theFirstCurve);
-          theFirstPnt1 = theFirstCurve->Value (aProjector.LowerDistanceParameter ());
+        theFirstPnt2 = ElCLib::Value (ElCLib::Parameter (aLin1, theFirstPnt1), aLin2);
+        theLastPnt2 = ElCLib::Value (ElCLib::Parameter (aLin1, theLastPnt1), aLin2);
+      }
+    }
+    else
+    {
+      if (theIsInfinite1 && !theIsInfinite2)
+      {
+        GeomAPI_ProjectPointOnCurve aProjector (theFirstPnt2, theFirstCurve);
+        theFirstPnt1 = theFirstCurve->Value (aProjector.LowerDistanceParameter());
 
-          aProjector.Init (theLastPnt2, theFirstCurve);
-          theLastPnt1 = theFirstCurve->Value (aProjector.LowerDistanceParameter ());
-        }
-        else if (!theIsInfinite1 && theIsInfinite2)
-        {
-          GeomAPI_ProjectPointOnCurve aProjector (theFirstPnt1, theSecondCurve);
-          theFirstPnt2 = theSecondCurve->Value (aProjector.LowerDistanceParameter ());
+        aProjector.Init (theLastPnt2, theFirstCurve);
+        theLastPnt1 = theFirstCurve->Value (aProjector.LowerDistanceParameter());
+      }
+      else if (!theIsInfinite1 && theIsInfinite2)
+      {
+        GeomAPI_ProjectPointOnCurve aProjector (theFirstPnt1, theSecondCurve);
+        theFirstPnt2 = theSecondCurve->Value (aProjector.LowerDistanceParameter());
 
-          aProjector.Init (theLastPnt1, theSecondCurve);
-          theLastPnt2 = theSecondCurve->Value (aProjector.LowerDistanceParameter ());
-        }
-        else
-        {
-          return Standard_False;
-        }
+        aProjector.Init (theLastPnt1, theSecondCurve);
+        theLastPnt2 = theSecondCurve->Value (aProjector.LowerDistanceParameter());
       }
+      else
+      {
+        return Standard_False;
+      }
+    }
   }
 
-    return Standard_True;
+  return Standard_True;
 }
 
 //=======================================================================
@@ -553,7 +518,7 @@ Standard_Boolean PrsDim::ComputeGeometry (const TopoDS_Edge& theFirstEdge,
 //           and the 'right' geometry of the edges if one doesn't
 //           belong to the current working plane.
 //           There may be only one curve that can't belong to the
-//           current working plane ( attachement constraint)
+//           current working plane (attachment constraint)
 //           if the 2 edges belong to the current WP, <WhatProj> = 0
 //
 //           indexExt = 0 2 edges are in the current wp
@@ -619,7 +584,7 @@ Standard_Boolean PrsDim::ComputeGeometry (const TopoDS_Edge& theFirstEdge,
   Handle(Geom_Curve) aSecondSaved = theSecondCurve;
 
   // Checks that the projected curve is not in the plane
-  Standard_Boolean isFirstOnPlane,isSecondOnPlane;
+  Standard_Boolean isFirstOnPlane, isSecondOnPlane;
 
   if ((!ComputeGeomCurve (theFirstCurve, aFirst1, aLast1, theFirstPnt1, theLastPnt1, thePlane, isFirstOnPlane))
       || (!ComputeGeomCurve( theSecondCurve, aFirst2, aLast2, theFirstPnt2, theLastPnt2, thePlane,isSecondOnPlane)))
@@ -644,7 +609,8 @@ Standard_Boolean PrsDim::ComputeGeometry (const TopoDS_Edge& theFirstEdge,
 
   if (theIsInfinite1 || theIsInfinite2)
   {
-    if (theFirstCurve->DynamicType() == theSecondCurve->DynamicType())
+    if (theFirstCurve->DynamicType() == theSecondCurve->DynamicType()
+     && theFirstCurve->IsInstance (STANDARD_TYPE (Geom_Line)))
     {
       gp_Lin aLin1 = Handle(Geom_Line)::DownCast (theFirstCurve)->Lin();
       gp_Lin aLin2 = Handle(Geom_Line)::DownCast (theSecondCurve)->Lin();
index 4952ca2..e0bb95b 100644 (file)
@@ -29,6 +29,7 @@
 #include <gce_MakePln.hxx>
 #include <Geom_TrimmedCurve.hxx>
 #include <GeomAPI_ExtremaCurveCurve.hxx>
+#include <GeomAPI_ProjectPointOnCurve.hxx>
 #include <GeomAPI_ExtremaSurfaceSurface.hxx>
 #include <Geom_Curve.hxx>
 #include <Geom_Line.hxx>
 
 IMPLEMENT_STANDARD_RTTIEXT(PrsDim_LengthDimension, PrsDim_Dimension)
 
+//=======================================================================
+//function : Constructor
+//purpose  :
+//=======================================================================
+PrsDim_LengthDimension::PrsDim_LengthDimension()
+: PrsDim_Dimension (PrsDim_KOD_LENGTH),
+  myHasCustomDirection (Standard_False)
+{
+  SetFlyout (15.0);
+}
+
 //=======================================================================
 //function : Constructor
 //purpose  : Dimension between two faces
@@ -354,28 +366,10 @@ Standard_Boolean PrsDim_LengthDimension::InitTwoEdgesLength (const TopoDS_Edge&
                                                              const TopoDS_Edge& theSecondEdge,
                                                              gp_Dir& theDirAttach)
 {
-  BRepAdaptor_Curve aFirstCurveAdapt (theFirstEdge);
-  if (aFirstCurveAdapt.GetType() != GeomAbs_Line)
-  {
-    return Standard_False;
-  }
-
-  BRepAdaptor_Curve aSecondCurveAdapt (theSecondEdge);
-  if (aSecondCurveAdapt.GetType() != GeomAbs_Line)
-  {
-    return Standard_False;
-  }
-
-  Handle(Geom_Curve) aFirstCurve;
-  Handle(Geom_Curve) aSecondCurve;
-
-  gp_Pnt aPoint11 (gp::Origin());
-  gp_Pnt aPoint12 (gp::Origin());
-  gp_Pnt aPoint21 (gp::Origin());
-  gp_Pnt aPoint22 (gp::Origin());
+  Handle(Geom_Curve) aFirstCurve, aSecondCurve;
+  gp_Pnt aPoint11, aPoint12, aPoint21, aPoint22;
   Standard_Boolean isFirstInfinite  = Standard_False;
   Standard_Boolean isSecondInfinite = Standard_False;
-
   if (!PrsDim::ComputeGeometry (theFirstEdge, theSecondEdge,
                                 aFirstCurve, aSecondCurve,
                                 aPoint11, aPoint12,
@@ -388,51 +382,79 @@ Standard_Boolean PrsDim_LengthDimension::InitTwoEdgesLength (const TopoDS_Edge&
 
   const Handle(Geom_Line) aFirstLine = Handle(Geom_Line)::DownCast (aFirstCurve);
   const Handle(Geom_Line) aSecondLine = Handle(Geom_Line)::DownCast (aSecondCurve);
-
-  if (!aFirstLine->Lin().Direction().IsParallel (aSecondLine->Lin().Direction(),Precision::Angular()))
+  if (!aFirstLine.IsNull()
+   && !aSecondLine.IsNull())
   {
-    return Standard_False;
-  }
-
-  theDirAttach = aFirstLine->Lin().Direction();
+    if (!aFirstLine->Lin().Direction().IsParallel (aSecondLine->Lin().Direction(), Precision::Angular()))
+    {
+      return Standard_False;
+    }
 
-  gp_Pnt aPoint;
+    theDirAttach = aFirstLine->Lin().Direction();
 
-  if (!isFirstInfinite)
-  {
-    if (PrsDim::Nearest (aSecondCurve, aPoint11, aPoint21, aPoint22, aPoint))
+    gp_Pnt aPoint;
+    if (!isFirstInfinite)
     {
-      myFirstPoint = aPoint11;
-      mySecondPoint = aPoint;
-      return IsValidPoints (myFirstPoint, mySecondPoint);
+      if (PrsDim::Nearest (aSecondCurve, aPoint11, aPoint21, aPoint22, aPoint))
+      {
+        myFirstPoint = aPoint11;
+        mySecondPoint = aPoint;
+        return IsValidPoints (myFirstPoint, mySecondPoint);
+      }
+      else if (PrsDim::Nearest (aSecondCurve, aPoint12, aPoint21, aPoint22, aPoint))
+      {
+        myFirstPoint = aPoint12;
+        mySecondPoint = aPoint;
+        return IsValidPoints (myFirstPoint, mySecondPoint);
+      }
     }
-    else if (PrsDim::Nearest (aSecondCurve, aPoint12, aPoint21, aPoint22, aPoint))
+
+    if (!isSecondInfinite)
     {
-      myFirstPoint = aPoint12;
-      mySecondPoint = aPoint;
-      return IsValidPoints (myFirstPoint, mySecondPoint);
+      if (PrsDim::Nearest (aFirstCurve, aPoint21, aPoint11, aPoint12, aPoint))
+      {
+        myFirstPoint = aPoint;
+        mySecondPoint = aPoint21;
+        return IsValidPoints (myFirstPoint, mySecondPoint);
+      }
+      if (PrsDim::Nearest (aFirstCurve, aPoint22, aPoint11, aPoint12, aPoint))
+      {
+        myFirstPoint = aPoint;
+        mySecondPoint = aPoint22;
+        return IsValidPoints (myFirstPoint, mySecondPoint);
+      }
     }
   }
 
-  if (!isSecondInfinite)
+  GeomAPI_ExtremaCurveCurve anExtrema (aFirstCurve, aSecondCurve);
+  if (anExtrema.NbExtrema() == 0)
   {
-    if (PrsDim::Nearest (aFirstCurve, aPoint21, aPoint11, aPoint12, aPoint))
-    {
-      myFirstPoint = aPoint;
-      mySecondPoint = aPoint21;
-      return IsValidPoints (myFirstPoint, mySecondPoint);
-    }
-    if (PrsDim::Nearest (aFirstCurve, aPoint22, aPoint11, aPoint12, aPoint))
-    {
-      myFirstPoint = aPoint;
-      mySecondPoint = aPoint22;
-      return IsValidPoints (myFirstPoint, mySecondPoint);
-    }
+    return false;
   }
 
-  GeomAPI_ExtremaCurveCurve anExtrema (aFirstCurve, aSecondCurve);
   anExtrema.NearestPoints (myFirstPoint, mySecondPoint);
-  return IsValidPoints (myFirstPoint, mySecondPoint);
+  if (!IsValidPoints (myFirstPoint, mySecondPoint))
+  {
+    return false;
+  }
+
+  if (aFirstLine.IsNull()
+   || aSecondLine.IsNull())
+  {
+    Standard_Real aParam1 = 0.0, aParam2 = 0.0;
+    anExtrema.LowerDistanceParameters (aParam1, aParam2);
+    BRepAdaptor_Curve aCurveAdaptor (theFirstEdge);
+    gp_Pnt aPoint;
+    gp_Vec aDir;
+    aCurveAdaptor.D1 (aParam1, aPoint, aDir);
+    if (aDir.SquareMagnitude() <= gp::Resolution())
+    {
+      return false;
+    }
+
+    theDirAttach = aDir;
+  }
+  return true;
 }
 
 //=======================================================================
@@ -444,10 +466,8 @@ Standard_Boolean PrsDim_LengthDimension::InitEdgeVertexLength (const TopoDS_Edge
                                                                gp_Dir& theEdgeDir,
                                                                Standard_Boolean isInfinite)
 {
-  gp_Pnt anEdgePoint1 (gp::Origin());
-  gp_Pnt anEdgePoint2 (gp::Origin());
+  gp_Pnt anEdgePoint1, anEdgePoint2;
   Handle(Geom_Curve) aCurve;
-
   if (!PrsDim::ComputeGeometry (theEdge, aCurve, anEdgePoint1, anEdgePoint2, isInfinite))
   {
     return Standard_False;
@@ -455,15 +475,39 @@ Standard_Boolean PrsDim_LengthDimension::InitEdgeVertexLength (const TopoDS_Edge
 
   myFirstPoint = BRep_Tool::Pnt (theVertex);
 
-  Handle(Geom_Line) aGeomLine (Handle(Geom_Line)::DownCast (aCurve));
-  const gp_Lin& aLin = aGeomLine->Lin();
+  if (Handle(Geom_Line) aGeomLine = Handle(Geom_Line)::DownCast (aCurve))
+  {
+    const gp_Lin aLin = aGeomLine->Lin();
 
-  // Get direction of edge to build plane automatically.
-  theEdgeDir = aLin.Direction();
+    // Get direction of edge to build plane automatically.
+    theEdgeDir = aLin.Direction();
 
-  mySecondPoint = PrsDim::Nearest (aLin, myFirstPoint);
+    mySecondPoint = PrsDim::Nearest (aLin, myFirstPoint);
+    return IsValidPoints (myFirstPoint, mySecondPoint);
+  }
 
-  return IsValidPoints (myFirstPoint, mySecondPoint);
+  GeomAPI_ProjectPointOnCurve anExtrema (myFirstPoint, aCurve);
+  if (anExtrema.NbPoints() == 0)
+  {
+    return false;
+  }
+
+  mySecondPoint = anExtrema.NearestPoint();
+  if (!IsValidPoints (myFirstPoint, mySecondPoint))
+  {
+    return false;
+  }
+
+  BRepAdaptor_Curve aCurveAdaptor (theEdge);
+  gp_Pnt aPoint;
+  gp_Vec aDir;
+  aCurveAdaptor.D1 (anExtrema.LowerDistanceParameter(), aPoint, aDir);
+  if (aDir.SquareMagnitude() <= gp::Resolution())
+  {
+    return false;
+  }
+  theEdgeDir = aDir;
+  return true;
 }
 
 //=======================================================================
index bfc227a..c2b20f3 100644 (file)
@@ -49,6 +49,10 @@ class PrsDim_LengthDimension : public PrsDim_Dimension
   DEFINE_STANDARD_RTTIEXT(PrsDim_LengthDimension, PrsDim_Dimension)
 public:
 
+  //! Construct an empty length dimension.
+  //! @sa SetMeasuredGeometry(), SetMeasuredShapes() for initialization.
+  Standard_EXPORT PrsDim_LengthDimension();
+
   //! Construct length dimension between face and edge.
   //! Here dimension can be built without user-defined plane.
   //! @param theFace [in] the face (first shape).
@@ -88,23 +92,23 @@ public:
 
 public:
 
-  //! @return first attachement point.
+  //! @return first attachment point.
   const gp_Pnt& FirstPoint() const { return myFirstPoint; }
 
-  //! @return second attachement point.
+  //! @return second attachment point.
   const gp_Pnt& SecondPoint() const { return mySecondPoint; }
 
-  //! @return first attachement shape.
+  //! @return first attachment shape.
   const TopoDS_Shape& FirstShape() const { return myFirstShape; }
 
-  //! @return second attachement shape.
+  //! @return second attachment shape.
   const TopoDS_Shape& SecondShape() const { return mySecondShape; }
 
 public:
 
   //! Measure distance between two points.
   //! The dimension will become invalid if the new distance between
-  //! attachement points is less than Precision::Confusion().
+  //! attachment points is less than Precision::Confusion().
   //! @param theFirstPoint [in] the first point.
   //! @param theSecondPoint [in] the second point.
   //! @param thePlane [in] the user-defined plane
@@ -208,8 +212,7 @@ protected:
   //! Auxiliary method for InitTwoShapesPoints()
   //! in case of the distance between edge and vertex.
   //! Finds the point on the edge that is the closest one to <theVertex>.
-  //! @param theEdgeDir [out] is the direction on the edge to build
-  //! automatical plane.
+  //! @param theEdgeDir [out] is the direction on the edge to build automatic plane.
   Standard_EXPORT Standard_Boolean InitEdgeVertexLength (const TopoDS_Edge& theEdge,
                                                          const TopoDS_Vertex& theVertex,
                                                          gp_Dir& theEdgeDir,
@@ -220,9 +223,8 @@ protected:
   //! The first attachment point is first parameter point from <theEdge>.
   //! Find the second attachment point which belongs to <theFace>
   //! Iterate over the edges of the face and find the closest point according
-  //! to finded point on edge.
-  //! @param theEdgeDir [out] is the direction on the edge to build
-  //! automatical plane.
+  //! to found point on edge.
+  //! @param theEdgeDir [out] is the direction on the edge to build automatic plane.
   Standard_EXPORT Standard_Boolean InitEdgeFaceLength (const TopoDS_Edge& theEdge,
                                                        const TopoDS_Face& theFace,
                                                        gp_Dir& theEdgeDir);
@@ -236,7 +238,7 @@ protected:
   //! Initialization of two attach points in case of one owner shape.
   Standard_EXPORT Standard_Boolean InitOneShapePoints (const TopoDS_Shape& theShape);
 
-private:
+protected:
 
   gp_Pnt myFirstPoint;
   gp_Pnt mySecondPoint;
index 2c85248..3f634c9 100644 (file)
@@ -770,26 +770,9 @@ static int VDimBuilder (Draw_Interpretor& /*theDi*/,
         }
 
         // Face-Face case
-        if (aShape1.ShapeType() == TopAbs_FACE && aShape2.ShapeType() == TopAbs_FACE)
+        Handle(PrsDim_LengthDimension) aLenDim = new PrsDim_LengthDimension();
+        if (isPlaneCustom)
         {
-          aDim = new PrsDim_LengthDimension (TopoDS::Face (aShape1), TopoDS::Face (aShape2));
-        }
-        else if (aShape1.ShapeType() == TopAbs_FACE && aShape2.ShapeType() == TopAbs_EDGE)
-        {
-          aDim = new PrsDim_LengthDimension (TopoDS::Face (aShape1), TopoDS::Edge (aShape2));
-        }
-        else if (aShape1.ShapeType() == TopAbs_EDGE && aShape2.ShapeType() == TopAbs_FACE)
-        {
-          aDim = new PrsDim_LengthDimension (TopoDS::Face (aShape2), TopoDS::Edge (aShape1));
-        }
-        else
-        {
-          if (!isPlaneCustom)
-          {
-            Message::SendFail ("Error: can not build dimension without working plane.");
-            return 1;
-          }
-          // Vertex-Vertex case
           if (aShape1.ShapeType() == TopAbs_VERTEX)
           {
             aWorkingPlane.SetLocation (BRep_Tool::Pnt (TopoDS::Vertex (aShape1)));
@@ -798,9 +781,16 @@ static int VDimBuilder (Draw_Interpretor& /*theDi*/,
           {
             aWorkingPlane.SetLocation (BRep_Tool::Pnt (TopoDS::Vertex (aShape2)));
           }
-
-          aDim = new PrsDim_LengthDimension (aShape1, aShape2, aWorkingPlane);
+          aLenDim->SetCustomPlane (aWorkingPlane);
+        }
+        else if (aShape1.ShapeType() == TopAbs_VERTEX
+              && aShape2.ShapeType() == TopAbs_VERTEX)
+        {
+          Message::SendFail ("Error: can not build dimension without working plane");
+          return 1;
         }
+        aLenDim->SetMeasuredShapes (aShape1, aShape2);
+        aDim = aLenDim;
       }
       else
       {
index af814c5..d395ae2 100644 (file)
@@ -11,7 +11,7 @@ vclear
 vaxo
 explode b F
 vdisplay b_1 b_2
-vdimension len -length -shapes b_1 b_2 -plane zox
+vdimension len -length -shapes b_1 b_2
 vfit
 
 vdump ${imagedir}/${casename}.png
diff --git a/tests/v3d/dimensions/bug32351 b/tests/v3d/dimensions/bug32351
new file mode 100644 (file)
index 0000000..9c3a73d
--- /dev/null
@@ -0,0 +1,23 @@
+puts "========"
+puts "0032351: Visualization, PrsDim_LengthDimension - add NULL checks for handling non-Line curves"
+puts "========"
+
+pload MODELING VISUALIZATION
+box b 200 0 0 100 200 300
+pcylinder c 100 200
+vinit View1
+vdisplay -dispMode 0 b c
+vfit
+
+explode b V
+explode c E
+vdisplay c_1 b_1
+vdimension d1 -length -shapes c_1 b_1 -plane zox
+
+explode b E
+explode c E
+vdisplay c_1 b_3
+vdimension d2 -length -shapes c_1 b_3
+
+vfit
+vdump $imagedir/${casename}.png