[TD]fix issues reported by 3d dimension testers

- correct interpretation of True vs Projected

- handle long subelement names in references

- fix "too small" value condition

- better error messages for bad dimension geometry
This commit is contained in:
wandererfan
2022-11-27 19:35:33 -05:00
committed by WandererFan
parent 1b547dff72
commit 17554e29f1
11 changed files with 148 additions and 64 deletions

View File

@@ -58,6 +58,8 @@ std::string DimensionFormatter::formatValue(qreal value,
int partial,
bool isDim)
{
// Base::Console().Message("DF::formatValue() - %s isRestoring: %d\n",
// m_dimension->getNameInDocument(), m_dimension->isRestoring());
bool angularMeasure = false;
QLocale loc;
@@ -129,7 +131,8 @@ std::string DimensionFormatter::formatValue(qreal value,
}
if (isTooSmall(userVal, formatSpecifier)) {
Base::Console().Warning("Dimension value is too small for format specifier: %s\n", qPrintable(formatSpecifier));
Base::Console().Warning("Dimension %s value %.6f is too small for format specifier: %s\n",
m_dimension->getNameInDocument(), userVal, qPrintable(formatSpecifier));
}
formattedValue = formatValueToSpec(userVal, formatSpecifier);
@@ -398,7 +401,7 @@ bool DimensionFormatter::isTooSmall(double value, QString formatSpec)
QString decimalGroup = rxMatch.captured(1);
int factor = decimalGroup.toInt();
double minValue = pow(10.0, -factor);
if (value < minValue) {
if (std::fabs(value) < minValue) {
return true;
}
} else {

View File

@@ -65,6 +65,19 @@ TopoDS_Shape ReferenceEntry::getGeometry() const
return shape.getSubShape(getSubName().c_str());
}
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;
}
std::string ReferenceEntry::geomType() const
{
return DrawUtil::getGeomTypeFromName(getSubName());

View File

@@ -54,7 +54,7 @@ public:
App::DocumentObject* getObject() const { return m_object; }
void setObject(App::DocumentObject* docObj) { m_object = docObj; }
std::string getSubName() const { return m_subName; }
std::string getSubName(bool longForm = false) const;
void setSubName(std::string subName) { m_subName = subName; }
TopoDS_Shape getGeometry() const;
std::string geomType() const;

View File

@@ -267,7 +267,7 @@ void DrawViewDimension::onChanged(const App::Property* prop)
}
return;
} else if (prop == &OverTolerance) {
= // if EqualTolerance set negated overtolerance for untertolerance
// if EqualTolerance set negated overtolerance for untertolerance
if (EqualTolerance.getValue()) {
UnderTolerance.setValue(-1.0 * OverTolerance.getValue());
UnderTolerance.setUnit(OverTolerance.getUnit());
@@ -567,8 +567,15 @@ pointPair DrawViewDimension::getPointsOneEdge(ReferenceVector references)
//TODO: Notify if not straight line Edge?
//this is a 2d object (a DVP + subelements)
TechDraw::BaseGeomPtr geom = getViewPart()->getGeomByIndex(iSubelement);
if (!geom || geom->geomType != TechDraw::GeomType::GENERIC) {
throw Base::RuntimeError("Missing geometry for dimension");
if (!geom) {
std::stringstream ssMessage;
ssMessage << getNameInDocument() << " can not find geometry for 2d reference (1)";
throw Base::RuntimeError(ssMessage.str());
}
if (geom->geomType != TechDraw::GeomType::GENERIC) {
std::stringstream ssMessage;
ssMessage << getNameInDocument() << " 2d reference is a " << geom->geomTypeName();
throw Base::RuntimeError(ssMessage.str());
}
TechDraw::GenericPtr generic = std::static_pointer_cast<TechDraw::Generic>(geom);
return { generic->points[0], generic->points[1] };
@@ -600,14 +607,16 @@ 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(0).getSubName());
int iSubelement1 = DrawUtil::getIndexFromName(references.at(1).getSubName());
if (refObject->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId()) &&
!references.at(0).getSubName().empty()) {
//this is a 2d object (a DVP + subelements)
TechDraw::BaseGeomPtr geom0 = getViewPart()->getGeomByIndex(iSubelement0);
TechDraw::BaseGeomPtr geom1 = getViewPart()->getGeomByIndex(iSubelement1);
if (!geom0 || !geom1) {
throw Base::RuntimeError("Missing geometry for dimension");
std::stringstream ssMessage;
ssMessage << getNameInDocument() << " can not find geometry for 2d reference (2)";
throw Base::RuntimeError(ssMessage.str());
}
return closestPoints(geom0->occEdge, geom1->occEdge);
}
@@ -640,8 +649,11 @@ pointPair DrawViewDimension::getPointsTwoVerts(ReferenceVector references)
TechDraw::VertexPtr v0 = getViewPart()->getProjVertexByIndex(iSubelement0);
TechDraw::VertexPtr v1 = getViewPart()->getProjVertexByIndex(iSubelement1);
if (!v0 || !v1) {
throw Base::RuntimeError("Missing geometry for dimension");
std::stringstream ssMessage;
ssMessage << getNameInDocument() << " can not find geometry for 2d reference (3)";
throw Base::RuntimeError(ssMessage.str());
}
return { v0->pnt, v1->pnt };
}
@@ -670,7 +682,7 @@ 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(0).getSubName());
int iSubelement1 = DrawUtil::getIndexFromName(references.at(1).getSubName());
if (refObject->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId()) &&
!references.at(0).getSubName().empty()) {
//this is a 2d object (a DVP + subelements)
@@ -684,7 +696,7 @@ pointPair DrawViewDimension::getPointsEdgeVert(ReferenceVector references)
vertex = getViewPart()->getProjVertexByIndex(iSubelement0);
}
if (!vertex || !edge) {
throw Base::RuntimeError("Missing geometry for dimension");
throw Base::RuntimeError("Missing geometry for dimension (4)");
}
return closestPoints(edge->occEdge, vertex->occVertex);
}
@@ -715,8 +727,9 @@ arcPoints DrawViewDimension::getArcParameters(ReferenceVector references)
//this is a 2d object (a DVP + subelements)
TechDraw::BaseGeomPtr geom = getViewPart()->getGeomByIndex(iSubelement);
if (!geom) {
Base::Console().Error("DVD - %s - 2D references are corrupt (1)\n",getNameInDocument());
return arcPoints();
std::stringstream ssMessage;
ssMessage << getNameInDocument() << " can not find geometry for 2d reference (4)";
throw Base::RuntimeError(ssMessage.str());
}
return arcPointsFromBaseGeom(getViewPart()->getGeomByIndex(iSubelement));
}
@@ -820,8 +833,9 @@ arcPoints DrawViewDimension::arcPointsFromBaseGeom(TechDraw::BaseGeomPtr base)
throw Base::RuntimeError("Bad BSpline geometry for arc dimension");
}
} else {
Base::Console().Log("Error: DVD - %s - 2D references are corrupt\n", getNameInDocument());
throw Base::RuntimeError("Bad geometry for arc dimension");
std::stringstream ssMessage;
ssMessage << getNameInDocument() << " 2d reference is a " << base->geomTypeName();
throw Base::RuntimeError(ssMessage.str());
}
return pts;
}
@@ -922,13 +936,19 @@ anglePoints DrawViewDimension::getAnglePointsTwoEdges(ReferenceVector references
TechDraw::BaseGeomPtr geom0 = getViewPart()->getGeomByIndex(iSubelement0);
TechDraw::BaseGeomPtr geom1 = getViewPart()->getGeomByIndex(iSubelement1);
if (!geom0 || !geom1) {
throw Base::RuntimeError("Missing geometry for dimension");
std::stringstream ssMessage;
ssMessage << getNameInDocument() << " can not find geometry for 2d reference (5)";
throw Base::RuntimeError(ssMessage.str());
}
if (!geom0 || geom0->geomType != TechDraw::GeomType::GENERIC) {
throw Base::RuntimeError("Missing geometry for dimension");
if (geom0->geomType != TechDraw::GeomType::GENERIC) {
std::stringstream ssMessage;
ssMessage << getNameInDocument() << " first 2d reference is a " << geom0->geomTypeName();
throw Base::RuntimeError(ssMessage.str());
}
if (!geom1 || geom1->geomType != TechDraw::GeomType::GENERIC) {
throw Base::RuntimeError("Missing geometry for dimension");
if (geom1->geomType != TechDraw::GeomType::GENERIC) {
std::stringstream ssMessage;
ssMessage << getNameInDocument() << " second 2d reference is a " << geom0->geomTypeName();
throw Base::RuntimeError(ssMessage.str());
}
TechDraw::GenericPtr generic0 = std::static_pointer_cast<TechDraw::Generic>(geom0);
TechDraw::GenericPtr generic1 = std::static_pointer_cast<TechDraw::Generic>(geom1);
@@ -1128,6 +1148,34 @@ ReferenceVector DrawViewDimension::getEffectiveReferences() const
return effectiveRefs;
}
//return the 2d references as a ReferenceVector
ReferenceVector DrawViewDimension::getReferences2d() const
{
const std::vector<App::DocumentObject*>& objects = References2D.getValues();
const std::vector<std::string>& subElements = References2D.getSubValues();
ReferenceVector refs2d;
int refCount = objects.size();
for (int i = 0; i < refCount; i++) {
ReferenceEntry ref(objects.at(i), subElements.at(i));
refs2d.push_back(ref);
}
return refs2d;
}
//return the 3d references as a ReferenceVector
ReferenceVector DrawViewDimension::getReferences3d() const
{
const std::vector<App::DocumentObject*>& objects3d = References3D.getValues();
const std::vector<std::string>& subElements3d = References3D.getSubValues();
ReferenceVector refs3d;
int refCount = objects3d.size();
for (int i = 0; i < refCount; i++) {
ReferenceEntry ref(objects3d.at(i), subElements3d.at(i));
refs3d.push_back(ref);
}
return refs3d;
}
//what configuration of references do we have - Vertex-Vertex, Edge-Vertex, Edge, ...
int DrawViewDimension::getRefType() const
{

View File

@@ -139,6 +139,8 @@ enum DimensionType {
void setReferences2d(ReferenceVector refs);
void setReferences3d(ReferenceVector refs);
ReferenceVector getReferences2d() const;
ReferenceVector getReferences3d() const;
void setAll3DMeasurement();
void clear3DMeasurements();

View File

@@ -415,6 +415,24 @@ bool BaseGeom::closed()
return false;
}
//keep this in sync with enum GeomType
std::string BaseGeom::geomTypeName()
{
std::vector<std::string> typeNames {
"NotDefined",
"Circle",
"ArcOfCircle",
"Ellipse",
"ArcOfEllipse",
"Bezier",
"BSpline",
"Line", //why was this ever called "Generic"?
"Unknown" } ;
if (geomType >= typeNames.size()) {
return "Unknown";
}
return typeNames.at(geomType);
}
//! Convert 1 OCC edge into 1 BaseGeom (static factory method)
BaseGeomPtr BaseGeom::baseFactory(TopoDS_Edge edge)

View File

@@ -133,6 +133,8 @@ class TechDrawExport BaseGeom : public std::enable_shared_from_this<BaseGeom>
boost::uuids::uuid getTag() const;
virtual std::string getTagAsString() const;
std::string geomTypeName();
private:
void intersectionLL(TechDraw::BaseGeomPtr geom1,
TechDraw::BaseGeomPtr geom2,

View File

@@ -612,6 +612,7 @@ void execDistance(Gui::Command* cmd)
acceptableGeometry,
minimumCounts,
acceptableDimensionGeometrys);
if ( geometryRefs2d == TechDraw::isInvalid ) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("Incorrect Selection"),
@@ -628,6 +629,7 @@ void execDistance(Gui::Command* cmd)
acceptableGeometry,
minimumCounts,
acceptableDimensionGeometrys);
if ( geometryRefs3d == TechDraw::isInvalid ) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("Incorrect Selection"),
@@ -699,7 +701,7 @@ void execDistanceX(Gui::Command* cmd)
//Define the geometric configuration required for a length dimension
StringVector acceptableGeometry( { "Edge", "Vertex" } );
std::vector<int> minimumCounts( { 1, 2 } );
std::vector<DimensionGeometryType> acceptableDimensionGeometrys( { isHorizontal } );
std::vector<DimensionGeometryType> acceptableDimensionGeometrys( { isHorizontal, isDiagonal } );
//what 2d geometry configuration did we receive?
DimensionGeometryType geometryRefs2d = validateDimSelection(references2d,
@@ -794,7 +796,7 @@ void execDistanceY(Gui::Command* cmd)
//Define the geometric configuration required for a length dimension
StringVector acceptableGeometry( { "Edge", "Vertex" } );
std::vector<int> minimumCounts( { 1, 2 } );
std::vector<DimensionGeometryType> acceptableDimensionGeometrys( { isVertical } );
std::vector<DimensionGeometryType> acceptableDimensionGeometrys( { isVertical, isDiagonal } );
//what 2d geometry configuration did we receive?
DimensionGeometryType geometryRefs2d = validateDimSelection(references2d,
@@ -1632,12 +1634,9 @@ DrawViewDimension* dimensionMaker(TechDraw::DrawViewPart* dvp,
Gui::Command::doCommand(Gui::Command::Doc, "App.activeDocument().addObject('TechDraw::DrawViewDimension', '%s')", dimName.c_str());
Gui::Command::doCommand(Gui::Command::Doc, "App.activeDocument().%s.Type = '%s'", dimName.c_str()
,dimType.c_str());
std::string measureType("True");
if (references3d.empty()) {
measureType = "Projected";
}
Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().%s.MeasureType = '%s'", dimName.c_str(),
measureType.c_str());
"Projected");
dim = dynamic_cast<TechDraw::DrawViewDimension *>(dvp->getDocument()->getObject(dimName.c_str()));
if (!dim) {

View File

@@ -459,23 +459,25 @@ DimensionGeometryType TechDraw::isValidMultiEdge(ReferenceVector refs)
return isInvalid;
}
//must be an extent?
if (refs.size() > 2) {
return isMultiEdge;
}
auto objFeat0( dynamic_cast<TechDraw::DrawViewPart *>(refs.at(0).getObject()));
if ( !objFeat0 ) {
//probably redundant
throw Base::RuntimeError("Logic error in isValidMultiEdge");
}
//they both must start with "Edge"
if(TechDraw::DrawUtil::getGeomTypeFromName(refs.at(0).getSubName()) != "Edge" ||
TechDraw::DrawUtil::getGeomTypeFromName(refs.at(1).getSubName()) != "Edge") {
return isInvalid;
//they all must start with "Edge"
for (auto& ref : refs) {
if(TechDraw::DrawUtil::getGeomTypeFromName(ref.getSubName()) != "Edge" ) {
return isInvalid;
}
}
if (refs.size() > 2) {
//many edges, must be an extent?
return isMultiEdge;
}
//exactly 2 edges. could be angle, could be distance
int GeoId0( TechDraw::DrawUtil::getIndexFromName(refs.at(0).getSubName()) );
int GeoId1( TechDraw::DrawUtil::getIndexFromName(refs.at(1).getSubName()) );
TechDraw::BaseGeomPtr geom0 = objFeat0->getGeomByIndex(GeoId0);

View File

@@ -49,7 +49,6 @@
#include <Mod/TechDraw/App/DrawViewPart.h>
#include <Mod/TechDraw/App/DrawUtil.h>
#include "PreferencesGui.h"
#include "DimensionValidators.h"
#include "TaskDimRepair.h"
#include <Mod/TechDraw/Gui/ui_TaskDimRepair.h>
@@ -68,6 +67,13 @@ TaskDimRepair::TaskDimRepair(TechDraw::DrawViewDimension* inDvd,
{
ui->setupUi(this);
if (m_references2d.size() == 1 &&
m_references2d.front().getSubName().empty() &&
m_references3d.empty()) {
//the entry in references2d is a spurious View reference (from getReferencesFromSelection),
// not a geometry reference, so we treat it as empty
m_references2d.clear();
}
connect(ui->pbSelection, SIGNAL(clicked(bool)), this, SLOT(slotUseSelection()));
saveDimState();
@@ -105,7 +111,7 @@ void TaskDimRepair::setUiPrimary()
if (!m_references3d.empty()) {
references3d = m_references3d;
} else if (!objs3d.empty()) {
references3d = m_dim->getEffectiveReferences();
references3d = m_dim->getReferences3d();
}
loadTableWidget(ui->twReferences3d, references3d);
}
@@ -115,21 +121,18 @@ void TaskDimRepair::saveDimState()
m_saveMeasureType = m_dim->MeasureType.getValue();
m_saveDimType = m_dim->Type.getValue();
m_dimType = m_dim->Type.getValue();
m_saveObjs3d = m_dim->References3D.getValues();
m_saveSubs3d = m_dim->References3D.getSubValues();
m_saveDvp = static_cast<DrawViewPart*>(m_dim->References2D.getValues().front());
m_saveSubs2d = m_dim->References2D.getSubValues();
m_saveRefs3d = m_dim->getReferences3d();
m_saveRefs2d = m_dim->getReferences2d();
m_saveDvp = m_dim->getViewPart();
}
//restore the start conditions
void TaskDimRepair::restoreDimState()
{
// Base::Console().Message("TDR::restoreDimState()\n");
if (m_dim != nullptr) {
std::vector<App::DocumentObject*> objs2d(m_saveSubs2d.size());
std::iota(objs2d.begin(), objs2d.end(), m_saveDvp);
m_dim->References2D.setValues(objs2d, m_saveSubs2d);
m_dim->References3D.setValues(m_saveObjs3d, m_saveSubs3d);
if (m_dim) {
m_dim->setReferences2d(m_saveRefs2d);
m_dim->setReferences3d(m_saveRefs3d);
}
}
@@ -137,6 +140,7 @@ void TaskDimRepair::restoreDimState()
//use the current selection to replace the references in dim
void TaskDimRepair::slotUseSelection()
{
// Base::Console().Message("TDR::slotUseSelection()\n");
const std::vector<App::DocumentObject*> dimObjects = Gui::Selection().getObjectsOfType(TechDraw::DrawViewDimension::getClassTypeId());
if (dimObjects.empty()) {
//selection does not include a dimension, so we need to add our dimension to keep the
@@ -256,29 +260,24 @@ void TaskDimRepair::fillList(QListWidget* lwItems, std::vector<std::string> labe
}
void TaskDimRepair::replaceReferences()
{
if (m_dim) {
// Base::Console().Message("TDR::replaceReferences() - refs2d: %d refs3d %d\n", m_references2d.size(), m_references3d.size());
if (!m_dim) {
return;
}
if (!m_references2d.empty()) {
m_dim->setReferences2d(m_references2d);
}
if (!m_references3d.empty()) {
m_dim->setReferences3d(m_references3d);
}
}
void TaskDimRepair::updateTypes()
{
if (m_references3d.empty()) {
m_dim->MeasureType.setValue("Projected");
} else {
m_dim->MeasureType.setValue("True");
}
m_dim->Type.setValue(m_dimType);
}
bool TaskDimRepair::accept()
{
// Base::Console().Message("TDR::accept()\n");
Gui::Command::doCommand(Gui::Command::Gui, "Gui.ActiveDocument.resetEdit()");
replaceReferences();
updateTypes();
m_dim->Type.setValue(m_dimType);
m_dim->recomputeFeature();
return true;
}

View File

@@ -65,7 +65,6 @@ protected:
void setUiPrimary();
void replaceReferences();
void updateTypes();
void updateUi();
void fillList(QListWidget* lwItems, std::vector<std::string> labels, std::vector<std::string> names);
void loadTableWidget(QTableWidget* tw, TechDraw::ReferenceVector refs);
@@ -82,9 +81,8 @@ private:
long int m_saveMeasureType;
long int m_saveDimType;
TechDraw::DrawViewPart* m_saveDvp;
std::vector<std::string> m_saveSubs2d;
std::vector<App::DocumentObject*> m_saveObjs3d;
std::vector<std::string> m_saveSubs3d;
TechDraw::ReferenceVector m_saveRefs2d;
TechDraw::ReferenceVector m_saveRefs3d;
};
class TaskDlgDimReference : public Gui::TaskView::TaskDialog