Fix crash on Dimension with corrupted References
This commit is contained in:
@@ -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>
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
#include <QPointF>
|
||||
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
@@ -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
|
||||
@@ -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
|
||||
return App::DocumentObject::StdReturn;
|
||||
}
|
||||
|
||||
if (!getViewPart()->hasGeometry()) { //happens when loading saved document
|
||||
Base::Console().Log("INFO - DVD::getDimValue ViewPart has no Geometry yet\n");
|
||||
//any empty Reference2D??
|
||||
if (!has2DReferences()) { //too soon?
|
||||
return App::DocumentObject::StdReturn;
|
||||
}
|
||||
|
||||
if (!checkReferences2D()) {
|
||||
Base::Console().Log("Error: DVD - %s - 2D references are corrupt\n",getNameInDocument());
|
||||
//can't do anything until Source has geometry
|
||||
if (!getViewPart()->hasGeometry()) { //happens when loading saved document
|
||||
return App::DocumentObject::StdReturn;
|
||||
}
|
||||
|
||||
|
||||
//now we can check if Reference2ds have valid targets.
|
||||
if (!checkReferences2D()) {
|
||||
return App::DocumentObject::StdReturn;
|
||||
}
|
||||
|
||||
const std::vector<std::string> &subElements = References2D.getSubValues();
|
||||
|
||||
if ( Type.isValue("Distance") ||
|
||||
@@ -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();
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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") ||
|
||||
@@ -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();
|
||||
|
||||
@@ -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]);
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user