Part:Improve support for Links

This commit is contained in:
mwganson
2022-02-28 00:46:10 -06:00
committed by Uwe
parent 6467ecab33
commit 731ed820b5
10 changed files with 379 additions and 241 deletions

View File

@@ -26,6 +26,7 @@
#include "FeatureOffset.h"
#include <App/Link.h>
using namespace Part;
@@ -131,8 +132,14 @@ short Offset2D::mustExecute() const
App::DocumentObjectExecReturn *Offset2D::execute(void)
{
App::DocumentObject* source = Source.getValue();
if (!(source && source->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())))
if (!source) {
return new App::DocumentObjectExecReturn("No source shape linked.");
}
const TopoShape shape = Part::Feature::getTopoShape(source);
if (shape.isNull()) {
return new App::DocumentObjectExecReturn("No source shape linked.");
}
double offset = Value.getValue();
short mode = (short)Mode.getValue();
short join = (short)Join.getValue();
@@ -140,7 +147,7 @@ App::DocumentObjectExecReturn *Offset2D::execute(void)
bool inter = Intersection.getValue();
if (mode == 2)
return new App::DocumentObjectExecReturn("Mode 'Recto-Verso' is not supported for 2D offset.");
const TopoShape& shape = static_cast<Part::Feature*>(source)->Shape.getShape();
this->Shape.setValue(shape.makeOffset2D(offset, join, fill, mode == 0, inter));
return App::DocumentObject::StdReturn;
}

View File

