[TD]fix extent dimension

This commit is contained in:
wandererfan
2022-09-08 20:12:29 -04:00
committed by WandererFan
parent 968fb5be34
commit 20f5db1ad1
10 changed files with 93 additions and 181 deletions

View File

@@ -31,21 +31,19 @@
#include <string>
# include <exception>
#include <limits>
#include <Precision.hxx>
#include <Bnd_Box2d.hxx>
#include <BndLib_Add2dCurve.hxx>
#include <Bnd_Box.hxx>
#include <BRep_Tool.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include "BRepBuilderAPI_MakeShape.hxx"
#include <BRepBndLib.hxx>
#include <Extrema_ExtCC2d.hxx>
#include <Geom2dAdaptor_Curve.hxx>
#include <Geom2d_Curve.hxx>
#include <Geom2d_Line.hxx>
#include <Geom2dAPI_ProjectPointOnCurve.hxx>
#include <GeomAPI.hxx>
#include <BRepExtrema_DistShapeShape.hxx>
#include <Geom_Line.hxx>
#include <Geom_Curve.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <gp_Pnt2d.hxx>
#include <gp_Pln.hxx>
#include <TopoDS_Edge.hxx>
#endif
@@ -76,16 +74,6 @@
using namespace TechDraw;
hTrimCurve::hTrimCurve(Handle(Geom2d_Curve) hCurveIn,
double parm1,
double parm2) :
hCurve(hCurveIn),
first(parm1),
last(parm2)
{
//just a convenient struct for now.
}
//All this OCC math is being done on edges(&vertices) that have been through the center/scale/mirror process.
//TODO: this needs to be exposed to Python
@@ -187,55 +175,53 @@ std::pair<Base::Vector3d, Base::Vector3d> DrawDimHelper::minMax(DrawViewPart* dv
}
Bnd_Box edgeBbx;
edgeBbx.SetGap(0.0);
edgeBbx.SetGap(1.0); //make the box a bit bigger
std::vector<Handle(Geom_Curve)> selCurves;
std::vector<hTrimCurve> hTCurve2dList;
std::vector<TopoDS_Edge> inEdges;
for (auto& bg: selEdges) {
TopoDS_Edge e = bg->occEdge;
BRepBndLib::AddOptimal(e, edgeBbx);
double first = 0.0;
double last = 0.0;
Handle(Geom_Curve) hCurve = BRep_Tool::Curve(e, first, last);
Handle(Geom2d_Curve) hCurve2 = GeomAPI::To2d (hCurve, projPlane);
hTrimCurve temp(hCurve2, first, last);
hTCurve2dList.push_back(temp);
inEdges.push_back(bg->occEdge);
BRepBndLib::Add(bg->occEdge, edgeBbx);
}
//can't use Bnd_Box2d here as BndLib_Add2dCurve::Add adds the poles of splines to the box.
//poles are not necessarily on the curve! 3d Bnd_Box does it properly.
//this has to be the bbx of the selected edges, not the dvp!!!
double minX, minY, minZ, maxX, maxY, maxZ;
edgeBbx.Get(minX, minY, minZ, maxX, maxY, maxZ);
double xMid = (maxX + minX) / 2.0;
double yMid = (maxY + minY) / 2.0;
gp_Pnt2d rightMid(maxX, yMid);
gp_Pnt2d leftMid(minX, yMid);
gp_Pnt2d topMid(xMid, maxY);
gp_Pnt2d bottomMid(xMid, minY);
gp_Pnt rightMid(maxX, yMid, 0.0);
gp_Pnt leftMid(minX, yMid, 0.0);
gp_Pnt topMid(xMid, maxY, 0.0);
gp_Pnt bottomMid(xMid, minY, 0.0);
gp_Dir2d xDir(1.0, 0.0);
gp_Dir2d yDir(0.0, 1.0);
gp_Dir xDir(1.0, 0.0, 0.0);
gp_Dir yDir(0.0, 1.0, 0.0);
if (direction == HORIZONTAL) {
Handle(Geom2d_Line) boundaryLeft = new Geom2d_Line(leftMid, yDir);
gp_Pnt2d leftPoint = findClosestPoint(hTCurve2dList,
boundaryLeft);
Handle(Geom2d_Line) boundaryRight = new Geom2d_Line(rightMid, yDir);
gp_Pnt2d rightPoint = findClosestPoint(hTCurve2dList,
boundaryRight);
Handle(Geom_Line) lineLeft = new Geom_Line(leftMid, yDir);
BRepBuilderAPI_MakeEdge mkEdgeLeft(lineLeft);
TopoDS_Edge edgeLeft = mkEdgeLeft.Edge();
gp_Pnt leftPoint = findClosestPoint(inEdges,
edgeLeft);
Handle(Geom_Line) lineRight = new Geom_Line(rightMid, yDir);
BRepBuilderAPI_MakeEdge mkEdgeRight(lineRight);
TopoDS_Edge edgeRight = mkEdgeRight.Edge();
gp_Pnt rightPoint = findClosestPoint(inEdges,
edgeRight);
refMin = Base::Vector3d(leftPoint.X(), leftPoint.Y(), 0.0);
refMax = Base::Vector3d(rightPoint.X(), rightPoint.Y(), 0.0);
} else if (direction == VERTICAL) {
Handle(Geom2d_Line) boundaryBottom = new Geom2d_Line(bottomMid, xDir);
gp_Pnt2d bottomPoint = findClosestPoint(hTCurve2dList,
boundaryBottom);
Handle(Geom2d_Line) boundaryTop = new Geom2d_Line(topMid, xDir);
gp_Pnt2d topPoint = findClosestPoint(hTCurve2dList,
boundaryTop);
Handle(Geom_Line) lineBottom = new Geom_Line(bottomMid, xDir);
BRepBuilderAPI_MakeEdge mkEdgeBottom(lineBottom);
TopoDS_Edge edgeBottom = mkEdgeBottom.Edge();
gp_Pnt bottomPoint = findClosestPoint(inEdges,
edgeBottom);
Handle(Geom_Line) lineTop = new Geom_Line(topMid, xDir);
BRepBuilderAPI_MakeEdge mkEdgeTop(lineTop);
TopoDS_Edge edgeTop = mkEdgeTop.Edge();
gp_Pnt topPoint = findClosestPoint(inEdges,
edgeTop);
refMin = Base::Vector3d(bottomPoint.X(), bottomPoint.Y(), 0.0);
refMax = Base::Vector3d(topPoint.X(), topPoint.Y(), 0.0);
}
@@ -247,87 +233,30 @@ std::pair<Base::Vector3d, Base::Vector3d> DrawDimHelper::minMax(DrawViewPart* dv
//given list of curves, find the closest point from any curve to a boundary
//computation intensive for a cosmetic result.
gp_Pnt2d DrawDimHelper::findClosestPoint(std::vector<hTrimCurve> hTCurve2dList,
Handle(Geom2d_Curve) boundary)
gp_Pnt DrawDimHelper::findClosestPoint(std::vector<TopoDS_Edge> inEdges,
TopoDS_Edge& boundary)
{
// Base::Console().Message("DDH::findClosestPoint() - curves: %d\n", hTCurve2dList.size());
// Base::Console().Message("DDH::findClosestPoint() - edges: %d\n", inEdges.size());
//
//find an extent point that is actually on one of the curves
gp_Pnt2d result(-1.0, -1.0);
Geom2dAdaptor_Curve aBoundary(boundary);
double globalNearDist = FLT_MAX;
gp_Pnt2d globalNearPoint;
bool found = false;
for (auto& hCurve2d : hTCurve2dList) {
Geom2dAdaptor_Curve aCurve(hCurve2d.hCurve,
hCurve2d.first,
hCurve2d.last);
Extrema_ExtCC2d mkExtr(aBoundary, aCurve);
if (mkExtr.IsDone()) {
double nearDist = FLT_MAX;
int nearIdx = 0;
gp_Pnt2d nearPoint;
if (mkExtr.NbExt() > 0) {
int stop = mkExtr.NbExt();
int i = 1; //this is OCC start (1) not conventional start (0)
for ( ; i <= stop; i++) {
double dist = mkExtr.SquareDistance(i);
if (dist < nearDist) {
found = true;
nearDist = dist;
nearIdx = i;
Extrema_POnCurv2d p1, p2;
mkExtr.Points(nearIdx, p1, p2);
nearPoint = p2.Value();
}
}
} else { //no extrema? - might be a line parallel to boundary
if (mkExtr.IsParallel()) {
//get midpoint of aCurve
double mid = (hCurve2d.first + hCurve2d.last) / 2.0;
gp_Pnt2d midPoint = hCurve2d.hCurve->Value(mid);
//get distance midpoint to boundary => nearDist
Geom2dAPI_ProjectPointOnCurve mkProj(midPoint, boundary);
double dist = mkProj.LowerDistance() * mkProj.LowerDistance();
if (dist < nearDist) {
found = true;
nearDist = dist;
nearPoint = mkProj.NearestPoint();
}
} else { //skew and no extrema?
gp_Pnt2d pFirst = hCurve2d.hCurve->Value(hCurve2d.first);
Geom2dAPI_ProjectPointOnCurve mkFirst(pFirst, boundary);
double dist1 = mkFirst.LowerDistance() * mkFirst.LowerDistance();
gp_Pnt2d pLast = hCurve2d.hCurve->Value(hCurve2d.last);
Geom2dAPI_ProjectPointOnCurve mkLast(pLast, boundary);
double dist2 = mkLast.LowerDistance() * mkLast.LowerDistance();
if (dist1 < dist2) {
if (dist1 < nearDist) {
found = true;
nearDist = dist1;
nearPoint = mkFirst.NearestPoint();
}
} else {
if (dist2 < nearDist) {
found = true;
nearDist = dist2;
nearPoint = mkLast.NearestPoint();
}
}
}
}
if (nearDist < globalNearDist) {
globalNearDist = nearDist;
globalNearPoint = nearPoint;
}
double minDistance(std::numeric_limits<float>::max());
gp_Pnt nearPoint;
for (auto& edge : inEdges) {
BRepExtrema_DistShapeShape extss(edge, boundary);
if (!extss.IsDone()) {
Base::Console().Warning("DDH::findClosestPoint - BRepExtrema_DistShapeShape failed - 1\n");
continue;
}
if (extss.NbSolution() == 0) {
Base::Console().Warning("DDH::findClosestPoint - BRepExtrema_DistShapeShape failed - 2\n");
continue;
}
if (extss.Value() < minDistance) {
minDistance = extss.Value();
nearPoint = extss.PointOnShape1(1);
}
}
if (found) {
result = globalNearPoint;
}
return result;
return nearPoint;
}
DrawViewDimension* DrawDimHelper::makeDistDim(DrawViewPart* dvp,
@@ -349,6 +278,8 @@ DrawViewDimension* DrawDimHelper::makeDistDim(DrawViewPart* dvp,
dimName = doc->getUniqueObjectName("DimExtent");
}
std::vector<TechDraw::VertexPtr> gVerts = dvp->getVertexGeometry();
Base::Vector3d cleanMin = DrawUtil::invertY(inMin);
std::string tag1 = dvp->addCosmeticVertex(cleanMin);
int iGV1 = dvp->add1CVToGV(tag1);
@@ -357,6 +288,7 @@ DrawViewDimension* DrawDimHelper::makeDistDim(DrawViewPart* dvp,
std::string tag2 = dvp->addCosmeticVertex(cleanMax);
int iGV2 = dvp->add1CVToGV(tag2);
gVerts = dvp->getVertexGeometry();
std::vector<App::DocumentObject *> objs;
std::vector<std::string> subs;
@@ -385,18 +317,16 @@ DrawViewDimension* DrawDimHelper::makeDistDim(DrawViewPart* dvp,
Base::Interpreter().runStringArg("App.activeDocument().%s.Type = '%s'",
dimName.c_str(), dimType.c_str());
Base::Interpreter().runStringArg("App.activeDocument().%s.addView(App.activeDocument().%s)",
pageName.c_str(), dimName.c_str());
dim = dynamic_cast<TechDraw::DrawViewDimension *>(doc->getObject(dimName.c_str()));
if (!dim) {
throw Base::TypeError("DDH::makeDistDim - dim not found\n");
}
dim->References2D.setValues(objs, subs);
dvp->requestPaint();
dim->recomputeFeature();
Base::Interpreter().runStringArg("App.activeDocument().%s.addView(App.activeDocument().%s)",
pageName.c_str(), dimName.c_str());
dvp->requestPaint();
return dim;
}

View File

@@ -26,45 +26,36 @@
#include <Mod/TechDraw/TechDrawGlobal.h>
#include <Geom2d_Curve.hxx>
#include <gp_Pnt.hxx>
#include <TopoDS_Edge.hxx>
#include <string>
#include <Base/Vector3D.h>
#include <vector>
class gp_Pnt2d;
#include <Base/Vector3D.h>
namespace TechDraw
{
class BaseGeom;
class DrawViewPart;
class TechDrawExport hTrimCurve {
public:
hTrimCurve() : first(0.0), last(0.0) {}
hTrimCurve(Handle(Geom2d_Curve) hCurveIn,
double parm1,
double parm2);
~hTrimCurve() = default;
Handle(Geom2d_Curve) hCurve;
double first;
double last;
};
class DrawViewDimension;
/// Additional functions for working with Dimensions
class TechDrawExport DrawDimHelper {
public:
static void makeExtentDim(DrawViewPart* dvp,
// std::vector<TechDraw::BaseGeomPtr> selEdges,
std::vector<std::string> edgeNames,
int direction);
static gp_Pnt2d findClosestPoint(std::vector<hTrimCurve> hCurve2dList,
Handle(Geom2d_Curve) boundary);
static gp_Pnt findClosestPoint(std::vector<TopoDS_Edge> inEdges,
TopoDS_Edge& boundary);
static TechDraw::DrawViewDimension* makeDistDim(DrawViewPart* dvp,
std::string dimType,
Base::Vector3d refMin,
Base::Vector3d refMax,
bool extent = false);
static std::pair<Base::Vector3d, Base::Vector3d> minMax(DrawViewPart* dvp,
std::vector<std::string> edgeNames,
int direction);

View File

@@ -122,13 +122,16 @@ App::DocumentObjectExecReturn *DrawViewDimExtent::execute(void)
std::vector<std::string> cTags = CosmeticTags.getValues();
if (cTags.size() <= 1) {
return DrawViewDimension::execute();
//not ready yet.
return DrawView::execute();
}
TechDraw::VertexPtr v0 = dvp->getProjVertexByCosTag(cTags[0]);
TechDraw::VertexPtr v1 = dvp->getProjVertexByCosTag(cTags[1]);
if (!v0 || !v1)
return DrawViewDimension::execute();
if (!v0 || !v1) {
//either not ready yet or something has gone wrong
return DrawView::execute();
}
double length00 = (v0->pnt - refMin).Length();
double length11 = (v1->pnt - refMax).Length();
@@ -158,8 +161,9 @@ App::DocumentObjectExecReturn *DrawViewDimExtent::execute(void)
std::vector<std::string> DrawViewDimExtent::getSubNames(void)
{
std::vector<std::string> edgeNames = Source.getSubValues();
// Base::Console().Message("DVDE::getSubNames - edgeNames: %d\n", edgeNames.size());
if (edgeNames.empty() ||
!edgeNames[0].empty()) {
edgeNames[0].empty()) {
return std::vector<std::string>(); //garbage first entry - nop
}
return edgeNames;
@@ -179,7 +183,8 @@ pointPair DrawViewDimExtent::getPointsTwoVerts()
}
std::vector<std::string> cTags = CosmeticTags.getValues();
if (cTags.empty()) {
if (cTags.size() < 2) {
// Base::Console().Message("DVDE::getPointsTwoVerts - not enough tags!\n");
return errorValue;
}
@@ -201,8 +206,9 @@ bool DrawViewDimExtent::checkReferences2D() const
}
std::vector<std::string> cTags = CosmeticTags.getValues();
if (cTags.empty()) {
return false;
if (cTags.size() < 2) {
//still building this dimension, so treat as valid?
return true;
}
CosmeticVertex* cv0 = dvp->getCosmeticVertex(cTags[0]);

View File

@@ -55,6 +55,8 @@ public:
void unsetupObject() override;
bool checkReferences2D() const override;
int getRefType() const override { return twoVertex; }
pointPair getLinearPoints() override { return getPointsTwoVerts(); }
//return PyObject as DrawViewDimExtentPy
PyObject *getPyObject() override;

View File

@@ -1183,7 +1183,7 @@ double DrawViewDimension::getDimValue()
if ( Type.isValue("Distance") ||
Type.isValue("DistanceX") ||
Type.isValue("DistanceY") ) {
pointPair pts = m_linearPoints;
pointPair pts = getLinearPoints();
Base::Vector3d dimVec = pts.first - pts.second;
if (Type.isValue("Distance")) {
result = dimVec.Length() / getViewPart()->getScale();

View File

@@ -199,7 +199,7 @@ public:
void setAll3DMeasurement();
void clear3DMeasurements();
virtual bool checkReferences2D() const;
pointPair getLinearPoints() {return m_linearPoints; }
virtual pointPair getLinearPoints() {return m_linearPoints; }
arcPoints getArcPoints() {return m_arcPoints; }
anglePoints getAnglePoints() {return m_anglePoints; }
bool leaderIntersectsArc(Base::Vector3d s, Base::Vector3d pointOnCircle);

View File

@@ -1263,10 +1263,10 @@ void DrawViewPart::addCosmeticVertexesToGeom()
int DrawViewPart::add1CVToGV(std::string tag)
{
// Base::Console().Message("DVP::add1CVToGV(%s) 2\n", tag.c_str());
// Base::Console().Message("DVP::add1CVToGV(%s)\n", tag.c_str());
TechDraw::CosmeticVertex* cv = getCosmeticVertex(tag);
if (!cv) {
Base::Console().Message("DVP::add1CVToGV 2 - cv %s not found\n", tag.c_str());
Base::Console().Message("DVP::add1CVToGV - cv %s not found\n", tag.c_str());
return 0;
}
int iGV = geometryObject->addCosmeticVertex(cv->scaled(getScale()),

View File

@@ -1196,11 +1196,7 @@ void execHExtent(Gui::Command* cmd)
std::vector<Gui::SelectionObject>::iterator itSel = selection.begin();
for (; itSel != selection.end(); itSel++) {
if ((*itSel).getObject()->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) {
// baseFeat = static_cast<TechDraw::DrawViewPart*> ((*itSel).getObject());
SubNames = (*itSel).getSubNames();
if (SubNames.empty() || SubNames[0].empty()) {
SubNames.clear();
}
}
}

View File

@@ -840,6 +840,7 @@ void MDIViewPage::sceneSelectionChanged()
//Note: Qt says: "no guarantee of selection order"!!!
void MDIViewPage::setTreeToSceneSelect()
{
// Base::Console().Message("MDIVP::setTreeToSceneSelect()\n");
bool saveBlock = blockSelection(true); // block selectionChanged signal from Tree/Observer
blockSceneSelection(true);
Gui::Selection().clearSelection();
@@ -1003,15 +1004,12 @@ bool MDIViewPage::compareSelections(std::vector<Gui::SelectionObject> treeSel, Q
int treeCount = 0;
int sceneCount = 0;
int subCount = 0;
int ppCount = 0;
std::vector<std::string> treeNames;
std::vector<std::string> sceneNames;
for (auto tn: treeSel) {
if (tn.getObject()->isDerivedFrom(TechDraw::DrawView::getClassTypeId())) {
int treeSubs = tn.getSubNames().size();
subCount += treeSubs;
std::string s = tn.getObject()->getNameInDocument();
treeNames.push_back(s);
}
@@ -1081,20 +1079,10 @@ void MDIViewPage::showStatusMsg(const char* string1, const char* string2, const
QString::fromUtf8(string2),
QString::fromUtf8(string3));
if (Gui::getMainWindow()) {
Gui::getMainWindow()->showMessage(msg, 3000);
Gui::getMainWindow()->showMessage(msg, 6000);
}
}
//return the MDIViewPage that owns the scene
MDIViewPage *MDIViewPage::getFromScene(const QGSPage *scene)
{
if (scene && scene->parent()) {
return dynamic_cast<MDIViewPage *>(scene->parent());
}
return nullptr;
}
// ----------------------------------------------------------------------------
void MDIViewPagePy::init_type()

View File

@@ -102,7 +102,6 @@ public:
void setTabText(std::string tabText);
static MDIViewPage *getFromScene(const QGSPage *scene);
void contextMenuEvent(QContextMenuEvent *event) override;
void setScene(QGSPage* scene, QGVPage* view);