[TD]Long and link dim refs (fix #13375) (#18641)

* [Meas]Changes for TD dimension refs for links

* [TD]App changes for dim refs to links

* [TD]Gui changes for dim refs to links

* [TD]fix 2 lint messages

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
WandererFan
2024-12-23 17:36:22 -05:00
committed by GitHub
parent a13ecd87db
commit f144a87539
16 changed files with 1092 additions and 198 deletions

View File

@@ -44,7 +44,7 @@
// // reference
// replace(ref, newRef)
// else:
// // auto correct phase 2
// // auto correct phase 2 - to be implemented
// // we don't have any geometry that is identical to our saved geometry.
// // finding a match now becomes guess work. we have to find the most
// // similar geometry (with at least some level of same-ness) and use
@@ -68,6 +68,7 @@
#include <Base/Tools.h>
#include <Mod/Part/App/TopoShape.h>
#include <Mod/Measure/App/ShapeFinder.h>
#include "GeometryMatcher.h"
#include "DimensionReferences.h"
@@ -77,6 +78,7 @@
#include "Preferences.h"
using namespace TechDraw;
using namespace Measure;
using DU = DrawUtil;
//! true if references point to valid geometry and the valid geometry matches the
@@ -173,17 +175,17 @@ bool DimensionAutoCorrect::autocorrectReferences(std::vector<bool>& referenceSta
continue;
}
// we did not find an exact match, so check for an similar match
// we did not find an exact match, so check for a similar match
success = fix1GeomSimilar(fixedRef, savedGeometry.at(iRef).getShape());
if (success) {
// we did find an similar match
// we did find a similar match
referenceState.at(iRef) = true;
repairedRefs.push_back(fixedRef);
iRef++;
continue;
}
// we did not find an similar match the geometry
// we did not find a similar match the geometry
result = false;
referenceState.at(iRef) = false;
repairedRefs.push_back(fixedRef);
@@ -289,7 +291,8 @@ bool DimensionAutoCorrect::findExactEdge2d(ReferenceEntry& refToFix, const Part:
return true;
}
}
// no match
// no match, return the input reference
return false;
}
@@ -413,8 +416,16 @@ bool DimensionAutoCorrect::findSimilarEdge3d(ReferenceEntry& refToFix,
bool DimensionAutoCorrect::isMatchingGeometry(const ReferenceEntry& ref,
const Part::TopoShape& savedGeometry) const
{
// Base::Console().Message("DAC::isMatchingGeometry()\n");
Part::TopoShape temp = ref.asCanonicalTopoShape();
Part::TopoShape temp;
if (ref.is3d()) {
auto shape3d = ShapeFinder::getLocatedShape(*ref.getObject(), ref.getSubName(true));
temp = Part::TopoShape(shape3d);
} else {
auto shape2d = ref.getGeometry();
temp = Part::TopoShape(shape2d);
}
if (temp.isNull()) {
// this shouldn't happen as we already know that this ref points to valid geometry
return false;
@@ -435,7 +446,7 @@ ReferenceEntry DimensionAutoCorrect::searchObjForVert(App::DocumentObject* obj,
bool exact) const
{
(void)exact;
auto shape3d = Part::Feature::getShape(obj);
auto shape3d = ShapeFinder::getLocatedShape(*obj, "");
if (shape3d.IsNull()) {
// how to handle this?
return {};
@@ -443,7 +454,7 @@ ReferenceEntry DimensionAutoCorrect::searchObjForVert(App::DocumentObject* obj,
auto vertsAll = getDimension()->getVertexes(shape3d);
size_t iVert {1};
for (auto& vert : vertsAll) {
bool isSame = getMatcher()->compareGeometry(vert, refVertex);
bool isSame = getMatcher()->compareGeometry(refVertex, vert);
if (isSame) {
auto newSubname = std::string("Vertex") + std::to_string(iVert);
return {obj, newSubname, getDimension()->getDocument()};

View File

@@ -33,7 +33,10 @@
#include <App/GeoFeature.h>
#include <App/DocumentObject.h>
#include <App/Document.h>
#include <App/Link.h>
#include <Base/Console.h>
#include <Mod/Measure/App/ShapeFinder.h>
#include <Mod/Part/App/TopoShape.h>
#include <Mod/PartDesign/App/Body.h>
#include <Mod/PartDesign/App/Feature.h>
@@ -45,11 +48,12 @@
#include "CosmeticVertex.h"
using namespace TechDraw;
using namespace Measure;
using DU = DrawUtil;
using SU = ShapeUtils;
ReferenceEntry::ReferenceEntry( App::DocumentObject* docObject, std::string subName, App::Document* document)
ReferenceEntry::ReferenceEntry( App::DocumentObject* docObject, const std::string& subName, App::Document* document)
{
setObject(docObject);
setSubName(subName);
@@ -66,7 +70,7 @@ ReferenceEntry::ReferenceEntry( App::DocumentObject* docObject, std::string subN
ReferenceEntry::ReferenceEntry(const ReferenceEntry& other)
{
setObject(other.getObject());
setSubName(other.getSubName());
setSubName(other.getSubName(true));
setObjectName(other.getObjectName());
setDocument(other.getDocument());
}
@@ -79,7 +83,7 @@ ReferenceEntry& ReferenceEntry::operator=(const ReferenceEntry& otherRef)
return *this;
}
setObject(otherRef.getObject());
setSubName(otherRef.getSubName());
setSubName(otherRef.getSubName(true));
setObjectName(otherRef.getObjectName());
setDocument(otherRef.getDocument());
return *this;
@@ -94,8 +98,6 @@ bool ReferenceEntry::operator==(const ReferenceEntry& otherRef) const
TopoDS_Shape ReferenceEntry::getGeometry() const
{
// Base::Console().Message("RE::getGeometry() - objectName: %s sub: **%s**\n",
// getObjectName(), getSubName());
// first, make sure the object has not been deleted!
App::DocumentObject* obj = getDocument()->getObject(getObjectName().c_str());
if (!obj) {
@@ -112,24 +114,13 @@ TopoDS_Shape ReferenceEntry::getGeometry() const
}
// 3d geometry
Part::TopoShape shape = Part::Feature::getTopoShape(getObject());
auto geoFeat = getObject<App::GeoFeature>();
if (geoFeat) {
shape.setPlacement(geoFeat->globalPlacement());
}
if (getSubName().empty()) {
return shape.getShape();
}
// TODO: what happens if the subelement is no longer present?
return shape.getSubShape(getSubName().c_str());
return ShapeFinder::getLocatedShape(*getObject(), getSubName(true));
}
//! get a shape for this 2d reference
TopoDS_Shape ReferenceEntry::getGeometry2d() const
{
// Base::Console().Message("RE::getGeometry2d()\n");
std::string gType;
try {
auto dvp = getObject<TechDraw::DrawViewPart>(); //NOLINT cppcoreguidelines-pro-type-static-cast-downcast
@@ -160,7 +151,6 @@ TopoDS_Shape ReferenceEntry::getGeometry2d() const
}
catch (...) {
Base::Console().Message("RE::getGeometry2d - no shape for dimension 2d reference - gType: **%s**\n", gType.c_str());
return {};
}
return {};
@@ -172,12 +162,8 @@ std::string ReferenceEntry::getSubName(bool longForm) const
if (longForm) {
return m_subName;
}
std::string workingSubName(m_subName);
size_t lastDot = workingSubName.rfind('.');
if (lastDot != std::string::npos) {
workingSubName = workingSubName.substr(lastDot + 1);
}
return workingSubName;
return ShapeFinder::getLastTerm(m_subName);
}
@@ -198,10 +184,8 @@ App::DocumentObject* ReferenceEntry::getObject() const
//! return the reference geometry as a Part::TopoShape.
Part::TopoShape ReferenceEntry::asTopoShape() const
{
// Base::Console().Message("RE::asTopoShape()\n");
TopoDS_Shape geom = getGeometry();
if (geom.IsNull()) {
// throw Base::RuntimeError("Dimension Reference has null geometry");
return {};
}
if (geom.ShapeType() == TopAbs_VERTEX) {
@@ -222,7 +206,6 @@ Part::TopoShape ReferenceEntry::asTopoShape() const
//! returns unscaled, unrotated version of inShape. inShape is assumed to be a 2d shape, but this is not enforced.
Part::TopoShape ReferenceEntry::asCanonicalTopoShape() const
{
// Base::Console().Message("RE::asCanonicalTopoShape()\n");
if (is3d()) {
return asTopoShape();
}
@@ -240,7 +223,6 @@ Part::TopoShape ReferenceEntry::asCanonicalTopoShape() const
//! operations.
Part::TopoShape ReferenceEntry::asCanonicalTopoShape(const Part::TopoShape& inShape, const DrawViewPart& dvp)
{
// Base::Console().Message("RE::(static)asCanonicalTopoShape()\n");
gp_Ax2 OXYZ;
auto unscaledShape = SU::scaleShape(inShape.getShape(), 1.0 / dvp.getScale());
if (dvp.Rotation.getValue() != 0.0) {
@@ -270,7 +252,6 @@ Part::TopoShape ReferenceEntry::asTopoShapeFace(const TopoDS_Face &face)
std::string ReferenceEntry::geomType() const
{
// Base::Console().Message("RE::geomType() - subName: **%s**\n", getSubName().c_str());
return DrawUtil::getGeomTypeFromName(getSubName());
}
@@ -295,14 +276,21 @@ bool ReferenceEntry::isWholeObject() const
//! true if this reference point to 3d model geometry
bool ReferenceEntry::is3d() const
{
if (!getObject()) {
// we should really fail here?
return false;
}
if (getObject()->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) {
if (getObject() &&
getObject()->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId()) &&
!getSubName().empty()) {
// this is a well formed 2d reference
return false;
}
if (getObject() &&
getObject()->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId()) &&
getSubName().empty()) {
// this is a broken 3d reference, so it should be treated as 3d
return true;
}
// either we have no object or we have an object and it is a 3d object
return true;
}
@@ -310,7 +298,6 @@ bool ReferenceEntry::is3d() const
//! true if the target of this reference has a shape
bool ReferenceEntry::hasGeometry() const
{
// Base::Console().Message("RE::hasGeometry()\n");
if (!getObject()) {
return false;
}
@@ -321,6 +308,7 @@ bool ReferenceEntry::hasGeometry() const
}
// 3d reference
// TODO: shouldn't this be ShapeFinder.getLocatedShape?
auto shape = Part::Feature::getTopoShape(getObject());
auto subShape = shape.getSubShape(getSubName().c_str());

View File

@@ -55,7 +55,7 @@ class TechDrawExport ReferenceEntry
{
public:
ReferenceEntry() = default;
ReferenceEntry( App::DocumentObject* docObject, std::string subName, App::Document* document = nullptr);
ReferenceEntry( App::DocumentObject* docObject, const std::string& subName, App::Document* document = nullptr);
ReferenceEntry(const ReferenceEntry& other);
~ReferenceEntry() = default;

View File

@@ -645,7 +645,6 @@ QStringList DrawViewDimension::getPrefixSuffixSpec(const QString &fSpec)
//! NOTE: this returns the Dimension value in internal units (ie mm)!!!!
double DrawViewDimension::getDimValue()
{
// Base::Console().Message("DVD::getDimValue()\n");
constexpr double CircleDegrees{360.0};
double result = 0.0;
if (!has2DReferences() && !has3DReferences()) {
@@ -703,7 +702,7 @@ double DrawViewDimension::getTrueDimValue() const
result = measurement->radius();
}
else if (Type.isValue("Diameter")) {
result = 2.0 * measurement->radius();
result = 2 * measurement->radius();
}
else if (Type.isValue("Angle") || Type.isValue("Angle3Pt")) {
result = measurement->angle();
@@ -720,7 +719,6 @@ double DrawViewDimension::getTrueDimValue() const
//! retrieve the dimension value for "projected" (2d) dimensions. The returned value is in internal units (mm).
double DrawViewDimension::getProjectedDimValue() const
{
// Base::Console().Message("DVD::getProjectedDimValue()\n");
double result = 0.0;
double scale = getViewPart()->getScale();
@@ -736,7 +734,8 @@ double DrawViewDimension::getProjectedDimValue() const
// then we should not move the points.
//
pts.invertY();
pts.scale(1.0 / scale);
// unscale the points, map them to the broken view then rescale them to draw.
pts.scale(1 / scale);
pts.first(dbv->mapPoint2dFromView(pts.first()));
pts.second(dbv->mapPoint2dFromView(pts.second()));
pts.invertY();
@@ -808,7 +807,6 @@ pointPair DrawViewDimension::getLinearPoints() const
pointPair DrawViewDimension::getPointsOneEdge(ReferenceVector references)
{
// Base::Console().Message("DVD::getPointsOneEdge()\n");
App::DocumentObject* refObject = references.front().getObject();
int iSubelement = DrawUtil::getIndexFromName(references.front().getSubName());
if (refObject->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())
@@ -849,7 +847,6 @@ pointPair DrawViewDimension::getPointsOneEdge(ReferenceVector references)
pointPair DrawViewDimension::getPointsTwoEdges(ReferenceVector references)
{
// Base::Console().Message("DVD::getPointsTwoEdges() - %s\n", getNameInDocument());
App::DocumentObject* refObject = references.front().getObject();
int iSubelement0 = DrawUtil::getIndexFromName(references.at(0).getSubName());
int iSubelement1 = DrawUtil::getIndexFromName(references.at(1).getSubName());
@@ -882,7 +879,6 @@ pointPair DrawViewDimension::getPointsTwoEdges(ReferenceVector references)
pointPair DrawViewDimension::getPointsTwoVerts(ReferenceVector references)
{
// Base::Console().Message("DVD::getPointsTwoVerts() - %s\n", getNameInDocument());
App::DocumentObject* refObject = references.front().getObject();
int iSubelement0 = DrawUtil::getIndexFromName(references.at(0).getSubName());
int iSubelement1 = DrawUtil::getIndexFromName(references.at(1).getSubName());
@@ -920,7 +916,6 @@ pointPair DrawViewDimension::getPointsTwoVerts(ReferenceVector references)
pointPair DrawViewDimension::getPointsEdgeVert(ReferenceVector references)
{
// Base::Console().Message("DVD::getPointsEdgeVert() - %s\n", getNameInDocument());
App::DocumentObject* refObject = references.front().getObject();
int iSubelement0 = DrawUtil::getIndexFromName(references.at(0).getSubName());
int iSubelement1 = DrawUtil::getIndexFromName(references.at(1).getSubName());
@@ -978,7 +973,6 @@ pointPair DrawViewDimension::getPointsEdgeVert(ReferenceVector references)
arcPoints DrawViewDimension::getArcParameters(ReferenceVector references)
{
// Base::Console().Message("DVD::getArcParameters()\n");
App::DocumentObject* refObject = references.front().getObject();
int iSubelement = DrawUtil::getIndexFromName(references.front().getSubName());
if (refObject->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())
@@ -1039,7 +1033,7 @@ arcPoints DrawViewDimension::arcPointsFromBaseGeom(TechDraw::BaseGeomPtr base)
if (ellipse->closed()) {
double r1 = ellipse->minor;
double r2 = ellipse->major;
double rAvg = (r1 + r2) / 2.0;
double rAvg = (r1 + r2) / 2;
pts.center = Base::Vector3d(ellipse->center.x, ellipse->center.y, 0.0);
pts.radius = rAvg;
pts.isArc = false;
@@ -1052,7 +1046,7 @@ arcPoints DrawViewDimension::arcPointsFromBaseGeom(TechDraw::BaseGeomPtr base)
TechDraw::AOEPtr aoe = std::static_pointer_cast<TechDraw::AOE>(base);
double r1 = aoe->minor;
double r2 = aoe->major;
double rAvg = (r1 + r2) / 2.0;
double rAvg = (r1 + r2) / 2;
pts.isArc = true;
pts.center = Base::Vector3d(aoe->center.x, aoe->center.y, 0.0);
pts.radius = rAvg;
@@ -1113,10 +1107,12 @@ arcPoints DrawViewDimension::arcPointsFromEdge(TopoDS_Edge occEdge)
arcPoints pts;
pts.isArc = !BRep_Tool::IsClosed(occEdge);
pts.arcCW = false;
// get all the common information for circle, ellipse and bspline conversions
BRepAdaptor_Curve adapt(occEdge);
double pFirst = adapt.FirstParameter();
double pLast = adapt.LastParameter();
double pMid = (pFirst + pLast) / 2.0;
double pMid = (pFirst + pLast) / 2;
BRepLProp_CLProps props(adapt, pFirst, 0, Precision::Confusion());
pts.arcEnds.first(DrawUtil::toVector3d(props.Value()));
props.SetParameter(pLast);
@@ -1208,7 +1204,6 @@ arcPoints DrawViewDimension::arcPointsFromEdge(TopoDS_Edge occEdge)
anglePoints DrawViewDimension::getAnglePointsTwoEdges(ReferenceVector references)
{
// Base::Console().Message("DVD::getAnglePointsTwoEdges() - %s\n", getNameInDocument());
App::DocumentObject* refObject = references.front().getObject();
int iSubelement0 = DrawUtil::getIndexFromName(references.at(0).getSubName());
int iSubelement1 = DrawUtil::getIndexFromName(references.at(1).getSubName());
@@ -1343,7 +1338,6 @@ anglePoints DrawViewDimension::getAnglePointsTwoEdges(ReferenceVector references
// somewhere?
anglePoints DrawViewDimension::getAnglePointsThreeVerts(ReferenceVector references)
{
// Base::Console().Message("DVD::getAnglePointsThreeVerts() - %s\n", getNameInDocument());
if (references.size() < 3) {
throw Base::RuntimeError("Not enough references to make angle dimension");
}
@@ -1478,7 +1472,6 @@ DrawViewPart* DrawViewDimension::getViewPart() const
// subName)
ReferenceVector DrawViewDimension::getEffectiveReferences() const
{
// Base::Console().Message("DVD::getEffectiveReferences()\n");
const std::vector<App::DocumentObject*>& objects3d = References3D.getValues();
const std::vector<std::string>& subElements3d = References3D.getSubValues();
const std::vector<App::DocumentObject*>& objects = References2D.getValues();
@@ -1549,7 +1542,7 @@ int DrawViewDimension::getRefType() const
// decide what the reference configuration is by examining the names of the sub elements
int DrawViewDimension::getRefTypeSubElements(const std::vector<std::string>& subElements)
{
int refType = invalidRef;
int refType{invalidRef};
int refEdges{0};
int refVertices{0};
int refFaces{0};
@@ -1591,7 +1584,6 @@ int DrawViewDimension::getRefTypeSubElements(const std::vector<std::string>& sub
//! validate 2D references - only checks if the target exists
bool DrawViewDimension::checkReferences2D() const
{
// Base::Console().Message("DVD::checkReferences2d() - %s\n", getNameInDocument());
const std::vector<App::DocumentObject*>& objects = References2D.getValues();
if (objects.empty()) {
return false;
@@ -1650,8 +1642,6 @@ bool DrawViewDimension::hasBroken3dReferences() const
void DrawViewDimension::updateSavedGeometry()
{
// Base::Console().Message("DVD::updateSavedGeometry() - %s - savedGeometry: %d\n",
// getNameInDocument(), SavedGeometry.getValues().size());
ReferenceVector references = getEffectiveReferences();
if (references.empty()) {
// no references to save
@@ -1719,6 +1709,20 @@ std::vector<TopoShape> DrawViewDimension::getVertexes(const TopoShape& inShape)
return ret;
}
//! returns the angle subtended by an arc from 3 points.
double DrawViewDimension::getArcAngle(Base::Vector3d center, Base::Vector3d startPoint, Base::Vector3d endPoint)
{
auto leg0 = startPoint - center;
auto leg1 = endPoint - startPoint;
auto referenceDirection = leg0.Cross(leg1);
gp_Ax1 axis{DU::togp_Pnt(center), DU::togp_Vec(referenceDirection)};
gp_Vec startVec = DrawUtil::togp_Vec(leg0);
gp_Vec endVec = DrawUtil::togp_Vec(leg1);
double angle = startVec.AngleWithRef(endVec, axis.Direction().XYZ());
return angle;
}
pointPair DrawViewDimension::closestPoints(TopoDS_Shape s1, TopoDS_Shape s2) const
{
pointPair result;
@@ -1740,7 +1744,6 @@ pointPair DrawViewDimension::closestPoints(TopoDS_Shape s1, TopoDS_Shape s2) con
// set the reference property from a reference vector
void DrawViewDimension::setReferences2d(const ReferenceVector& refsAll)
{
// Base::Console().Message("DVD::setReferences2d(%d)\n", refs.size());
std::vector<App::DocumentObject*> objects;
std::vector<std::string> subNames;
if (objects.size() != subNames.size()) {
@@ -1759,7 +1762,6 @@ void DrawViewDimension::setReferences2d(const ReferenceVector& refsAll)
// set the reference property from a reference vector
void DrawViewDimension::setReferences3d(const ReferenceVector &refsAll)
{
// Base::Console().Message("DVD::setReferences3d()\n");
if (refsAll.empty() && !References3D.getValues().empty()) {
// clear the property of any old links
References3D.setValue(nullptr, nullptr);
@@ -1773,7 +1775,7 @@ void DrawViewDimension::setReferences3d(const ReferenceVector &refsAll)
for (auto& ref : refsAll) {
objects.push_back(ref.getObject());
subNames.push_back(ref.getSubName());
subNames.push_back(ref.getSubName(true));
// cache the referenced object
m_3dObjectCache.insert(ref.getObject()->getNameInDocument());
// cache the parent object if available. Ideally, we would handle deletion
@@ -1794,7 +1796,6 @@ void DrawViewDimension::setReferences3d(const ReferenceVector &refsAll)
//! add Dimension 3D references to measurement
void DrawViewDimension::setAll3DMeasurement()
{
// Base::Console().Message("DVD::setAll3dMeasurement()\n");
measurement->clear();
const std::vector<App::DocumentObject*>& Objs = References3D.getValues();
const std::vector<std::string>& Subs = References3D.getSubValues();
@@ -1820,7 +1821,6 @@ void DrawViewDimension::setAll3DMeasurement()
//! dimension.
bool DrawViewDimension::validateReferenceForm() const
{
// Base::Console().Message("DVD::validateReferenceForm()\n");
// we have either or both valid References3D and References2D
ReferenceVector references = getEffectiveReferences();
if (references.empty()) {
@@ -1925,8 +1925,8 @@ void DrawViewDimension::dumpRefs2D(const char* text) const
Base::Console().Message("DUMP - %s\n", text);
const std::vector<App::DocumentObject*>& objects = References2D.getValues();
const std::vector<std::string>& subElements = References2D.getSubValues();
std::vector<App::DocumentObject*>::const_iterator objIt = objects.begin();
std::vector<std::string>::const_iterator subIt = subElements.begin();
auto objIt = objects.begin();
auto subIt = subElements.begin();
int i = 0;
for (; objIt != objects.end(); objIt++, subIt++, i++) {
Base::Console().Message("DUMP - ref: %d object: %s subElement: %s\n",
@@ -1936,6 +1936,7 @@ void DrawViewDimension::dumpRefs2D(const char* text) const
}
}
// TODO: this should go into DrawUtil or ShapeUtil or ??
double DrawViewDimension::dist2Segs(Base::Vector3d s1,
Base::Vector3d e1,
Base::Vector3d s2,
@@ -2043,7 +2044,6 @@ pointPair DrawViewDimension::getArrowPositions()
bool DrawViewDimension::has2DReferences() const
{
// Base::Console().Message("DVD::has2DReferences() - %s\n",getNameInDocument());
const std::vector<App::DocumentObject*>& objects = References2D.getValues();
const std::vector<std::string>& subNames = References2D.getSubValues();
if (objects.empty()) {
@@ -2120,6 +2120,8 @@ PyObject* DrawViewDimension::getPyObject()
return Py::new_reference_to(PythonObject);
}
//! store the corners of this dimension's base view for use by phase 2 of the auto correct process.
void DrawViewDimension::saveFeatureBox()
{
std::vector<Base::Vector3d> bbxCorners;

View File

@@ -204,9 +204,9 @@ public:
return m_corrector;
}
// these should probably be static as they don't use the dimension at all
std::vector<Part::TopoShape> getEdges(const Part::TopoShape& inShape);
std::vector<Part::TopoShape> getVertexes(const Part::TopoShape& inShape);
static std::vector<Part::TopoShape> getEdges(const Part::TopoShape& inShape);
static std::vector<Part::TopoShape> getVertexes(const Part::TopoShape& inShape);
static double getArcAngle(Base::Vector3d center, Base::Vector3d startPoint, Base::Vector3d endPoint);
// autocorrect support methods
void saveFeatureBox();

View File

@@ -47,6 +47,7 @@
#include <Mod/Part/App/PrimitiveFeature.h>
#include <Mod/Part/App/FeaturePartCircle.h>
#include <Mod/Part/App/TopoShapePy.h>
#include <Mod/Measure/App/ShapeFinder.h>
//#include <Mod/Sketcher/App/SketchObject.h>
#include "ShapeExtractor.h"
@@ -55,6 +56,7 @@
#include "Preferences.h"
using namespace TechDraw;
using namespace Measure;
using DU = DrawUtil;
using SU = ShapeUtils;
@@ -166,7 +168,7 @@ TopoDS_Shape ShapeExtractor::getShapes(const std::vector<App::DocumentObject*> l
continue;
} else if (s.ShapeType() < TopAbs_SOLID) {
//clean up composite shapes
TopoDS_Shape cleanShape = stripInfiniteShapes(s);
TopoDS_Shape cleanShape = ShapeFinder::ShapeFinder::stripInfiniteShapes(s);
if (!cleanShape.IsNull()) {
builder.Add(comp, cleanShape);
}
@@ -226,7 +228,7 @@ std::vector<TopoDS_Shape> ShapeExtractor::getXShapes(const App::Link* xLink)
auto shape = Part::Feature::getShape(l); // TODO: getTopoShape() ?
Part::TopoShape ts(shape);
if (ts.isInfinite()) {
shape = stripInfiniteShapes(shape);
shape = ShapeFinder::stripInfiniteShapes(shape);
}
if (!checkShape(l, shape)) {
continue;
@@ -285,7 +287,7 @@ TopoDS_Shape ShapeExtractor::getShapeFromXLink(const App::Link* xLink)
}
Part::TopoShape ts(shape);
if (ts.isInfinite()) {
shape = stripInfiniteShapes(shape);
shape = ShapeFinder::stripInfiniteShapes(shape);
ts = Part::TopoShape(shape);
}
//ts might be garbage now, better check
@@ -379,30 +381,6 @@ TopoDS_Shape ShapeExtractor::getShapesFused(const std::vector<App::DocumentObjec
return baseShape;
}
//inShape is a compound
//The shapes of datum features (Axis, Plan and CS) are infinite
//Infinite shapes can not be projected, so they need to be removed.
TopoDS_Shape ShapeExtractor::stripInfiniteShapes(TopoDS_Shape inShape)
{
BRep_Builder builder;
TopoDS_Compound comp;
builder.MakeCompound(comp);
TopoDS_Iterator it(inShape);
for (; it.More(); it.Next()) {
TopoDS_Shape s = it.Value();
if (s.ShapeType() < TopAbs_SOLID) {
//look inside composite shapes
s = stripInfiniteShapes(s);
} else if (Part::TopoShape(s).isInfinite()) {
continue;
} else {
//simple shape
}
builder.Add(comp, s);
}
return TopoDS_Shape(std::move(comp));
}
bool ShapeExtractor::is2dObject(const App::DocumentObject* obj)
{

View File

@@ -42,9 +42,10 @@ public:
static TopoDS_Shape getShapes(const std::vector<App::DocumentObject*> links, bool include2d = true);
static std::vector<TopoDS_Shape> getShapes2d(const std::vector<App::DocumentObject*> links);
static std::vector<TopoDS_Shape> getXShapes(const App::Link* xLink);
static std::vector<TopoDS_Shape> getShapesFromObject(const App::DocumentObject* docObj);
static TopoDS_Shape getShapesFused(const std::vector<App::DocumentObject*> links);
static TopoDS_Shape getShapeFromXLink(const App::Link* xLink);
static std::vector<TopoDS_Shape> getShapesFromXRoot(const App::DocumentObject *xLinkRoot);
static std::vector<TopoDS_Shape> getShapesFromObject(const App::DocumentObject* docObj);
static bool is2dObject(const App::DocumentObject* obj);
static bool isEdgeType(const App::DocumentObject* obj);
@@ -52,14 +53,19 @@ public:
static bool isDraftPoint(const App::DocumentObject* obj);
static bool isDatumPoint(const App::DocumentObject* obj);
static bool isSketchObject(const App::DocumentObject* obj);
static bool isExplodedAssembly(const App::DocumentObject* obj);
static Base::Vector3d getLocation3dFromFeat(const App::DocumentObject *obj);
static TopoDS_Shape stripInfiniteShapes(TopoDS_Shape inShape);
static TopoDS_Shape getLocatedShape(const App::DocumentObject* docObj);
static bool checkShape(const App::DocumentObject* shapeObj, TopoDS_Shape shape);
static App::DocumentObject* getExplodedAssembly(std::vector<TopoDS_Shape>& sourceShapes,
App::DocumentObject* link);
static void restoreExplodedAssembly(App::DocumentObject* link);
static App::DocumentObject* getLinkedObject(const App::DocumentObject* root);
protected:
private:

View File

@@ -30,6 +30,7 @@
#include <App/DocumentObject.h>
#include <Base/Console.h>
#include <Gui/Selection.h>
#include <Mod/Measure/App/ShapeFinder.h>
#include <Mod/TechDraw/App/DrawViewPart.h>
#include <Mod/TechDraw/App/ShapeExtractor.h>
@@ -37,6 +38,7 @@
using namespace TechDraw;
using namespace Measure;
using DU = DrawUtil;
TechDraw::DrawViewPart* TechDraw::getReferencesFromSelection(ReferenceVector& references2d,
@@ -44,15 +46,21 @@ TechDraw::DrawViewPart* TechDraw::getReferencesFromSelection(ReferenceVector& re
{
TechDraw::DrawViewPart* dvp(nullptr);
TechDraw::DrawViewDimension* dim(nullptr);
std::vector<Gui::SelectionObject> selectionAll = Gui::Selection().getSelectionEx();
constexpr bool allowOnlySingle{false};
std::vector<Gui::SelectionObject> selectionAll =
Gui::Selection().getSelectionEx("*",
App::DocumentObject::getClassTypeId(),
Gui::ResolveMode::NoResolve,
allowOnlySingle);
for (auto& selItem : selectionAll) {
if (selItem.getObject()->isDerivedFrom(TechDraw::DrawViewDimension::getClassTypeId())) {
//we are probably repairing a dimension, but we will check later
dim = static_cast<TechDraw::DrawViewDimension*>(selItem.getObject());
dim = static_cast<TechDraw::DrawViewDimension*>(selItem.getObject()); //NOLINT cppcoreguidelines-pro-type-static-cast-downcast
} else if (selItem.getObject()->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) {
//this could be a 2d geometry selection or just a DrawViewPart for context in
//a 3d selection
dvp = static_cast<TechDraw::DrawViewPart*>(selItem.getObject());
dvp = static_cast<TechDraw::DrawViewPart*>(selItem.getObject()); //NOLINT cppcoreguidelines-pro-type-static-cast-downcast
if (selItem.getSubNames().empty()) {
//there are no subNames, so we think this is a 3d case,
//and we only need to select the view. We set the reference
@@ -62,38 +70,17 @@ TechDraw::DrawViewPart* TechDraw::getReferencesFromSelection(ReferenceVector& re
continue;
}
for (auto& sub : selItem.getSubNames()) {
ReferenceEntry ref(dvp, sub);
// plain ordinary 2d view + geometry reference
ReferenceEntry ref(dvp, ShapeFinder::getLastTerm(sub));
references2d.push_back(ref);
}
} else if (!selItem.getObject()->isDerivedFrom(TechDraw::DrawView::getClassTypeId())) {
//this is not a TechDraw object, so we check to see if it has 3d geometry
std::vector<App::DocumentObject*> links;
links.push_back(selItem.getObject());
if (!ShapeExtractor::getShapes(links).IsNull()) {
//this item has 3d geometry so we are interested
App::DocumentObject* obj3d = selItem.getObject();
if (selItem.getSubNames().empty()) {
if (ShapeExtractor::isPointType(obj3d)) {
//a point object may not have a subName when selected,
//so we need to perform some special handling.
ReferenceEntry ref(obj3d, "Vertex1");
references3d.push_back(ref);
continue;
} else {
//this is a whole object reference, probably for an extent dimension
ReferenceEntry ref(obj3d, std::string());
references3d.push_back(ref);
continue;
}
}
//this is a regular reference in form obj+subelement
for (auto& sub3d : selItem.getSubNames()) {
ReferenceEntry ref(obj3d, sub3d);
references3d.push_back(ref);
}
} else {
Base::Console().Message("DV::getRefsFromSel - %s has no shape!\n",
selItem.getObject()->getNameInDocument());
App::DocumentObject* obj3d = selItem.getObject();
// this is a regular 3d reference in form obj + long subelement
for (auto& sub3d : selItem.getSubNames()) {
ReferenceEntry ref(obj3d, sub3d);
references3d.push_back(ref);
}
}
}
@@ -109,15 +96,15 @@ TechDraw::DrawViewPart* TechDraw::getReferencesFromSelection(ReferenceVector& re
//! verify that the proposed references contains valid geometries from a 2d DrawViewPart.
DimensionGeometryType TechDraw::validateDimSelection(
ReferenceVector references, //[(dvp*, std::string),...,(dvp*, std::string)]
StringVector acceptableGeometry,//"Edge", "Vertex", etc
std::vector<int> minimumCounts, //how many of each geometry are needed for a good dimension
std::vector<DimensionGeometryType> acceptableDimensionGeometrys)//isVertical, isHorizontal, ...
const ReferenceVector& references, //[(dvp*, std::string),...,(dvp*, std::string)]
const StringVector& acceptableGeometry,//"Edge", "Vertex", etc
const std::vector<int>& minimumCounts, //how many of each geometry are needed for a good dimension
const std::vector<DimensionGeometryType>& acceptableDimensionGeometrys)//isVertical, isHorizontal, ...
{
StringVector subNames;
TechDraw::DrawViewPart* dvpSave(nullptr);
for (auto& ref : references) {
auto* dvp = dynamic_cast<TechDraw::DrawViewPart*>(ref.getObject());
auto dvp = dynamic_cast<TechDraw::DrawViewPart*>(ref.getObject());
if (dvp) {
dvpSave = dvp;
if (!ref.getSubName().empty()) {
@@ -181,15 +168,15 @@ DimensionGeometryType TechDraw::validateDimSelection(
//! verify that the proposed references contains valid geometries from non-TechDraw objects.
DimensionGeometryType TechDraw::validateDimSelection3d(
TechDraw::DrawViewPart* dvp,
ReferenceVector references, //[(dvp*, std::string),...,(dvp*, std::string)]
StringVector acceptableGeometry,//"Edge", "Vertex", etc
std::vector<int> minimumCounts, //how many of each geometry are needed for a good dimension
std::vector<DimensionGeometryType> acceptableDimensionGeometrys)//isVertical, isHorizontal, ...
const ReferenceVector& references, //[(dvp*, std::string),...,(dvp*, std::string)]
const StringVector& acceptableGeometry,//"Edge", "Vertex", etc
const std::vector<int>& minimumCounts, //how many of each geometry are needed for a good dimension
const std::vector<DimensionGeometryType>& acceptableDimensionGeometrys)//isVertical, isHorizontal, ...
{
StringVector subNames;
for (auto& ref : references) {
if (!ref.getSubName().empty()) {
subNames.push_back(ref.getSubName());
subNames.push_back(ref.getSubName(true));
}
}
@@ -225,7 +212,7 @@ DimensionGeometryType TechDraw::validateDimSelection3d(
bool TechDraw::validateSubnameList(StringVector subNames, GeometrySet acceptableGeometrySet)
{
for (auto& sub : subNames) {
std::string geometryType = DrawUtil::getGeomTypeFromName(sub);
std::string geometryType = DrawUtil::getGeomTypeFromName(ShapeFinder::getLastTerm(sub));
if (acceptableGeometrySet.count(geometryType) == 0) {
//this geometry type is not allowed
return false;
@@ -240,7 +227,7 @@ bool TechDraw::checkGeometryOccurrences(StringVector subNames, GeomCountMap keye
//how many of each geometry descriptor are input
GeomCountMap foundCounts;
for (auto& sub : subNames) {
std::string geometryType = DrawUtil::getGeomTypeFromName(sub);
std::string geometryType = DrawUtil::getGeomTypeFromName(ShapeFinder::getLastTerm(sub));
std::map<std::string, int>::iterator it0(foundCounts.find(geometryType));
if (it0 == foundCounts.end()) {
//first occurrence of this geometryType
@@ -355,8 +342,8 @@ DimensionGeometryType TechDraw::getGeometryConfiguration3d(DrawViewPart* dvp,
//fill the GeomCountMap with pairs made from corresponding items in acceptableGeometry
//and minimumCounts
GeomCountMap TechDraw::loadRequiredCounts(StringVector& acceptableGeometry,
std::vector<int>& minimumCounts)
GeomCountMap TechDraw::loadRequiredCounts(const StringVector& acceptableGeometry,
const std::vector<int>& minimumCounts)
{
if (acceptableGeometry.size() != minimumCounts.size()) {
throw Base::IndexError("acceptableGeometry and minimum counts have different sizes.");

View File

@@ -66,16 +66,15 @@ enum DimensionGeometryEnum {
DrawViewPart* getReferencesFromSelection(ReferenceVector& references2d,
ReferenceVector& references3d);
DimensionGeometryType validateDimSelection(
ReferenceVector references,
StringVector acceptableGeometry,//"Edge", "Vertex", etc
std::vector<int> minimumCounts, //how many of each geometry are needed for a good dimension
std::vector<DimensionGeometryType> acceptableDimensionGeometrys);//isVertical, isHorizontal, ...
DimensionGeometryType validateDimSelection3d(
DrawViewPart* dvp, ReferenceVector references,
StringVector acceptableGeometry,//"Edge", "Vertex", etc
std::vector<int> minimumCounts, //how many of each geometry are needed for a good dimension
std::vector<DimensionGeometryType> acceptableDimensionGeometrys);//isVertical, isHorizontal, ...
DimensionGeometryType validateDimSelection(const ReferenceVector& references,
const StringVector& acceptableGeometry,//"Edge", "Vertex", etc
const std::vector<int>& minimumCounts, //how many of each geometry are needed for a good dimension
const std::vector<DimensionGeometryType>& acceptableDimensionGeometrys);//isVertical, isHorizontal, ...
DimensionGeometryType validateDimSelection3d(DrawViewPart* dvp,
const ReferenceVector& references,
const StringVector& acceptableGeometry, //"Edge", "Vertex", etc
const std::vector<int>& minimumCounts, //how many of each geometry are needed for a good dimension
const std::vector<DimensionGeometryType>& acceptableDimensionGeometrys);//isVertical, isHorizontal, ...
bool validateSubnameList(StringVector subNames, GeometrySet acceptableGeometrySet);
@@ -83,8 +82,8 @@ DimensionGeometryType getGeometryConfiguration(ReferenceVector valid2dReferences
DimensionGeometryType getGeometryConfiguration3d(DrawViewPart* dvp,
ReferenceVector valid3dReferences);
GeomCountMap loadRequiredCounts(StringVector& acceptableGeometry,
std::vector<int>& minimumCouts);
GeomCountMap loadRequiredCounts(const StringVector& acceptableGeometry,
const std::vector<int>& minimumCouts);
bool checkGeometryOccurrences(StringVector subNames, GeomCountMap keyedMinimumCounts);
DimensionGeometryType isValidVertexes(ReferenceVector refs);