Skip to content

Commit

Permalink
Fix crash on Dimension with corrupted References
Browse files Browse the repository at this point in the history
  • Loading branch information
WandererFan committed Apr 24, 2019
1 parent 95ad7dc commit ede3bd2
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 32 deletions.
18 changes: 15 additions & 3 deletions src/Mod/TechDraw/App/DrawUtil.cpp
Expand Up @@ -27,13 +27,14 @@
# include <cstring>
# include <cstdlib>
#include <cmath>
#include <string>
# include <exception>
# include <boost/regex.hpp>
# include <QString>
# include <QStringList>
# include <QRegExp>
#include <QChar>

#include <QPointF>

#include <BRep_Tool.hxx>
#include <gp_Ax3.hxx>
Expand Down Expand Up @@ -74,22 +75,24 @@ using namespace TechDraw;

/*static*/ int DrawUtil::getIndexFromName(std::string geomName)
{
// Base::Console().Message("DU::getIndexFromName(%s)\n", geomName.c_str());
boost::regex re("\\d+$"); // one of more digits at end of string
boost::match_results<std::string::const_iterator> what;
boost::match_flag_type flags = boost::match_default;
char* endChar;
// char* endChar;
std::string::const_iterator begin = geomName.begin();
std::string::const_iterator end = geomName.end();
std::stringstream ErrorMsg;

if (!geomName.empty()) {
if (boost::regex_search(begin, end, what, re, flags)) {
return int (std::strtol(what.str().c_str(), &endChar, 10)); //TODO: use std::stoi() in c++11
return int (std::stoi(what.str()));
} else {
ErrorMsg << "getIndexFromName: malformed geometry name - " << geomName;
throw Base::ValueError(ErrorMsg.str());
}
} else {
Base::Console().Log("DU::getIndexFromName(%s) - empty geometry name\n",geomName.c_str());
throw Base::ValueError("getIndexFromName - empty geometry name");
}
}
Expand Down Expand Up @@ -327,6 +330,15 @@ std::string DrawUtil::formatVector(const gp_Pnt& v)
return result;
}

std::string DrawUtil::formatVector(const QPointF& v)
{
std::string result;
std::stringstream builder;
builder << std::fixed << std::setprecision(3) ;
builder << " (" << v.x() << "," << v.y() << ") ";
result = builder.str();
return result;
}

//! compare 2 vectors for sorting - true if v1 < v2
bool DrawUtil::vectorLess(const Base::Vector3d& v1, const Base::Vector3d& v2)
Expand Down
3 changes: 3 additions & 0 deletions src/Mod/TechDraw/App/DrawUtil.h
Expand Up @@ -27,6 +27,7 @@

#include <QString>
#include <QByteArray>
#include <QPointF>

