[TD]Refactor LTNP correction code for Dimensions
- additional geometry types - add method to handle line like bsplines - handle deleted ref body feature - add test for empty savedGeometry - add switch for matcher/LTNP on/off
This commit is contained in:
@@ -106,6 +106,8 @@ SET(Draw_SRCS
|
||||
DimensionFormatter.h
|
||||
GeometryMatcher.cpp
|
||||
GeometryMatcher.h
|
||||
DimensionAutoCorrect.cpp
|
||||
DimensionAutoCorrect.h
|
||||
DrawViewBalloon.cpp
|
||||
DrawViewBalloon.h
|
||||
DrawViewSection.cpp
|
||||
|
||||
596
src/Mod/TechDraw/App/DimensionAutoCorrect.cpp
Normal file
596
src/Mod/TechDraw/App/DimensionAutoCorrect.cpp
Normal file
@@ -0,0 +1,596 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 WandererFan <wandererfan@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
// a class to validate and correct dimension references
|
||||
|
||||
// the dimension reference auto correct algo:
|
||||
//
|
||||
// when a dimension is created, the shape of each reference is saved, so in addition
|
||||
// to the dimensionedObject + subElement reference, we also keep a Part::TopoShape copy
|
||||
// of the reference.
|
||||
//
|
||||
// when we later use that dimension, we check its references as follows:
|
||||
// for each reference:
|
||||
// // auto correct phase 1
|
||||
// if ref.currentGeometry == ref.savedGeometry:
|
||||
// // the reference points to the same geometry as before, so we
|
||||
// // so we consider this to be correct. same geometry, same index case.
|
||||
// continue
|
||||
// else:
|
||||
// // search all the source shapes for a subelement with the exact same
|
||||
// // geometry. same geometry, different index case.
|
||||
// newRef = searchForExactSameGeometry(ref) // geometry matcher
|
||||
// if newRef:
|
||||
// // substitute the reference we just found in place of the old
|
||||
// // reference
|
||||
// replace(ref, newRef)
|
||||
// else:
|
||||
// // auto correct phase 2
|
||||
// // 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
|
||||
// // that to rebuild our reference.
|
||||
// // we do not have a good algo for searchForMostSimilarGeometry() yet.
|
||||
// newRef = searchForMostSimilarGeometry(ref) // geometry guesser
|
||||
// if newRef:
|
||||
// replace(ref, newRef)
|
||||
// else:
|
||||
// //we can't fix this
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#endif
|
||||
|
||||
#include <TopoDS_Shape.hxx>
|
||||
|
||||
#include <App/Document.h>
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Tools.h>
|
||||
|
||||
#include <Mod/Part/App/TopoShape.h>
|
||||
|
||||
#include "GeometryMatcher.h"
|
||||
#include "DimensionReferences.h"
|
||||
#include "DimensionGeometry.h"
|
||||
#include "DimensionAutoCorrect.h"
|
||||
#include "DrawUtil.h"
|
||||
#include "Preferences.h"
|
||||
|
||||
using namespace TechDraw;
|
||||
using DU = DrawUtil;
|
||||
|
||||
//! true if references point to valid geometry and the valid geometry matches the
|
||||
//! corresponding saved geometry. this method does not correct anything, it just
|
||||
//! verifies if the references point to the same geometry as when the reference
|
||||
//! was created.
|
||||
bool DimensionAutoCorrect::referencesHaveValidGeometry(std::vector<bool>& referenceState) const
|
||||
{
|
||||
// Base::Console().Message("DAC::referencesHaveValidGeometry()\n");
|
||||
|
||||
ReferenceVector refsAll = getDimension()->getEffectiveReferences();
|
||||
const std::vector<Part::TopoShape> savedGeometry = getDimension()->SavedGeometry.getValues();
|
||||
|
||||
if (savedGeometry.empty() || savedGeometry.size() != refsAll.size()) {
|
||||
// this must be an old document without savedGeometry property. We can not
|
||||
// validate the references in this case so we hope they are valid.
|
||||
referenceState = std::vector<bool>(refsAll.size(), true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool result {true};
|
||||
size_t iRef {0};
|
||||
for (auto& entry : refsAll) {
|
||||
if (entry.hasGeometry()) {
|
||||
// entry points to something, is it the correct geom?
|
||||
if (isMatchingGeometry(entry, savedGeometry.at(iRef))) {
|
||||
referenceState.emplace_back(true);
|
||||
}
|
||||
else {
|
||||
result = false;
|
||||
referenceState.emplace_back(false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = false;
|
||||
referenceState.emplace_back(false);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//! try to correct references that point to non-existent geometry or when the saved
|
||||
//! geometry does not match the current geometry the reference points to.
|
||||
//! referenceState is the output of a previous use of referencesHaveValidGeometry.
|
||||
bool DimensionAutoCorrect::autocorrectReferences(std::vector<bool>& referenceState,
|
||||
ReferenceVector& repairedRefs) const
|
||||
{
|
||||
// Base::Console().Message("DAC::autocorrectReferences()\n");
|
||||
if (!Preferences::autoCorrectDimRefs()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result {true};
|
||||
ReferenceVector refsAll = getDimension()->getEffectiveReferences();
|
||||
const std::vector<Part::TopoShape> savedGeometry = getDimension()->SavedGeometry.getValues();
|
||||
if (savedGeometry.empty() || savedGeometry.size() != refsAll.size()) {
|
||||
// this must be an old document without savedGeometry property. We can not
|
||||
// validate the references in this case.
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<Part::TopoShape> referenceGeometry;
|
||||
for (auto& entry : refsAll) {
|
||||
if (entry.hasGeometry()) {
|
||||
referenceGeometry.push_back(entry.asTopoShape());
|
||||
}
|
||||
else {
|
||||
referenceGeometry.push_back(Part::TopoShape());
|
||||
}
|
||||
}
|
||||
|
||||
size_t iRef {0};
|
||||
for (const auto& state : referenceState) {
|
||||
if (state) {
|
||||
// ref points to valid geometry that matches saved geometry
|
||||
referenceState.at(iRef) = true;
|
||||
repairedRefs.push_back(refsAll.at(iRef));
|
||||
iRef++;
|
||||
continue;
|
||||
}
|
||||
|
||||
Part::TopoShape temp = savedGeometry.at(iRef);
|
||||
if (temp.isNull()) {
|
||||
result = false;
|
||||
referenceState.at(iRef) = false;
|
||||
repairedRefs.push_back(refsAll.at(iRef));
|
||||
iRef++;
|
||||
// we could exit here instead of checking all the refs?
|
||||
continue;
|
||||
}
|
||||
|
||||
// this ref does not point to valid geometry or
|
||||
// the geometry it points to does not match the saved geometry
|
||||
|
||||
ReferenceEntry fixedRef = refsAll.at(iRef);
|
||||
|
||||
// first, look for an exact match to the saved geometry
|
||||
bool success = fix1GeomExact(fixedRef, savedGeometry.at(iRef).getShape());
|
||||
if (success) {
|
||||
// we did find a match
|
||||
referenceState.at(iRef) = true;
|
||||
repairedRefs.push_back(fixedRef);
|
||||
iRef++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// we did not find an exact match, so check for an Similar match
|
||||
success = fix1GeomSimilar(fixedRef, savedGeometry.at(iRef).getShape());
|
||||
if (success) {
|
||||
// we did find an Similar match
|
||||
referenceState.at(iRef) = true;
|
||||
repairedRefs.push_back(fixedRef);
|
||||
iRef++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// we did not find an Similar match the geometry
|
||||
result = false;
|
||||
referenceState.at(iRef) = false;
|
||||
repairedRefs.push_back(fixedRef);
|
||||
iRef++;
|
||||
// we could exit here
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//! fix a single reference with an exact match to geomToFix
|
||||
bool DimensionAutoCorrect::fix1GeomExact(ReferenceEntry& refToFix, TopoDS_Shape geomToFix) const
|
||||
{
|
||||
// Base::Console().Message("DAC::fix1GeomExact()\n");
|
||||
ReferenceEntry fixedRef = refToFix;
|
||||
Part::TopoShape topoShapeToFix(geomToFix);
|
||||
bool success {false};
|
||||
if (refToFix.is3d()) {
|
||||
if (!refToFix.getObject() && m_3dObjectCache.empty()) {
|
||||
return false;
|
||||
}
|
||||
if (geomToFix.ShapeType() == TopAbs_VERTEX) {
|
||||
success = findExactVertex3d(refToFix, topoShapeToFix);
|
||||
}
|
||||
else {
|
||||
success = findExactEdge3d(refToFix, topoShapeToFix);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (geomToFix.ShapeType() == TopAbs_VERTEX) {
|
||||
success = findExactVertex2d(refToFix, topoShapeToFix);
|
||||
}
|
||||
else {
|
||||
success = findExactEdge2d(refToFix, topoShapeToFix);
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
//! fix a single reference with an Similar match to geomToFix
|
||||
bool DimensionAutoCorrect::fix1GeomSimilar(ReferenceEntry& refToFix, TopoDS_Shape geomToFix) const
|
||||
{
|
||||
// Base::Console().Message("DAC::fix1GeomSimilar()\n");
|
||||
Part::TopoShape topoShapeToFix(geomToFix);
|
||||
bool success {false};
|
||||
if (refToFix.is3d()) {
|
||||
if (!refToFix.getObject() && m_3dObjectCache.empty()) {
|
||||
// can't fix this. nothing to compare.
|
||||
return false;
|
||||
}
|
||||
if (geomToFix.ShapeType() == TopAbs_VERTEX) {
|
||||
success = findSimilarVertex3d(refToFix, topoShapeToFix);
|
||||
}
|
||||
else {
|
||||
success = findSimilarEdge3d(refToFix, topoShapeToFix);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (geomToFix.ShapeType() == TopAbs_VERTEX) {
|
||||
success = findSimilarVertex2d(refToFix, topoShapeToFix);
|
||||
}
|
||||
else {
|
||||
success = findSimilarEdge2d(refToFix, topoShapeToFix);
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
//! search the view for a 2d vertex that is the same as the saved reference geometry
|
||||
//! and return a reference pointing to the matching vertex
|
||||
bool DimensionAutoCorrect::findExactVertex2d(ReferenceEntry& refToFix,
|
||||
Part::TopoShape refGeom) const
|
||||
{
|
||||
// Base::Console().Message("DAC::findExactVertex2d()\n");
|
||||
getMatcher()->setPointTolerance(EWTOLERANCE);
|
||||
auto refObj = refToFix.getObject();
|
||||
auto refDvp = dynamic_cast<TechDraw::DrawViewPart*>(refObj);
|
||||
if (refDvp) {
|
||||
ReferenceEntry fixedRef = searchViewForVert(refDvp, refGeom);
|
||||
if (fixedRef.getObject()) {
|
||||
refToFix = fixedRef;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// no match
|
||||
return false;
|
||||
}
|
||||
|
||||
//! search the view for a 2d edge that is the same as the saved reference geometry
|
||||
//! and return a reference pointing to the matching edge.
|
||||
bool DimensionAutoCorrect::findExactEdge2d(ReferenceEntry& refToFix, Part::TopoShape refGeom) const
|
||||
{
|
||||
// Base::Console().Message("DAC::findExactEdge2d()\n");
|
||||
double scale = getDimension()->getViewPart()->getScale();
|
||||
BaseGeomPtrVector gEdgeAll = getDimension()->getViewPart()->getEdgeGeometry();
|
||||
int iEdge {0};
|
||||
for (auto& edge : gEdgeAll) {
|
||||
Part::TopoShape temp = edge->asTopoShape(scale);
|
||||
bool isSame = getMatcher()->compareGeometry(refGeom, temp);
|
||||
if (isSame) {
|
||||
refToFix.setSubName(std::string("Edge") + std::to_string(iEdge));
|
||||
return true;
|
||||
}
|
||||
iEdge++;
|
||||
}
|
||||
|
||||
// no match, return the input reference
|
||||
return false;
|
||||
}
|
||||
|
||||
//! search the model for a 3d vertex that is the same as the saved reference geometry
|
||||
//! and return a reference pointing to the matching vertex
|
||||
bool DimensionAutoCorrect::findExactVertex3d(ReferenceEntry& refToFix,
|
||||
Part::TopoShape refGeom) const
|
||||
{
|
||||
// Base::Console().Message("DAC::findExactVertex3d()\n");
|
||||
getMatcher()->setPointTolerance(EWTOLERANCE);
|
||||
|
||||
// try the referenced object
|
||||
auto refObj = refToFix.getObject();
|
||||
if (refObj) {
|
||||
ReferenceEntry fixedRef = searchObjForVert(refObj, refGeom);
|
||||
if (fixedRef.getObject()) {
|
||||
refToFix = fixedRef;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// not match in refObj (or no refObj!)
|
||||
for (auto& objectName : m_3dObjectCache) {
|
||||
auto object3d = getDimension()->getDocument()->getObject(objectName.c_str());
|
||||
ReferenceEntry fixedRef = searchObjForVert(object3d, refGeom);
|
||||
if (fixedRef.getObject()) {
|
||||
refToFix = fixedRef;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//! search the model for a 3d edge that is the same as the saved reference geometry
|
||||
//! and return a reference pointing to the matching edge.
|
||||
bool DimensionAutoCorrect::findExactEdge3d(ReferenceEntry& refToFix, Part::TopoShape refGeom) const
|
||||
{
|
||||
// Base::Console().Message("DAC::findExactEdge3d() - cache: %d\n", m_3dObjectCache.size());
|
||||
// first, try to find a match in the referenced object
|
||||
auto refObj = refToFix.getObject();
|
||||
if (refObj) {
|
||||
ReferenceEntry fixedRef = searchObjForEdge(refObj, refGeom);
|
||||
if (fixedRef.getObject()) {
|
||||
refToFix = fixedRef;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// no match in refObj, so now search the cached objects
|
||||
for (auto& objectName : m_3dObjectCache) {
|
||||
auto object3d = getDimension()->getDocument()->getObject(objectName.c_str());
|
||||
auto shape3d = Part::Feature::getShape(object3d);
|
||||
auto edgesAll = getDimension()->getEdges(shape3d);
|
||||
size_t iEdge {1};
|
||||
for (auto& edge : edgesAll) {
|
||||
if (getMatcher()->compareGeometry(edge, refGeom)) {
|
||||
// found a match!
|
||||
refToFix.setObjectName(objectName);
|
||||
refToFix.setObject(object3d);
|
||||
refToFix.setSubName(std::string("Edge") + std::to_string(iEdge));
|
||||
return true;
|
||||
}
|
||||
iEdge++;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//! search the view for a vertex that is within a tolerance of the saved reference geometry
|
||||
//! and return a reference pointing to the matching vertex
|
||||
bool DimensionAutoCorrect::findSimilarVertex2d(ReferenceEntry& refToFix,
|
||||
Part::TopoShape refGeom) const
|
||||
{
|
||||
// Base::Console().Message("DAC::findSimilarVertex2d()\n");
|
||||
(void)refToFix;
|
||||
(void)refGeom;
|
||||
Base::Console().Message("DAC::findSimilarVertex2d is not implemented yet\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
//! search the view for a 2d edge that is similar to the saved reference geometry
|
||||
//! and return a reference pointing to the similar edge.
|
||||
bool DimensionAutoCorrect::findSimilarEdge2d(ReferenceEntry& refToFix,
|
||||
Part::TopoShape refGeom) const
|
||||
{
|
||||
// Base::Console().Message("DAC::findSimilarEdge2d()\n");
|
||||
(void)refToFix;
|
||||
(void)refGeom;
|
||||
Base::Console().Message("DAC::findSimilarEdge2d is not implemented yet\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
//! search the referenced 3d object and the object cache for a vertex that is within
|
||||
//! a tolerance of the saved reference geometry and return a reference pointing
|
||||
//! to the matching vertex
|
||||
bool DimensionAutoCorrect::findSimilarVertex3d(ReferenceEntry& refToFix,
|
||||
Part::TopoShape refGeom) const
|
||||
{
|
||||
// Base::Console().Message("DAC::findSimilarVertex3d()\n");
|
||||
(void)refToFix;
|
||||
(void)refGeom;
|
||||
Base::Console().Message("DAC::findSimilarVertex3d is not implemented yet\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
//! search the referenced 3d object and the object cache for an edge that is
|
||||
//! similar to the saved reference geometry and return a reference pointing
|
||||
//! to the similar edge
|
||||
bool DimensionAutoCorrect::findSimilarEdge3d(ReferenceEntry& refToFix,
|
||||
Part::TopoShape refGeom) const
|
||||
{
|
||||
// Base::Console().Message("DAC::findSimilarEdge3d(%s)\n", refToFix.getObjectName().c_str());
|
||||
(void)refToFix;
|
||||
(void)refGeom;
|
||||
Base::Console().Message("DAC::findSimilarEdge3d is not implemented yet\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
//! compare the geometry pointed to by a reference to the corresponding saved geometry
|
||||
bool DimensionAutoCorrect::isMatchingGeometry(ReferenceEntry ref,
|
||||
Part::TopoShape savedGeometry) const
|
||||
{
|
||||
Part::TopoShape temp = ref.asTopoShape();
|
||||
if (temp.isNull()) {
|
||||
// this shouldn't happen as we already know that this ref points to valid geometry
|
||||
return false;
|
||||
}
|
||||
if (getMatcher()->compareGeometry(temp, savedGeometry)) {
|
||||
// reference still points to the same geometry
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//! search obj (3d object with a shape) for a match to refVertex. This is always
|
||||
//! an exact match for phase 1 (GeometryMatcher), but in phase 2 (GeometryGuesser)
|
||||
//! a similar match will be allowed.
|
||||
ReferenceEntry DimensionAutoCorrect::searchObjForVert(App::DocumentObject* obj,
|
||||
Part::TopoShape refVertex,
|
||||
bool exact) const
|
||||
{
|
||||
(void)exact;
|
||||
auto shape3d = Part::Feature::getShape(obj);
|
||||
if (shape3d.IsNull()) {
|
||||
// how to handle this?
|
||||
return {};
|
||||
}
|
||||
auto vertsAll = getDimension()->getVertexes(shape3d);
|
||||
size_t iVert {1};
|
||||
for (auto& vert : vertsAll) {
|
||||
bool isSame = getMatcher()->compareGeometry(refVertex, vert);
|
||||
if (isSame) {
|
||||
auto newSubname = std::string("Vertex") + std::to_string(iVert);
|
||||
return {obj, newSubname, getDimension()->getDocument()};
|
||||
}
|
||||
iVert++;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
//! search View (2d part display) for a match to refVertex. This can be an
|
||||
//! exact or Similar match depending on the setting of exact.
|
||||
ReferenceEntry DimensionAutoCorrect::searchViewForVert(DrawViewPart* obj,
|
||||
Part::TopoShape refVertex,
|
||||
bool exact) const
|
||||
{
|
||||
(void)exact;
|
||||
double scale = getDimension()->getViewPart()->getScale();
|
||||
std::vector<TechDraw::VertexPtr> gVertexAll =
|
||||
getDimension()->getViewPart()->getVertexGeometry();
|
||||
getMatcher()->setPointTolerance(EWTOLERANCE);
|
||||
int iVertex = 0;
|
||||
for (auto& vert : gVertexAll) {
|
||||
Part::TopoShape temp = vert->asTopoShape(scale);
|
||||
bool isSame = getMatcher()->compareGeometry(refVertex, temp);
|
||||
if (isSame) {
|
||||
auto newSubname = std::string("Vertex") + std::to_string(iVertex);
|
||||
return {obj, newSubname, getDimension()->getDocument()};
|
||||
}
|
||||
iVertex++;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
//! search View (2d part display) for an exact match to refEdge.
|
||||
ReferenceEntry DimensionAutoCorrect::searchViewForExactEdge(DrawViewPart* obj,
|
||||
Part::TopoShape refEdge) const
|
||||
{
|
||||
// Base::Console().Message("DAC::searchViewForExactEdge()\n");
|
||||
double scale = getDimension()->getViewPart()->getScale();
|
||||
auto gEdgeAll = getDimension()->getViewPart()->getEdgeGeometry();
|
||||
int iEdge {0};
|
||||
for (auto& edge : gEdgeAll) {
|
||||
Part::TopoShape temp = edge->asTopoShape(scale);
|
||||
bool isSame = getMatcher()->compareGeometry(refEdge, temp);
|
||||
if (isSame) {
|
||||
auto newSubname = std::string("Edge") + std::to_string(iEdge);
|
||||
return {obj, newSubname, getDimension()->getDocument()};
|
||||
}
|
||||
iEdge++;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
//! search View (2d part display) for an edge that is similar to refEdge
|
||||
ReferenceEntry DimensionAutoCorrect::searchViewForSimilarEdge(DrawViewPart* obj,
|
||||
Part::TopoShape refEdge) const
|
||||
{
|
||||
// Base::Console().Message("DAC::searchViewForSimilarEdge()\n");
|
||||
(void)obj;
|
||||
(void)refEdge;
|
||||
Base::Console().Message("DAC::searchViewForSimilarEdge is not implemented yet\n");
|
||||
return {};
|
||||
}
|
||||
|
||||
//! search model for for a 3d edge that is a match to refEdge
|
||||
//! note that only the exact match is implemented in phase 1
|
||||
ReferenceEntry DimensionAutoCorrect::searchObjForEdge(App::DocumentObject* obj,
|
||||
Part::TopoShape refEdge,
|
||||
bool exact) const
|
||||
{
|
||||
// Base::Console().Message("DAC::searchObjForEdge(%s)\n", obj->Label.getValue());
|
||||
(void)exact;
|
||||
auto shape3d = Part::Feature::getShape(obj);
|
||||
if (shape3d.IsNull()) {
|
||||
// how to handle this?
|
||||
// Base::Console().Message("DAC::searchObjForEdge - object shape is null\n");
|
||||
return {};
|
||||
}
|
||||
auto edgesAll = getDimension()->getEdges(shape3d);
|
||||
size_t iEdge {1};
|
||||
for (auto& edge : edgesAll) {
|
||||
bool isSame = getMatcher()->compareGeometry(refEdge, edge);
|
||||
if (isSame) {
|
||||
auto newSubname = std::string("Edge") + std::to_string(iEdge);
|
||||
return {obj, newSubname, getDimension()->getDocument()};
|
||||
}
|
||||
iEdge++;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
//! rebuild 3d references from saved geometry. returns true is all references
|
||||
//! have been repaired
|
||||
bool DimensionAutoCorrect::fixBrokenReferences(ReferenceVector& fixedReferences) const
|
||||
{
|
||||
// Base::Console().Message("DAC::fixBrokenReferences()\n");
|
||||
bool success {true};
|
||||
const std::vector<Part::TopoShape> savedGeometry = getDimension()->SavedGeometry.getValues();
|
||||
int iGeom {0};
|
||||
for (auto& geom : savedGeometry) {
|
||||
if (fixedReferences.at(iGeom).hasGeometry()) {
|
||||
iGeom++;
|
||||
continue;
|
||||
}
|
||||
//
|
||||
TopoDS_Shape geomShape = geom.getShape();
|
||||
for (auto& objectName : m_3dObjectCache) {
|
||||
auto object3d = getDimension()->getDocument()->getObject(objectName.c_str());
|
||||
if (!object3d) {
|
||||
// cached object has been deleted
|
||||
continue;
|
||||
}
|
||||
// TODO: do we need to check for Similar matches here too?
|
||||
ReferenceEntry newRef;
|
||||
if (geomShape.ShapeType() == TopAbs_VERTEX) {
|
||||
newRef = searchObjForVert(object3d, geomShape);
|
||||
fixedReferences.at(iGeom) = newRef;
|
||||
}
|
||||
else {
|
||||
newRef = searchObjForEdge(object3d, geomShape);
|
||||
fixedReferences.at(iGeom) = newRef;
|
||||
}
|
||||
fixedReferences.at(iGeom) = newRef;
|
||||
if (!newRef.getObject()) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GeometryMatcher* DimensionAutoCorrect::getMatcher() const
|
||||
{
|
||||
return getDimension()->getMatcher();
|
||||
}
|
||||
101
src/Mod/TechDraw/App/DimensionAutoCorrect.h
Normal file
101
src/Mod/TechDraw/App/DimensionAutoCorrect.h
Normal file
@@ -0,0 +1,101 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 WandererFan <wandererfan@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
// a class to validate and correct dimension references
|
||||
|
||||
#ifndef DIMAUTOCORRECT_H
|
||||
#define DIMAUTOCORRECT_H
|
||||
|
||||
#include <Mod/TechDraw/TechDrawGlobal.h>
|
||||
|
||||
#include <DrawViewDimension.h>
|
||||
|
||||
namespace Part
|
||||
{
|
||||
class TopoShape;
|
||||
}
|
||||
|
||||
namespace TechDraw
|
||||
{
|
||||
class GeometryMatcher;
|
||||
|
||||
|
||||
class TechDrawExport DimensionAutoCorrect
|
||||
{
|
||||
public:
|
||||
DimensionAutoCorrect()
|
||||
{}
|
||||
explicit DimensionAutoCorrect(DrawViewDimension* dim)
|
||||
{
|
||||
m_dimension = dim;
|
||||
}
|
||||
~DimensionAutoCorrect() = default;
|
||||
|
||||
bool referencesHaveValidGeometry(std::vector<bool>& referenceState) const;
|
||||
bool autocorrectReferences(std::vector<bool>& referenceState,
|
||||
ReferenceVector& repairedRefs) const;
|
||||
|
||||
void set3dObjectCache(std::set<std::string> cache)
|
||||
{
|
||||
m_3dObjectCache = cache;
|
||||
}
|
||||
bool fixBrokenReferences(ReferenceVector& fixedReferences) const;
|
||||
|
||||
private:
|
||||
bool fix1GeomExact(ReferenceEntry& refToFix, TopoDS_Shape geomToFix) const;
|
||||
bool fix1GeomSimilar(ReferenceEntry& refToFix, TopoDS_Shape geomToFix) const;
|
||||
|
||||
bool findExactVertex2d(ReferenceEntry& refToFix, Part::TopoShape refGeom) const;
|
||||
bool findExactEdge2d(ReferenceEntry& refToFix, Part::TopoShape refGeom) const;
|
||||
bool findExactVertex3d(ReferenceEntry& refToFix, Part::TopoShape refGeom) const;
|
||||
bool findExactEdge3d(ReferenceEntry& refToFix, Part::TopoShape refGeom) const;
|
||||
|
||||
bool findSimilarVertex2d(ReferenceEntry& refToFix, Part::TopoShape refGeom) const;
|
||||
bool findSimilarEdge2d(ReferenceEntry& refToFix, Part::TopoShape refGeom) const;
|
||||
bool findSimilarVertex3d(ReferenceEntry& refToFix, Part::TopoShape refGeom) const;
|
||||
bool findSimilarEdge3d(ReferenceEntry& refToFix, Part::TopoShape refGeom) const;
|
||||
|
||||
ReferenceEntry
|
||||
searchObjForVert(App::DocumentObject* obj, Part::TopoShape refVertex, bool exact = true) const;
|
||||
ReferenceEntry
|
||||
searchViewForVert(DrawViewPart* obj, Part::TopoShape refVertex, bool exact = true) const;
|
||||
ReferenceEntry
|
||||
searchObjForEdge(App::DocumentObject* obj, Part::TopoShape refEdge, bool exact = true) const;
|
||||
|
||||
ReferenceEntry searchViewForExactEdge(DrawViewPart* obj, Part::TopoShape refEdge) const;
|
||||
ReferenceEntry searchViewForSimilarEdge(DrawViewPart* obj, Part::TopoShape refEdge) const;
|
||||
|
||||
|
||||
bool isMatchingGeometry(ReferenceEntry ref, Part::TopoShape savedGeometry) const;
|
||||
|
||||
DrawViewDimension* getDimension() const
|
||||
{
|
||||
return m_dimension;
|
||||
}
|
||||
GeometryMatcher* getMatcher() const;
|
||||
|
||||
DrawViewDimension* m_dimension;
|
||||
std::set<std::string> m_3dObjectCache;
|
||||
};
|
||||
|
||||
} // end namespace TechDraw
|
||||
#endif
|
||||
@@ -31,6 +31,8 @@
|
||||
#include <TopExp.hxx>
|
||||
|
||||
#include <App/GeoFeature.h>
|
||||
#include <App/DocumentObject.h>
|
||||
#include <App/Document.h>
|
||||
#include <Base/Console.h>
|
||||
#include <Mod/Part/App/TopoShape.h>
|
||||
#include <Mod/PartDesign/App/Body.h>
|
||||
@@ -44,16 +46,65 @@
|
||||
using namespace TechDraw;
|
||||
using DU = DrawUtil;
|
||||
|
||||
|
||||
ReferenceEntry::ReferenceEntry( App::DocumentObject* docObject, std::string subName, App::Document* document)
|
||||
{
|
||||
setObject(docObject);
|
||||
setSubName(subName);
|
||||
setDocument(document);
|
||||
if (docObject) {
|
||||
setObjectName(docObject->getNameInDocument());
|
||||
if (document == nullptr) {
|
||||
setDocument(docObject->getDocument());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReferenceEntry::ReferenceEntry(const ReferenceEntry& other)
|
||||
{
|
||||
setObject(other.getObject());
|
||||
setSubName(other.getSubName());
|
||||
setObjectName(other.getObjectName());
|
||||
setDocument(other.getDocument());
|
||||
}
|
||||
|
||||
|
||||
|
||||
ReferenceEntry& ReferenceEntry::operator=(const ReferenceEntry& otherRef)
|
||||
{
|
||||
setObject(otherRef.getObject());
|
||||
setSubName(otherRef.getSubName());
|
||||
setObjectName(otherRef.getObjectName());
|
||||
setDocument(otherRef.getDocument());
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
TopoDS_Shape ReferenceEntry::getGeometry() const
|
||||
{
|
||||
// Base::Console().Message("RE::getGeometry() - obj: %s sub: %s\n",
|
||||
// getObject()->getNameInDocument(), getSubName());
|
||||
// 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) {
|
||||
Base::Console().Message("RE::getGeometry - %s no longer exists!\n", getObjectName().c_str());
|
||||
return {};
|
||||
}
|
||||
|
||||
if (getSubName().empty()) {
|
||||
Base::Console().Message("RE::getGeometry - Reference has no subelement!\n");
|
||||
return {};
|
||||
}
|
||||
|
||||
if ( getObject()->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId()) ) {
|
||||
// Base::Console().Message("RE::getGeometry - getting 2d geometry\n");
|
||||
std::string gType;
|
||||
try {
|
||||
auto dvp = static_cast<TechDraw::DrawViewPart*>(getObject());
|
||||
gType = geomType();
|
||||
if (gType == "Vertex") {
|
||||
// getVertex throws on not found, but we want to return null
|
||||
// shape
|
||||
auto vgeom = dvp->getVertex(getSubName());
|
||||
return vgeom->getOCCVertex();
|
||||
}
|
||||
@@ -67,11 +118,12 @@ TopoDS_Shape ReferenceEntry::getGeometry() const
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
// Base::Console().Message("RE::getGeometry - no shape for dimension reference - gType: %s\n", gType.c_str());
|
||||
Base::Console().Message("RE::getGeometry - no shape for dimension 2d reference - gType: **%s**\n", gType.c_str());
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
// Base::Console().Message("RE::getGeometry - getting 2d geometry\n");
|
||||
Part::TopoShape shape = Part::Feature::getTopoShape(getObject());
|
||||
auto geoFeat = dynamic_cast<App::GeoFeature*>(getObject());
|
||||
if (geoFeat) {
|
||||
@@ -100,13 +152,15 @@ std::string ReferenceEntry::getSubName(bool longForm) const
|
||||
|
||||
App::DocumentObject* ReferenceEntry::getObject() const
|
||||
{
|
||||
// For PartDesign objects, when the reference is created from a selection,
|
||||
// the SelectionObject is a Feature within the Body.
|
||||
PartDesign::Body* pdBody = PartDesign::Body::findBodyOf(m_object);
|
||||
if (pdBody && pdBody->Tip.getValue()) {
|
||||
return pdBody->Tip.getValue();
|
||||
if (!getDocument()) {
|
||||
return nullptr;
|
||||
}
|
||||
return m_object;
|
||||
App::DocumentObject* obj = getDocument()->getObject(getObjectName().c_str());
|
||||
if (!obj) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
Part::TopoShape ReferenceEntry::asTopoShape() const
|
||||
@@ -114,7 +168,9 @@ 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");
|
||||
// throw Base::RuntimeError("Dimension Reference has null geometry");
|
||||
Base::Console().Message("RE::asTopoShape - reference geometry is null\n");
|
||||
return {};
|
||||
}
|
||||
if (geom.ShapeType() == TopAbs_VERTEX) {
|
||||
TopoDS_Vertex vert = TopoDS::Vertex(geom);
|
||||
@@ -153,6 +209,7 @@ Part::TopoShape ReferenceEntry::asTopoShapeEdge(TopoDS_Edge &edge) const
|
||||
|
||||
std::string ReferenceEntry::geomType() const
|
||||
{
|
||||
// Base::Console().Message("RE::geomType() - subName: **%s**\n", getSubName().c_str());
|
||||
return DrawUtil::getGeomTypeFromName(getSubName());
|
||||
}
|
||||
|
||||
@@ -163,15 +220,61 @@ bool ReferenceEntry::isWholeObject() const
|
||||
|
||||
bool ReferenceEntry::is3d() const
|
||||
{
|
||||
return !getObject()->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId());
|
||||
}
|
||||
|
||||
//! check if this reference has valid geometry
|
||||
bool ReferenceEntry::isValid() const
|
||||
{
|
||||
TopoDS_Shape geom = getGeometry();
|
||||
if (geom.IsNull()) {
|
||||
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;
|
||||
}
|
||||
|
||||
//! check if this reference has valid geometry in the model
|
||||
bool ReferenceEntry::hasGeometry() const
|
||||
{
|
||||
// Base::Console().Message("RE::hasGeometry()\n");
|
||||
if (!getObject()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( getObject()->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId()) ) {
|
||||
// 2d reference
|
||||
auto dvp = static_cast<TechDraw::DrawViewPart*>(getObject());
|
||||
if (getSubName().empty()) {
|
||||
return false;
|
||||
}
|
||||
int geomNumber = DU::getIndexFromName(getSubName());
|
||||
std::string gType = geomType();
|
||||
if (gType == "Vertex") {
|
||||
auto vert = dvp->getProjVertexByIndex(geomNumber);
|
||||
if (vert) {
|
||||
return true;
|
||||
}
|
||||
} else if (gType == "Edge") {
|
||||
auto edge = dvp->getGeomByIndex(geomNumber);
|
||||
if (edge) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// if we ever have dimensions for faces, add something here.
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3d reference
|
||||
auto shape = Part::Feature::getTopoShape(getObject());
|
||||
auto subShape = shape.getSubShape(getSubName().c_str());
|
||||
if (!subShape.IsNull()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
namespace App
|
||||
{
|
||||
class DocumentObject;
|
||||
class Document;
|
||||
}
|
||||
|
||||
namespace Part
|
||||
@@ -51,34 +52,39 @@ namespace TechDraw
|
||||
class TechDrawExport ReferenceEntry
|
||||
{
|
||||
public:
|
||||
ReferenceEntry( App::DocumentObject* docObject, std::string subName ) {
|
||||
setObject(docObject);
|
||||
setSubName(subName);
|
||||
}
|
||||
ReferenceEntry(const ReferenceEntry& other) {
|
||||
setObject(other.getObject());
|
||||
setSubName(other.getSubName());
|
||||
}
|
||||
ReferenceEntry() {};
|
||||
ReferenceEntry( App::DocumentObject* docObject, std::string subName, App::Document* document = nullptr);
|
||||
ReferenceEntry(const ReferenceEntry& other);
|
||||
~ReferenceEntry() = default;
|
||||
|
||||
ReferenceEntry& operator= (const ReferenceEntry& otherRef);
|
||||
|
||||
App::DocumentObject* getObject() const;
|
||||
void setObject(App::DocumentObject* docObj) { m_object = docObj; }
|
||||
std::string getSubName(bool longForm = false) const;
|
||||
void setSubName(std::string subName) { m_subName = subName; }
|
||||
std::string getObjectName() const { return m_objectName; }
|
||||
void setObjectName(std::string name) { m_objectName = name; }
|
||||
App::Document* getDocument() const { return m_document; }
|
||||
void setDocument(App::Document* document) { m_document = document; }
|
||||
|
||||
TopoDS_Shape getGeometry() const;
|
||||
std::string geomType() const;
|
||||
bool isWholeObject() const;
|
||||
|
||||
Part::TopoShape asTopoShape() const;
|
||||
|
||||
bool is3d() const;
|
||||
bool hasGeometry() const;
|
||||
|
||||
private:
|
||||
Part::TopoShape asTopoShapeVertex(TopoDS_Vertex &vert) const;
|
||||
Part::TopoShape asTopoShapeEdge(TopoDS_Edge& edge) const;
|
||||
|
||||
bool is3d() const;
|
||||
bool isValid() const;
|
||||
|
||||
private:
|
||||
App::DocumentObject* m_object;
|
||||
std::string m_subName;
|
||||
App::DocumentObject* m_object{nullptr};
|
||||
std::string m_subName{""};
|
||||
std::string m_objectName{""};
|
||||
App::Document* m_document{nullptr};
|
||||
};
|
||||
|
||||
using ReferenceVector = std::vector<ReferenceEntry>;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,8 +23,6 @@
|
||||
#ifndef TechDraw_DrawViewDimension_h_
|
||||
#define TechDraw_DrawViewDimension_h_
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#include <App/DocumentObject.h>
|
||||
#include <Base/UnitsApi.h>
|
||||
#include <Mod/Part/App/PropertyTopoShapeList.h>
|
||||
@@ -39,7 +37,8 @@
|
||||
|
||||
class TopoDS_Shape;
|
||||
|
||||
namespace Measure {
|
||||
namespace Measure
|
||||
{
|
||||
class Measurement;
|
||||
}
|
||||
namespace TechDraw
|
||||
@@ -47,60 +46,63 @@ namespace TechDraw
|
||||
class DrawViewPart;
|
||||
class DimensionFormatter;
|
||||
class GeometryMatcher;
|
||||
class DimensionAutoCorrect;
|
||||
|
||||
class TechDrawExport DrawViewDimension : public TechDraw::DrawView
|
||||
class TechDrawExport DrawViewDimension: public TechDraw::DrawView
|
||||
{
|
||||
PROPERTY_HEADER_WITH_OVERRIDE(TechDraw::DrawViewDimension);
|
||||
|
||||
public:
|
||||
|
||||
// keep this enum synchronized with TypeEnums
|
||||
enum DimensionType {
|
||||
Distance,
|
||||
DistanceX,
|
||||
DistanceY,
|
||||
DistanceZ,
|
||||
Radius,
|
||||
Diameter,
|
||||
Angle,
|
||||
Angle3Pt
|
||||
};
|
||||
// keep this enum synchronized with TypeEnums
|
||||
enum DimensionType
|
||||
{
|
||||
Distance,
|
||||
DistanceX,
|
||||
DistanceY,
|
||||
DistanceZ,
|
||||
Radius,
|
||||
Diameter,
|
||||
Angle,
|
||||
Angle3Pt
|
||||
};
|
||||
|
||||
/// Constructor
|
||||
DrawViewDimension();
|
||||
~DrawViewDimension() override;
|
||||
|
||||
App::PropertyEnumeration MeasureType; //True/Projected
|
||||
App::PropertyLinkSubList References2D; //Points to Projection SubFeatures
|
||||
App::PropertyLinkSubList References3D; //Points to 3D Geometry SubFeatures
|
||||
App::PropertyEnumeration Type; //DistanceX, DistanceY, Diameter, etc.
|
||||
App::PropertyEnumeration MeasureType; // True/Projected
|
||||
App::PropertyLinkSubList References2D; // Points to Projection SubFeatures
|
||||
App::PropertyLinkSubList References3D; // Points to 3D Geometry SubFeatures
|
||||
App::PropertyEnumeration Type; // DistanceX, DistanceY, Diameter, etc.
|
||||
|
||||
App::PropertyBool TheoreticalExact;
|
||||
App::PropertyBool Inverted;
|
||||
App::PropertyString FormatSpec;
|
||||
App::PropertyString FormatSpecOverTolerance;
|
||||
App::PropertyString FormatSpecUnderTolerance;
|
||||
App::PropertyBool Arbitrary;
|
||||
App::PropertyBool ArbitraryTolerances;
|
||||
App::PropertyBool EqualTolerance;
|
||||
App::PropertyBool TheoreticalExact;
|
||||
App::PropertyBool Inverted;
|
||||
App::PropertyString FormatSpec;
|
||||
App::PropertyString FormatSpecOverTolerance;
|
||||
App::PropertyString FormatSpecUnderTolerance;
|
||||
App::PropertyBool Arbitrary;
|
||||
App::PropertyBool ArbitraryTolerances;
|
||||
App::PropertyBool EqualTolerance;
|
||||
App::PropertyQuantityConstraint OverTolerance;
|
||||
App::PropertyQuantityConstraint UnderTolerance;
|
||||
|
||||
App::PropertyBool AngleOverride;
|
||||
App::PropertyAngle LineAngle;
|
||||
App::PropertyAngle ExtensionAngle;
|
||||
App::PropertyBool AngleOverride;
|
||||
App::PropertyAngle LineAngle;
|
||||
App::PropertyAngle ExtensionAngle;
|
||||
|
||||
Part::PropertyTopoShapeList SavedGeometry;
|
||||
Part::PropertyTopoShapeList SavedGeometry;
|
||||
App::PropertyVectorList BoxCorners;
|
||||
|
||||
enum RefType{
|
||||
invalidRef,
|
||||
oneEdge,
|
||||
twoEdge,
|
||||
twoVertex,
|
||||
vertexEdge,
|
||||
threeVertex,
|
||||
extent
|
||||
};
|
||||
enum RefType
|
||||
{
|
||||
invalidRef,
|
||||
oneEdge,
|
||||
twoEdge,
|
||||
twoVertex,
|
||||
vertexEdge,
|
||||
threeVertex,
|
||||
extent
|
||||
};
|
||||
|
||||
|
||||
short mustExecute() const override;
|
||||
@@ -108,23 +110,20 @@ enum DimensionType {
|
||||
virtual bool has3DReferences() const;
|
||||
bool hasOverUnderTolerance() const;
|
||||
|
||||
/** @name methods override Feature */
|
||||
//@{
|
||||
/// recalculate the Feature
|
||||
App::DocumentObjectExecReturn *execute() override;
|
||||
//@}
|
||||
App::DocumentObjectExecReturn* execute() override;
|
||||
|
||||
/// returns the type name of the ViewProvider
|
||||
const char* getViewProviderName() const override {
|
||||
const char* getViewProviderName() const override
|
||||
{
|
||||
return "TechDrawGui::ViewProviderDimension";
|
||||
}
|
||||
//return PyObject as DrawViewDimensionPy
|
||||
PyObject *getPyObject() override;
|
||||
// return PyObject as DrawViewDimensionPy
|
||||
PyObject* getPyObject() override;
|
||||
|
||||
virtual std::string getFormattedToleranceValue(int partial);
|
||||
virtual std::pair<std::string, std::string> getFormattedToleranceValues(int partial = 0);
|
||||
virtual std::string getFormattedDimensionValue(int partial = 0);
|
||||
virtual std::string formatValue(qreal value, QString qFormatSpec, int partial = 0, bool isDim = true);
|
||||
virtual std::string
|
||||
formatValue(qreal value, QString qFormatSpec, int partial = 0, bool isDim = true);
|
||||
|
||||
virtual bool haveTolerance();
|
||||
|
||||
@@ -132,24 +131,51 @@ enum DimensionType {
|
||||
QStringList getPrefixSuffixSpec(QString fSpec);
|
||||
|
||||
virtual DrawViewPart* getViewPart() const;
|
||||
QRectF getRect() const override { return {0, 0, 1, 1}; } //pretend dimensions always fit!
|
||||
virtual int getRefType() const; //Vertex-Vertex, Edge, Edge-Edge
|
||||
static int getRefTypeSubElements(const std::vector<std::string> &); //Vertex-Vertex, Edge, Edge-Edge
|
||||
QRectF getRect() const override
|
||||
{
|
||||
return {0, 0, 1, 1};
|
||||
} // pretend dimensions always fit!
|
||||
virtual int getRefType() const; // Vertex-Vertex, Edge, Edge-Edge
|
||||
static int
|
||||
getRefTypeSubElements(const std::vector<std::string>&); // Vertex-Vertex, Edge, Edge-Edge
|
||||
|
||||
void setReferences2d(ReferenceVector refs);
|
||||
void setReferences3d(ReferenceVector refs);
|
||||
ReferenceVector getReferences2d() const;
|
||||
ReferenceVector getReferences3d() const;
|
||||
bool hasGoodReferences() const
|
||||
{
|
||||
return m_referencesCorrect;
|
||||
}
|
||||
|
||||
void setAll3DMeasurement();
|
||||
void clear3DMeasurements();
|
||||
virtual bool checkReferences2D() const;
|
||||
virtual pointPair getLinearPoints() const {return m_linearPoints; }
|
||||
virtual void setLinearPoints(Base::Vector3d point0, Base::Vector3d point1) { m_linearPoints.first(point0);
|
||||
m_linearPoints.second(point1); };
|
||||
virtual void setLinearPoints(pointPair newPair) { m_linearPoints = newPair; }
|
||||
arcPoints getArcPoints() {return m_arcPoints; }
|
||||
anglePoints getAnglePoints() {return m_anglePoints; }
|
||||
bool hasBroken3dReferences() const;
|
||||
|
||||
|
||||
virtual pointPair getLinearPoints() const
|
||||
{
|
||||
return m_linearPoints;
|
||||
}
|
||||
virtual void setLinearPoints(Base::Vector3d point0, Base::Vector3d point1)
|
||||
{
|
||||
m_linearPoints.first(point0);
|
||||
m_linearPoints.second(point1);
|
||||
};
|
||||
virtual void setLinearPoints(pointPair newPair)
|
||||
{
|
||||
m_linearPoints = newPair;
|
||||
}
|
||||
arcPoints getArcPoints()
|
||||
{
|
||||
return m_arcPoints;
|
||||
}
|
||||
anglePoints getAnglePoints()
|
||||
{
|
||||
return m_anglePoints;
|
||||
}
|
||||
|
||||
bool leaderIntersectsArc(Base::Vector3d s, Base::Vector3d pointOnCircle);
|
||||
|
||||
bool isMultiValueSchema() const;
|
||||
@@ -161,10 +187,27 @@ enum DimensionType {
|
||||
bool useDecimals() const;
|
||||
bool isExtentDim() const;
|
||||
virtual ReferenceVector getEffectiveReferences() const;
|
||||
bool goodReferenceGeometry() const { return m_referencesCorrect; }
|
||||
|
||||
GeometryMatcher* getMatcher() const
|
||||
{
|
||||
return m_matcher;
|
||||
}
|
||||
DimensionAutoCorrect* getCorrector() const
|
||||
{
|
||||
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);
|
||||
|
||||
// autocorrect support methods
|
||||
void saveFeatureBox();
|
||||
Base::BoundBox3d getSavedBox();
|
||||
Base::BoundBox3d getFeatureBox();
|
||||
|
||||
protected:
|
||||
void handleChangedPropertyType(Base::XMLReader &, const char * , App::Property * ) override;
|
||||
void handleChangedPropertyType(Base::XMLReader&, const char*, App::Property*) override;
|
||||
void Restore(Base::XMLReader& reader) override;
|
||||
void onChanged(const App::Property* prop) override;
|
||||
void onDocumentRestored() override;
|
||||
@@ -182,13 +225,10 @@ protected:
|
||||
virtual anglePoints getAnglePointsTwoEdges(ReferenceVector references);
|
||||
virtual anglePoints getAnglePointsThreeVerts(ReferenceVector references);
|
||||
|
||||
Measure::Measurement *measurement;
|
||||
double dist2Segs(Base::Vector3d s1,
|
||||
Base::Vector3d e1,
|
||||
Base::Vector3d s2,
|
||||
Base::Vector3d e2) const;
|
||||
pointPair closestPoints(TopoDS_Shape s1,
|
||||
TopoDS_Shape s2) const;
|
||||
Measure::Measurement* measurement;
|
||||
double
|
||||
dist2Segs(Base::Vector3d s1, Base::Vector3d e1, Base::Vector3d s2, Base::Vector3d e2) const;
|
||||
pointPair closestPoints(TopoDS_Shape s1, TopoDS_Shape s2) const;
|
||||
|
||||
void resetLinear();
|
||||
void resetAngular();
|
||||
@@ -196,36 +236,27 @@ protected:
|
||||
|
||||
bool okToProceed();
|
||||
void updateSavedGeometry();
|
||||
bool compareSavedGeometry();
|
||||
bool fixExactMatch();
|
||||
void handleNoExactMatch();
|
||||
std::string recoverChangedEdge2d(int iReference);
|
||||
std::string recoverChangedEdge3d(int iReference);
|
||||
std::string recoverChangedVertex2d(int iReference);
|
||||
std::string recoverChangedVertex3d(int iReference);
|
||||
void replaceReferenceSubElement2d(int iRef, std::string &newSubelement);
|
||||
void replaceReferenceSubElement3d(int iRef, std::string &newSubelement);
|
||||
|
||||
std::vector<Part::TopoShape> getEdges(const Part::TopoShape& inShape);
|
||||
std::vector<Part::TopoShape> getVertexes(const Part::TopoShape& inShape);
|
||||
|
||||
private:
|
||||
static const char* TypeEnums[];
|
||||
static const char* MeasureTypeEnums[];
|
||||
void dumpRefs2D(const char* text) const;
|
||||
//Dimension "geometry"
|
||||
pointPair m_linearPoints;
|
||||
pointPair m_arrowPositions;
|
||||
arcPoints m_arcPoints;
|
||||
// Dimension "geometry"
|
||||
pointPair m_linearPoints;
|
||||
pointPair m_arrowPositions;
|
||||
arcPoints m_arcPoints;
|
||||
anglePoints m_anglePoints;
|
||||
bool m_hasGeometry;
|
||||
bool m_hasGeometry;
|
||||
|
||||
friend class DimensionFormatter;
|
||||
DimensionFormatter* m_formatter;
|
||||
GeometryMatcher* m_matcher;
|
||||
DimensionAutoCorrect* m_corrector;
|
||||
|
||||
bool m_referencesCorrect;
|
||||
bool m_referencesCorrect {false};
|
||||
|
||||
std::set<std::string> m_3dObjectCache;
|
||||
};
|
||||
|
||||
} //namespace TechDraw
|
||||
} // namespace TechDraw
|
||||
#endif
|
||||
|
||||
@@ -862,7 +862,7 @@ TechDraw::VertexPtr DrawViewPart::getProjVertexByIndex(int idx) const
|
||||
return nullptr;
|
||||
}
|
||||
if ((unsigned)idx >= geoms.size()) {
|
||||
Base::Console().Error("DVP::getProjVertexByIndex(%d) - invalid index\n", idx);
|
||||
Base::Console().Error("DVP::getProjVertexByIndex(%d) - invalid index - size: %d\n", idx);
|
||||
return nullptr;
|
||||
}
|
||||
return geoms.at(idx);
|
||||
|
||||
@@ -1716,3 +1716,21 @@ bool GeometryUtils::isLine(TopoDS_Edge occEdge)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//! make a line Edge from BSpline Edge
|
||||
TopoDS_Edge GeometryUtils::asLine(TopoDS_Edge occEdge)
|
||||
{
|
||||
BRepAdaptor_Curve c(occEdge);
|
||||
|
||||
// find the two ends
|
||||
Handle(Geom_Curve) curve = c.Curve().Curve();
|
||||
double first = c.FirstParameter();
|
||||
double last = c.LastParameter();
|
||||
gp_Pnt start = c.Value(first);
|
||||
gp_Pnt end = c.Value(last);
|
||||
|
||||
TopoDS_Edge result = BRepBuilderAPI_MakeEdge(start, end);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -446,6 +446,8 @@ class TechDrawExport GeometryUtils
|
||||
static bool getCircleParms(TopoDS_Edge occEdge, double& radius, Base::Vector3d& center, bool& isArc);
|
||||
static TopoDS_Edge asCircle(TopoDS_Edge occEdge, bool& arc);
|
||||
static bool isLine(TopoDS_Edge occEdge);
|
||||
static TopoDS_Edge asLine(TopoDS_Edge occEdge);
|
||||
|
||||
};
|
||||
|
||||
} //end namespace TechDraw
|
||||
|
||||
@@ -45,23 +45,29 @@
|
||||
|
||||
#include "GeometryMatcher.h"
|
||||
#include "DrawUtil.h"
|
||||
#include "Preferences.h"
|
||||
|
||||
using namespace TechDraw;
|
||||
using DU = DrawUtil;
|
||||
|
||||
// a set of routines for comparing geometry for equality.
|
||||
|
||||
bool GeometryMatcher::compareGeometry(Part::TopoShape shape1, Part::TopoShape shape2)
|
||||
bool GeometryMatcher::compareGeometry(Part::TopoShape shape1, Part::TopoShape shape2)
|
||||
{
|
||||
// Base::Console().Message("GM::compareGeometry()\n");
|
||||
// Base::Console().Message("GM::compareGeometry()\n");
|
||||
if (!Preferences::useExactMatchOnDims()) {
|
||||
return false;
|
||||
}
|
||||
if (shape1.isNull() || shape2.isNull()) {
|
||||
// Base::Console().Message("GM::compareGeometry - one or more TopoShapes are null\n");
|
||||
// Base::Console().Message("GM::compareGeometry - one or more TopoShapes are
|
||||
// null\n");
|
||||
return false;
|
||||
}
|
||||
TopoDS_Shape geom1 = shape1.getShape();
|
||||
TopoDS_Shape geom2 = shape2.getShape();
|
||||
if (geom1.IsNull() || geom2.IsNull()) {
|
||||
// Base::Console().Message("GM::compareGeometry - one or more TopoDS_Shapes are null\n");
|
||||
// Base::Console().Message("GM::compareGeometry - one or more TopoDS_Shapes are
|
||||
// null\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -74,11 +80,11 @@ bool GeometryMatcher::compareGeometry(Part::TopoShape shape1, Part::TopoShape s
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GeometryMatcher::comparePoints(TopoDS_Shape &shape1, TopoDS_Shape &shape2)
|
||||
bool GeometryMatcher::comparePoints(TopoDS_Shape& shape1, TopoDS_Shape& shape2)
|
||||
{
|
||||
// Base::Console().Message("GM::comparePoints()\n");
|
||||
if (shape1.ShapeType() != TopAbs_VERTEX ||
|
||||
shape2.ShapeType() != TopAbs_VERTEX) {
|
||||
// Base::Console().Message("GM::comparePoints()\n");
|
||||
|
||||
if (shape1.ShapeType() != TopAbs_VERTEX || shape2.ShapeType() != TopAbs_VERTEX) {
|
||||
// can not compare these shapes
|
||||
return false;
|
||||
}
|
||||
@@ -92,50 +98,47 @@ bool GeometryMatcher::comparePoints(TopoDS_Shape &shape1, TopoDS_Shape &shape2)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GeometryMatcher::compareEdges(TopoDS_Shape &shape1, TopoDS_Shape &shape2)
|
||||
bool GeometryMatcher::compareEdges(TopoDS_Shape& shape1, TopoDS_Shape& shape2)
|
||||
{
|
||||
// Base::Console().Message("GM::compareEdges()\n");
|
||||
if (shape1.ShapeType() != TopAbs_EDGE ||
|
||||
shape2.ShapeType() != TopAbs_EDGE) {
|
||||
// Base::Console().Message("GM::compareEdges()\n");
|
||||
if (shape1.ShapeType() != TopAbs_EDGE || shape2.ShapeType() != TopAbs_EDGE) {
|
||||
// can not compare these shapes
|
||||
// Base::Console().Message("GM::compareEdges - shape is not an edge\n");
|
||||
// Base::Console().Message("GM::compareEdges - shape is not an edge\n");
|
||||
return false;
|
||||
}
|
||||
TopoDS_Edge edge1 = TopoDS::Edge(shape1);
|
||||
TopoDS_Edge edge2 = TopoDS::Edge(shape2);
|
||||
if (edge1.IsNull() || edge2.IsNull()) {
|
||||
// Base::Console().Message("GM::compareEdges - an input edge is null\n");
|
||||
if (edge1.IsNull() || edge2.IsNull()) {
|
||||
// Base::Console().Message("GM::compareEdges - an input edge is null\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
BRepAdaptor_Curve adapt1(edge1);
|
||||
BRepAdaptor_Curve adapt2(edge2);
|
||||
|
||||
if (adapt1.GetType() == GeomAbs_Line &&
|
||||
adapt2.GetType() == GeomAbs_Line) {
|
||||
if (adapt1.GetType() == GeomAbs_Line && adapt2.GetType() == GeomAbs_Line) {
|
||||
return compareLines(edge1, edge2);
|
||||
}
|
||||
|
||||
if (adapt1.GetType() == GeomAbs_Circle &&
|
||||
adapt2.GetType() == GeomAbs_Circle) {
|
||||
if (adapt1.GetType() == GeomAbs_Circle && adapt2.GetType() == GeomAbs_Circle) {
|
||||
if (adapt1.IsClosed() && adapt2.IsClosed()) {
|
||||
return compareCircles(edge1, edge2);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return compareCircleArcs(edge1, edge2);
|
||||
}
|
||||
}
|
||||
|
||||
if (adapt1.GetType() == GeomAbs_Ellipse &&
|
||||
adapt2.GetType() == GeomAbs_Ellipse) {
|
||||
if (adapt1.GetType() == GeomAbs_Ellipse && adapt2.GetType() == GeomAbs_Ellipse) {
|
||||
if (adapt1.IsClosed() && adapt2.IsClosed()) {
|
||||
return compareEllipses(edge1, edge2);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return compareEllipseArcs(edge1, edge2);
|
||||
}
|
||||
}
|
||||
|
||||
if (adapt1.GetType() == GeomAbs_BSplineCurve &&
|
||||
adapt2.GetType() == GeomAbs_BSplineCurve) {
|
||||
if (adapt1.GetType() == GeomAbs_BSplineCurve && adapt2.GetType() == GeomAbs_BSplineCurve) {
|
||||
return compareBSplines(edge1, edge2);
|
||||
}
|
||||
|
||||
@@ -143,33 +146,32 @@ bool GeometryMatcher::compareEdges(TopoDS_Shape &shape1, TopoDS_Shape &shape2)
|
||||
return compareDifferent(edge1, edge2);
|
||||
}
|
||||
|
||||
bool GeometryMatcher::compareLines(TopoDS_Edge &edge1, TopoDS_Edge &edge2)
|
||||
bool GeometryMatcher::compareLines(TopoDS_Edge& edge1, TopoDS_Edge& edge2)
|
||||
{
|
||||
// Base::Console().Message("GM::compareLines()\n");
|
||||
// Base::Console().Message("GM::compareLines()\n");
|
||||
// how does the edge that was NOT null in compareEdges become null here?
|
||||
// should not happen, but does!
|
||||
if (edge1.IsNull() || edge2.IsNull()) {
|
||||
// Base::Console().Message("GM::compareLine - an input edge is null\n");
|
||||
// Base::Console().Message("GM::compareLine - an input edge is null\n");
|
||||
return false;
|
||||
}
|
||||
auto start1 = DU::toVector3d(BRep_Tool::Pnt(TopExp::FirstVertex(edge1)));
|
||||
auto end1 = DU::toVector3d(BRep_Tool::Pnt(TopExp::LastVertex(edge1)));
|
||||
auto start2 = DU::toVector3d(BRep_Tool::Pnt(TopExp::FirstVertex(edge2)));
|
||||
auto end2 = DU::toVector3d(BRep_Tool::Pnt(TopExp::LastVertex(edge2)));
|
||||
if (start1.IsEqual(start2, EWTOLERANCE) &&
|
||||
end1.IsEqual(end2, EWTOLERANCE)) {
|
||||
//exact match
|
||||
if (start1.IsEqual(start2, EWTOLERANCE) && end1.IsEqual(end2, EWTOLERANCE)) {
|
||||
// exact match
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GeometryMatcher::compareCircles(TopoDS_Edge &edge1, TopoDS_Edge &edge2)
|
||||
bool GeometryMatcher::compareCircles(TopoDS_Edge& edge1, TopoDS_Edge& edge2)
|
||||
{
|
||||
// Base::Console().Message("GM::compareCircles()\n");
|
||||
// Base::Console().Message("GM::compareCircles()\n");
|
||||
// how does the edge that was NOT null in compareEdges become null here?
|
||||
if (edge1.IsNull() || edge2.IsNull()) {
|
||||
// Base::Console().Message("GM::compareCircles - an input edge is null\n");
|
||||
// Base::Console().Message("GM::compareCircles - an input edge is null\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -181,19 +183,18 @@ bool GeometryMatcher::compareCircles(TopoDS_Edge &edge1, TopoDS_Edge &edge2)
|
||||
double radius2 = circle2.Radius();
|
||||
auto center1 = DU::toVector3d(circle1.Location());
|
||||
auto center2 = DU::toVector3d(circle2.Location());
|
||||
if (DU::fpCompare(radius1, radius2, EWTOLERANCE) &&
|
||||
center1.IsEqual(center2, EWTOLERANCE)) {
|
||||
//exact match
|
||||
if (DU::fpCompare(radius1, radius2, EWTOLERANCE) && center1.IsEqual(center2, EWTOLERANCE)) {
|
||||
// exact match
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GeometryMatcher::compareEllipses(TopoDS_Edge &edge1, TopoDS_Edge &edge2)
|
||||
bool GeometryMatcher::compareEllipses(TopoDS_Edge& edge1, TopoDS_Edge& edge2)
|
||||
{
|
||||
// how does the edge that was NOT null in compareEdges become null here?
|
||||
if (edge1.IsNull() || edge2.IsNull()) {
|
||||
// Base::Console().Message("GM::compareEllipses - an input edge is null\n");
|
||||
// Base::Console().Message("GM::compareEllipses - an input edge is null\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -207,19 +208,18 @@ bool GeometryMatcher::compareEllipses(TopoDS_Edge &edge1, TopoDS_Edge &edge2)
|
||||
double minor2 = ellipse2.MinorRadius();
|
||||
auto center1 = DU::toVector3d(ellipse1.Location());
|
||||
auto center2 = DU::toVector3d(ellipse2.Location());
|
||||
if (DU::fpCompare(major1, major2, EWTOLERANCE) &&
|
||||
DU::fpCompare(minor1, minor2, EWTOLERANCE) &&
|
||||
center1.IsEqual(center2, EWTOLERANCE)) {
|
||||
if (DU::fpCompare(major1, major2, EWTOLERANCE) && DU::fpCompare(minor1, minor2, EWTOLERANCE)
|
||||
&& center1.IsEqual(center2, EWTOLERANCE)) {
|
||||
// exact match
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// for our purposes, only lines or circles masquerading as bsplines are of interest
|
||||
bool GeometryMatcher::compareBSplines(TopoDS_Edge &edge1, TopoDS_Edge &edge2)
|
||||
bool GeometryMatcher::compareBSplines(TopoDS_Edge& edge1, TopoDS_Edge& edge2)
|
||||
{
|
||||
// Base::Console().Message("GM::compareBSplines()\n");
|
||||
// Base::Console().Message("GM::compareBSplines()\n");
|
||||
// how does the edge that was NOT null in compareEdges become null here?
|
||||
if (edge1.IsNull() || edge2.IsNull()) {
|
||||
Base::Console().Message("GM::compareBSplines - an input edge is null\n");
|
||||
@@ -258,31 +258,31 @@ bool GeometryMatcher::compareBSplines(TopoDS_Edge &edge1, TopoDS_Edge &edge2)
|
||||
}
|
||||
|
||||
// this is a weak comparison. we should also check center & radius?
|
||||
bool GeometryMatcher::compareCircleArcs(TopoDS_Edge &edge1, TopoDS_Edge &edge2)
|
||||
bool GeometryMatcher::compareCircleArcs(TopoDS_Edge& edge1, TopoDS_Edge& edge2)
|
||||
{
|
||||
return compareEndPoints(edge1, edge2);
|
||||
}
|
||||
|
||||
bool GeometryMatcher::compareEllipseArcs(TopoDS_Edge &edge1, TopoDS_Edge &edge2)
|
||||
bool GeometryMatcher::compareEllipseArcs(TopoDS_Edge& edge1, TopoDS_Edge& edge2)
|
||||
{
|
||||
return compareEndPoints(edge1, edge2);
|
||||
}
|
||||
}
|
||||
|
||||
// this is where we would try to match a bspline against a line or a circle.
|
||||
// not sure how successful this would be. For now, we just say it doesn't match
|
||||
bool GeometryMatcher::compareDifferent(TopoDS_Edge &edge1, TopoDS_Edge &edge2)
|
||||
bool GeometryMatcher::compareDifferent(TopoDS_Edge& edge1, TopoDS_Edge& edge2)
|
||||
{
|
||||
// Base::Console().Message("GM::compareDifferent()\n");
|
||||
// Base::Console().Message("GM::compareDifferent()\n");
|
||||
BRepAdaptor_Curve adapt1(edge1);
|
||||
BRepAdaptor_Curve adapt2(edge2);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GeometryMatcher::compareEndPoints(TopoDS_Edge &edge1, TopoDS_Edge &edge2)
|
||||
bool GeometryMatcher::compareEndPoints(TopoDS_Edge& edge1, TopoDS_Edge& edge2)
|
||||
{
|
||||
// how does the edge that was NOT null in compareEdges become null here?
|
||||
if (edge1.IsNull() || edge2.IsNull()) {
|
||||
// Base::Console().Message("GM::compareLine - an input edge is null\n");
|
||||
// Base::Console().Message("GM::compareLine - an input edge is null\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -301,9 +301,8 @@ bool GeometryMatcher::compareEndPoints(TopoDS_Edge &edge1, TopoDS_Edge &edge2)
|
||||
props2.SetParameter(pLast2);
|
||||
auto end2 = DU::toVector3d(props2.Value());
|
||||
|
||||
if (begin1.IsEqual(begin2, EWTOLERANCE) &&
|
||||
end1.IsEqual(end2, EWTOLERANCE)) {
|
||||
//exact match
|
||||
if (begin1.IsEqual(begin2, EWTOLERANCE) && end1.IsEqual(end2, EWTOLERANCE)) {
|
||||
// exact match
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -33,17 +33,23 @@ namespace Part
|
||||
class TopoShape;
|
||||
}
|
||||
|
||||
namespace TechDraw {
|
||||
namespace TechDraw
|
||||
{
|
||||
|
||||
class TechDrawExport GeometryMatcher {
|
||||
class TechDrawExport GeometryMatcher
|
||||
{
|
||||
public:
|
||||
GeometryMatcher() {}
|
||||
explicit GeometryMatcher(DrawViewDimension* dim) { m_dimension = dim; }
|
||||
GeometryMatcher()
|
||||
{}
|
||||
explicit GeometryMatcher(DrawViewDimension* dim)
|
||||
{
|
||||
m_dimension = dim;
|
||||
}
|
||||
~GeometryMatcher() = default;
|
||||
|
||||
bool compareGeometry(Part::TopoShape geom1, Part::TopoShape geom2);
|
||||
bool comparePoints(TopoDS_Shape& shape1, TopoDS_Shape& shape2);
|
||||
bool compareEdges(TopoDS_Shape& shape1, TopoDS_Shape& shape2);
|
||||
bool compareGeometry(Part::TopoShape geom1, Part::TopoShape geom2);
|
||||
bool comparePoints(TopoDS_Shape& shape1, TopoDS_Shape& shape2);
|
||||
bool compareEdges(TopoDS_Shape& shape1, TopoDS_Shape& shape2);
|
||||
|
||||
bool compareLines(TopoDS_Edge& edge1, TopoDS_Edge& edge2);
|
||||
bool compareCircles(TopoDS_Edge& edge1, TopoDS_Edge& edge2);
|
||||
@@ -53,12 +59,21 @@ public:
|
||||
bool compareCircleArcs(TopoDS_Edge& edge1, TopoDS_Edge& edge2);
|
||||
bool compareEllipseArcs(TopoDS_Edge& edge1, TopoDS_Edge& edge2);
|
||||
|
||||
double getPointTolerance() const
|
||||
{
|
||||
return m_pointTolerance;
|
||||
}
|
||||
void setPointTolerance(double tol)
|
||||
{
|
||||
m_pointTolerance = tol;
|
||||
}
|
||||
|
||||
private:
|
||||
bool compareEndPoints(TopoDS_Edge& edge1, TopoDS_Edge& edge2);
|
||||
|
||||
DrawViewDimension* m_dimension;
|
||||
double m_pointTolerance {EWTOLERANCE};
|
||||
};
|
||||
|
||||
} //end namespace TechDraw
|
||||
} // end namespace TechDraw
|
||||
#endif
|
||||
|
||||
|
||||
@@ -527,3 +527,13 @@ int Preferences::sectionLineConvention()
|
||||
{
|
||||
return getPreferenceGroup("Standards")->GetInt("SectionLineStandard", 1);
|
||||
}
|
||||
|
||||
|
||||
//! true if the GeometryMatcher should be used in correcting Dimension references
|
||||
bool Preferences::useExactMatchOnDims()
|
||||
{
|
||||
return getPreferenceGroup("Dimensions")->GetBool("UseMatcher", true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -126,6 +126,8 @@ public:
|
||||
static std::string currentElementDefFile();
|
||||
|
||||
static int sectionLineConvention();
|
||||
|
||||
static bool useExactMatchOnDims();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include <QApplication>
|
||||
#include <QFileInfo>
|
||||
#include <QMessageBox>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#endif
|
||||
|
||||
@@ -75,7 +74,7 @@
|
||||
#include "TaskProjection.h"
|
||||
#include "TaskSectionView.h"
|
||||
#include "ViewProviderPage.h"
|
||||
#include "ViewProviderViewPart.h"
|
||||
#include "ViewProviderDrawingView.h"
|
||||
|
||||
void execSimpleSection(Gui::Command* cmd);
|
||||
void execComplexSection(Gui::Command* cmd);
|
||||
|
||||
@@ -630,10 +630,9 @@ void QGIViewDimension::updateView(bool update)
|
||||
updateDim();
|
||||
}
|
||||
|
||||
if (dim->goodReferenceGeometry()) {
|
||||
if (dim->hasGoodReferences()) {
|
||||
m_refFlag->hide();
|
||||
} else {
|
||||
// m_refFlag->setPos(datumLabel->pos());
|
||||
m_refFlag->centerAt(datumLabel->pos() + datumLabel->boundingRect().center());
|
||||
m_refFlag->show();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user