@@ -46,6 +46,7 @@
#include "PartFeatures.h"
#include <App/Link.h>
using namespace Part;
@@ -82,20 +83,21 @@ App::DocumentObjectExecReturn* RuledSurface::getShape(const App::PropertyLinkSub
TopoDS_Shape& shape) const
{
App::DocumentObject* obj = link.getValue();
if (!(obj && obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())))
const Part::TopoShape part = Part::Feature::getShape(obj, "", false, 0, 0, true, false);
if (part.isNull()) {
return new App::DocumentObjectExecReturn("No shape linked.");
}
// if no explicit sub-shape is selected use the whole part
const std::vector<std::string>& element = link.getSubValues();
if (element.empty()) {
shape = static_cast<Part::Feature*>(obj)->Shape.getValue();
shape = part.getShape();
return nullptr;
}
else if (element.size() != 1) {
return new App::DocumentObjectExecReturn("Not exactly one sub-shape linked.");
}
const Part::TopoShape& part = static_cast<Part::Feature*>(obj)->Shape.getValue();
if (!part.getShape().IsNull()) {
if (!element[0].empty()) {
shape = part.getSubShape(element[0].c_str());

View File

@@ -12,11 +12,17 @@ import FreeCAD as App
def roundVector(v,dec):
return str([round(v[0],dec), round(v[1],dec), round(v[2],dec)])
def buildShapeContent(obj, decimals=2, advancedShapeContent=True):
def buildShapeContent(objArg, decimals=2, advancedShapeContent=True):
linkName = ""
if objArg.isDerivedFrom("App::Link"):
obj = objArg.getLinkedObject()
linkName = "<" + objArg.Name + "> "
else:
obj = objArg
shp = obj.Shape
typeStr = str(shp.ShapeType)
lbl = '' if obj.Name == obj.Label else '(' + obj.Label + ')'
result = obj.Name + lbl + '\n'
result = linkName + obj.Name + lbl + '\n'
result += 'Shape type: '+typeStr+'\n'
result += 'Vertices: '+str(len(shp.Vertexes))+'\n'
result += 'Edges: '+str(len(shp.Edges))+'\n'
@@ -64,17 +70,17 @@ def buildShapeContent(obj, decimals=2, advancedShapeContent=True):
result += str(p)+': '+roundVector(props[p],decimals) +'\n'
else:
result += str(p)+': '+str(props[p])+'\n'
if obj.getGlobalPlacement() != obj.Placement:
rpl = obj.getGlobalPlacement() * obj.Placement.inverse()
rot = rpl.Rotation
if hasattr(shp, 'CenterOfMass'):
result += 'Global CenterOfMass: '+roundVector(rpl.multVec(shp.CenterOfMass),decimals)+'\n'
if hasattr(shp, 'PrincipalProperties'):
props = shp.PrincipalProperties
for p in props:
if 'AxisOfInertia' in p:
result += 'Global ' + str(p)+': '+roundVector(rot.multVec(props[p]),decimals) +'\n'
else:
result += 'Global Placement = Placement'
if hasattr(obj,"getGlobalPlacement"):
if obj.getGlobalPlacement() != obj.Placement:
rpl = obj.getGlobalPlacement() * obj.Placement.inverse()
rot = rpl.Rotation
if hasattr(shp, 'CenterOfMass'):
result += 'Global CenterOfMass: '+roundVector(rpl.multVec(shp.CenterOfMass),decimals)+'\n'
if hasattr(shp, 'PrincipalProperties'):
props = shp.PrincipalProperties
for p in props:
if 'AxisOfInertia' in p:
result += 'Global ' + str(p)+': '+roundVector(rot.multVec(props[p]),decimals) +'\n'
else:
result += 'Global Placement = Placement'
return result

View File

@@ -37,6 +37,7 @@
#include <Base/Console.h>
#include <Base/Exception.h>
#include <Base/Tools.h>
#include <App/Link.h>
#include <Gui/Action.h>
#include <Gui/Application.h>
#include <Gui/BitmapFactory.h>
@@ -251,6 +252,38 @@ bool checkForSolids(const TopoDS_Shape& shape)
return true;
}
/*
* returns vector of Part::TopoShapes from selected Part::Feature derived objects,
* App::Links linked to Part::Features, or App::Part containers with visible Part::Features
*/
std::vector<Part::TopoShape> getShapesFromSelection()
{
std::vector<App::DocumentObject*> objs = Gui::Selection().getObjectsOfType(App::DocumentObject::getClassTypeId());
std::vector <Part::TopoShape> shapes;
for (std::vector<App::DocumentObject*>::iterator it = objs.begin(); it != objs.end(); ++it) {
Part::TopoShape shp = Part::Feature::getTopoShape(*it);
if (!shp.isNull()){
shapes.push_back(shp);
}
}
return shapes;
}
/*
* returns true if selected objects contain valid Part::TopoShapes.
* Objects can be Part::Features, App::Links, or App::Parts
*/
bool hasShapesInSelection()
{
bool hasShapes = false;
std::vector<App::DocumentObject*> docobjs = Gui::Selection().getObjectsOfType(App::DocumentObject::getClassTypeId());
for (std::vector<App::DocumentObject*>::iterator it = docobjs.begin(); it != docobjs.end(); ++it) {
if (!Part::Feature::getTopoShape(*it).isNull()) {
hasShapes = true;
break;
}
}
return hasShapes;
}
}
//===========================================================================
@@ -1005,7 +1038,7 @@ void CmdPartImport::activated(int iMsg)
Gui::WaitCursor wc;
App::Document* pDoc = getDocument();
if (!pDoc) // no document
return;
return;
fn = Base::Tools::escapeEncodeFilename(fn);
openCommand(QT_TRANSLATE_NOOP("Command", "Import Part"));
@@ -1067,7 +1100,7 @@ void CmdPartExport::activated(int iMsg)
if (!fn.isEmpty()) {
App::Document* pDoc = getDocument();
if (!pDoc) // no document
return;
return;
if (select == filter[1] ||
select == filter[3]) {
Gui::Application::Instance->exportTo((const char*)fn.toUtf8(),pDoc->getName(),"ImportGui");
@@ -1270,7 +1303,7 @@ void CmdPartReverseShape::activated(int iMsg)
bool CmdPartReverseShape::isActive(void)
{
return Gui::Selection().countObjectsOfType
(Part::Feature::getClassTypeId()) > 0;
(Part::Feature::getClassTypeId(), 0, 3) > 0;
}
//===========================================================================
@@ -1518,11 +1551,10 @@ void CmdPartCrossSections::activated(int iMsg)
Q_UNUSED(iMsg);
Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog();
if (!dlg) {
std::vector<App::DocumentObject*> obj = Gui::Selection().getObjectsOfType
(Part::Feature::getClassTypeId());
std::vector<Part::TopoShape> shapes = PartGui::getShapesFromSelection();
Base::BoundBox3d bbox;
for (std::vector<App::DocumentObject*>::iterator it = obj.begin(); it != obj.end(); ++it) {
bbox.Add(static_cast<Part::Feature*>(*it)->Shape.getBoundingBox());
for (std::vector<Part::TopoShape>::iterator it = shapes.begin(); it != shapes.end(); ++it) {
bbox.Add((*it).getBoundBox());
}
dlg = new PartGui::TaskCrossSections(bbox);
}
@@ -1531,8 +1563,8 @@ void CmdPartCrossSections::activated(int iMsg)
bool CmdPartCrossSections::isActive(void)
{
return (Gui::Selection().countObjectsOfType(Part::Feature::getClassTypeId()) > 0 &&
!Gui::Control().activeDialog());
bool hasShapes = PartGui::hasShapesInSelection();
return (hasShapes && !Gui::Control().activeDialog());
}
//===========================================================================
@@ -1643,9 +1675,16 @@ CmdPartOffset::CmdPartOffset()
void CmdPartOffset::activated(int iMsg)
{
Q_UNUSED(iMsg);
auto shapes = getSelection().getObjectsOfType(Part::Feature::getClassTypeId(),nullptr,3);
if(shapes.empty())
std::vector<App::DocumentObject*> docobjs = Gui::Selection().getObjectsOfType(App::DocumentObject::getClassTypeId());
std::vector<App::DocumentObject*> shapes;
for (std::vector<App::DocumentObject*>::iterator it = docobjs.begin(); it != docobjs.end(); ++it) {
if (!Part::Feature::getTopoShape(*it).isNull()) {
shapes.push_back(*it);
}
}
if (shapes.size() != 1) {
return;
}
App::DocumentObject* shape = shapes.front();
std::string offset = getUniqueObjectName("Offset");
@@ -1668,9 +1707,15 @@ void CmdPartOffset::activated(int iMsg)
bool CmdPartOffset::isActive(void)
{
Base::Type partid = Base::Type::fromName("Part::Feature");
bool objectsSelected = Gui::Selection().countObjectsOfType(partid,nullptr,3) == 1;
return (objectsSelected && !Gui::Control().activeDialog());
{
bool hasShapes = PartGui::hasShapesInSelection();
std::vector<App::DocumentObject*> docobjs = Gui::Selection().getObjectsOfType(App::DocumentObject::getClassTypeId());
return (hasShapes && !Gui::Control().activeDialog() && docobjs.size() == 1);
}
// Base::Type partid = Base::Type::fromName("Part::Feature");
// bool objectsSelected = Gui::Selection().countObjectsOfType(partid,0,3) == 1;
// return (objectsSelected && !Gui::Control().activeDialog());
}
@@ -1695,9 +1740,17 @@ CmdPartOffset2D::CmdPartOffset2D()
void CmdPartOffset2D::activated(int iMsg)
{
Q_UNUSED(iMsg);
auto shapes = getSelection().getObjectsOfType(Part::Feature::getClassTypeId(),nullptr,3);
if(shapes.empty())
std::vector<App::DocumentObject*> docobjs = Gui::Selection().getObjectsOfType(App::DocumentObject::getClassTypeId());
std::vector<App::DocumentObject*> shapes;
for (std::vector<App::DocumentObject*>::iterator it = docobjs.begin(); it != docobjs.end(); ++it) {
if (!Part::Feature::getTopoShape(*it).isNull()) {
shapes.push_back(*it);
}
}
if (shapes.size() != 1) {
return;
}
App::DocumentObject* shape = shapes.front();
std::string offset = getUniqueObjectName("Offset2D");
@@ -1720,9 +1773,9 @@ void CmdPartOffset2D::activated(int iMsg)
bool CmdPartOffset2D::isActive(void)
{
Base::Type partid = Base::Type::fromName("Part::Feature");
bool objectsSelected = Gui::Selection().countObjectsOfType(partid,nullptr,3) == 1;
return (objectsSelected && !Gui::Control().activeDialog());
bool hasShapes = PartGui::hasShapesInSelection();
std::vector<App::DocumentObject*> docobjs = Gui::Selection().getObjectsOfType(App::DocumentObject::getClassTypeId());
return (hasShapes && !Gui::Control().activeDialog() && docobjs.size() == 1);
}
//===========================================================================
@@ -1813,11 +1866,10 @@ void CmdPartCompOffset::languageChange()
bool CmdPartCompOffset::isActive(void)
{
Base::Type partid = Base::Type::fromName("Part::Feature");
bool objectsSelected = Gui::Selection().countObjectsOfType(partid,nullptr,3) == 1;
return (objectsSelected && !Gui::Control().activeDialog());
bool hasShapes = PartGui::hasShapesInSelection();
std::vector<App::DocumentObject*> docobjs = Gui::Selection().getObjectsOfType(App::DocumentObject::getClassTypeId());
return (hasShapes && !Gui::Control().activeDialog() && docobjs.size() == 1);
}
//===========================================================================
// Part_Thickness
//===========================================================================
@@ -1839,31 +1891,48 @@ CmdPartThickness::CmdPartThickness()
void CmdPartThickness::activated(int iMsg)
{
Q_UNUSED(iMsg);
Gui::SelectionFilter faceFilter ("SELECT Part::Feature SUBELEMENT Face COUNT 1..");
if (!faceFilter.match()) {
QMessageBox::warning(Gui::getMainWindow(),
QApplication::translate("CmdPartThickness", "Wrong selection"),
QApplication::translate("CmdPartThickness", "Selected one or more faces of a shape"));
return;
const App::DocumentObject* obj = nullptr;
std::string selection;
const std::vector<Gui::SelectionObject> selobjs = Gui::Selection().getSelectionEx();
std::vector<Part::TopoShape> subShapes;
Part::TopoShape topoShape = Part::TopoShape();
bool ok = true;
if (selobjs.size() == 1) {
selection = selobjs[0].getAsPropertyLinkSubString();
const std::vector<std::string>& subnames = selobjs[0].getSubNames();
obj = selobjs[0].getObject();
topoShape = Part::Feature::getTopoShape(obj);
if (!topoShape.isNull()) {
for (std::vector<std::string>::const_iterator it = subnames.begin(); it != subnames.end(); ++it) {
subShapes.push_back(topoShape.getSubShape(subnames[0].c_str()));
}
for (std::vector<Part::TopoShape>::iterator it = subShapes.begin(); it != subShapes.end(); ++it) {
TopoDS_Shape dsShape = (*it).getShape();
if (dsShape.IsNull() || dsShape.ShapeType() != TopAbs_FACE) { //only face selection allowed
ok = false;
}
}
} else { //could be not a part::feature or app:link to non-part::feature or app::part without a visible part::feature
ok = false;
}
} else { //not just one object selected
ok = false;
}
// get the selected object
const std::vector<Gui::SelectionObject>& result = faceFilter.Result[0];
std::string selection = result.front().getAsPropertyLinkSubString();
const Part::Feature* shape = static_cast<const Part::Feature*>(result.front().getObject());
if (shape->Shape.getValue().IsNull())
return;
int countSolids = 0;
TopExp_Explorer xp;
xp.Init(shape->Shape.getValue(),TopAbs_SOLID);
for (;xp.More(); xp.Next()) {
countSolids++;
if (!topoShape.isNull()){
xp.Init(topoShape.getShape(), TopAbs_SOLID);
for (;xp.More(); xp.Next()) {
countSolids++;
}
}
if (countSolids != 1) {
if (countSolids != 1 || !ok) {
QMessageBox::warning(Gui::getMainWindow(),
QApplication::translate("CmdPartThickness", "Wrong selection"),
QApplication::translate("CmdPartThickness", "Selected shape is not a solid"));
QApplication::translate("CmdPartThickness", "Wrong selection"),
QApplication::translate("CmdPartThickness", "Selected shape is not a solid"));
return;
}
@@ -1874,22 +1943,24 @@ void CmdPartThickness::activated(int iMsg)
doCommand(Doc,"App.ActiveDocument.%s.Faces = %s" ,thick.c_str(), selection.c_str());
doCommand(Doc,"App.ActiveDocument.%s.Value = 1.0",thick.c_str());
updateActive();
if (isActiveObjectValid())
doCommand(Gui,"Gui.ActiveDocument.hide(\"%s\")",shape->getNameInDocument());
if (isActiveObjectValid()) {
doCommand(App,"App.getDocument(\"%s\").getObject(\"%s\").ViewObject.Visibility = False",
obj->getDocument()->getName(), obj->getNameInDocument());
}
doCommand(Gui,"Gui.ActiveDocument.setEdit('%s')",thick.c_str());
//commitCommand();
adjustCameraPosition();
copyVisual(thick.c_str(), "ShapeColor", shape->getNameInDocument());
copyVisual(thick.c_str(), "LineColor" , shape->getNameInDocument());
copyVisual(thick.c_str(), "PointColor", shape->getNameInDocument());
copyVisual(thick.c_str(), "ShapeColor", obj->getNameInDocument());
copyVisual(thick.c_str(), "LineColor" , obj->getNameInDocument());
copyVisual(thick.c_str(), "PointColor", obj->getNameInDocument());
}
bool CmdPartThickness::isActive(void)
{
Base::Type partid = Base::Type::fromName("Part::Feature");
bool objectsSelected = Gui::Selection().countObjectsOfType(partid) > 0;
bool objectsSelected = Gui::Selection().countObjectsOfType(partid, 0, 3) > 0;
return (objectsSelected && !Gui::Control().activeDialog());
}
@@ -2014,92 +2085,83 @@ CmdPartRuledSurface::CmdPartRuledSurface()
void CmdPartRuledSurface::activated(int iMsg)
{
Q_UNUSED(iMsg);
bool ok = false;
bool ok = true;
TopoDS_Shape curve1, curve2;
std::string link1, link2, obj1, obj2;
Gui::SelectionFilter edgeFilter ("SELECT Part::Feature SUBELEMENT Edge COUNT 1..2");
Gui::SelectionFilter wireFilter ("SELECT Part::Feature SUBELEMENT Wire COUNT 1..2");
Gui::SelectionFilter partFilter ("SELECT Part::Feature COUNT 2");
bool matchEdge = edgeFilter.match();
bool matchWire = wireFilter.match();
if (matchEdge || matchWire) {
// get the selected object
const std::vector<Gui::SelectionObject>& result = matchEdge
? edgeFilter.Result[0] : wireFilter.Result[0];
// two edges from one object
if (result.size() == 1) {
const Part::Feature* part = static_cast<const Part::Feature*>(result[0].getObject());
const std::vector<std::string>& edges = result[0].getSubNames();
if (edges.size() != 2) {
ok = false;
}
else {
ok = true;
// get the selected sub-shapes
const Part::TopoShape& shape = part->Shape.getValue();
curve1 = shape.getSubShape(edges[0].c_str());
curve2 = shape.getSubShape(edges[1].c_str());
obj1 = result[0].getObject()->getNameInDocument();
link1 = edges[0];
obj2 = result[0].getObject()->getNameInDocument();
link2 = edges[1];
}
}
// two objects and one edge per object
else if (result.size() == 2) {
const Part::Feature* part1 = static_cast<const Part::Feature*>(result[0].getObject());
const std::vector<std::string>& edges1 = result[0].getSubNames();
const Part::Feature* part2 = static_cast<const Part::Feature*>(result[1].getObject());
const std::vector<std::string>& edges2 = result[1].getSubNames();
if (edges1.size() != 1 || edges2.size() != 1) {
ok = false;
}
else {
ok = true;
const Part::TopoShape& shape1 = part1->Shape.getValue();
curve1 = shape1.getSubShape(edges1[0].c_str());
const Part::TopoShape& shape2 = part2->Shape.getValue();
curve2 = shape2.getSubShape(edges2[0].c_str());
obj1 = result[0].getObject()->getNameInDocument();
link1 = edges1[0];
obj2 = result[1].getObject()->getNameInDocument();
link2 = edges2[0];
}
}
}
else if (partFilter.match()) {
const std::vector<Gui::SelectionObject>& result = partFilter.Result[0];
const Part::Feature* part1 = static_cast<const Part::Feature*>(result[0].getObject());
const Part::Feature* part2 = static_cast<const Part::Feature*>(result[1].getObject());
const Part::TopoShape& shape1 = part1->Shape.getValue();
curve1 = shape1.getShape();
const Part::TopoShape& shape2 = part2->Shape.getValue();
curve2 = shape2.getShape();
obj1 = part1->getNameInDocument();
obj2 = part2->getNameInDocument();
const std::vector<Gui::SelectionObject> selobjs = Gui::Selection().getSelectionEx();
const App::DocumentObject* docobj1 = nullptr;
const App::DocumentObject* docobj2 = nullptr;
if (selobjs.size() != 1 && selobjs.size() != 2) {
ok = false;
}
if (ok && selobjs.size() <= 2) {
if (selobjs.size() >= 1) {
const std::vector<std::string>& subnames1= selobjs[0].getSubNames();
docobj1 = selobjs[0].getObject();
obj1 = docobj1->getNameInDocument();
obj2 = obj1; //changed later if 2 objects were selected
const Part::TopoShape& shape1 = Part::Feature::getTopoShape(docobj1);
if (shape1.isNull()) {
ok = false;
}
if (ok && subnames1.size() <= 2) {
if (subnames1.size() >= 1) {
curve1 = shape1.getSubShape(subnames1[0].c_str());
link1 = subnames1[0];
}
if (subnames1.size() == 2) {
curve2 = shape1.getSubShape(subnames1[1].c_str());
link2 = subnames1[1];
}
if (subnames1.size() == 0) {
curve1 = shape1.getShape();
}
} else {
ok = false;
}
}
if (selobjs.size() == 2) {
const std::vector<std::string>& subnames2 = selobjs[1].getSubNames();
docobj2 = selobjs[1].getObject();
obj2 = docobj2->getNameInDocument();
const Part::TopoShape& shape2 = Part::Feature::getTopoShape(docobj2);
if (shape2.isNull()) {
ok = false;
}
if (ok && subnames2.size() == 1) {
curve2 = shape2.getSubShape(subnames2[0].c_str());
link2 = subnames2[0];
} else {
if (subnames2.size() == 0) {
curve2 = shape2.getShape();
}
}
}
if (!curve1.IsNull() && !curve2.IsNull()) {
if (curve1.ShapeType() == TopAbs_EDGE &&
curve2.ShapeType() == TopAbs_EDGE)
ok = true;
if (curve1.ShapeType() == TopAbs_WIRE &&
curve2.ShapeType() == TopAbs_WIRE)
if ((curve1.ShapeType() == TopAbs_EDGE || curve1.ShapeType() == TopAbs_WIRE)
&& (curve2.ShapeType() == TopAbs_EDGE || curve2.ShapeType() == TopAbs_WIRE)) {
ok = true;
}
}
}
if (!ok) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("You have to select either two edges or two wires."));
QObject::tr("You have to select either two edges or two wires."));
return;
}
openCommand(QT_TRANSLATE_NOOP("Command", "Create ruled surface"));
doCommand(Doc, "FreeCAD.ActiveDocument.addObject('Part::RuledSurface', 'Ruled Surface')");
doCommand(Doc, "FreeCAD.ActiveDocument.ActiveObject.Curve1=(FreeCAD.ActiveDocument.%s,['%s'])"
,obj1.c_str(), link1.c_str());
,obj1.c_str(), link1.c_str());
doCommand(Doc, "FreeCAD.ActiveDocument.ActiveObject.Curve2=(FreeCAD.ActiveDocument.%s,['%s'])"
,obj2.c_str(), link2.c_str());
,obj2.c_str(), link2.c_str());
commitCommand();
updateActive();
}
@@ -2138,9 +2200,8 @@ void CmdCheckGeometry::activated(int iMsg)
bool CmdCheckGeometry::isActive(void)
{
Base::Type partid = Base::Type::fromName("Part::Feature");
bool objectsSelected = Gui::Selection().countObjectsOfType(partid) > 0;
return (hasActiveDocument() && !Gui::Control().activeDialog() && objectsSelected);
bool hasShapes = PartGui::hasShapesInSelection();
return (hasShapes && !Gui::Control().activeDialog());
}
//===========================================================================
@@ -2502,8 +2563,7 @@ void CmdPartSectionCut::activated(int iMsg)
bool CmdPartSectionCut::isActive(void)
{
Gui::View3DInventor* view = dynamic_cast<Gui::View3DInventor*>(Gui::getMainWindow()->activeWindow());
return view ? true : false;
return hasActiveDocument();
}
//---------------------------------------------------------------

View File

@@ -58,6 +58,7 @@
#include <Gui/Document.h>
#include <Gui/View3DInventor.h>
#include <Gui/View3DInventorViewer.h>
#include <App/Link.h>
#include <Base/Sequencer.h>
#include <Base/UnitsApi.h>
@@ -194,8 +195,14 @@ void CrossSections::accept()
void CrossSections::apply()
{
std::vector<App::DocumentObject*> obj = Gui::Selection().
getObjectsOfType(Part::Feature::getClassTypeId());
std::vector<App::DocumentObject*> docobjs = Gui::Selection().
getObjectsOfType(App::DocumentObject::getClassTypeId());
std::vector<App::DocumentObject*> obj;
for (std::vector<App::DocumentObject*>::iterator it = docobjs.begin(); it != docobjs.end(); ++it){
if (!Part::Feature::getTopoShape(*it).isNull()) {
obj.push_back((*it)->getLinkedObject());
}
}
std::vector<double> d;
if (ui->sectionsBox->isChecked())

View File

@@ -38,8 +38,9 @@
#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentObject.h>
#include <Base/Interpreter.h>
#include <Base/UnitsApi.h>
#include <App/Link.h>
#include <App/Part.h>
#include <Gui/Application.h>
#include <Gui/BitmapFactory.h>
#include <Gui/Command.h>
@@ -69,16 +70,18 @@ public:
bool allow(App::Document* /*pDoc*/, App::DocumentObject* pObj, const char* sSubName)
{
this->canSelect = false;
if (!pObj->isDerivedFrom(Part::Feature::getClassTypeId()))
return false;
if (!sSubName || sSubName[0] == '\0')
return false;
std::string element(sSubName);
if (element.substr(0,4) != "Edge")
return false;
Part::Feature* fea = static_cast<Part::Feature*>(pObj);
Part::TopoShape part = Part::Feature::getTopoShape(pObj);
if (part.isNull()) {
return false;
}
try {
TopoDS_Shape sub = fea->Shape.getShape().getSubShape(sSubName);
TopoDS_Shape sub = part.getSubShape(sSubName);
if (!sub.IsNull() && sub.ShapeType() == TopAbs_EDGE) {
const TopoDS_Edge& edge = TopoDS::Edge(sub);
BRepAdaptor_Curve adapt(edge);
@@ -112,6 +115,8 @@ DlgExtrusion::DlgExtrusion(QWidget* parent, Qt::WindowFlags fl)
Gui::ItemViewSelection sel(ui->treeWidget);
sel.applyFrom(Gui::Selection().getObjectsOfType(Part::Feature::getClassTypeId()));
sel.applyFrom(Gui::Selection().getObjectsOfType(App::Link::getClassTypeId()));
sel.applyFrom(Gui::Selection().getObjectsOfType(App::Part::getClassTypeId()));
this->on_DirMode_changed();
ui->spinLenFwd->selectAll();
@@ -317,27 +322,28 @@ void DlgExtrusion::fetchDir()
void DlgExtrusion::autoSolid()
{
try{
App::DocumentObject &dobj = this->getShapeToExtrude();
if (dobj.isDerivedFrom(Part::Feature::getClassTypeId())){
Part::Feature &feature = static_cast<Part::Feature&>(dobj);
TopoDS_Shape sh = feature.Shape.getValue();
if (sh.IsNull())
App::DocumentObject* dobj = &this->getShapeToExtrude();
Part::TopoShape shape = Part::Feature::getTopoShape(dobj);
if (shape.isNull()) {
return;
}
TopoDS_Shape sh = shape.getShape();
if (sh.IsNull())
return;
ShapeExtend_Explorer xp;
Handle(TopTools_HSequenceOfShape) leaves = xp.SeqFromCompound(sh, /*recursive= */Standard_True);
int cntClosedWires = 0;
for(int i = 0; i < leaves->Length(); i++){
const TopoDS_Shape &leaf = leaves->Value(i+1);
if (leaf.IsNull())
return;
ShapeExtend_Explorer xp;
Handle(TopTools_HSequenceOfShape) leaves = xp.SeqFromCompound(sh, /*recursive= */Standard_True);
int cntClosedWires = 0;
for(int i = 0; i < leaves->Length(); i++){
const TopoDS_Shape &leaf = leaves->Value(i+1);
if (leaf.IsNull())
return;
if (leaf.ShapeType() == TopAbs_WIRE || leaf.ShapeType() == TopAbs_EDGE){
if (BRep_Tool::IsClosed(leaf)){
cntClosedWires++;
}
if (leaf.ShapeType() == TopAbs_WIRE || leaf.ShapeType() == TopAbs_EDGE){
if (BRep_Tool::IsClosed(leaf)){
cntClosedWires++;
}
}
ui->chkSolid->setChecked( cntClosedWires == leaves->Length() );
}
ui->chkSolid->setChecked( cntClosedWires == leaves->Length() );
} catch(...) {
}
@@ -352,10 +358,15 @@ void DlgExtrusion::findShapes()
this->document = activeDoc->getName();
this->label = activeDoc->Label.getValue();
std::vector<App::DocumentObject*> objs = activeDoc->getObjectsOfType
(Part::Feature::getClassTypeId());
std::vector<App::DocumentObject*> objs = activeDoc->getObjectsOfType<App::DocumentObject>();
for (std::vector<App::DocumentObject*>::iterator it = objs.begin(); it!=objs.end(); ++it) {
const TopoDS_Shape& shape = static_cast<Part::Feature*>(*it)->Shape.getValue();
Part::TopoShape topoShape = Part::Feature::getTopoShape(*it);
if (topoShape.isNull()) {
continue;
}
TopoDS_Shape shape = topoShape.getShape();
if (shape.IsNull()) continue;
if (canExtrude(shape)) {
QTreeWidgetItem* item = new QTreeWidgetItem(ui->treeWidget);
item->setText(0, QString::fromUtf8((*it)->Label.getValue()));
@@ -429,7 +440,7 @@ void DlgExtrusion::apply()
for (App::DocumentObject* sourceObj: objects) {
assert(sourceObj);
if (!sourceObj->isDerivedFrom(Part::Feature::getClassTypeId())){
if (Part::Feature::getTopoShape(sourceObj).isNull()){
FC_ERR("Object " << sourceObj->getFullName()
<< " is not Part object (has no OCC shape). Can't extrude it.");
continue;

View File

@@ -44,6 +44,8 @@
#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentObject.h>
#include <App/Link.h>
#include <App/Part.h>
#include <Gui/Application.h>
#include <Gui/BitmapFactory.h>
#include <Gui/Command.h>
@@ -73,16 +75,18 @@ public:
bool allow(App::Document* /*pDoc*/, App::DocumentObject*pObj, const char*sSubName)
{
this->canSelect = false;
if (!pObj->isDerivedFrom(Part::Feature::getClassTypeId()))
return false;
if (!sSubName || sSubName[0] == '\0')
return false;
std::string element(sSubName);
if (element.substr(0,4) != "Edge")
return false;
Part::Feature* fea = static_cast<Part::Feature*>(pObj);
Part::TopoShape part = Part::Feature::getTopoShape(pObj);
if (part.isNull()) {
return false;
}
try {
TopoDS_Shape sub = fea->Shape.getShape().getSubShape(sSubName);
TopoDS_Shape sub = part.getSubShape(sSubName);
if (!sub.IsNull() && sub.ShapeType() == TopAbs_EDGE) {
const TopoDS_Edge& edge = TopoDS::Edge(sub);
BRepAdaptor_Curve adapt(edge);
@@ -127,6 +131,8 @@ DlgRevolution::DlgRevolution(QWidget* parent, Qt::WindowFlags fl)
Gui::ItemViewSelection sel(ui->treeWidget);
sel.applyFrom(Gui::Selection().getObjectsOfType(Part::Feature::getClassTypeId()));
sel.applyFrom(Gui::Selection().getObjectsOfType(App::Link::getClassTypeId()));
sel.applyFrom(Gui::Selection().getObjectsOfType(App::Part::getClassTypeId()));
connect(ui->txtAxisLink, SIGNAL(textChanged(QString)), this, SLOT(on_txtAxisLink_textChanged(QString)));
@@ -327,10 +333,14 @@ void DlgRevolution::findShapes()
return;
Gui::Document* activeGui = Gui::Application::Instance->getDocument(activeDoc);
std::vector<App::DocumentObject*> objs = activeDoc->getObjectsOfType
(Part::Feature::getClassTypeId());
std::vector<App::DocumentObject*> objs = activeDoc->getObjectsOfType<App::DocumentObject>();
for (std::vector<App::DocumentObject*>::iterator it = objs.begin(); it!=objs.end(); ++it) {
const TopoDS_Shape& shape = static_cast<Part::Feature*>(*it)->Shape.getValue();
Part::TopoShape topoShape = Part::Feature::getTopoShape(*it);
if (topoShape.isNull()) {
continue;
}
TopoDS_Shape shape = topoShape.getShape();
if (shape.IsNull()) continue;
TopExp_Explorer xp;
@@ -521,9 +531,11 @@ void DlgRevolution::autoSolid()
{
try{
App::DocumentObject &dobj = this->getShapeToRevolve();
if (dobj.isDerivedFrom(Part::Feature::getClassTypeId())){
Part::Feature &feature = static_cast<Part::Feature&>(dobj);
TopoDS_Shape sh = feature.Shape.getValue();
Part::TopoShape topoShape = Part::Feature::getTopoShape(&dobj);
if (topoShape.isNull()) {
return;
} else {
TopoDS_Shape sh = topoShape.getShape();
if (sh.IsNull())
return;
ShapeExtend_Explorer xp;

View File

@@ -41,6 +41,8 @@
#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentObject.h>
#include <App/Link.h>
#include <App/Part.h>
#include <Gui/Application.h>
#include <Gui/BitmapFactory.h>
#include <Gui/Command.h>
@@ -68,6 +70,8 @@ Mirroring::Mirroring(QWidget* parent)
Gui::ItemViewSelection sel(ui->shapes);
sel.applyFrom(Gui::Selection().getObjectsOfType(Part::Feature::getClassTypeId()));
sel.applyFrom(Gui::Selection().getObjectsOfType(App::Link::getClassTypeId()));
sel.applyFrom(Gui::Selection().getObjectsOfType(App::Part::getClassTypeId()));
}
/*
@@ -89,19 +93,18 @@ void Mirroring::changeEvent(QEvent *e)
void Mirroring::findShapes()
{
App::Document* activeDoc = App::GetApplication().getActiveDocument();
if (!activeDoc)
if (!activeDoc)
return;
Gui::Document* activeGui = Gui::Application::Instance->getDocument(activeDoc);
if (!activeGui)
if (!activeGui)
return;
this->document = QString::fromLatin1(activeDoc->getName());
std::vector<App::DocumentObject*> objs = activeDoc->getObjectsOfType
(Part::Feature::getClassTypeId());
std::vector<App::DocumentObject*> objs = activeDoc->getObjectsOfType<App::DocumentObject>();
for (std::vector<App::DocumentObject*>::iterator it = objs.begin(); it!=objs.end(); ++it) {
const TopoDS_Shape& shape = static_cast<Part::Feature*>(*it)->Shape.getValue();
if (!shape.IsNull()) {
Part::TopoShape shape = Part::Feature::getTopoShape(*it);
if (!shape.isNull()) {
QString label = QString::fromUtf8((*it)->Label.getValue());
QString name = QString::fromLatin1((*it)->getNameInDocument());

View File

@@ -50,6 +50,7 @@
#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentObject.h>
#include <App/Link.h>
#include <Mod/Part/App/PartFeature.h>
@@ -102,10 +103,14 @@ void LoftWidget::findShapes()
return;
d->document = activeDoc->getName();
std::vector<Part::Feature*> objs = activeDoc->getObjectsOfType<Part::Feature>();
std::vector<App::DocumentObject*> objs = activeDoc->getObjectsOfType<App::DocumentObject>();
for (std::vector<Part::Feature*>::iterator it = objs.begin(); it!=objs.end(); ++it) {
TopoDS_Shape shape = (*it)->Shape.getValue();
for (std::vector<App::DocumentObject*>::iterator it = objs.begin(); it!=objs.end(); ++it) {
Part::TopoShape topoShape = Part::Feature::getTopoShape(*it);
if (topoShape.isNull()) {
continue;
}
TopoDS_Shape shape = topoShape.getShape();
if (shape.IsNull()) continue;
// also allow compounds with a single face, wire or vertex or
@@ -145,7 +150,6 @@ void LoftWidget::findShapes()
shape.ShapeType() == TopAbs_VERTEX) {
QString label = QString::fromUtf8((*it)->Label.getValue());
QString name = QString::fromLatin1((*it)->getNameInDocument());
QTreeWidgetItem* child = new QTreeWidgetItem();
child->setText(0, label);
child->setToolTip(0, label);

View File

@@ -56,6 +56,7 @@
#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentObject.h>
#include <App/Link.h>
#include <Mod/Part/App/PartFeature.h>
@@ -83,39 +84,41 @@ public:
}
bool allow(App::Document* /*pDoc*/, App::DocumentObject*pObj, const char*sSubName)
{
if (pObj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
if (!sSubName || sSubName[0] == '\0') {
// If selecting again the same edge the passed sub-element is empty. If the whole
// shape is an edge or wire we can use it completely.
const TopoDS_Shape& shape = static_cast<Part::Feature*>(pObj)->Shape.getValue();
if (!shape.IsNull()) {
// a single edge
if (shape.ShapeType() == TopAbs_EDGE) {
return true;
}
// a single wire
if (shape.ShapeType() == TopAbs_WIRE) {
return true;
}
// a compound of only edges or wires
if (shape.ShapeType() == TopAbs_COMPOUND) {
TopoDS_Iterator it(shape);
for (; it.More(); it.Next()) {
if (it.Value().IsNull())
return false;
if ((it.Value().ShapeType() != TopAbs_EDGE) &&
if (!sSubName || sSubName[0] == '\0') {
// If selecting again the same edge the passed sub-element is empty. If the whole
// shape is an edge or wire we can use it completely.
Part::TopoShape topoShape = Part::Feature::getTopoShape(pObj);
if (topoShape.isNull()) {
return false;
}
const TopoDS_Shape shape = topoShape.getShape();
if (!shape.IsNull()) {
// a single edge
if (shape.ShapeType() == TopAbs_EDGE) {
return true;
}
// a single wire
if (shape.ShapeType() == TopAbs_WIRE) {
return true;
}
// a compound of only edges or wires
if (shape.ShapeType() == TopAbs_COMPOUND) {
TopoDS_Iterator it(shape);
for (; it.More(); it.Next()) {
if (it.Value().IsNull())
return false;
if ((it.Value().ShapeType() != TopAbs_EDGE) &&
(it.Value().ShapeType() != TopAbs_WIRE))
return false;
}
return true;
return false;
}
return true;
}
}
else {
std::string element(sSubName);
return element.substr(0,4) == "Edge";
}
}
else {
std::string element(sSubName);
return element.substr(0,4) == "Edge";
}
return false;
@@ -159,10 +162,14 @@ void SweepWidget::findShapes()
return;
d->document = activeDoc->getName();
std::vector<Part::Feature*> objs = activeDoc->getObjectsOfType<Part::Feature>();
std::vector<App::DocumentObject*> objs = activeDoc->getObjectsOfType<App::DocumentObject>();
for (std::vector<Part::Feature*>::iterator it = objs.begin(); it!=objs.end(); ++it) {
TopoDS_Shape shape = (*it)->Shape.getValue();
for (std::vector<App::DocumentObject*>::iterator it = objs.begin(); it!=objs.end(); ++it) {
Part::TopoShape topoShape = Part::Feature::getTopoShape(*it);
if (topoShape.isNull()) {
continue;
}
TopoDS_Shape shape = topoShape.getShape();
if (shape.IsNull()) continue;
// also allow compounds with a single face, wire or vertex or
@@ -217,13 +224,13 @@ void SweepWidget::findShapes()
bool SweepWidget::isPathValid(const Gui::SelectionObject& sel) const
{
const App::DocumentObject* path = sel.getObject();
if (!(path && path->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())))
return false;
const std::vector<std::string>& sub = sel.getSubNames();
TopoDS_Shape pathShape;
const Part::TopoShape& shape = static_cast<const Part::Feature*>(path)->Shape.getValue();
const Part::TopoShape& shape = Part::Feature::getTopoShape(path);
if (shape.isNull()){
return false;
}
if (!sub.empty()) {
try {
BRepBuilderAPI_MakeWire mkWire;
@@ -276,23 +283,38 @@ bool SweepWidget::accept()
{
if (d->ui.buttonPath->isChecked())
return false;
Gui::SelectionFilter edgeFilter ("SELECT Part::Feature SUBELEMENT Edge COUNT 1..");
Gui::SelectionFilter partFilter ("SELECT Part::Feature COUNT 1");
bool matchEdge = edgeFilter.match();
bool matchPart = partFilter.match();
if (!matchEdge && !matchPart) {
QMessageBox::critical(this, tr("Sweep path"), tr("Select one or more connected edges you want to sweep along."));
return false;
}
// get the selected object
const App::DocumentObject* docobj = nullptr;
std::string selection;
const std::vector<Gui::SelectionObject> selobjs = Gui::Selection().getSelectionEx();
std::vector<Part::TopoShape> subShapes;
Part::TopoShape topoShape = Part::TopoShape();
std::string spineObject, spineLabel;
const std::vector<Gui::SelectionObject>& result = matchEdge
? edgeFilter.Result[0] : partFilter.Result[0];
selection = result.front().getAsPropertyLinkSubString();
spineObject = result.front().getFeatName();
spineLabel = result.front().getObject()->Label.getValue();
bool ok = true;
if (selobjs.size() == 1) {
selection = selobjs[0].getAsPropertyLinkSubString();
const std::vector<std::string>& subnames = selobjs[0].getSubNames();
docobj = selobjs[0].getObject();
spineObject = selobjs[0].getFeatName();
spineLabel = docobj->Label.getValue();
topoShape = Part::Feature::getTopoShape(docobj);
if (!topoShape.isNull()) {
for (std::vector<std::string>::const_iterator it = subnames.begin(); it != subnames.end(); ++it) {
subShapes.push_back(topoShape.getSubShape(subnames[0].c_str()));
}
for (std::vector<Part::TopoShape>::iterator it = subShapes.begin(); it != subShapes.end(); ++it) {
TopoDS_Shape dsShape = (*it).getShape();
if (dsShape.IsNull() || dsShape.ShapeType() != TopAbs_EDGE) { //only edge selection allowed
ok = false;
}
}
} else { //could be not a part::feature or app:link to non-part::feature or app::part without a visible part::feature
ok = false;
}
} else { //not just one object selected
ok = false;
}
QString list, solid, frenet;
if (d->ui.checkSolid->isChecked())
@@ -312,6 +334,10 @@ bool SweepWidget::accept()
QMessageBox::critical(this, tr("Too few elements"), tr("At least one edge or wire is required."));
return false;
}
if (!ok) {
QMessageBox::critical(this, tr("Invalid selection"), tr("Select one or more edges from a single object."));
return false;
}
for (int i=0; i<count; i++) {
QTreeWidgetItem* child = d->ui.selector->selectedTreeWidget()->topLevelItem(i);
QString name = child->data(0, Qt::UserRole).toString();