#include <gp_Ax2.hxx>
#include <gp_Dir.hxx>
Expand Down Expand Up @@ -74,6 +75,8 @@ class TechDrawExport DrawUtil {
static std::string formatVector(const gp_Dir& v);
static std::string formatVector(const gp_Vec& v);
static std::string formatVector(const gp_Pnt& v);
static std::string formatVector(const QPointF& v);

static bool vectorLess(const Base::Vector3d& v1, const Base::Vector3d& v2);
static Base::Vector3d toR3(const gp_Ax2 fromSystem, const Base::Vector3d fromPoint);
static bool checkParallel(const Base::Vector3d v1, const Base::Vector3d v2, double tolerance = FLT_EPSILON);
Expand Down
88 changes: 59 additions & 29 deletions src/Mod/TechDraw/App/DrawViewDimension.cpp
Expand Up @@ -41,6 +41,7 @@
#include <QLocale>

#include <App/Application.h>
#include <App/Document.h>
#include <Base/Console.h>
#include <Base/Exception.h>
#include <Base/Parameter.h>
Expand Down Expand Up @@ -107,7 +108,7 @@ DrawViewDimension::DrawViewDimension(void)
ADD_PROPERTY_TYPE(UnderTolerance ,(0.0),"",App::Prop_None,"- Tolerance value");

//hide the properties the user can't edit in the property editor
References2D.setStatus(App::Property::Hidden,true);
// References2D.setStatus(App::Property::Hidden,true);
References3D.setStatus(App::Property::Hidden,true);

//hide the DrawView properties that don't apply to Dimensions
Expand Down Expand Up @@ -208,24 +209,26 @@ short DrawViewDimension::mustExecute() const

App::DocumentObjectExecReturn *DrawViewDimension::execute(void)
{
// Base::Console().Message("DVD::execute() - %s\n", getNameInDocument());
if (!keepUpdated()) {
return App::DocumentObject::StdReturn;
}

if (!has2DReferences()) { //too soon
//any empty Reference2D??
if (!has2DReferences()) { //too soon?
return App::DocumentObject::StdReturn;
}


//can't do anything until Source has geometry
if (!getViewPart()->hasGeometry()) { //happens when loading saved document
Base::Console().Log("INFO - DVD::getDimValue ViewPart has no Geometry yet\n");
return App::DocumentObject::StdReturn;
}

//now we can check if Reference2ds have valid targets.
if (!checkReferences2D()) {
Base::Console().Log("Error: DVD - %s - 2D references are corrupt\n",getNameInDocument());
return App::DocumentObject::StdReturn;
}

const std::vector<std::string> &subElements = References2D.getSubValues();

if ( Type.isValue("Distance") ||
Expand Down Expand Up @@ -433,6 +436,7 @@ App::DocumentObjectExecReturn *DrawViewDimension::execute(void)

std::string DrawViewDimension::getFormatedValue(bool obtuse)
{
// Base::Console().Message("DVD::getFormatedValue()\n");
std::string result;
if (Arbitrary.getValue()) {
return FormatSpec.getStrValue();
Expand Down Expand Up @@ -554,14 +558,13 @@ std::string DrawViewDimension::getFormatedValue(bool obtuse)
//!NOTE: this returns the Dimension value in internal units (ie mm)!!!!
double DrawViewDimension::getDimValue()
{
// Base::Console().Message("DVD::getDimValue()\n");
double result = 0.0;
if (!has2DReferences()) { //happens during Dimension creation
Base::Console().Log("INFO - DVD::getDimValue - Dimension has no References\n");
return result;
}

if (!getViewPart()->hasGeometry()) { //happens when loading saved document
Base::Console().Log("INFO - DVD::getDimValue ViewPart has no Geometry yet\n");
return result;
}

Expand All @@ -586,7 +589,7 @@ double DrawViewDimension::getDimValue()
} else {
// Projected Values
if (!checkReferences2D()) {
Base::Console().Log("Error: DVD - %s - 2D references are corrupt\n",getNameInDocument());
Base::Console().Warning("Error: DVD::getDimValue - %s - 2D references are corrupt\n",getNameInDocument());
return result;
}
if ( Type.isValue("Distance") ||
Expand Down Expand Up @@ -633,6 +636,7 @@ double DrawViewDimension::getDimValue()

pointPair DrawViewDimension::getPointsOneEdge()
{
// Base::Console().Message("DVD::getPointsOneEdge() - %s\n",getNameInDocument());
pointPair result;
const std::vector<std::string> &subElements = References2D.getSubValues();

Expand All @@ -643,7 +647,7 @@ pointPair DrawViewDimension::getPointsOneEdge()
if (geom && geom->geomType == TechDrawGeometry::GeomType::GENERIC) {
gen = static_cast<TechDrawGeometry::Generic*>(geom);
} else {
Base::Console().Log("Error: DVD - %s - 2D references are corrupt\n",getNameInDocument());
Base::Console().Error("Error: DVD - %s - 2D references are corrupt\n",getNameInDocument());
return result;
}
result.first = DrawUtil::vector23(gen->points[0]);
Expand All @@ -653,6 +657,7 @@ pointPair DrawViewDimension::getPointsOneEdge()

pointPair DrawViewDimension::getPointsTwoEdges()
{
// Base::Console().Message("DVD::getPointsTwoEdges() - %s\n",getNameInDocument());
pointPair result;
const std::vector<std::string> &subElements = References2D.getSubValues();

Expand All @@ -671,6 +676,7 @@ pointPair DrawViewDimension::getPointsTwoEdges()

pointPair DrawViewDimension::getPointsTwoVerts()
{
// Base::Console().Message("DVD::getPointsTwoVerts() - %s\n",getNameInDocument());
pointPair result;
const std::vector<std::string> &subElements = References2D.getSubValues();

Expand All @@ -690,6 +696,7 @@ pointPair DrawViewDimension::getPointsTwoVerts()

pointPair DrawViewDimension::getPointsEdgeVert()
{
// Base::Console().Message("DVD::getPointsEdgeVert() - %s\n",getNameInDocument());
pointPair result;
const std::vector<std::string> &subElements = References2D.getSubValues();

Expand All @@ -706,7 +713,7 @@ pointPair DrawViewDimension::getPointsEdgeVert()
}
if ((v == nullptr) ||
(e == nullptr) ) {
Base::Console().Log("Error: DVD - %s - 2D references are corrupt\n",getNameInDocument());
Base::Console().Error("Error: DVD - %s - 2D references are corrupt\n",getNameInDocument());
return result;
}
result = closestPoints(e->occEdge,v->occVertex);
Expand Down Expand Up @@ -781,28 +788,42 @@ int DrawViewDimension::getRefType3(const std::string g1,
}


//! validate 2D references - only checks if they exist, not if they are the right type
//! validate 2D references - only checks if the target exists
bool DrawViewDimension::checkReferences2D() const
{
// Base::Console().Message("DVD::checkReFerences2d() - %s\n",getNameInDocument());
bool result = true;
//const std::vector<App::DocumentObject*> &objects = References2D.getValues();
const std::vector<std::string> &subElements = References2D.getSubValues();

for (auto& s: subElements) {
int idx = DrawUtil::getIndexFromName(s);
if (DrawUtil::getGeomTypeFromName(s) == "Edge") {
TechDrawGeometry::BaseGeom* geom = getViewPart()->getProjEdgeByIndex(idx);
if (geom == nullptr) {
result = false;
break;
}
} else if (DrawUtil::getGeomTypeFromName(s) == "Vertex") {
TechDrawGeometry::Vertex* v = getViewPart()->getProjVertexByIndex(idx);
if (v == nullptr) {
result = false;
break;
const std::vector<App::DocumentObject*> &objects = References2D.getValues();
if (!objects.empty()) {
const std::vector<std::string> &subElements = References2D.getSubValues();
if (!subElements.empty()) {
for (auto& s: subElements) {
if (!s.empty()) {
int idx = DrawUtil::getIndexFromName(s);
if (DrawUtil::getGeomTypeFromName(s) == "Edge") {
TechDrawGeometry::BaseGeom* geom = getViewPart()->getProjEdgeByIndex(idx);
if (geom == nullptr) {
result = false;
break;
}
} else if (DrawUtil::getGeomTypeFromName(s) == "Vertex") {
TechDrawGeometry::Vertex* v = getViewPart()->getProjVertexByIndex(idx);
if (v == nullptr) {
result = false;
break;
}
}
} else {
result = false;
}
}
} else {
Base::Console().Log("DVD::checkRegerences2d() - %s - subelements empty!\n",getNameInDocument());
result = false;
}
} else {
Base::Console().Log("DVD::checkRegerences2d() - %s - objects empty!\n",getNameInDocument());
result = false;
}
return result;
}
Expand Down Expand Up @@ -913,16 +934,25 @@ bool DrawViewDimension::leaderIntersectsArc(Base::Vector3d s, Base::Vector3d poi
return result;
}

//are there non-blank references?
bool DrawViewDimension::has2DReferences(void) const
{
// Base::Console().Message("DVD::has2DReferences() - %s\n",getNameInDocument());
bool result = false;

const std::vector<App::DocumentObject*> &objects = References2D.getValues();
const std::vector<std::string> &SubNames = References2D.getSubValues();
if (!objects.empty()) {
App::DocumentObject* testRef = objects.at(0);
if (testRef != nullptr) {
if (!SubNames.empty()) {
result = true;
result = true; //not empty is good
for (auto& s: SubNames) { //but check individual entries
if (s.empty()) {
result = false;
break;
}
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/Mod/TechDraw/Gui/QGIViewDimension.cpp
Expand Up @@ -516,6 +516,9 @@ void QGIViewDimension::draw()

const char *dimType = dim->Type.getValueAsString();

datumLabel->show();
show();

if (strcmp(dimType, "Distance") == 0 ||
strcmp(dimType, "DistanceX") == 0 ||
strcmp(dimType, "DistanceY") == 0) {
Expand Down

0 comments on commit ede3bd2

Please sign in to comment.