// Copyright (c) 2020 OPEN CASCADE SAS // // This file is part of the examples of the Open CASCADE Technology software library. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE #include "Sample2D_Face.h" #include #include #include #include #include #include #include #include #include Sample2D_Face::Sample2D_Face (const TopoDS_Shape& theFace) : myFORWARDColor (Quantity_NOC_BLUE1), myREVERSEDColor (Quantity_NOC_YELLOW), myINTERNALColor (Quantity_NOC_RED1), myEXTERNALColor (Quantity_NOC_MAGENTA1), myWidthIndex (1), myTypeIndex (1), // myshape (theFace), myForwardNum (0), myReversedNum (0), myInternalNum (0), myExternalNum (0), // myForwardBounds (0), myReversedBounds (0), myInternalBounds (0), myExternalBounds (0) { SetAutoHilight(Standard_False); FillData(Standard_True); } void Sample2D_Face::DrawMarker (const Handle(Geom2d_TrimmedCurve)& theCurve, const Handle(Prs3d_Presentation)& thePresentation) { Standard_Real aCenterParam = (theCurve->FirstParameter() + theCurve->LastParameter()) / 2; gp_Pnt2d p; gp_Vec2d v; theCurve->D1(aCenterParam, p, v); if (v.Magnitude() > gp::Resolution()) { gp_Vec aDir(v.X(), v.Y(), 0.); gp_Pnt aPoint(p.X(), p.Y(), 0.); aDir.Normalize(); aDir.Reverse(); gp_Dir aZ(0, 0, 1); gp_Pnt aLeft (aPoint.Translated(aDir.Rotated(gp_Ax1(aPoint, aZ), M_PI / 6) * 5)); gp_Pnt aRight(aPoint.Translated(aDir.Rotated(gp_Ax1(aPoint, aZ), M_PI * 11 / 6) * 5)); Handle(Graphic3d_ArrayOfPolylines) anArrow = new Graphic3d_ArrayOfPolylines(3); anArrow->AddVertex(aLeft); anArrow->AddVertex(aPoint); anArrow->AddVertex(aRight); thePresentation->CurrentGroup()->AddPrimitiveArray(anArrow); } } void Sample2D_Face::FillData(Standard_Boolean isSizesRecompute) { if (myshape.IsNull() || myshape.ShapeType() != TopAbs_FACE) { return; } Standard_Real f, l; TopoDS_Face aFace = TopoDS::Face(myshape); // count number of vertices and bounds in primitive arrays if (isSizesRecompute) { mySeq_FORWARD.Clear(); mySeq_REVERSED.Clear(); mySeq_INTERNAL.Clear(); mySeq_EXTERNAL.Clear(); myshape.Orientation(TopAbs_FORWARD); for (TopExp_Explorer anEdgeIter (myshape, TopAbs_EDGE); anEdgeIter.More(); anEdgeIter.Next()) { const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgeIter.Current()); BRepAdaptor_Curve2d aCurveOnEdge (anEdge, aFace); GCPnts_QuasiUniformDeflection anEdgeDistrib(aCurveOnEdge, 1.e-2); if (!anEdgeDistrib.IsDone()) { continue; } switch (anEdge.Orientation()) { case TopAbs_FORWARD: { myForwardNum += anEdgeDistrib.NbPoints(); myForwardBounds++; break; } case TopAbs_REVERSED: { myReversedNum += anEdgeDistrib.NbPoints(); myReversedBounds++; break; } case TopAbs_INTERNAL: { myInternalNum += anEdgeDistrib.NbPoints(); myInternalBounds++; break; } case TopAbs_EXTERNAL: { myExternalNum += anEdgeDistrib.NbPoints(); myExternalBounds++; break; } } } } myForwardArray = new Graphic3d_ArrayOfPolylines(myForwardNum, myForwardBounds); myReversedArray = new Graphic3d_ArrayOfPolylines(myReversedNum, myReversedBounds); myInternalArray = new Graphic3d_ArrayOfPolylines(myInternalNum, myInternalBounds); myExternalArray = new Graphic3d_ArrayOfPolylines(myExternalNum, myExternalBounds); // fill primitive arrays for (TopExp_Explorer anEdgeIter (myshape, TopAbs_EDGE); anEdgeIter.More(); anEdgeIter.Next()) { const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgeIter.Current()); const Handle(Geom2d_Curve) aCurve = BRep_Tool::CurveOnSurface (anEdge, aFace, f, l); Handle(Geom2d_TrimmedCurve) aTrimmedCurve = new Geom2d_TrimmedCurve(aCurve, f, l); if (!aTrimmedCurve.IsNull()) { Handle(Geom_Curve) aCurve3d = GeomLib::To3d(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aTrimmedCurve); BRepAdaptor_Curve2d aCurveOnEdge (anEdge, aFace); GCPnts_QuasiUniformDeflection anEdgeDistrib (aCurveOnEdge, 1.e-2); if (!anEdgeDistrib.IsDone()) { continue; } switch (anEdge.Orientation()) { case TopAbs_FORWARD: { myForwardArray->AddBound(anEdgeDistrib.NbPoints()); for (Standard_Integer i = 1; i <= anEdgeDistrib.NbPoints(); ++i) { myForwardArray->AddVertex(anEdgeDistrib.Value(i)); } if (isSizesRecompute) { mySeq_FORWARD.Append(aCurve3d); } break; } case TopAbs_REVERSED: { myReversedArray->AddBound(anEdgeDistrib.NbPoints()); for (Standard_Integer i = 1; i <= anEdgeDistrib.NbPoints(); ++i) { myReversedArray->AddVertex(anEdgeDistrib.Value(i)); } if (isSizesRecompute) { mySeq_REVERSED.Append(aCurve3d); } break; } case TopAbs_INTERNAL: { myInternalArray->AddBound(anEdgeDistrib.NbPoints()); for (Standard_Integer i = 1; i <= anEdgeDistrib.NbPoints(); ++i) { myInternalArray->AddVertex(anEdgeDistrib.Value(i)); } if (isSizesRecompute) { mySeq_INTERNAL.Append(aCurve3d); } break; } case TopAbs_EXTERNAL: { myExternalArray->AddBound(anEdgeDistrib.NbPoints()); for (Standard_Integer i = 1; i <= anEdgeDistrib.NbPoints(); ++i) { myExternalArray->AddVertex(anEdgeDistrib.Value(i)); } if (isSizesRecompute) { mySeq_EXTERNAL.Append(aCurve3d); } break; } } } } } void Sample2D_Face::Compute (const Handle(PrsMgr_PresentationManager)& , const Handle(Prs3d_Presentation)& thePresentation, const Standard_Integer theMode) { if (theMode != 0) { return; } thePresentation->Clear(); myDrawer->SetWireDraw(1); if (myshape.IsNull() || myshape.ShapeType() != TopAbs_FACE) { return; } Handle(Graphic3d_AspectLine3d) aLineAspect_FORWARD = new Graphic3d_AspectLine3d(myFORWARDColor, Aspect_TOL_SOLID, 1); Handle(Graphic3d_AspectLine3d) aLineAspect_REVERSED = new Graphic3d_AspectLine3d(myREVERSEDColor, Aspect_TOL_SOLID, 1); Handle(Graphic3d_AspectLine3d) aLineAspect_INTERNAL = new Graphic3d_AspectLine3d(myINTERNALColor, Aspect_TOL_SOLID, 1); Handle(Graphic3d_AspectLine3d) aLineAspect_EXTERNAL = new Graphic3d_AspectLine3d(myEXTERNALColor, Aspect_TOL_SOLID, 1); Standard_Real f, l; TopoDS_Face aFace = TopoDS::Face(myshape); // estimating number of vertices in primitive arrays for (TopExp_Explorer anEdgeIter (myshape, TopAbs_EDGE); anEdgeIter.More(); anEdgeIter.Next()) { const TopoDS_Edge& anEdge = TopoDS::Edge(anEdgeIter.Current()); const Handle(Geom2d_Curve) aCurve = BRep_Tool::CurveOnSurface (anEdge, aFace, f, l); Handle(Geom2d_TrimmedCurve) aTrimmedCurve = new Geom2d_TrimmedCurve(aCurve, f, l); // make a 3D curve from 2D trimmed curve to display it Handle(Geom_Curve) aCurve3d = GeomLib::To3d(gp_Ax2(gp_Pnt(0, 0, 0), gp_Dir(0, 0, 1)), aTrimmedCurve); // make distribution of points BRepAdaptor_Curve2d aCurveOnEdge (anEdge, aFace); GCPnts_QuasiUniformDeflection anEdgeDistrib(aCurveOnEdge, 1.e-2); if (anEdgeDistrib.IsDone()) { switch (anEdge.Orientation()) { case TopAbs_FORWARD: { thePresentation->CurrentGroup()->SetPrimitivesAspect(aLineAspect_FORWARD); DrawMarker(aTrimmedCurve, thePresentation); break; } case TopAbs_REVERSED: { thePresentation->CurrentGroup()->SetPrimitivesAspect(aLineAspect_REVERSED); DrawMarker(aTrimmedCurve, thePresentation); break; } case TopAbs_INTERNAL: { thePresentation->CurrentGroup()->SetPrimitivesAspect(aLineAspect_INTERNAL); DrawMarker(aTrimmedCurve, thePresentation); mySeq_INTERNAL.Append(aCurve3d); break; } case TopAbs_EXTERNAL: { thePresentation->CurrentGroup()->SetPrimitivesAspect(aLineAspect_EXTERNAL); DrawMarker(aTrimmedCurve, thePresentation); break; } } } } // add all primitives to the presentation thePresentation->CurrentGroup()->SetPrimitivesAspect(aLineAspect_FORWARD); thePresentation->CurrentGroup()->AddPrimitiveArray(myForwardArray); thePresentation->CurrentGroup()->SetPrimitivesAspect(aLineAspect_REVERSED); thePresentation->CurrentGroup()->AddPrimitiveArray(myReversedArray); thePresentation->CurrentGroup()->SetPrimitivesAspect(aLineAspect_INTERNAL); thePresentation->CurrentGroup()->AddPrimitiveArray(myInternalArray); thePresentation->CurrentGroup()->SetPrimitivesAspect(aLineAspect_EXTERNAL); thePresentation->CurrentGroup()->AddPrimitiveArray(myExternalArray); } void Sample2D_Face::HilightSelected (const Handle(PrsMgr_PresentationManager)& thePrsMgr, const SelectMgr_SequenceOfOwner& theOwners) { Handle(Prs3d_Presentation) aSelectionPrs = GetSelectPresentation (thePrsMgr); Handle(Graphic3d_AspectLine3d) aLineAspect = new Graphic3d_AspectLine3d(Quantity_NOC_ANTIQUEWHITE, Aspect_TOL_SOLID, 2); if (HasPresentation()) { aSelectionPrs->SetTransformPersistence(Presentation()->TransformPersistence()); } const Standard_Integer aLength = theOwners.Length(); aSelectionPrs->Clear(); FillData(); Handle(Graphic3d_Group) aSelectGroup = aSelectionPrs->NewGroup(); for (Standard_Integer i = 1; i <= aLength; ++i) { Handle(SelectMgr_EntityOwner) anOwner = theOwners.Value(i); // check priority of owner to add primitives in one of array // containing primitives with certain type of orientation switch (anOwner->Priority()) { case 7: { // add to objects with forward orientation aSelectGroup->SetGroupPrimitivesAspect(aLineAspect); aSelectGroup->AddPrimitiveArray(myForwardArray); break; } case 6: { // add to objects with reversed orientation aSelectGroup->SetGroupPrimitivesAspect(aLineAspect); aSelectGroup->AddPrimitiveArray(myReversedArray); break; } case 5: { // add to objects with internal orientation aSelectGroup->SetGroupPrimitivesAspect(aLineAspect); aSelectGroup->AddPrimitiveArray(myInternalArray); break; } case 4: { // add to objects with external orientation aSelectGroup->SetGroupPrimitivesAspect(aLineAspect); aSelectGroup->AddPrimitiveArray(myExternalArray); break; } } } aSelectionPrs->Display(); } void Sample2D_Face::ClearSelected() { if (Handle(Prs3d_Presentation) aSelectionPrs = GetSelectPresentation(NULL)) { aSelectionPrs->Clear(); } } void Sample2D_Face::HilightOwnerWithColor (const Handle(PrsMgr_PresentationManager)& thePM, const Handle(Prs3d_Drawer)& theStyle, const Handle(SelectMgr_EntityOwner)& theOwner) { Handle(Prs3d_Presentation) aHighlightPrs = GetHilightPresentation(thePM); if (HasPresentation()) { aHighlightPrs->SetTransformPersistence(Presentation()->TransformPersistence()); } if (theOwner.IsNull()) { return; } aHighlightPrs->Clear(); FillData(); // Direct highlighting aHighlightPrs->NewGroup(); Handle(Graphic3d_Group) aHilightGroup = aHighlightPrs->CurrentGroup(); Handle(Graphic3d_AspectLine3d) aLineAspect = new Graphic3d_AspectLine3d(theStyle->Color(), Aspect_TOL_SOLID, 2); switch (theOwner->Priority()) { case 7: { aHilightGroup->SetGroupPrimitivesAspect(aLineAspect); aHilightGroup->AddPrimitiveArray(myForwardArray); break; } case 6: { aHilightGroup->SetGroupPrimitivesAspect(aLineAspect); aHilightGroup->AddPrimitiveArray(myReversedArray); break; } case 5: { aHilightGroup->SetGroupPrimitivesAspect(aLineAspect); aHilightGroup->AddPrimitiveArray(myInternalArray); break; } case 4: { aHilightGroup->SetGroupPrimitivesAspect(aLineAspect); aHilightGroup->AddPrimitiveArray(myExternalArray); break; } } if (thePM->IsImmediateModeOn()) { thePM->AddToImmediateList(aHighlightPrs); } } void Sample2D_Face::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection, const Standard_Integer theMode) { if (myshape.IsNull() || theMode != 0) { return; } if (mySeq_FORWARD.IsEmpty() && mySeq_REVERSED.IsEmpty() && mySeq_INTERNAL.IsEmpty() && mySeq_EXTERNAL.IsEmpty()) { return; } // create entity owner for every part of the face // set different priorities for primitives of different orientation Handle(SelectMgr_EntityOwner) anOwner_Forward = new SelectMgr_EntityOwner(this, 7); Handle(SelectMgr_EntityOwner) anOwner_Reversed = new SelectMgr_EntityOwner(this, 6); Handle(SelectMgr_EntityOwner) anOwner_Internal = new SelectMgr_EntityOwner(this, 5); Handle(SelectMgr_EntityOwner) anOwner_External = new SelectMgr_EntityOwner(this, 4); // create a sensitive for every part Handle(Select3D_SensitiveGroup) aForwardGroup = new Select3D_SensitiveGroup(anOwner_Forward); Handle(Select3D_SensitiveGroup) aReversedGroup = new Select3D_SensitiveGroup(anOwner_Reversed); Handle(Select3D_SensitiveGroup) aInternalGroup = new Select3D_SensitiveGroup(anOwner_Internal); Handle(Select3D_SensitiveGroup) aExternalGroup = new Select3D_SensitiveGroup(anOwner_External); Standard_Integer aLength = mySeq_FORWARD.Length(); for (Standard_Integer i = 1; i <= aLength; ++i) { Handle(Select3D_SensitiveCurve) aSensitveCurve = new Select3D_SensitiveCurve(anOwner_Forward, mySeq_FORWARD(i)); aForwardGroup->Add(aSensitveCurve); } theSelection->Add(aForwardGroup); aLength = mySeq_REVERSED.Length(); for (Standard_Integer i = 1; i <= aLength; ++i) { Handle(Select3D_SensitiveCurve) aSensitveCurve = new Select3D_SensitiveCurve(anOwner_Reversed, mySeq_REVERSED(i)); aReversedGroup->Add(aSensitveCurve); } theSelection->Add(aReversedGroup); aLength = mySeq_INTERNAL.Length(); for (Standard_Integer i = 1; i <= aLength; ++i) { Handle(Select3D_SensitiveCurve) aSensitveCurve = new Select3D_SensitiveCurve(anOwner_Internal, mySeq_INTERNAL(i)); aInternalGroup->Add(aSensitveCurve); } theSelection->Add(aInternalGroup); aLength = mySeq_EXTERNAL.Length(); for (Standard_Integer i = 1; i <= aLength; ++i) { Handle(Select3D_SensitiveCurve) aSensitveCurve = new Select3D_SensitiveCurve(anOwner_External, mySeq_EXTERNAL(i)); aExternalGroup->Add(aSensitveCurve); } theSelection->Add(aExternalGroup); }