From fec86abc094d75bf442dd045abdd29e70e09e731 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Tr=C3=B6ger?= Date: Tue, 19 May 2015 22:05:46 +0200 Subject: [PATCH] visualize the primitive add/sub shape in edit --- src/Mod/Part/Gui/ViewProviderExt.cpp | 2 +- src/Mod/Part/Gui/ViewProviderExt.h | 5 + src/Mod/PartDesign/Gui/CommandPrimitive.cpp | 9 +- .../Gui/TaskPrimitiveParameters.cpp | 15 +- .../PartDesign/Gui/TaskPrimitiveParameters.h | 1 + .../PartDesign/Gui/ViewProviderDatumCS.cpp | 20 +- .../PartDesign/Gui/ViewProviderPrimitive.cpp | 236 +++++++++++++++++- .../PartDesign/Gui/ViewProviderPrimitive.h | 13 + 8 files changed, 286 insertions(+), 15 deletions(-) diff --git a/src/Mod/Part/Gui/ViewProviderExt.cpp b/src/Mod/Part/Gui/ViewProviderExt.cpp index 73621fc9b..34bb85db0 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.cpp +++ b/src/Mod/Part/Gui/ViewProviderExt.cpp @@ -127,7 +127,7 @@ using namespace PartGui; PROPERTY_SOURCE(PartGui::ViewProviderPartExt, Gui::ViewProviderGeometryObject) -void GetNormals(const TopoDS_Face& theFace, +void ViewProviderPartExt::GetNormals(const TopoDS_Face& theFace, const Handle(Poly_Triangulation)& aPolyTri, TColgp_Array1OfDir& theNormals) { diff --git a/src/Mod/Part/Gui/ViewProviderExt.h b/src/Mod/Part/Gui/ViewProviderExt.h index 97170e878..0f68a0024 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.h +++ b/src/Mod/Part/Gui/ViewProviderExt.h @@ -27,6 +27,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -125,6 +128,8 @@ protected: virtual void onChanged(const App::Property* prop); bool loadParameter(); void updateVisual(const TopoDS_Shape &); + void GetNormals(const TopoDS_Face& theFace, const Handle(Poly_Triangulation)& aPolyTri, + TColgp_Array1OfDir& theNormals); // nodes for the data representation SoMaterialBinding * pcShapeBind; diff --git a/src/Mod/PartDesign/Gui/CommandPrimitive.cpp b/src/Mod/PartDesign/Gui/CommandPrimitive.cpp index d702c346c..208440295 100644 --- a/src/Mod/PartDesign/Gui/CommandPrimitive.cpp +++ b/src/Mod/PartDesign/Gui/CommandPrimitive.cpp @@ -24,6 +24,7 @@ #include "PreCompiled.h" #include "Workbench.h" #include +#include #ifndef _PreComp_ # include # include @@ -95,11 +96,9 @@ void CmdPrimtiveCompAdditive::activated(int iMsg) FeatName.c_str(), CSName.c_str()); Gui::Command::updateActive(); - if (isActiveObjectValid() && (pcActiveBody != NULL)) { - App::DocumentObject* prevSolidFeature = pcActiveBody->getPrevSolidFeature(NULL, false); - if (prevSolidFeature != NULL && strcmp(prevSolidFeature->getNameInDocument(), FeatName.c_str())!=0) - doCommand(Gui,"Gui.activeDocument().hide(\"%s\")", prevSolidFeature->getNameInDocument()); - } + auto* prm = static_cast(getDocument()->getObject(FeatName.c_str())); + if (prm->BaseFeature.getValue()) + doCommand(Gui,"Gui.activeDocument().hide(\"%s\")", prm->BaseFeature.getValue()->getNameInDocument()); Gui::Command::doCommand(Gui, "Gui.activeDocument().hide(\'%s\')", CSName.c_str()); Gui::Command::doCommand(Gui, "Gui.activeDocument().setEdit(\'%s\')", FeatName.c_str()); diff --git a/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.cpp b/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.cpp index 5487590c4..d73a27d70 100644 --- a/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.cpp @@ -528,7 +528,7 @@ void TaskBoxPrimitives::createPrimitive(const QString& placement) } }*/ -TaskPrimitiveParameters::TaskPrimitiveParameters(ViewProviderPrimitive* PrimitiveView) +TaskPrimitiveParameters::TaskPrimitiveParameters(ViewProviderPrimitive* PrimitiveView) : vp_prm(PrimitiveView) { assert(PrimitiveView); @@ -548,8 +548,15 @@ TaskPrimitiveParameters::TaskPrimitiveParameters(ViewProviderPrimitive* Primitiv Gui::Application::Instance->activeDocument()->getViewProvider(cs)); assert(vp); + + //make sure the relevant things are visible cs_visibility = vp->isVisible(); vp->Visibility.setValue(true); + if(prm->BaseFeature.getValue()) { + Gui::Application::Instance->activeDocument()->getViewProvider(prm->BaseFeature.getValue())->setVisible(true); + vp_prm->setVisible(false); + } + parameter = new TaskDatumParameters(vp); Content.push_back(parameter); @@ -562,6 +569,12 @@ TaskPrimitiveParameters::~TaskPrimitiveParameters() ViewProviderDatumCoordinateSystem* vp = static_cast( Gui::Application::Instance->activeDocument()->getViewProvider(cs)); vp->setVisible(cs_visibility); + + auto* prm = static_cast(vp_prm->getObject()); + if(prm->BaseFeature.getValue()) { + Gui::Application::Instance->activeDocument()->getViewProvider(prm->BaseFeature.getValue())->setVisible(false); + } + vp_prm->setVisible(true); } bool TaskPrimitiveParameters::accept() diff --git a/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.h b/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.h index e10d15e75..4e4681f68 100644 --- a/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.h +++ b/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.h @@ -92,6 +92,7 @@ private: TaskBoxPrimitives* primitive; TaskDatumParameters* parameter; PartDesign::CoordinateSystem* cs; + ViewProviderPrimitive* vp_prm; bool cs_visibility; }; diff --git a/src/Mod/PartDesign/Gui/ViewProviderDatumCS.cpp b/src/Mod/PartDesign/Gui/ViewProviderDatumCS.cpp index 54c2e581f..05719943e 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderDatumCS.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderDatumCS.cpp @@ -81,6 +81,13 @@ void ViewProviderDatumCoordinateSystem::updateData(const App::Property* prop) getPointForDirection(Base::Vector3d(1,0,0), x); getPointForDirection(Base::Vector3d(0,1,0), y); getPointForDirection(Base::Vector3d(0,0,1), z); + + //normalize all to equal lengths + Base::Vector3d axis = (x.Sqr() > y.Sqr()) ? x : y; + axis = (axis.Sqr() > z.Sqr()) ? axis : z; + x = x.Normalize()*axis.Length(); + y = y.Normalize()*axis.Length(); + z = z.Normalize()*axis.Length(); // Display the line @@ -97,13 +104,12 @@ void ViewProviderDatumCoordinateSystem::updateData(const App::Property* prop) pShapeSep->addChild(coord); lineSet = new PartGui::SoBrepEdgeSet(); - lineSet->coordIndex.setNum(6); - lineSet->coordIndex.set1Value(0, 0); - lineSet->coordIndex.set1Value(1, 1); - lineSet->coordIndex.set1Value(2, 0); - lineSet->coordIndex.set1Value(3, 2); - lineSet->coordIndex.set1Value(4, 0); - lineSet->coordIndex.set1Value(5, 3); + lineSet->coordIndex.setNum(5); + lineSet->coordIndex.set1Value(0, 1); + lineSet->coordIndex.set1Value(1, 0); + lineSet->coordIndex.set1Value(2, 2); + lineSet->coordIndex.set1Value(3, 0); + lineSet->coordIndex.set1Value(4, 3); pShapeSep->addChild(lineSet); } else { coord = static_cast(pShapeSep->getChild(1)); diff --git a/src/Mod/PartDesign/Gui/ViewProviderPrimitive.cpp b/src/Mod/PartDesign/Gui/ViewProviderPrimitive.cpp index 6a33dfa93..acd4ee3b9 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderPrimitive.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderPrimitive.cpp @@ -29,6 +29,7 @@ #include "ViewProviderPrimitive.h" #include "TaskPrimitiveParameters.h" +#include "Mod/Part/Gui/SoBrepFaceSet.h" #include #include #include @@ -36,6 +37,17 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace PartDesignGui; @@ -44,15 +56,223 @@ PROPERTY_SOURCE(PartDesignGui::ViewProviderPrimitive,PartDesignGui::ViewProvider ViewProviderPrimitive::ViewProviderPrimitive() { - + + previewSwitch = new SoSwitch(); + previewSwitch->ref(); + previewShape = new SoSeparator(); + previewShape->ref(); + previewFaceSet = new PartGui::SoBrepFaceSet(); + previewFaceSet->ref(); + previewCoords = new SoCoordinate3(); + previewCoords->ref(); + previewNorm = new SoNormal(); + previewNorm->ref(); + } ViewProviderPrimitive::~ViewProviderPrimitive() { + previewFaceSet->unref(); + previewCoords->unref(); + previewNorm->unref(); + previewShape->unref(); + previewSwitch->unref(); } +void ViewProviderPrimitive::attach(App::DocumentObject* obj) { + + ViewProvider::attach(obj); + + auto* bind = new SoMaterialBinding(); + bind->value = SoMaterialBinding::OVERALL; + auto* material = new SoMaterial(); + if(static_cast(obj)->getAddSubType() == PartDesign::FeatureAddSub::Additive) + material->diffuseColor = SbColor(1,1,0); + else + material->diffuseColor = SbColor(1,0,0); + + material->transparency = 0.7; + auto* pick = new SoPickStyle(); + pick->style = SoPickStyle::UNPICKABLE; + + previewShape->addChild(pick); + previewShape->addChild(bind); + previewShape->addChild(material); + previewShape->addChild(previewCoords); + previewShape->addChild(previewNorm); + previewShape->addChild(previewFaceSet); + previewSwitch->addChild(previewShape); + previewSwitch->whichChild = -1; + getRoot()->addChild(previewSwitch); + updateAddSubShapeIndicator(); +} + +void ViewProviderPrimitive::updateAddSubShapeIndicator() { + + + TopoDS_Shape cShape(static_cast(getObject())->AddSubShape.getValue()); + if (cShape.IsNull()) { + previewCoords ->point .setNum(0); + previewNorm ->vector .setNum(0); + previewFaceSet ->coordIndex .setNum(0); + previewFaceSet ->partIndex .setNum(0); + return; + } + + int numTriangles=0,numNodes=0,numNorms=0,numFaces=0; + std::set faceEdges; + + try { + // calculating the deflection value + Bnd_Box bounds; + BRepBndLib::Add(cShape, bounds); + bounds.SetGap(0.0); + Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; + bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax); + Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 * + Deviation.getValue(); + Standard_Real AngDeflectionRads = AngularDeflection.getValue() / 180.0 * M_PI; + + // create or use the mesh on the data structure +#if OCC_VERSION_HEX >= 0x060600 + BRepMesh_IncrementalMesh(cShape,deflection,Standard_False, + AngDeflectionRads,Standard_True); +#else + BRepMesh_IncrementalMesh(cShape,deflection); +#endif + // We must reset the location here because the transformation data + // are set in the placement property + TopLoc_Location aLoc; + cShape.Location(aLoc); + + // count triangles and nodes in the mesh + TopExp_Explorer Ex; + for (Ex.Init(cShape,TopAbs_FACE);Ex.More();Ex.Next()) { + Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(TopoDS::Face(Ex.Current()), aLoc); + // Note: we must also count empty faces + if (!mesh.IsNull()) { + numTriangles += mesh->NbTriangles(); + numNodes += mesh->NbNodes(); + numNorms += mesh->NbNodes(); + } + numFaces++; + } + + // create memory for the nodes and indexes + previewCoords ->point .setNum(numNodes); + previewNorm ->vector .setNum(numNorms); + previewFaceSet ->coordIndex .setNum(numTriangles*4); + previewFaceSet ->partIndex .setNum(numFaces); + // get the raw memory for fast fill up + SbVec3f* verts = previewCoords ->point .startEditing(); + SbVec3f* previewNorms = previewNorm ->vector .startEditing(); + int32_t* index = previewFaceSet ->coordIndex .startEditing(); + int32_t* parts = previewFaceSet ->partIndex .startEditing(); + + // preset the previewNormal vector with null vector + for (int i=0;i < numNorms;i++) + previewNorms[i]= SbVec3f(0.0,0.0,0.0); + + int ii = 0,faceNodeOffset=0,faceTriaOffset=0; + for (Ex.Init(cShape, TopAbs_FACE); Ex.More(); Ex.Next(),ii++) { + TopLoc_Location aLoc; + const TopoDS_Face &actFace = TopoDS::Face(Ex.Current()); + // get the mesh of the shape + Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(actFace,aLoc); + if (mesh.IsNull()) continue; + + // getting the transformation of the shape/face + gp_Trsf myTransf; + Standard_Boolean identity = true; + if (!aLoc.IsIdentity()) { + identity = false; + myTransf = aLoc.Transformation(); + } + + // getting size of node and triangle array of this face + int nbNodesInFace = mesh->NbNodes(); + int nbTriInFace = mesh->NbTriangles(); + // check orientation + TopAbs_Orientation orient = actFace.Orientation(); + + + // cycling through the poly mesh + const Poly_Array1OfTriangle& Triangles = mesh->Triangles(); + const TColgp_Array1OfPnt& Nodes = mesh->Nodes(); + TColgp_Array1OfDir Normals (Nodes.Lower(), Nodes.Upper()); + GetNormals(actFace, mesh, Normals); + + for (int g=1;g<=nbTriInFace;g++) { + // Get the triangle + Standard_Integer N1,N2,N3; + Triangles(g).Get(N1,N2,N3); + + // change orientation of the triangle if the face is reversed + if ( orient != TopAbs_FORWARD ) { + Standard_Integer tmp = N1; + N1 = N2; + N2 = tmp; + } + + // get the 3 points of this triangle + gp_Pnt V1(Nodes(N1)), V2(Nodes(N2)), V3(Nodes(N3)); + + // get the 3 previewNormals of this triangle + gp_Dir NV1(Normals(N1)), NV2(Normals(N2)), NV3(Normals(N3)); + + // transform the vertices and previewNormals to the place of the face + if(!identity) { + V1.Transform(myTransf); + V2.Transform(myTransf); + V3.Transform(myTransf); + NV1.Transform(myTransf); + NV2.Transform(myTransf); + NV3.Transform(myTransf); + } + + // add the previewNormals for all points of this triangle + previewNorms[faceNodeOffset+N1-1] += SbVec3f(NV1.X(),NV1.Y(),NV1.Z()); + previewNorms[faceNodeOffset+N2-1] += SbVec3f(NV2.X(),NV2.Y(),NV2.Z()); + previewNorms[faceNodeOffset+N3-1] += SbVec3f(NV3.X(),NV3.Y(),NV3.Z()); + + // set the vertices + verts[faceNodeOffset+N1-1].setValue((float)(V1.X()),(float)(V1.Y()),(float)(V1.Z())); + verts[faceNodeOffset+N2-1].setValue((float)(V2.X()),(float)(V2.Y()),(float)(V2.Z())); + verts[faceNodeOffset+N3-1].setValue((float)(V3.X()),(float)(V3.Y()),(float)(V3.Z())); + + // set the index vector with the 3 point indexes and the end delimiter + index[faceTriaOffset*4+4*(g-1)] = faceNodeOffset+N1-1; + index[faceTriaOffset*4+4*(g-1)+1] = faceNodeOffset+N2-1; + index[faceTriaOffset*4+4*(g-1)+2] = faceNodeOffset+N3-1; + index[faceTriaOffset*4+4*(g-1)+3] = SO_END_FACE_INDEX; + } + + parts[ii] = nbTriInFace; // new part + + // counting up the per Face offsets + faceNodeOffset += nbNodesInFace; + faceTriaOffset += nbTriInFace; + } + + // previewNormalize all previewNormals + for (int i = 0; i< numNorms ;i++) + previewNorms[i].normalize(); + + // end the editing of the nodes + previewCoords ->point .finishEditing(); + previewNorm ->vector .finishEditing(); + previewFaceSet ->coordIndex .finishEditing(); + previewFaceSet ->partIndex .finishEditing(); + } + catch (...) { + Base::Console().Error("Cannot compute Inventor representation for the shape of %s.\n",pcObject->getNameInDocument()); + } +} + + bool ViewProviderPrimitive::setEdit(int ModNum) { + previewSwitch->whichChild = 0; if (ModNum == ViewProvider::Default ) { // When double-clicking on the item for this fillet the // object unsets and sets its edit mode without closing @@ -93,6 +313,20 @@ bool ViewProviderPrimitive::setEdit(int ModNum) } } +void ViewProviderPrimitive::unsetEdit(int ModNum) { + previewSwitch->whichChild = -1; +} + +void ViewProviderPrimitive::updateData(const App::Property* p) { + + if(strcmp(p->getName(), "AddSubShape")==0) + updateAddSubShapeIndicator(); + + PartDesignGui::ViewProvider::updateData(p); +} + + + std::vector< App::DocumentObject* > ViewProviderPrimitive::claimChildren(void) const { std::vector< App::DocumentObject* > vec; diff --git a/src/Mod/PartDesign/Gui/ViewProviderPrimitive.h b/src/Mod/PartDesign/Gui/ViewProviderPrimitive.h index d1d2f6821..1ae47d1b1 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderPrimitive.h +++ b/src/Mod/PartDesign/Gui/ViewProviderPrimitive.h @@ -25,7 +25,9 @@ #define PARTGUI_ViewProviderPrimitive_H #include "ViewProvider.h" +#include +class SoSwitch; namespace PartDesignGui { @@ -40,10 +42,21 @@ public: virtual ~ViewProviderPrimitive(); virtual std::vector< App::DocumentObject* > claimChildren(void) const; + virtual void attach(App::DocumentObject*); + virtual void updateData(const App::Property*); protected: virtual QIcon getIcon(void) const; virtual bool setEdit(int ModNum); + virtual void unsetEdit(int ModNum); + + void updateAddSubShapeIndicator(); + + SoSwitch* previewSwitch; + SoSeparator* previewShape; + PartGui::SoBrepFaceSet* previewFaceSet; + SoCoordinate3* previewCoords; + SoNormal* previewNorm; }; } // namespace PartDesignGui