diff --git a/src/Mod/TechDraw/App/DrawProjGroup.cpp b/src/Mod/TechDraw/App/DrawProjGroup.cpp index 1db38b9931..3eebe56587 100644 --- a/src/Mod/TechDraw/App/DrawProjGroup.cpp +++ b/src/Mod/TechDraw/App/DrawProjGroup.cpp @@ -64,6 +64,7 @@ DrawProjGroup::DrawProjGroup(void) ADD_PROPERTY_TYPE(Source ,(0), group, App::Prop_None,"Shape to view"); + Source.setScope(App::LinkScope::Global); ADD_PROPERTY_TYPE(Anchor, (0), group, App::Prop_None, "The root view to align projections with"); ProjectionType.setEnums(ProjectionTypeEnums); ADD_PROPERTY(ProjectionType, ((long)0)); @@ -96,8 +97,8 @@ void DrawProjGroup::onChanged(const App::Property* prop) TechDraw::DrawPage *page = getPage(); if (!isRestoring() && page) { if (prop == &Source) { - App::DocumentObject* sourceObj = Source.getValue(); - if (sourceObj != nullptr) { + std::vector sourceObjs = Source.getValues(); + if (!sourceObjs.empty()) { if (!hasAnchor()) { // if we have a Source, but no Anchor, make an anchor Anchor.setValue(addProjection("Front")); @@ -142,12 +143,12 @@ App::DocumentObjectExecReturn *DrawProjGroup::execute(void) return DrawViewCollection::execute(); } - App::DocumentObject* docObj = Source.getValue(); - if (docObj == nullptr) { + std::vector docObjs = Source.getValues(); + if (docObjs.empty()) { return DrawViewCollection::execute(); } - docObj = Anchor.getValue(); + App::DocumentObject* docObj = Anchor.getValue(); if (docObj == nullptr) { return DrawViewCollection::execute(); } @@ -380,7 +381,7 @@ App::DocumentObject * DrawProjGroup::addProjection(const char *viewProjType) auto docObj( getDocument()->addObject( "TechDraw::DrawProjGroupItem", //add to Document FeatName.c_str() ) ); view = static_cast( docObj ); - view->Source.setValue( Source.getValue() ); + view->Source.setValues( Source.getValues() ); if (ScaleType.isValue("Automatic")) { view->ScaleType.setValue("Custom"); } else { @@ -389,7 +390,7 @@ App::DocumentObject * DrawProjGroup::addProjection(const char *viewProjType) view->Scale.setValue( getScale() ); view->Type.setValue( viewProjType ); view->Label.setValue( viewProjType ); - view->Source.setValue( Source.getValue() ); + view->Source.setValues( Source.getValues() ); view->Direction.setValue(m_cube->getViewDir(viewProjType)); view->RotationVector.setValue(m_cube->getRotationDir(viewProjType)); addView(view); //from DrawViewCollection diff --git a/src/Mod/TechDraw/App/DrawProjGroup.h b/src/Mod/TechDraw/App/DrawProjGroup.h index af0d123ca4..8b59cb715b 100644 --- a/src/Mod/TechDraw/App/DrawProjGroup.h +++ b/src/Mod/TechDraw/App/DrawProjGroup.h @@ -54,7 +54,7 @@ public: DrawProjGroup(); ~DrawProjGroup(); - App::PropertyLinkGlobal Source; + App::PropertyLinkList Source; App::PropertyEnumeration ProjectionType; App::PropertyBool AutoDistribute; diff --git a/src/Mod/TechDraw/App/DrawViewDetail.cpp b/src/Mod/TechDraw/App/DrawViewDetail.cpp index 17344252eb..c6ab41617f 100644 --- a/src/Mod/TechDraw/App/DrawViewDetail.cpp +++ b/src/Mod/TechDraw/App/DrawViewDetail.cpp @@ -150,27 +150,23 @@ App::DocumentObjectExecReturn *DrawViewDetail::execute(void) return App::DocumentObject::StdReturn; } - App::DocumentObject* link = Source.getValue(); - App::DocumentObject* base = BaseView.getValue(); - if (!link || !base) { - Base::Console().Log("INFO - DVD::execute - No Source or Link - creation?\n"); + App::DocumentObject* baseObj = BaseView.getValue(); + if (!baseObj) { + Base::Console().Log("INFO - DVD::execute - No BaseView - creation?\n"); return DrawView::execute(); } - if (!link->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) - return new App::DocumentObjectExecReturn("Source object is not a Part object"); DrawViewPart* dvp = nullptr; - if (!base->getTypeId().isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) { + if (!baseObj->getTypeId().isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) { return new App::DocumentObjectExecReturn("BaseView object is not a DrawViewPart object"); } else { - dvp = static_cast(base); + dvp = static_cast(baseObj); } - //Base::Console().Message("TRACE - DVD::execute() - %s/%s\n",getNameInDocument(),Label.getValue()); - - const Part::TopoShape &partTopo = static_cast(link)->Shape.getShape(); - if (partTopo.getShape().IsNull()) - return new App::DocumentObjectExecReturn("Linked shape object is empty"); + TopoDS_Shape shape = dvp->getSourceShapeFused(); + if (shape.IsNull()) { + return new App::DocumentObjectExecReturn("DVD - Linked shape object is invalid"); + } Base::Vector3d anchor = AnchorPoint.getValue(); //this is a 2D point anchor = Base::Vector3d(anchor.x,anchor.y, 0.0); @@ -179,15 +175,17 @@ App::DocumentObjectExecReturn *DrawViewDetail::execute(void) double scale = getScale(); gp_Ax2 viewAxis = getViewAxis(Base::Vector3d(0.0,0.0,0.0), dirDetail, false); - Base::BoundBox3d bbxSource = partTopo.getBoundBox(); + Bnd_Box bbxSource; + BRepBndLib::Add(shape, bbxSource); + bbxSource.SetGap(0.0); + double diag = sqrt(bbxSource.SquareExtent()); - BRepBuilderAPI_Copy BuilderCopy(partTopo.getShape()); + BRepBuilderAPI_Copy BuilderCopy(shape); TopoDS_Shape myShape = BuilderCopy.Shape(); gp_Pnt gpCenter = TechDrawGeometry::findCentroid(myShape, dirDetail); Base::Vector3d shapeCenter = Base::Vector3d(gpCenter.X(),gpCenter.Y(),gpCenter.Z()); - double diag = bbxSource.CalcDiagonalLength(); Base::Vector3d extentFar,extentNear; extentFar = shapeCenter + dirDetail * diag; extentNear = shapeCenter + dirDetail * diag * -1.0; diff --git a/src/Mod/TechDraw/App/DrawViewPart.cpp b/src/Mod/TechDraw/App/DrawViewPart.cpp index 162c71f30b..223ec94a02 100644 --- a/src/Mod/TechDraw/App/DrawViewPart.cpp +++ b/src/Mod/TechDraw/App/DrawViewPart.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -127,6 +128,7 @@ DrawViewPart::DrawViewPart(void) : geometryObject(0) //properties that affect Geometry ADD_PROPERTY_TYPE(Source ,(0),group,App::Prop_None,"3D Shape to view"); + Source.setScope(App::LinkScope::Global); ADD_PROPERTY_TYPE(Direction ,(0,0,1.0) ,group,App::Prop_None,"Projection direction. The direction you are looking from."); ADD_PROPERTY_TYPE(Perspective ,(false),group,App::Prop_None,"Perspective(true) or Orthographic(false) projection"); ADD_PROPERTY_TYPE(Focus,(defDist),group,App::Prop_None,"Perspective view focus distance"); @@ -178,14 +180,33 @@ DrawViewPart::~DrawViewPart() TopoDS_Shape DrawViewPart::getSourceShape(void) const { TopoDS_Shape result; - App::DocumentObject *link = Source.getValue(); - if (!link) { - Base::Console().Error("DVP - No Source object linked - %s\n",getNameInDocument()); - } else if (link->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { - result = static_cast(link)->Shape.getShape().getShape(); - } else if (link->getTypeId().isDerivedFrom(App::Part::getClassTypeId())) { - result = getShapeFromPart(static_cast(link)); - } else { Base::Console().Error("DVP - Can't handle this Source - %s\n",getNameInDocument()); + const std::vector& links = Source.getValues(); + if (links.empty()) { + Base::Console().Log("DVP::getSourceShape - No Sources - creation? - %s\n",getNameInDocument()); + } else { + BRep_Builder builder; + TopoDS_Compound comp; + builder.MakeCompound(comp); + for (auto& l:links) { + if (l->isDerivedFrom(Part::Feature::getClassTypeId())){ + const Part::TopoShape &partTopo = static_cast(l)->Shape.getShape(); + if (partTopo.isNull()) { + continue; //has no shape + } + BRepBuilderAPI_Copy BuilderCopy(partTopo.getShape()); + TopoDS_Shape shape = BuilderCopy.Shape(); + builder.Add(comp, shape); + } else if (l->getTypeId().isDerivedFrom(App::Part::getClassTypeId())) { + TopoDS_Shape s = getShapeFromPart(static_cast(l)); + if (s.IsNull()) { + continue; + } + BRepBuilderAPI_Copy BuilderCopy(s); + TopoDS_Shape shape = BuilderCopy.Shape(); + builder.Add(comp, shape); + } + } + result = comp; } return result; } @@ -214,7 +235,25 @@ TopoDS_Shape DrawViewPart::getShapeFromPart(App::Part* ap) const return result; } - +TopoDS_Shape DrawViewPart::getSourceShapeFused(void) const +{ + TopoDS_Shape baseShape = getSourceShape(); + TopoDS_Iterator it(baseShape); + TopoDS_Shape fusedShape = it.Value(); + it.Next(); + for (; it.More(); it.Next()) { + const TopoDS_Shape& aChild = it.Value(); + BRepAlgoAPI_Fuse mkFuse(fusedShape, aChild); + // Let's check if the fusion has been successful + if (!mkFuse.IsDone()) { + Base::Console().Error("DVp - Fusion failed\n"); + return baseShape; + } + fusedShape = mkFuse.Shape(); + } + baseShape = fusedShape; + return baseShape; +} App::DocumentObjectExecReturn *DrawViewPart::execute(void) { diff --git a/src/Mod/TechDraw/App/DrawViewPart.h b/src/Mod/TechDraw/App/DrawViewPart.h index 3ddb8b7d36..2ce0b48160 100644 --- a/src/Mod/TechDraw/App/DrawViewPart.h +++ b/src/Mod/TechDraw/App/DrawViewPart.h @@ -82,7 +82,7 @@ public: DrawViewPart(void); virtual ~DrawViewPart(); - App::PropertyLinkGlobal Source; //Part Feature + App::PropertyLinkList Source; App::PropertyVector Direction; //TODO: Rename to YAxisDirection or whatever this actually is (ProjectionDirection) App::PropertyBool Perspective; App::PropertyDistance Focus; @@ -166,7 +166,8 @@ public: virtual std::vector getWireForFace(int idx) const; virtual TopoDS_Shape getSourceShape(void) const; virtual TopoDS_Shape getShapeFromPart(App::Part* ap) const; - + virtual TopoDS_Shape getSourceShapeFused(void) const; + protected: TechDrawGeometry::GeometryObject *geometryObject; Base::BoundBox3d bbox; diff --git a/src/Mod/TechDraw/App/DrawViewSection.cpp b/src/Mod/TechDraw/App/DrawViewSection.cpp index 69ceec3f06..40b1bba132 100644 --- a/src/Mod/TechDraw/App/DrawViewSection.cpp +++ b/src/Mod/TechDraw/App/DrawViewSection.cpp @@ -199,7 +199,7 @@ App::DocumentObjectExecReturn *DrawViewSection::execute(void) if (!base->getTypeId().isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) return new App::DocumentObjectExecReturn("BaseView object is not a DrawViewPart object"); - TopoDS_Shape baseShape = static_cast(base)->getSourceShape(); + TopoDS_Shape baseShape = static_cast(base)->getSourceShapeFused(); if (baseShape.IsNull()) { Base::Console().Log("DVS::execute - baseShape is Null\n"); } @@ -244,6 +244,7 @@ App::DocumentObjectExecReturn *DrawViewSection::execute(void) } TopoDS_Shape rawShape = mkCut.Shape(); + Bnd_Box testBox; BRepBndLib::Add(rawShape, testBox); testBox.SetGap(0.0); diff --git a/src/Mod/TechDraw/Gui/Command.cpp b/src/Mod/TechDraw/Gui/Command.cpp index 6e5b78a07c..4ea1ae2a15 100644 --- a/src/Mod/TechDraw/Gui/Command.cpp +++ b/src/Mod/TechDraw/Gui/Command.cpp @@ -272,34 +272,17 @@ void CmdTechDrawNewView::activated(int iMsg) Gui::WaitCursor wc; const auto selectedProjections( getSelection().getObjectsOfType(TechDraw::DrawView::getClassTypeId()) ); - float newScale = 1.0; - float newRotation = 0.0; - Base::Vector3d newDirection(0.0, 0.0, 1.0); - if (!selectedProjections.empty()) { - const auto myView( static_cast(selectedProjections.front()) ); - - newScale = myView->getScale(); - newRotation = myView->Rotation.getValue(); - - // The "Direction" property does not belong to TechDraw::DrawView, but to one of the - // many child classes that are projecting objects into the drawing. Therefore, we get the - // property by name. - const App::PropertyVector* const propDirection = dynamic_cast(myView->getPropertyByName("Direction")); - if (propDirection) { - newDirection = propDirection->getValue(); - } - } openCommand("Create view"); - for (std::vector::iterator it = shapes.begin(); it != shapes.end(); ++it) { - std::string FeatName = getUniqueObjectName("View"); - doCommand(Doc,"App.activeDocument().addObject('TechDraw::DrawViewPart','%s')",FeatName.c_str()); - doCommand(Doc,"App.activeDocument().%s.Source = App.activeDocument().%s",FeatName.c_str(),(*it)->getNameInDocument()); - doCommand(Doc,"App.activeDocument().%s.Direction = (%e,%e,%e)",FeatName.c_str(), newDirection.x, newDirection.y, newDirection.z); - doCommand(Doc,"App.activeDocument().%s.Scale = %e",FeatName.c_str(), newScale); - doCommand(Doc,"App.activeDocument().%s.Rotation = %e",FeatName.c_str(), newRotation); - doCommand(Doc,"App.activeDocument().%s.addView(App.activeDocument().%s)",PageName.c_str(),FeatName.c_str()); + std::string FeatName = getUniqueObjectName("View"); + doCommand(Doc,"App.activeDocument().addObject('TechDraw::DrawViewPart','%s')",FeatName.c_str()); + App::DocumentObject *docObj = getDocument()->getObject(FeatName.c_str()); + TechDraw::DrawViewPart* dvp = dynamic_cast(docObj); + if (!dvp) { + throw Base::Exception("CmdTechDrawNewView DVP not found\n"); } + dvp->Source.setValues(shapes); + doCommand(Doc,"App.activeDocument().%s.addView(App.activeDocument().%s)",PageName.c_str(),FeatName.c_str()); updateActive(); commitCommand(); } @@ -335,35 +318,32 @@ void CmdTechDrawNewViewSection::activated(int iMsg) return; } - //std::vector shapes = getSelection().getObjectsOfType(Part::Feature::getClassTypeId()); - std::vector shapes = getSelection().getObjectsOfType(TechDraw::DrawViewPart::getClassTypeId()); - if (shapes.empty()) { + std::vector baseObj = getSelection().getObjectsOfType(TechDraw::DrawViewPart::getClassTypeId()); + if (baseObj.empty()) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), - QObject::tr("Select at least 1 DrawingView object.")); + QObject::tr("Select at least 1 DrawViewPart object as Base.")); return; } - App::DocumentObject* dObj = *(shapes.begin()); - TechDraw::DrawViewPart* dvp = static_cast(dObj); - + TechDraw::DrawViewPart* dvp = static_cast(*baseObj.begin()); + std::string BaseName = dvp->getNameInDocument(); std::string PageName = page->getNameInDocument(); Gui::WaitCursor wc; openCommand("Create view"); - std::string FeatName = getUniqueObjectName("Section"); - std::string SourceName = dvp->Source.getValue()->getNameInDocument(); - std::string BaseName = (dObj)->getNameInDocument(); + doCommand(Doc,"App.activeDocument().addObject('TechDraw::DrawViewSection','%s')",FeatName.c_str()); - doCommand(Doc,"App.activeDocument().%s.Source = App.activeDocument().%s",FeatName.c_str(),SourceName.c_str()); - doCommand(Doc,"App.activeDocument().%s.BaseView = App.activeDocument().%s",FeatName.c_str(),BaseName.c_str()); - doCommand(Doc,"App.activeDocument().%s.Scale = App.activeDocument().%s.Scale",FeatName.c_str(),BaseName.c_str()); - doCommand(Doc,"App.activeDocument().%s.ScaleType = App.activeDocument().%s.ScaleType",FeatName.c_str(),BaseName.c_str()); - doCommand(Doc,"App.activeDocument().%s.addView(App.activeDocument().%s)",PageName.c_str(),FeatName.c_str()); + App::DocumentObject *docObj = getDocument()->getObject(FeatName.c_str()); TechDraw::DrawViewSection* dsv = dynamic_cast(docObj); if (!dsv) { throw Base::Exception("CmdTechDrawNewViewSection DSV not found\n"); } + dsv->Source.setValues(dvp->Source.getValues()); + doCommand(Doc,"App.activeDocument().%s.BaseView = App.activeDocument().%s",FeatName.c_str(),BaseName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Scale = App.activeDocument().%s.Scale",FeatName.c_str(),BaseName.c_str()); + doCommand(Doc,"App.activeDocument().%s.ScaleType = App.activeDocument().%s.ScaleType",FeatName.c_str(),BaseName.c_str()); + doCommand(Doc,"App.activeDocument().%s.addView(App.activeDocument().%s)",PageName.c_str(),FeatName.c_str()); Gui::Control().showDialog(new TaskDlgSectionView(dvp,dsv)); updateActive(); @@ -407,14 +387,13 @@ void CmdTechDrawNewViewDetail::activated(int iMsg) return; } - std::vector shapes = getSelection().getObjectsOfType(TechDraw::DrawViewPart::getClassTypeId()); - if (shapes.empty()) { + std::vector baseObj = getSelection().getObjectsOfType(TechDraw::DrawViewPart::getClassTypeId()); + if (baseObj.empty()) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), - QObject::tr("Select at least 1 DrawingView object.")); + QObject::tr("Select at least 1 DrawViewPart object as Base.")); return; } - App::DocumentObject* dObj = *(shapes.begin()); - TechDraw::DrawViewPart* dvp = static_cast(dObj); + TechDraw::DrawViewPart* dvp = static_cast(*(baseObj.begin())); std::string PageName = page->getNameInDocument(); @@ -422,11 +401,16 @@ void CmdTechDrawNewViewDetail::activated(int iMsg) openCommand("Create view"); std::string FeatName = getUniqueObjectName("Detail"); - std::string SourceName = dvp->Source.getValue()->getNameInDocument(); doCommand(Doc,"App.activeDocument().addObject('TechDraw::DrawViewDetail','%s')",FeatName.c_str()); - doCommand(Doc,"App.activeDocument().%s.Source = App.activeDocument().%s",FeatName.c_str(),SourceName.c_str()); - doCommand(Doc,"App.activeDocument().%s.BaseView = App.activeDocument().%s",FeatName.c_str(),(dObj)->getNameInDocument()); - doCommand(Doc,"App.activeDocument().%s.Direction = App.activeDocument().%s.Direction",FeatName.c_str(),(dObj)->getNameInDocument()); + App::DocumentObject *docObj = getDocument()->getObject(FeatName.c_str()); + TechDraw::DrawViewDetail* dvd = dynamic_cast(docObj); + if (!dvd) { + throw Base::Exception("CmdTechDrawNewViewDetail DVD not found\n"); + } + dvd->Source.setValues(dvp->Source.getValues()); + + doCommand(Doc,"App.activeDocument().%s.BaseView = App.activeDocument().%s",FeatName.c_str(),dvp->getNameInDocument()); + doCommand(Doc,"App.activeDocument().%s.Direction = App.activeDocument().%s.Direction",FeatName.c_str(),dvp->getNameInDocument()); doCommand(Doc,"App.activeDocument().%s.addView(App.activeDocument().%s)",PageName.c_str(),FeatName.c_str()); updateActive(); @@ -500,10 +484,11 @@ void CmdTechDrawProjGroup::activated(int iMsg) std::string SourceName = (*shapes.begin())->getNameInDocument(); doCommand(Doc,"App.activeDocument().addObject('TechDraw::DrawProjGroup','%s')",multiViewName.c_str()); doCommand(Doc,"App.activeDocument().%s.addView(App.activeDocument().%s)",PageName.c_str(),multiViewName.c_str()); - doCommand(Doc,"App.activeDocument().%s.Source = App.activeDocument().%s",multiViewName.c_str(),SourceName.c_str()); +// doCommand(Doc,"App.activeDocument().%s.Source = App.activeDocument().%s",multiViewName.c_str(),SourceName.c_str()); App::DocumentObject *docObj = getDocument()->getObject(multiViewName.c_str()); auto multiView( static_cast(docObj) ); + multiView->Source.setValues(shapes); //updateActive(); //exec all pending actions, but there's nothing to do here. commitCommand(); //write the undo