[TD]Refactor Dimensions for 3d upgrade

- separate validation, geometry and reference handling into
  individual files
- improve 3d reference geometry handling
- eliminate duplicate dim creation code

- add Dimension reference repair dialog

- Refactor formatting out of DrawViewDimension

- move dimension repaint control to ViewProvider
This commit is contained in:
wandererfan
2022-10-28 08:46:37 -04:00
committed by WandererFan
parent aeeb62d204
commit 1b547dff72
39 changed files with 5181 additions and 2544 deletions

View File

@@ -62,6 +62,7 @@
#include "DrawUtil.h"
#include "DrawViewAnnotation.h"
#include "DrawViewDimension.h"
#include "DimensionGeometry.h"
#include "DrawViewPart.h"
#include "DrawViewPartPy.h"
#include "EdgeWalker.h"
@@ -725,13 +726,13 @@ private:
Base::Vector3d textLocn(dvd->X.getValue() + parentX, dvd->Y.getValue() + parentY, 0.0);
Base::Vector3d lineLocn(dvd->X.getValue() + parentX, dvd->Y.getValue() + parentY, 0.0);
pointPair pts = dvd->getLinearPoints();
Base::Vector3d dimLine = pts.first - pts.second;
Base::Vector3d dimLine = pts.first() - pts.second();
Base::Vector3d norm(-dimLine.y, dimLine.x, 0.0);
norm.Normalize();
lineLocn = lineLocn + (norm * gap);
Base::Vector3d extLine1Start = Base::Vector3d(pts.first.x, -pts.first.y, 0.0) +
Base::Vector3d extLine1Start = Base::Vector3d(pts.first().x, - pts.first().y, 0.0) +
Base::Vector3d(parentX, parentY, 0.0);
Base::Vector3d extLine2Start = Base::Vector3d(pts.second.x, -pts.second.y, 0.0) +
Base::Vector3d extLine2Start = Base::Vector3d(pts.second().x, - pts.second().y, 0.0) +
Base::Vector3d(parentX, parentY, 0.0);
if (dvd->Type.isValue("DistanceX") ) {
type = 1;
@@ -743,12 +744,12 @@ private:
Base::Vector3d textLocn(dvd->X.getValue() + parentX, dvd->Y.getValue() + parentY, 0.0);
Base::Vector3d lineLocn(dvd->X.getValue() + parentX, dvd->Y.getValue() + parentY, 0.0);
anglePoints pts = dvd->getAnglePoints();
Base::Vector3d end1 = pts.ends.first;
Base::Vector3d end1 = pts.first();
end1.y = -end1.y;
Base::Vector3d end2 = pts.ends.second;
Base::Vector3d end2 = pts.second();
end2.y = -end2.y;
Base::Vector3d apex = pts.vertex;
Base::Vector3d apex = pts.vertex();
apex.y = -apex.y;
apex = apex + parentPos;
@@ -766,7 +767,7 @@ private:
Base::Vector3d center = pts.center;
center.y = -center.y;
center = center + parentPos;
Base::Vector3d lineDir = (arrowPts.first - arrowPts.second).Normalize();
Base::Vector3d lineDir = (arrowPts.first() - arrowPts.second()).Normalize();
Base::Vector3d arcPoint = center + lineDir * pts.radius;
writer.exportRadialDim(center, textLocn, arcPoint, dimText);
} else if(dvd->Type.isValue("Diameter")){
@@ -776,7 +777,7 @@ private:
Base::Vector3d center = pts.center;
center.y = -center.y;
center = center + parentPos;
Base::Vector3d lineDir = (arrowPts.first - arrowPts.second).Normalize();
Base::Vector3d lineDir = (arrowPts.first() - arrowPts.second()).Normalize();
Base::Vector3d end1 = center + lineDir * pts.radius;
Base::Vector3d end2 = center - lineDir * pts.radius;
writer.exportDiametricDim(textLocn, end1, end2, dimText);

View File

@@ -108,6 +108,12 @@ SET(Draw_SRCS
DrawViewDimExtent.h
LandmarkDimension.cpp
LandmarkDimension.h
DimensionGeometry.cpp
DimensionGeometry.h
DimensionReferences.cpp
DimensionReferences.h
DimensionFormatter.cpp
DimensionFormatter.h
DrawViewBalloon.cpp
DrawViewBalloon.h
DrawViewSection.cpp

View File

@@ -0,0 +1,408 @@
/***************************************************************************
* Copyright (c) 2022 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 *
* *
***************************************************************************/
#include "PreCompiled.h"
#include <QRegularExpression>
#ifndef _PreComp_
#endif
#include <Base/Tools.h>
#include <Base/UnitsApi.h>
#include "Preferences.h"
#include "DrawViewDimension.h"
#include "DimensionFormatter.h"
using namespace TechDraw;
bool DimensionFormatter::isMultiValueSchema() const
{
bool angularMeasure = (m_dimension->Type.isValue("Angle") ||
m_dimension->Type.isValue("Angle3Pt"));
if (Base::UnitsApi::isMultiUnitAngle() &&
angularMeasure) {
return true;
} else if (Base::UnitsApi::isMultiUnitLength() &&
!angularMeasure) {
return true;
}
return false;
}
//partial = 0 return the unaltered user string from the Units subsystem
//partial = 1 return value formatted according to the format spec and preferences for
// useAltDecimals and showUnits
//partial = 2 return only the unit of measure
std::string DimensionFormatter::formatValue(qreal value,
QString qFormatSpec,
int partial,
bool isDim)
{
bool angularMeasure = false;
QLocale loc;
Base::Quantity asQuantity;
asQuantity.setValue(value);
if ( (m_dimension->Type.isValue("Angle")) ||
(m_dimension->Type.isValue("Angle3Pt")) ) {
angularMeasure = true;
asQuantity.setUnit(Base::Unit::Angle);
} else {
asQuantity.setUnit(Base::Unit::Length);
}
QString qUserString = asQuantity.getUserString(); // this handles mm to inch/km/parsec etc
// and decimal positions but won't give more than
// Global_Decimals precision
//get formatSpec prefix/suffix/specifier
QStringList qsl = getPrefixSuffixSpec(qFormatSpec);
QString formatPrefix = qsl[0]; //FormatSpec prefix
QString formatSuffix = qsl[1]; //FormatSpec suffix
QString formatSpecifier = qsl[2]; //FormatSpec specifier
QString qMultiValueStr;
QString qBasicUnit = Base::Tools::fromStdString(Base::UnitsApi::getBasicLengthUnit());
QString formattedValue;
if (isMultiValueSchema() && partial == 0) {
//handle multi value schemes (yd/ft/in, dms, etc). don't even try to use Alt Decimals or hide units
qMultiValueStr = formatPrefix + qUserString + formatSuffix;
return qMultiValueStr.toStdString();
} else {
//not multivalue schema
if (formatSpecifier.isEmpty()) {
Base::Console().Warning("Warning - no numeric format in Format Spec %s - %s\n",
qPrintable(qFormatSpec), m_dimension->getNameInDocument());
return Base::Tools::toStdString(qFormatSpec);
}
// for older TD drawings the formatSpecifier "%g" was used, but the number of decimals was
// neverheless limited. To keep old drawings, we limit the number of decimals too
// if the TD preferences option to use the global decimal number is set
// the formatSpecifier can have a prefix and/or suffix
if (m_dimension->useDecimals() && formatSpecifier.contains(QString::fromLatin1("%g"), Qt::CaseInsensitive)) {
int globalPrecision = Base::UnitsApi::getDecimals();
// change formatSpecifier to e.g. "%.2f"
QString newSpecifier = QString::fromStdString("%." + std::to_string(globalPrecision) + "f");
formatSpecifier.replace(QString::fromLatin1("%g"), newSpecifier, Qt::CaseInsensitive);
}
// since we are not using a multiValueSchema, we know that angles are in '°' and for
// lengths we can get the unit of measure from UnitsApi::getBasicLengthUnit.
// TODO: check the weird schemas (MKS, Imperial1)that report different UoM
// for different values
// get value in the base unit with default decimals
// for the conversion we use the same method as in DlgUnitsCalculator::valueChanged
// get the conversion factor for the unit
// the result is now just val / convertValue because val is always in the base unit
// don't do this for angular values since they are not in the BaseLengthUnit
double userVal;
if (angularMeasure) {
userVal = asQuantity.getValue();
qBasicUnit = QString::fromUtf8("°");
} else {
double convertValue = Base::Quantity::parse(QString::fromLatin1("1") + qBasicUnit).getValue();
userVal = asQuantity.getValue() / convertValue;
}
if (isTooSmall(userVal, formatSpecifier)) {
Base::Console().Warning("Dimension value is too small for format specifier: %s\n", qPrintable(formatSpecifier));
}
formattedValue = formatValueToSpec(userVal, formatSpecifier);
// replace decimal sign if necessary
QChar dp = QChar::fromLatin1('.');
if (loc.decimalPoint() != dp) {
formattedValue.replace(dp, loc.decimalPoint());
}
}
//formattedValue is now in formatSpec format with local decimal separator
std::string formattedValueString = formattedValue.toStdString();
if (partial == 0) { //prefix + unit subsystem string + suffix
return Base::Tools::toStdString(formatPrefix) +
Base::Tools::toStdString(qUserString) +
Base::Tools::toStdString(formatSuffix);
} else if (partial == 1) { // prefix number[unit] suffix
if (angularMeasure) {
//always insert unit after value
return Base::Tools::toStdString(formatPrefix) +
formattedValueString + "°" +
Base::Tools::toStdString(formatSuffix);
} else if (m_dimension->showUnits()){
if (isDim && m_dimension->haveTolerance()) {
//unit will be included in tolerance so don't repeat it here
return Base::Tools::toStdString(formatPrefix) +
formattedValueString +
Base::Tools::toStdString(formatSuffix);
} else {
//no tolerance, so we need to include unit
return Base::Tools::toStdString(formatPrefix) +
formattedValueString + " " +
Base::Tools::toStdString(qBasicUnit) +
Base::Tools::toStdString(formatSuffix);
}
} else {
//showUnits is false
return Base::Tools::toStdString(formatPrefix) +
formattedValueString +
Base::Tools::toStdString(formatSuffix);
}
} else if (partial == 2) { // just the unit
if (angularMeasure) {
return Base::Tools::toStdString(qBasicUnit);
} else if (m_dimension->showUnits()) {
return Base::Tools::toStdString(qBasicUnit);
} else {
return "";
}
}
return formattedValueString;
}
std::string DimensionFormatter::getFormattedToleranceValue(int partial)
{
QString FormatSpec = QString::fromUtf8(m_dimension->FormatSpecOverTolerance.getStrValue().data());
QString ToleranceString;
if (m_dimension->ArbitraryTolerances.getValue())
ToleranceString = FormatSpec;
else
ToleranceString = QString::fromUtf8(formatValue(m_dimension->OverTolerance.getValue(),
FormatSpec,
partial,
false).c_str());
return ToleranceString.toStdString();
}
//get over and under tolerances
std::pair<std::string, std::string> DimensionFormatter::getFormattedToleranceValues(int partial)
{
QString underFormatSpec = QString::fromUtf8(m_dimension->FormatSpecUnderTolerance.getStrValue().data());
QString overFormatSpec = QString::fromUtf8(m_dimension->FormatSpecOverTolerance.getStrValue().data());
std::pair<std::string, std::string> tolerances;
QString underTolerance, overTolerance;
if (m_dimension->ArbitraryTolerances.getValue()) {
underTolerance = underFormatSpec;
overTolerance = overFormatSpec;
} else {
if (DrawUtil::fpCompare(m_dimension->UnderTolerance.getValue(), 0.0)) {
underTolerance = QString::fromUtf8(formatValue(m_dimension->UnderTolerance.getValue(),
QString::fromUtf8("%.0f"),
partial,
false).c_str());
}
else {
underTolerance = QString::fromUtf8(formatValue(m_dimension->UnderTolerance.getValue(),
underFormatSpec,
partial,
false).c_str());
}
if (DrawUtil::fpCompare(m_dimension->OverTolerance.getValue(), 0.0)) {
overTolerance = QString::fromUtf8(formatValue(m_dimension->OverTolerance.getValue(),
QString::fromUtf8("%.0f"),
partial,
false).c_str());
}
else {
overTolerance = QString::fromUtf8(formatValue(m_dimension->OverTolerance.getValue(),
overFormatSpec,
partial,
false).c_str());
}
}
tolerances.first = underTolerance.toStdString();
tolerances.second = overTolerance.toStdString();
return tolerances;
}
//partial = 2 unit only
std::string DimensionFormatter::getFormattedDimensionValue(int partial)
{
QString qFormatSpec = QString::fromUtf8(m_dimension->FormatSpec.getStrValue().data());
if ( (m_dimension->Arbitrary.getValue() && !m_dimension->EqualTolerance.getValue())
|| (m_dimension->Arbitrary.getValue() && m_dimension->TheoreticalExact.getValue()) ) {
return m_dimension->FormatSpec.getStrValue();
}
if (m_dimension->Arbitrary.getValue()) {
return m_dimension->FormatSpec.getStrValue();
}
// if there is an equal over-/undertolerance (so only 1 tolerance to show with +/-) and
// not theoretically exact (which has no tolerance), and
// tolerance has been specified, ie
// (OverTolerance != 0.0 (so a tolerance has been specified) or
// ArbitraryTolerances are specified)
// concatenate the tolerance to dimension
if (m_dimension->EqualTolerance.getValue() &&
!m_dimension->TheoreticalExact.getValue() &&
(!DrawUtil::fpCompare(m_dimension->OverTolerance.getValue(), 0.0) ||
m_dimension->ArbitraryTolerances.getValue())) {
QString labelText = QString::fromUtf8(formatValue(m_dimension->getDimValue(),
qFormatSpec,
1,
true).c_str()); //just the number pref/spec[unit]/suf
QString unitText = QString::fromUtf8(formatValue(m_dimension->getDimValue(),
qFormatSpec,
2,
false).c_str()); //just the unit
QString tolerance = QString::fromStdString(getFormattedToleranceValue(1).c_str());
// tolerance might start with a plus sign that we don't want, so cut it off
// note plus sign is not at pos = 0!
QRegularExpression plus(QString::fromUtf8("^\\s*\\+"));
tolerance.remove(plus);
return (labelText +
QString::fromUtf8(" \xC2\xB1 ") + // +/- symbol
tolerance).toStdString();
if (partial == 2) {
return unitText.toStdString();
}
return "";
}
//tolerance not specified, so just format dimension value?
std::string formattedValue = formatValue(m_dimension->getDimValue(), qFormatSpec, partial, true);
return formattedValue;
}
// format the value using the formatSpec. Also, handle the non-standard format-
// specifier '%w', which has the following rules: works as %f, but no trailing zeros
QString DimensionFormatter::formatValueToSpec(double value, QString formatSpecifier)
{
QString formattedValue;
if (formatSpecifier.contains(QRegularExpression(QStringLiteral("%.*[wW]")))) {
QString fs = formatSpecifier;
fs.replace(QRegularExpression(QStringLiteral("%(.*)w")), QStringLiteral("%\\1f"));
fs.replace(QRegularExpression(QStringLiteral("%(.*)W")), QStringLiteral("%\\1F"));
formattedValue = QString::asprintf(Base::Tools::toStdString(fs).c_str(), value);
// First, try to cut trailing zeros, if AFTER decimal dot there are nonzero numbers
// Second, try to cut also decimal dot and zeros, if there are just zeros after it
formattedValue.replace(QRegularExpression(QStringLiteral("([0-9][0-9]*\\.[0-9]*[1-9])00*$")), QStringLiteral("\\1"));
formattedValue.replace(QRegularExpression(QStringLiteral("([0-9][0-9]*)\\.0*$")), QStringLiteral("\\1"));
} else {
formattedValue = QString::asprintf(Base::Tools::toStdString(formatSpecifier).c_str(), value);
}
return formattedValue;
}
QStringList DimensionFormatter::getPrefixSuffixSpec(QString fSpec)
{
QStringList result;
//find the %x.y tag in FormatSpec
QRegularExpression rxFormat(QStringLiteral("%[+-]?[0-9]*\\.*[0-9]*[aefgwAEFGW]")); //printf double format spec
QRegularExpressionMatch rxMatch;
int pos = fSpec.indexOf(rxFormat, 0, &rxMatch);
if (pos != -1) {
QString match = rxMatch.captured(0); //entire capture of rx
QString formatPrefix = fSpec.left(pos);
result.append(formatPrefix);
QString formatSuffix = fSpec.right(fSpec.size() - pos - match.size());
result.append(formatSuffix);
result.append(match);
} else { //printf format not found!
Base::Console().Warning("Warning - no numeric format in formatSpec %s - %s\n",
qPrintable(fSpec), m_dimension->getNameInDocument());
result.append(QString());
result.append(QString());
result.append(fSpec);
}
return result;
}
std::string DimensionFormatter::getDefaultFormatSpec(bool isToleranceFormat) const
{
std::string prefFormat = Preferences::formatSpec();
QString formatSpec;
QString qPrefix;
if (prefFormat.empty()) {
QString format1 = Base::Tools::fromStdString("%.");
QString format2 = Base::Tools::fromStdString("f");
int precision;
if (m_dimension->useDecimals()) {
precision = Base::UnitsApi::getDecimals();
} else {
precision = Preferences::altDecimals();
}
QString formatPrecision = QString::number(precision);
std::string prefix = m_dimension->getPrefixForDimType();
if (!prefix.empty()) {
qPrefix = QString::fromUtf8(prefix.data(), prefix.size());
}
formatSpec = qPrefix + format1 + formatPrecision + format2;
} else {
std::string prefix = m_dimension->getPrefixForDimType();
qPrefix = QString::fromUtf8(prefix.data(), prefix.size());
formatSpec = qPrefix + QString::fromStdString(prefFormat);
}
if (isToleranceFormat) {
formatSpec.replace(QString::fromUtf8("%"), QString::fromUtf8("%+"));
}
return Base::Tools::toStdString(formatSpec);
}
//true if value is too small to display using formatSpec
bool DimensionFormatter::isTooSmall(double value, QString formatSpec)
{
if (DU::fpCompare(value, 0.0)) {
//zero values always fit, so it isn't too small
return false;
}
QRegularExpression rxFormat(QStringLiteral("%[+-]?[0-9]*\\.*([0-9]*)[aefgwAEFGW]")); //printf double format spec
QRegularExpressionMatch rxMatch = rxFormat.match(formatSpec);
if (rxMatch.hasMatch()) {
QString decimalGroup = rxMatch.captured(1);
int factor = decimalGroup.toInt();
double minValue = pow(10.0, -factor);
if (value < minValue) {
return true;
}
} else {
Base::Console().Warning("Failed to parse dimension format spec\n");
}
return false;
}

View File

@@ -0,0 +1,57 @@
/***************************************************************************
* Copyright (c) 2022 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 *
* *
***************************************************************************/
#ifndef DIMENSIONFORMATTER_H
#define DIMENSIONFORMATTER_H
#include <Mod/TechDraw/TechDrawGlobal.h>
#include <DrawViewDimension.h>
namespace TechDraw {
class TechDrawExport DimensionFormatter {
public:
DimensionFormatter() {}
DimensionFormatter(DrawViewDimension* dim) { m_dimension = dim; }
~DimensionFormatter() = default;
void setDimension(DrawViewDimension* dim) { m_dimension = dim; }
bool isMultiValueSchema() const;
std::string formatValue(qreal value,
QString qFormatSpec,
int partial,
bool isDim);
std::string getFormattedToleranceValue(int partial);
std::pair<std::string, std::string> getFormattedToleranceValues(int partial);
std::string getFormattedDimensionValue(int partial);
QStringList getPrefixSuffixSpec(QString fSpec);
std::string getDefaultFormatSpec(bool isToleranceFormat) const;
bool isTooSmall(double value, QString formatSpec);
QString formatValueToSpec(double value, QString formatSpecifier);
private:
DrawViewDimension* m_dimension;
};
} //end namespace TechDraw
#endif

View File

@@ -0,0 +1,251 @@
/***************************************************************************
* Copyright (c) 2022 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 *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#include <gp_Ax3.hxx>
#include <gp_Trsf.hxx>
#include <gp_Vec.hxx>
#endif
#include <Base/Console.h>
#include "DrawViewPart.h"
#include "DrawUtil.h"
#include "DimensionGeometry.h"
using namespace TechDraw;
using DU = DrawUtil;
pointPair::pointPair(const pointPair& pp)
{
first(pp.first());
second(pp.second());
}
void pointPair::move(Base::Vector3d offset)
{
m_first = m_first - offset;
m_second = m_second - offset;
}
void pointPair::project(DrawViewPart* dvp)
{
Base::Vector3d normal = DrawUtil::toVector3d(dvp->getProjectionCS().Direction());
Base::Vector3d stdOrigin(0.0, 0.0, 0.0);
m_first = m_first.ProjectToPlane(stdOrigin, normal) * dvp->getScale();
m_second = m_second.ProjectToPlane(stdOrigin, normal) * dvp->getScale();
}
void pointPair::mapToPage(DrawViewPart* dvp)
{
gp_Trsf xOXYZ;
gp_Ax3 OXYZ;
xOXYZ.SetTransformation(OXYZ, gp_Ax3(dvp->getProjectionCS()));
gp_Vec gvFirst = DU::togp_Vec(m_first).Transformed(xOXYZ);
m_first = DU::toVector3d(gvFirst);
gp_Vec gvSecond = DU::togp_Vec(m_second).Transformed(xOXYZ);
m_second = DU::toVector3d(gvSecond);
}
void pointPair::invertY()
{
m_first = DU::invertY(m_first);
m_second = DU::invertY(m_second);
}
void pointPair::dump(std::string text) const
{
Base::Console().Message("pointPair - %s\n", text.c_str());
Base::Console().Message("pointPair - first: %s second: %s\n",
DU::formatVector(first()).c_str(),
DU::formatVector(second()).c_str());
}
anglePoints::anglePoints()
{
m_ends.first(Base::Vector3d(0.0, 0.0, 0.0));
m_ends.second(Base::Vector3d(0.0, 0.0, 0.0));
m_vertex = Base::Vector3d(0.0, 0.0, 0.0);
}
anglePoints::anglePoints(const anglePoints& ap)
: m_ends(ap.ends()),
m_vertex(ap.vertex())
{
}
anglePoints& anglePoints::operator= (const anglePoints& ap)
{
m_ends = ap.ends();
m_vertex = ap.vertex();
return *this;
}
void anglePoints::move(Base::Vector3d offset)
{
m_ends.move(offset);
m_vertex = m_vertex - offset;
}
void anglePoints::project(DrawViewPart* dvp)
{
Base::Vector3d normal = DrawUtil::toVector3d(dvp->getProjectionCS().Direction());
Base::Vector3d stdOrigin(0.0, 0.0, 0.0);
m_ends.project(dvp);
m_vertex = m_vertex.ProjectToPlane(stdOrigin, normal) * dvp->getScale();
}
void anglePoints::mapToPage(DrawViewPart* dvp)
{
m_ends.mapToPage(dvp);
gp_Trsf xOXYZ;
gp_Ax3 OXYZ;
xOXYZ.SetTransformation(OXYZ, gp_Ax3(dvp->getProjectionCS()));
gp_Vec gvVertex = DU::togp_Vec(m_vertex).Transformed(xOXYZ);
m_vertex = DU::toVector3d(gvVertex);
}
void anglePoints::invertY()
{
m_ends.invertY();
m_vertex = DU::invertY(m_vertex);
}
void anglePoints::dump(std::string text) const
{
Base::Console().Message("anglePoints - %s\n", text.c_str());
Base::Console().Message("anglePoints - ends - first: %s second: %s\n",
DU::formatVector(first()).c_str(),
DU::formatVector(second()).c_str());
Base::Console().Message("anglePoints - vertex: %s\n",
DU::formatVector(vertex()).c_str());
}
arcPoints::arcPoints()
{
isArc = false;
radius = 0.0;
center = Base::Vector3d(0.0, 0.0, 0.0);
onCurve.first(Base::Vector3d(0.0, 0.0, 0.0));
onCurve.second(Base::Vector3d(0.0, 0.0, 0.0));
arcEnds.first(Base::Vector3d(0.0, 0.0, 0.0));
arcEnds.second(Base::Vector3d(0.0, 0.0, 0.0));
midArc = Base::Vector3d(0.0, 0.0, 0.0);
arcCW = false;
}
arcPoints::arcPoints(const arcPoints& ap)
: isArc(ap.isArc)
, radius(ap.radius)
, center(ap.center)
, onCurve(ap.onCurve)
, arcEnds(ap.arcEnds)
, midArc(ap.midArc)
, arcCW(ap.arcCW)
{
}
arcPoints& arcPoints::operator= (const arcPoints& ap)
{
isArc = ap.isArc;
radius = ap.radius;
center = ap.center;
onCurve = ap.onCurve;
arcEnds = ap.arcEnds;
midArc = ap.midArc;
arcCW = ap.arcCW;
return *this;
}
void arcPoints::move(Base::Vector3d offset)
{
center = center - offset;
onCurve.first(onCurve.first() - offset);
onCurve.second(onCurve.second() - offset);
arcEnds.first(arcEnds.first() - offset);
arcEnds.second(arcEnds.second() - offset);
midArc = midArc - offset;
}
void arcPoints::project(DrawViewPart* dvp)
{
radius = radius * dvp->getScale();
Base::Vector3d normal = DrawUtil::toVector3d(dvp->getProjectionCS().Direction());
Base::Vector3d stdOrigin(0.0, 0.0, 0.0);
center = center.ProjectToPlane(stdOrigin, normal) * dvp->getScale();
onCurve.first(onCurve.first().ProjectToPlane(stdOrigin, normal) * dvp->getScale());
onCurve.second(onCurve.second().ProjectToPlane(stdOrigin, normal) * dvp->getScale());
arcEnds.first(arcEnds.first().ProjectToPlane(stdOrigin, normal) * dvp->getScale());
arcEnds.second(arcEnds.second().ProjectToPlane(stdOrigin, normal) * dvp->getScale());
midArc = midArc.ProjectToPlane(stdOrigin, normal) * dvp->getScale();
}
void arcPoints::mapToPage(DrawViewPart* dvp)
{
gp_Trsf xOXYZ;
gp_Ax3 OXYZ;
xOXYZ.SetTransformation(OXYZ, gp_Ax3(dvp->getProjectionCS()));
gp_Vec gvCenter = DU::togp_Vec(center).Transformed(xOXYZ);
center = DU::toVector3d(gvCenter);
gp_Vec gvOnCurve1 = DU::togp_Vec(onCurve.first()).Transformed(xOXYZ);
onCurve.first(DU::toVector3d(gvOnCurve1));
gp_Vec gvOnCurve2 = DU::togp_Vec(onCurve.second()).Transformed(xOXYZ);
onCurve.second(DU::toVector3d(gvOnCurve2));
gp_Vec gvArcEnds1 = DU::togp_Vec(arcEnds.first()).Transformed(xOXYZ);
arcEnds.first(DU::toVector3d(gvArcEnds1));
gp_Vec gvArcEnds2 = DU::togp_Vec(arcEnds.second()).Transformed(xOXYZ);
arcEnds.second(DU::toVector3d(gvArcEnds2));
gp_Vec gvMidArc = DU::togp_Vec(midArc).Transformed(xOXYZ);
midArc = DU::toVector3d(gvMidArc);
}
void arcPoints::invertY()
{
center = DU::invertY(center);
onCurve.invertY();
arcEnds.invertY();
midArc = DU::invertY(midArc);
}
void arcPoints::dump(std::string text) const
{
Base::Console().Message("arcPoints - %s\n", text.c_str());
Base::Console().Message("arcPoints - radius: %.3f center: %s\n", radius, DrawUtil::formatVector(center).c_str());
Base::Console().Message("arcPoints - isArc: %d arcCW: %d\n", isArc, arcCW);
Base::Console().Message("arcPoints - onCurve: %s %s\n",
DrawUtil::formatVector(onCurve.first()).c_str(),
DrawUtil::formatVector(onCurve.second()).c_str());
Base::Console().Message("arcPoints - arcEnds: %s %s\n",
DrawUtil::formatVector(arcEnds.first()).c_str(),
DrawUtil::formatVector(arcEnds.second()).c_str());
Base::Console().Message("arcPoints - midArc: %s\n",
DrawUtil::formatVector(midArc).c_str());
}

View File

@@ -0,0 +1,124 @@
/***************************************************************************
* Copyright (c) 2022 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 *
* *
***************************************************************************/
#ifndef TECHDRAW_DIMENSIONGEOMETRY_h_
#define TECHDRAW_DIMENSIONGEOMETRY_h_
#include <Mod/TechDraw/TechDrawGlobal.h>
#include <string>
#include <Base/Vector3D.h>
namespace TechDraw
{
class DrawViewPart;
//a convenient container for linear dimension end points
class TechDrawExport pointPair
{
public:
pointPair() = default;
pointPair(Base::Vector3d point0, Base::Vector3d point1) { m_first = point0; m_second = point1; }
pointPair(const pointPair& pp);
pointPair& operator= (const pointPair& pp) {
m_first = pp.first();
m_second = pp.second();
return *this;
}
Base::Vector3d first() const { return m_first; }
void first(Base::Vector3d newFirst) { m_first = newFirst; }
Base::Vector3d second() const { return m_second; }
void second(Base::Vector3d newSecond) { m_second = newSecond; }
void move(Base::Vector3d offset);
void project(DrawViewPart* dvp);
void mapToPage(DrawViewPart* dvp);
void invertY();
void dump(std::string text) const;
private:
Base::Vector3d m_first;
Base::Vector3d m_second;
};
//a convenient container for angular dimension points
class TechDrawExport anglePoints
{
public:
anglePoints();
anglePoints(Base::Vector3d apex, Base::Vector3d point0, Base::Vector3d point1) {
vertex(apex); first(point0); second(point1); }
anglePoints(const anglePoints& ap);
anglePoints& operator= (const anglePoints& ap);
pointPair ends() const { return m_ends; }
void ends(pointPair newEnds) { m_ends = newEnds; }
Base::Vector3d first() const { return m_ends.first(); }
void first(Base::Vector3d newFirst) { m_ends.first(newFirst); }
Base::Vector3d second() const { return m_ends.second(); }
void second(Base::Vector3d newSecond) { m_ends.second(newSecond); }
Base::Vector3d vertex() const { return m_vertex; }
void vertex(Base::Vector3d newVertex) { m_vertex = newVertex; }
void move(Base::Vector3d offset);
void project(DrawViewPart* dvp);
void mapToPage(DrawViewPart* dvp);
void invertY();
void dump(std::string text) const;
private:
pointPair m_ends;
Base::Vector3d m_vertex;
};
//a convenient container for diameter or radius dimension points
class TechDrawExport arcPoints
{
public:
arcPoints();
arcPoints(const arcPoints& ap);
arcPoints& operator= (const arcPoints& ap);
void move(Base::Vector3d offset);
void project(DrawViewPart* dvp);
void mapToPage(DrawViewPart* dvp);
void invertY();
void dump(std::string text) const;
//TODO: setters and getters
bool isArc;
double radius;
Base::Vector3d center;
pointPair onCurve;
pointPair arcEnds;
Base::Vector3d midArc;
bool arcCW;
};
} //end namespace TechDraw
#endif

View File

@@ -0,0 +1,76 @@
/***************************************************************************
* Copyright (c) 2022 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 *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#endif
#include <TopoDS_Shape.hxx>
#include <App/GeoFeature.h>
#include <Mod/Part/App/PartFeature.h>
#include <Mod/Part/App/TopoShape.h>
#include "DrawViewPart.h"
#include "DrawUtil.h"
#include "Geometry.h"
#include "DimensionReferences.h"
using namespace TechDraw;
TopoDS_Shape ReferenceEntry::getGeometry() const
{
if ( getObject()->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId()) ) {
TechDraw::DrawViewPart* dvp = static_cast<TechDraw::DrawViewPart*>(getObject());
std::string gType = geomType();
if (gType == "Vertex") {
auto vgeom = dvp->getVertex(getSubName());
return vgeom->occVertex;
} else if (gType == "Edge") {
auto egeom = dvp->getEdge(getSubName());
return egeom->occEdge;
} else if (gType == "Face") {
auto fgeom = dvp->getFace(getSubName());
return fgeom->toOccFace();
}
return TopoDS_Shape();
}
Part::TopoShape shape = Part::Feature::getTopoShape(getObject());
App::GeoFeature* geoFeat = dynamic_cast<App::GeoFeature*>(getObject());
if (geoFeat) {
shape.setPlacement(geoFeat->globalPlacement());
}
if (getSubName().empty()) {
return shape.getShape();
}
return shape.getSubShape(getSubName().c_str());
}
std::string ReferenceEntry::geomType() const
{
return DrawUtil::getGeomTypeFromName(getSubName());
}
bool ReferenceEntry::isWholeObject() const
{
return getSubName().empty();
}

View File

@@ -0,0 +1,73 @@
/***************************************************************************
* Copyright (c) 2022 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 *
* *
***************************************************************************/
#ifndef TECHDRAW_DIMENSIONREFERENCES_H
#define TECHDRAW_DIMENSIONREFERENCES_H
#include <Mod/TechDraw/TechDrawGlobal.h>
#include <string>
#include <vector>
#include <TopoDS_Shape.hxx>
namespace App
{
class DocumentObject;
}
namespace TechDraw
{
//a convenient way of handling object+subName references
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() = default;
App::DocumentObject* getObject() const { return m_object; }
void setObject(App::DocumentObject* docObj) { m_object = docObj; }
std::string getSubName() const { return m_subName; }
void setSubName(std::string subName) { m_subName = subName; }
TopoDS_Shape getGeometry() const;
std::string geomType() const;
bool isWholeObject() const;
private:
bool is3d();
App::DocumentObject* m_object;
std::string m_subName;
};
using ReferenceVector = std::vector<ReferenceEntry>;
} // end namespace
#endif //TECHDRAW_DIMENSIONREFERENCES_H

View File

@@ -23,16 +23,17 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <cstdlib>
# include <sstream>
#include <cstdlib>
#include <sstream>
# include <Bnd_Box.hxx>
# include <BRepBndLib.hxx>
# include <BRepBuilderAPI_MakeEdge.hxx>
# include <BRepExtrema_DistShapeShape.hxx>
# include <Geom_Line.hxx>
# include <gp_Pln.hxx>
# include <TopoDS_Edge.hxx>
#include <Bnd_Box.hxx>
#include <BRepBndLib.hxx>
#include <BRep_Builder.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepExtrema_DistShapeShape.hxx>
#include <Geom_Line.hxx>
#include <gp_Pln.hxx>
#include <TopoDS_Edge.hxx>
#endif
#include <App/Document.h>
@@ -43,6 +44,7 @@
#include "DrawDimHelper.h"
#include "Geometry.h"
#include "GeometryObject.h"
#include "Cosmetic.h"
#include "DrawPage.h"
#include "DrawUtil.h"
@@ -57,9 +59,6 @@
using namespace TechDraw;
//All this OCC math is being done on edges(&vertices) that have been through the center/scale/mirror process.
//TODO: this needs to be exposed to Python
void DrawDimHelper::makeExtentDim(DrawViewPart* dvp,
std::vector<std::string> edgeNames,
int direction)
@@ -67,7 +66,6 @@ void DrawDimHelper::makeExtentDim(DrawViewPart* dvp,
// Base::Console().Message("DDH::makeExtentDim() - dvp: %s edgeNames: %d\n",
// dvp->Label.getValue(), edgeNames.size());
if (!dvp) {
// Base::Console().Message("DDH::makeExtentDim - dvp: %X\n", dvp);
return;
}
@@ -78,90 +76,132 @@ void DrawDimHelper::makeExtentDim(DrawViewPart* dvp,
dimNum = 1;
}
std::pair<Base::Vector3d, Base::Vector3d> endPoints = minMax(dvp,
edgeNames,
direction);
Base::Vector3d refMin = endPoints.first / dvp->getScale(); //unscale from geometry
Base::Vector3d refMax = endPoints.second / dvp->getScale();
TechDraw::DrawPage* page = dvp->findParentPage();
std::string pageName = page->getNameInDocument();
//pause recomputes
dvp->getDocument()->setStatus(App::Document::Status::SkipRecompute, true);
DrawViewDimension* distDim = makeDistDim(dvp, dimType, refMin, refMax, true);
std::string dimName = distDim->getNameInDocument();
App::Document* doc = dvp->getDocument();
std::string dimName = doc->getUniqueObjectName("DimExtent");
Base::Interpreter().runStringArg("App.activeDocument().addObject('TechDraw::DrawViewDimExtent', '%s')",
dimName.c_str());
Base::Interpreter().runStringArg("App.activeDocument().%s.Type = '%s'",
dimName.c_str(), dimType.c_str());
Base::Interpreter().runStringArg("App.activeDocument().%s.DirExtent = %d",
dimName.c_str(), dimNum);
DrawViewDimExtent* extDim = dynamic_cast<DrawViewDimExtent*>(distDim);
extDim->Source.setValue(dvp, edgeNames);
std::vector<std::string> subElements = extDim->References2D.getSubValues();
std::vector<std::string> cvTags;
std::string tag0;
std::string tag1;
TechDraw::VertexPtr v0;
TechDraw::VertexPtr v1;
if (subElements.size() > 1) {
int idx0 = DrawUtil::getIndexFromName(subElements[0]);
int idx1 = DrawUtil::getIndexFromName(subElements[1]);
v0 = dvp->getProjVertexByIndex(idx0);
v1 = dvp->getProjVertexByIndex(idx1);
if (v0 && !v0->cosmeticTag.empty()) {
tag0 = v0->cosmeticTag;
}
if (v1 && !v1->cosmeticTag.empty()) {
tag1 = v1->cosmeticTag;
}
cvTags.push_back(tag0);
cvTags.push_back(tag1);
extDim->CosmeticTags.setValues(cvTags);
TechDraw::DrawViewDimExtent* dimExt = dynamic_cast<TechDraw::DrawViewDimExtent*>(doc->getObject(dimName.c_str()));
if (!dimExt) {
throw Base::TypeError("Dim extent not found");
}
dimExt->Source.setValue(dvp, edgeNames);
ReferenceVector newRefs;
if (edgeNames.empty()) {
ReferenceEntry emptyRef(dvp, std::string());
newRefs.push_back(emptyRef);
} else {
for (auto& edge : edgeNames) {
ReferenceEntry ref(dvp, edge);
newRefs.push_back(ref);
}
}
dimExt->setReferences2d(newRefs);
//continue recomputes
dvp->getDocument()->setStatus(App::Document::Status::SkipRecompute, false);
extDim->recomputeFeature();
Base::Interpreter().runStringArg("App.activeDocument().%s.addView(App.activeDocument().%s)",
pageName.c_str(), dimName.c_str());
dimExt->recomputeFeature();
}
void DrawDimHelper::makeExtentDim3d(DrawViewPart* dvp,
ReferenceVector references,
int direction)
{
// Base::Console().Message("DDH::makeExtentDim3d() - dvp: %s references: %d\n",
// dvp->Label.getValue(), references.size());
if (!dvp) {
return;
}
std::string dimType = "DistanceX";
int dimNum = 0;
if (direction == VERTICAL) {
dimType = "DistanceY";
dimNum = 1;
}
TechDraw::DrawPage* page = dvp->findParentPage();
std::string pageName = page->getNameInDocument();
App::Document* doc = dvp->getDocument();
std::string dimName = doc->getUniqueObjectName("DimExtent");
Base::Interpreter().runStringArg("App.activeDocument().addObject('TechDraw::DrawViewDimExtent', '%s')",
dimName.c_str());
Base::Interpreter().runStringArg("App.activeDocument().%s.Type = '%s'",
dimName.c_str(), dimType.c_str());
Base::Interpreter().runStringArg("App.activeDocument().%s.DirExtent = %d",
dimName.c_str(), dimNum);
TechDraw::DrawViewDimExtent* dimExt = dynamic_cast<TechDraw::DrawViewDimExtent*>(doc->getObject(dimName.c_str()));
if (!dimExt) {
throw Base::TypeError("Dim extent not found");
}
dimExt->Source.setValue(dvp);
std::vector<App::DocumentObject*> objs3d;
std::vector<std::string> subs3d;
for (auto& ref : references) {
objs3d.push_back(ref.getObject());
subs3d.push_back(ref.getSubName());
}
dimExt->Source3d.setValues(objs3d, subs3d);
ReferenceVector newRefs2d;
ReferenceEntry emptyRef(dvp, std::string());
newRefs2d.push_back(emptyRef);
dimExt->setReferences2d(newRefs2d);
dimExt->setReferences3d(references);
Base::Interpreter().runStringArg("App.activeDocument().%s.addView(App.activeDocument().%s)",
pageName.c_str(), dimName.c_str());
dimExt->recomputeFeature();
}
std::pair<Base::Vector3d, Base::Vector3d> DrawDimHelper::minMax(DrawViewPart* dvp,
std::vector<std::string> edgeNames,
int direction)
{
// Base::Console().Message("DDH::minMax()\n");
// Base::Console().Message("DDH::minMax() - edgeName: %d\n", edgeNames.size());
std::pair<Base::Vector3d, Base::Vector3d> result;
Base::Vector3d refMin;
Base::Vector3d refMax;
gp_Pnt stdOrg(0.0, 0.0, 0.0);
gp_Dir stdZ(0.0, 0.0, 1.0);
gp_Dir stdX(1.0, 0.0, 0.0);
gp_Ax3 projAx3(stdOrg, stdZ, stdX);
gp_Pln projPlane(projAx3); // OZX
gp_Ax3 projAx3; // OXYZ
gp_Pln projPlane(projAx3);
BaseGeomPtrVector bgList;
if (!edgeNames.empty()) {
BaseGeomPtrVector edgeGeomList;
if (!edgeNames.empty() && !edgeNames.front().empty()) {
//we have edge names and the first one isn't null
for (auto& n: edgeNames) {
if (!n.empty()) {
std::string geomType = DrawUtil::getGeomTypeFromName(n);
if (!n.empty() && (geomType == "Edge")) {
int i = DrawUtil::getIndexFromName(n);
BaseGeomPtr bg = dvp->getGeomByIndex(i);
if (bg) {
bgList.push_back(bg);
}
std::string geomType = DrawUtil::getGeomTypeFromName(n);
if (geomType == "Edge") {
int i = DrawUtil::getIndexFromName(n);
BaseGeomPtr bg = dvp->getGeomByIndex(i);
if (bg) {
edgeGeomList.push_back(bg);
}
}
}
} else {
edgeGeomList = dvp->getEdgeGeometry(); //do the whole View
}
BaseGeomPtrVector selEdges = bgList;
if (selEdges.empty()) {
selEdges = dvp->getEdgeGeometry(); //do the whole View
}
Bnd_Box edgeBbx;
edgeBbx.SetGap(1.0); //make the box a bit bigger
std::vector<TopoDS_Edge> inEdges;
for (auto& bg: selEdges) {
for (auto& bg: edgeGeomList) {
inEdges.push_back(bg->occEdge);
BRepBndLib::Add(bg->occEdge, edgeBbx);
}
@@ -242,6 +282,94 @@ gp_Pnt DrawDimHelper::findClosestPoint(std::vector<TopoDS_Edge> inEdges,
return nearPoint;
}
std::pair<Base::Vector3d, Base::Vector3d> DrawDimHelper::minMax3d(DrawViewPart* dvp,
ReferenceVector references,
int direction)
{
// Base::Console().Message("DDH::minMax3d() - references: %d\n", references.size());
std::pair<Base::Vector3d, Base::Vector3d> result;
Base::Vector3d refMin;
Base::Vector3d refMax;
gp_Ax3 projAx3; //OXYZ
gp_Pln projPlane(projAx3);
BRep_Builder builder;
TopoDS_Compound comp;
builder.MakeCompound(comp);
for (auto& ref : references) {
builder.Add(comp, ref.getGeometry());
}
Base::Vector3d centroid = dvp->getOriginalCentroid();
TopoDS_Shape centeredShape = //this result is a throw away. We will work with comp.
DrawViewPart::centerScaleRotate(dvp, comp, centroid);
//project the selected 3d shapes in the dvp's coord system
TechDraw::GeometryObjectPtr go(std::make_shared<TechDraw::GeometryObject>(std::string(), nullptr));
go->setIsoCount(0);
go->isPerspective(false);
go->usePolygonHLR(false);
go->projectShape(comp, dvp->getProjectionCS());
auto edges = go->getEdgeGeometry();
Bnd_Box shapeBbx;
shapeBbx.SetGap(1.0); //make the box a bit bigger
std::vector<TopoDS_Edge> inEdges;
for (auto& bg: edges) {
inEdges.push_back(bg->occEdge);
BRepBndLib::Add(bg->occEdge, shapeBbx);
}
//from here on this is the same as 2d method
double minX, minY, minZ, maxX, maxY, maxZ;
shapeBbx.Get(minX, minY, minZ, maxX, maxY, maxZ);
double xMid = (maxX + minX) / 2.0;
double yMid = (maxY + minY) / 2.0;
gp_Pnt rightMid(maxX, yMid, 0.0);
gp_Pnt leftMid(minX, yMid, 0.0);
gp_Pnt topMid(xMid, maxY, 0.0);
gp_Pnt bottomMid(xMid, minY, 0.0);
gp_Dir xDir(1.0, 0.0, 0.0);
gp_Dir yDir(0.0, 1.0, 0.0);
if (direction == HORIZONTAL) {
Handle(Geom_Line) lineLeft = new Geom_Line(leftMid, yDir);
BRepBuilderAPI_MakeEdge mkEdgeLeft(lineLeft);
TopoDS_Edge edgeLeft = mkEdgeLeft.Edge();
gp_Pnt leftPoint = findClosestPoint(inEdges,
edgeLeft);
Handle(Geom_Line) lineRight = new Geom_Line(rightMid, yDir);
BRepBuilderAPI_MakeEdge mkEdgeRight(lineRight);
TopoDS_Edge edgeRight = mkEdgeRight.Edge();
gp_Pnt rightPoint = findClosestPoint(inEdges,
edgeRight);
refMin = Base::Vector3d(leftPoint.X(), leftPoint.Y(), 0.0);
refMax = Base::Vector3d(rightPoint.X(), rightPoint.Y(), 0.0);
} else if (direction == VERTICAL) {
Handle(Geom_Line) lineBottom = new Geom_Line(bottomMid, xDir);
BRepBuilderAPI_MakeEdge mkEdgeBottom(lineBottom);
TopoDS_Edge edgeBottom = mkEdgeBottom.Edge();
gp_Pnt bottomPoint = findClosestPoint(inEdges,
edgeBottom);
Handle(Geom_Line) lineTop = new Geom_Line(topMid, xDir);
BRepBuilderAPI_MakeEdge mkEdgeTop(lineTop);
TopoDS_Edge edgeTop = mkEdgeTop.Edge();
gp_Pnt topPoint = findClosestPoint(inEdges,
edgeTop);
refMin = Base::Vector3d(bottomPoint.X(), bottomPoint.Y(), 0.0);
refMax = Base::Vector3d(topPoint.X(), topPoint.Y(), 0.0);
}
result.first = refMin;
result.second = refMax;
return result;
}
DrawViewDimension* DrawDimHelper::makeDistDim(DrawViewPart* dvp,
std::string dimType,
Base::Vector3d inMin, //is this scaled or unscaled??
@@ -309,7 +437,6 @@ DrawViewDimension* DrawDimHelper::makeDistDim(DrawViewPart* dvp,
Base::Interpreter().runStringArg("App.activeDocument().%s.addView(App.activeDocument().%s)",
pageName.c_str(), dimName.c_str());
dvp->requestPaint();
return dim;
}

View File

@@ -31,7 +31,7 @@
#include <Base/Vector3D.h>
#include <Mod/TechDraw/TechDrawGlobal.h>
#include <Mod/TechDraw/App/DimensionReferences.h>
namespace TechDraw
{
@@ -45,6 +45,10 @@ class TechDrawExport DrawDimHelper {
static void makeExtentDim(DrawViewPart* dvp,
std::vector<std::string> edgeNames,
int direction);
static void makeExtentDim3d(DrawViewPart* dvp,
ReferenceVector references,
int direction);
static gp_Pnt findClosestPoint(std::vector<TopoDS_Edge> inEdges,
TopoDS_Edge& boundary);
@@ -58,6 +62,9 @@ class TechDrawExport DrawDimHelper {
static std::pair<Base::Vector3d, Base::Vector3d> minMax(DrawViewPart* dvp,
std::vector<std::string> edgeNames,
int direction);
static std::pair<Base::Vector3d, Base::Vector3d> minMax3d(DrawViewPart* dvp,
ReferenceVector references,
int direction);
};
} //end namespace TechDraw

View File

@@ -46,6 +46,7 @@
#include <BRepLProp_SLProps.hxx>
#include <BRepTools.hxx>
#include <GCPnts_AbscissaPoint.hxx>
#include <GeomAPI_ExtremaCurveCurve.hxx>
#include <gp_Ax3.hxx>
#include <gp_Dir.hxx>
#include <gp_Elips.hxx>
@@ -345,6 +346,25 @@ std::pair<Base::Vector3d, Base::Vector3d> DrawUtil::boxIntersect2d(Base::Vector3
return result;
}
//find the apparent intersection of 2 3d curves. We are only interested in curves that are lines, so we will have either 0 or 1
//apparent intersection. The intersection is "apparent" because the curve's progenator is a trimmed curve (line segment)
bool DrawUtil::apparentIntersection(const Handle(Geom_Curve) curve1,
const Handle(Geom_Curve) curve2,
Base::Vector3d& result)
{
GeomAPI_ExtremaCurveCurve intersector(curve1, curve2);
if (intersector.NbExtrema() == 0 ||
intersector.LowerDistance() > EWTOLERANCE ) {
//no intersection
return false;
}
//for our purposes, only one intersection point is required.
gp_Pnt p1, p2;
intersector.Points(1, p1, p2);
result = toVector3d(p1);
return true;
}
Base::Vector3d DrawUtil::vertex2Vector(const TopoDS_Vertex& v)
{
gp_Pnt gp = BRep_Tool::Pnt(v);

View File

@@ -29,6 +29,7 @@
#include <QPointF>
#include <QString>
#include <Geom_Curve.hxx>
#include <gp_Ax2.hxx>
#include <gp_Dir.hxx>
#include <gp_Dir2d.hxx>
@@ -98,6 +99,12 @@ class TechDrawExport DrawUtil {
Base::Vector3d dir,
double xRange,
double yRange) ;
static bool apparentIntersection(const Handle(Geom_Curve) curve1,
const Handle(Geom_Curve) curve2,
Base::Vector3d& result);
static Base::Vector3d vertex2Vector(const TopoDS_Vertex& v);
static std::string formatVector(const Base::Vector3d& v);

View File

@@ -33,11 +33,9 @@
#include <Mod/TechDraw/App/DrawViewDimExtentPy.h> // generated from DrawViewDimExtentPy.xml
#include "DrawViewDimExtent.h"
#include "Cosmetic.h"
#include "DrawDimHelper.h"
#include "DrawViewPart.h"
using namespace TechDraw;
//===========================================================================
@@ -49,36 +47,19 @@ PROPERTY_SOURCE(TechDraw::DrawViewDimExtent, TechDraw::DrawViewDimension)
DrawViewDimExtent::DrawViewDimExtent(void)
{
App::PropertyLinkSubList Source; //DrawViewPart & SubElements(Edges)
//Cosmetic End points are stored in DVD::References2d
App::PropertyLinkSubList Source3d; //Part::Feature & SubElements TBI
App::PropertyLinkSubList Source3d; //Part::Feature(s) & SubElements
ADD_PROPERTY_TYPE(Source, (nullptr, nullptr), "", (App::PropertyType)(App::Prop_Output), "View (Edges) to dimension");
ADD_PROPERTY_TYPE(Source, (nullptr, nullptr), "", (App::PropertyType)(App::Prop_Output), "View containing the dimension");
Source.setScope(App::LinkScope::Global);
ADD_PROPERTY_TYPE(Source3d, (nullptr, nullptr), "", (App::PropertyType)(App::Prop_Output), "View (Edges) to dimension"); //TBI
//Source3d is a candidate for deprecation as References3D contains the same information
ADD_PROPERTY_TYPE(Source3d, (nullptr, nullptr), "", (App::PropertyType)(App::Prop_Output), "3d geometry to be dimensioned");
Source3d.setScope(App::LinkScope::Global);
ADD_PROPERTY_TYPE(DirExtent ,(0), "", App::Prop_Output, "Horizontal / Vertical");
//CosmeticTags is a candidate for deprecation
ADD_PROPERTY_TYPE(CosmeticTags ,(""), "", App::Prop_Output, "Id of cosmetic endpoints");
//hide the properties the user can't edit in the property editor
Source3d.setStatus(App::Property::Hidden, true); //TBI
}
void DrawViewDimExtent::onChanged(const App::Property* prop)
{
if (!isRestoring()) {
if (prop == &Source) {
// Base::Console().Message("DVDE::onChanged - Source: %X\n", Source.getValue());
//recalculate the points?
}
}
DrawViewDimension::onChanged(prop);
}
short DrawViewDimExtent::mustExecute() const
{
return DrawViewDimension::mustExecute();
}
App::DocumentObjectExecReturn *DrawViewDimExtent::execute(void)
@@ -87,137 +68,81 @@ App::DocumentObjectExecReturn *DrawViewDimExtent::execute(void)
if (!keepUpdated()) {
return App::DocumentObject::StdReturn;
}
App::DocumentObject* docObj = Source.getValue();
if (!docObj)
return App::DocumentObject::StdReturn;
DrawViewPart* dvp = dynamic_cast<DrawViewPart*>(docObj);
if (!dvp)
if (!dvp)
return App::DocumentObject::StdReturn;
double tolerance = 0.00001;
std::vector<std::string> edgeNames = getSubNames();
int direction = DirExtent.getValue();
ReferenceVector references = getEffectiveReferences();
std::pair<Base::Vector3d, Base::Vector3d> endPoints =
DrawDimHelper::minMax(dvp,
edgeNames,
direction);
Base::Vector3d refMin = endPoints.first;
Base::Vector3d refMax = endPoints.second;
resetLinear();
resetAngular();
resetArc();
std::vector<std::string> cTags = CosmeticTags.getValues();
if (cTags.size() <= 1) {
//not ready yet.
return DrawView::execute();
}
TechDraw::VertexPtr v0 = dvp->getProjVertexByCosTag(cTags[0]);
TechDraw::VertexPtr v1 = dvp->getProjVertexByCosTag(cTags[1]);
if (!v0 || !v1) {
//either not ready yet or something has gone wrong
return DrawView::execute();
}
double length00 = (v0->pnt - refMin).Length();
double length11 = (v1->pnt - refMax).Length();
double length01 = (v0->pnt - refMax).Length();
double length10 = (v1->pnt - refMin).Length();
if ((length00 >= tolerance || length11 >= tolerance) &&
(length01 >= tolerance || length10 >= tolerance)) { // Something has changed
//update GV
v0->pnt = refMin;
v1->pnt = refMax;
// v0->occVertex = ???
// v1->occVertex = ???
//update CV
double scale = dvp->getScale();
CosmeticVertex* cvTemp = dvp->getCosmeticVertex(cTags[0]);
cvTemp->permaPoint = refMin / scale;
cvTemp = dvp->getCosmeticVertex(cTags[1]);
cvTemp->permaPoint = refMax / scale;
if ( Type.isValue("Distance") ||
Type.isValue("DistanceX") ||
Type.isValue("DistanceY") ) {
setLinearPoints(getPointsExtent(references));
}
overrideKeepUpdated(false);
return DrawViewDimension::execute();
}
//getSubValues returns a garbage 1st entry if there are no subelements.
std::vector<std::string> DrawViewDimExtent::getSubNames(void)
{
std::vector<std::string> edgeNames = Source.getSubValues();
// Base::Console().Message("DVDE::getSubNames - edgeNames: %d\n", edgeNames.size());
if (edgeNames.empty() ||
edgeNames[0].empty()) {
return std::vector<std::string>(); //garbage first entry - nop
}
return edgeNames;
}
pointPair DrawViewDimExtent::getPointsTwoVerts()
{
// Base::Console().Message("DVDE::getPointsTwoVerts() - %s\n", getNameInDocument());
pointPair errorValue(
Base::Vector3d(0.0, 0.0, 0.0),
Base::Vector3d(0.0, 0.0, 0.0)
);
TechDraw::DrawViewPart* dvp = getViewPart();
if (!dvp) {
return errorValue;
}
std::vector<std::string> cTags = CosmeticTags.getValues();
if (cTags.size() < 2) {
// Base::Console().Message("DVDE::getPointsTwoVerts - not enough tags!\n");
return errorValue;
}
TechDraw::VertexPtr v0 = dvp->getProjVertexByCosTag(cTags[0]);
TechDraw::VertexPtr v1 = dvp->getProjVertexByCosTag(cTags[1]);
if (!v0 || !v1)
return errorValue;
return pointPair(v0->pnt, v1->pnt);
return DrawView::execute();
}
//! validate 2D references - only checks if the target exists
bool DrawViewDimExtent::checkReferences2D() const
{
// Base::Console().Message("DVDE::checkReFerences2d() - %s\n", getNameInDocument());
TechDraw::DrawViewPart* dvp = getViewPart();
if (!dvp) {
// Base::Console().Message("DVDE::checkReferences2d() - %s\n", getNameInDocument());
const std::vector<App::DocumentObject*> &objects = References2D.getValues();
if (objects.empty()) {
return false;
}
std::vector<std::string> cTags = CosmeticTags.getValues();
if (cTags.size() < 2) {
//still building this dimension, so treat as valid?
const std::vector<std::string> &subElements = References2D.getSubValues();
//extent dims are the only dims allowed to have no subElements
if (subElements.empty() || subElements.front().empty()) {
return true;
}
CosmeticVertex* cv0 = dvp->getCosmeticVertex(cTags[0]);
CosmeticVertex* cv1 = dvp->getCosmeticVertex(cTags[1]);
if (!cv0 || !cv1)
return false;
return true;
//if we have an object and a non-empty subelement list, then extent dims are the same as other dims
return DrawViewDimension::checkReferences2D();
}
void DrawViewDimExtent::unsetupObject()
pointPair DrawViewDimExtent::getPointsExtent(ReferenceVector references)
{
// bool isRemoving = testStatus(App::ObjectStatus::Remove);
// Base::Console().Message("DVDE::unsetupObject - isRemove: %d status: %X\n",
// isRemoving, getStatus());
TechDraw::DrawViewPart* dvp = getViewPart();
// Base::Console().Message("DVD::getPointsExtent() - %s\n", getNameInDocument());
App::DocumentObject* refObject = references.front().getObject();
int direction = DirExtent.getValue();
if (refObject->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) {
auto dvp = static_cast<TechDraw::DrawViewPart*>(refObject);
std::vector<std::string> cTags = CosmeticTags.getValues();
dvp->removeCosmeticVertex(cTags);
DrawViewDimension::unsetupObject();
std::vector<std::string> edgeNames; //empty list means we are using all the edges
if (!references.at(0).getSubName().empty()) {
//this is the usual case of selected edges in a dvp
for (auto& ref : references) {
if (ref.getSubName().empty()) {
continue;
}
std::string geomType = DrawUtil::getGeomTypeFromName(ref.getSubName());
if (geomType == "Edge") {
edgeNames.push_back(ref.getSubName());
}
}
}
std::pair<Base::Vector3d, Base::Vector3d> endPoints =
DrawDimHelper::minMax(dvp,
edgeNames,
direction);
return pointPair(endPoints.first, endPoints.second);
}
//dvp probably needs recomp/repaint here.
dvp->enforceRecompute();
//this is a 3d reference
std::pair<Base::Vector3d, Base::Vector3d> endPoints =
DrawDimHelper::minMax3d(getViewPart(),
references,
direction);
return pointPair(endPoints.first, endPoints.second);
}
PyObject *DrawViewDimExtent::getPyObject(void)

View File

@@ -47,23 +47,17 @@ public:
//Cosmetic End points are stored in DVD::References2d
App::PropertyLinkSubList Source3d; //Part::Feature & SubElements TBI
App::PropertyInteger DirExtent; //Horizontal, Vertical, TBD
App::PropertyStringList CosmeticTags; //id of cosmetic end points.
App::PropertyStringList CosmeticTags; //id of cosmetic end points. obsolete!
App::DocumentObjectExecReturn *execute() override;
short mustExecute() const override;
void unsetupObject() override;
bool checkReferences2D() const override;
int getRefType() const override { return twoVertex; }
pointPair getLinearPoints() override { return getPointsTwoVerts(); }
int getRefType() const override { return extent; }
//return PyObject as DrawViewDimExtentPy
PyObject *getPyObject() override;
protected:
void onChanged(const App::Property* prop) override;
std::vector<std::string> getSubNames();
pointPair getPointsTwoVerts() override;
virtual pointPair getPointsExtent(ReferenceVector references);
bool checkReferences2D() const override;
private:
};

File diff suppressed because it is too large Load Diff

View File

@@ -25,13 +25,22 @@
#include <tuple>
#include <gp_Ax3.hxx>
#include <App/DocumentObject.h>
#include <Base/Console.h>
#include <Base/UnitsApi.h>
#include <Mod/TechDraw/TechDrawGlobal.h>
#include "DrawViewPart.h"
#include "DimensionGeometry.h"
#include "DimensionReferences.h"
#include "Geometry.h"
#include "DrawView.h"
#include "DrawUtil.h"
using DU = TechDraw::DrawUtil;
class TopoDS_Shape;
namespace Measure {
@@ -40,94 +49,26 @@ class Measurement;
namespace TechDraw
{
class DrawViewPart;
struct DimRef {
DrawViewPart* part;
std::string sub;
};
using pointPair = std::pair<Base::Vector3d,Base::Vector3d>;
struct anglePoints
{
pointPair ends;
Base::Vector3d vertex;
anglePoints()
{
ends.first = Base::Vector3d(0.0, 0.0, 0.0);
ends.second = Base::Vector3d(0.0, 0.0, 0.0);
vertex = Base::Vector3d(0.0, 0.0, 0.0);
}
anglePoints(const anglePoints& ap)
: ends(ap.ends)
, vertex(ap.vertex)
{
}
anglePoints& operator= (const anglePoints& ap)
{
ends = ap.ends;
vertex = ap.vertex;
return *this;
}
};
struct arcPoints
{
bool isArc;
double radius;
Base::Vector3d center;
pointPair onCurve;
pointPair arcEnds;
Base::Vector3d midArc;
bool arcCW;
arcPoints()
{
isArc = false;
radius = 0.0;
center = Base::Vector3d(0.0, 0.0, 0.0);
onCurve.first = Base::Vector3d(0.0, 0.0, 0.0);
onCurve.second = Base::Vector3d(0.0, 0.0, 0.0);
arcEnds.first = Base::Vector3d(0.0, 0.0, 0.0);
arcEnds.second = Base::Vector3d(0.0, 0.0, 0.0);
midArc = Base::Vector3d(0.0, 0.0, 0.0);
arcCW = false;
}
arcPoints(const arcPoints& ap)
: isArc(ap.isArc)
, radius(ap.radius)
, center(ap.center)
, onCurve(ap.onCurve)
, arcEnds(ap.arcEnds)
, midArc(ap.midArc)
, arcCW(ap.arcCW)
{
}
arcPoints& operator= (const arcPoints& ap)
{
isArc = ap.isArc;
radius = ap.radius;
center = ap.center;
onCurve = ap.onCurve;
arcEnds = ap.arcEnds;
midArc = ap.midArc;
arcCW = ap.arcCW;
return *this;
}
};
class DimensionFormatter;
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
};
/// Constructor
DrawViewDimension();
~DrawViewDimension() override;
@@ -158,7 +99,8 @@ public:
twoEdge,
twoVertex,
vertexEdge,
threeVertex
threeVertex,
extent
};
@@ -194,35 +136,49 @@ public:
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);
void setAll3DMeasurement();
void clear3DMeasurements();
virtual bool checkReferences2D() const;
virtual pointPair getLinearPoints() {return m_linearPoints; }
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;
std::string getBaseLengthUnit(Base::UnitSystem system);
pointPair getArrowPositions();
void saveArrowPositions(const Base::Vector2d positions[]);
bool showUnits() const;
bool useDecimals() const;
bool isExtentDim() const;
virtual ReferenceVector getEffectiveReferences() const;
protected:
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;
std::string getPrefix() const;
std::string getPrefixForDimType() const;
std::string getDefaultFormatSpec(bool isToleranceFormat = false) const;
virtual pointPair getPointsOneEdge();
virtual pointPair getPointsTwoEdges();
virtual pointPair getPointsTwoVerts();
virtual pointPair getPointsEdgeVert();
virtual pointPair getPointsOneEdge(ReferenceVector references);
virtual pointPair getPointsTwoEdges(ReferenceVector references);
virtual pointPair getPointsTwoVerts(ReferenceVector references);
virtual pointPair getPointsEdgeVert(ReferenceVector references);
virtual arcPoints getArcParameters(ReferenceVector references);
virtual arcPoints arcPointsFromBaseGeom(TechDraw::BaseGeomPtr base);
virtual arcPoints arcPointsFromEdge(TopoDS_Edge occEdge);
virtual anglePoints getAnglePointsTwoEdges(ReferenceVector references);
virtual anglePoints getAnglePointsThreeVerts(ReferenceVector references);
protected:
Measure::Measurement *measurement;
@@ -232,8 +188,6 @@ protected:
Base::Vector3d e2) const;
pointPair closestPoints(TopoDS_Shape s1,
TopoDS_Shape s2) const;
pointPair m_linearPoints;
pointPair m_arrowPositions;
void resetLinear();
void resetAngular();
@@ -244,10 +198,14 @@ private:
static const char* MeasureTypeEnums[];
void dumpRefs2D(const char* text) const;
//Dimension "geometry"
/* pointPair m_linearPoints;*/
pointPair m_linearPoints;
pointPair m_arrowPositions;
arcPoints m_arcPoints;
anglePoints m_anglePoints;
bool m_hasGeometry;
friend class DimensionFormatter;
DimensionFormatter* m_formatter;
};
} //namespace TechDraw

View File

@@ -73,8 +73,8 @@ PyObject* DrawViewDimensionPy::getLinearPoints(PyObject* args)
DrawViewDimension* dvd = getDrawViewDimensionPtr();
pointPair pts = dvd->getLinearPoints();
Py::List ret;
ret.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(pts.first))));
ret.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(pts.second))));
ret.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(pts.first()))));
ret.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(pts.second()))));
return Py::new_reference_to(ret);
}
@@ -88,10 +88,10 @@ PyObject* DrawViewDimensionPy::getArcPoints(PyObject* args)
arcPoints pts = dvd->getArcPoints();
Py::List ret;
ret.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(pts.center))));
ret.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(pts.onCurve.first))));
ret.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(pts.onCurve.second))));
ret.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(pts.arcEnds.first))));
ret.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(pts.arcEnds.second))));
ret.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(pts.onCurve.first()))));
ret.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(pts.onCurve.second()))));
ret.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(pts.arcEnds.first()))));
ret.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(pts.arcEnds.second()))));
ret.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(pts.midArc))));
return Py::new_reference_to(ret);
}
@@ -105,9 +105,9 @@ PyObject* DrawViewDimensionPy::getAnglePoints(PyObject* args)
DrawViewDimension* dvd = getDrawViewDimensionPtr();
anglePoints pts = dvd->getAnglePoints();
Py::List ret;
ret.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(pts.ends.first))));
ret.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(pts.ends.second))));
ret.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(pts.vertex))));
ret.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(pts.first()))));
ret.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(pts.second()))));
ret.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(pts.vertex()))));
return Py::new_reference_to(ret);
}
@@ -120,8 +120,8 @@ PyObject* DrawViewDimensionPy::getArrowPositions(PyObject* args)
DrawViewDimension* dvd = getDrawViewDimensionPtr();
pointPair pts = dvd->getArrowPositions();
Py::List ret;
ret.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(pts.first))));
ret.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(pts.second))));
ret.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(pts.first()))));
ret.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(pts.second()))));
return Py::new_reference_to(ret);
}
PyObject *DrawViewDimensionPy::getCustomAttributes(const char* /*attr*/) const

View File

@@ -264,7 +264,6 @@ App::DocumentObjectExecReturn* DrawViewPart::execute(void)
XDirection.purgeTouched();//don't trigger updates!
}
m_saveShape = shape;
partExec(shape);
return DrawView::execute();
@@ -319,28 +318,38 @@ void DrawViewPart::partExec(TopoDS_Shape& shape)
//prepare the shape for HLR processing by centering, scaling and rotating it
GeometryObjectPtr DrawViewPart::makeGeometryForShape(TopoDS_Shape& shape)
{
// Base::Console().Message("DVP::makeGeometryForShape() - %s\n", getNameInDocument());
gp_Pnt inputCenter;
Base::Vector3d stdOrg(0.0, 0.0, 0.0);
gp_Ax2 viewAxis = getProjectionCS(stdOrg);
inputCenter = TechDraw::findCentroid(shape, viewAxis);
Base::Vector3d centroid(inputCenter.X(), inputCenter.Y(), inputCenter.Z());
//center shape on origin
TopoDS_Shape centeredShape = TechDraw::moveShape(shape, centroid * -1.0);
m_saveCentroid = centroid;
m_saveShape = centeredShape;
TopoDS_Shape scaledShape = TechDraw::scaleShape(centeredShape, getScale());
if (!DrawUtil::fpCompare(Rotation.getValue(), 0.0)) {
scaledShape = TechDraw::rotateShape(scaledShape, viewAxis,
Rotation.getValue());//conventional rotation
}
GeometryObjectPtr go = buildGeometryObject(scaledShape, viewAxis);
// Base::Console().Message("DVP::makeGeometryForShape() - %s\n", getNameInDocument());
gp_Pnt inputCenter = TechDraw::findCentroid(shape,
getProjectionCS());
m_saveCentroid = DU::toVector3d(inputCenter);
m_saveShape = centerScaleRotate(this, shape, m_saveCentroid);
GeometryObjectPtr go = buildGeometryObject(shape, getProjectionCS());
return go;
}
//Modify a shape by centering, scaling and rotating and return the centered (but not rotated) shape
TopoDS_Shape DrawViewPart::centerScaleRotate(DrawViewPart* dvp,
TopoDS_Shape& inOutShape,
Base::Vector3d centroid)
{
// Base::Console().Message("DVP::centerScaleRotate() - %s\n", dvp->getNameInDocument());
gp_Ax2 viewAxis = dvp->getProjectionCS();
//center shape on origin
TopoDS_Shape centeredShape = TechDraw::moveShape(inOutShape,
centroid * -1.0);
inOutShape = TechDraw::scaleShape(centeredShape, dvp->getScale());
if (!DrawUtil::fpCompare(dvp->Rotation.getValue(), 0.0)) {
inOutShape = TechDraw::rotateShape(inOutShape,
viewAxis,
dvp->Rotation.getValue()); //conventional rotation
}
// BRepTools::Write(inOutShape, "DVPScaled.brep"); //debug
return centeredShape;
}
//create a geometry object and trigger the HLR process in another thread
TechDraw::GeometryObjectPtr DrawViewPart::buildGeometryObject(TopoDS_Shape& shape,
const gp_Ax2& viewAxis)
@@ -770,6 +779,53 @@ const std::vector<TechDraw::VertexPtr> DrawViewPart::getVertexGeometry() const
return result;
}
TechDraw::VertexPtr DrawViewPart::getVertex(std::string vertexName) const
{
const std::vector<TechDraw::VertexPtr> allVertex(DrawViewPart::getVertexGeometry());
size_t iTarget = DrawUtil::getIndexFromName(vertexName);
if (allVertex.empty()) {
//should not happen
throw Base::IndexError("DVP::getVertex - No vertices found.");
}
if (iTarget > allVertex.size()) {
//should not happen
throw Base::IndexError("DVP::getVertex - Vertex not found.");
}
return allVertex.at(iTarget);
}
//! returns existing BaseGeom of 2D Edge
TechDraw::BaseGeomPtr DrawViewPart::getEdge(std::string edgeName) const
{
const std::vector<TechDraw::BaseGeomPtr> &geoms = getEdgeGeometry();
if (geoms.empty()) {
//should not happen
throw Base::IndexError("DVP::getEdge - No edges found.");
}
size_t iEdge = DrawUtil::getIndexFromName(edgeName);
if ((unsigned)iEdge >= geoms.size()) {
throw Base::IndexError("DVP::getEdge - Edge not found.");
}
return geoms.at(iEdge);
}
//! returns existing 2d Face
TechDraw::FacePtr DrawViewPart::getFace(std::string faceName) const
{
const std::vector<TechDraw::FacePtr> &faces = getFaceGeometry();
if (faces.empty()) {
//should not happen
throw Base::IndexError("DVP::getFace - No faces found.");
}
size_t iFace = DrawUtil::getIndexFromName(faceName);
if (iFace >= faces.size()) {
throw Base::IndexError("DVP::getFace - Face not found.");
}
return faces.at(iFace);
}
const std::vector<TechDraw::FacePtr> DrawViewPart::getFaceGeometry() const
{
std::vector<TechDraw::FacePtr> result;

View File

@@ -114,6 +114,9 @@ public:
const char* getViewProviderName() const override { return "TechDrawGui::ViewProviderViewPart"; }
PyObject* getPyObject() override;
static TopoDS_Shape centerScaleRotate(DrawViewPart* dvp,
TopoDS_Shape& inOutShape,
Base::Vector3d centroid);
std::vector<TechDraw::DrawHatch*> getHatches() const;
std::vector<TechDraw::DrawGeomHatch*> getGeomHatches() const;
std::vector<TechDraw::DrawViewDimension*> getDimensions() const;
@@ -127,10 +130,13 @@ public:
bool hasGeometry() const;
TechDraw::GeometryObjectPtr getGeometryObject() const { return geometryObject; }
TechDraw::BaseGeomPtr
getGeomByIndex(int idx) const;//get existing geom for edge idx in projection
TechDraw::VertexPtr
getProjVertexByIndex(int idx) const;//get existing geom for vertex idx in projection
TechDraw::VertexPtr getVertex(std::string vertexName) const;
TechDraw::BaseGeomPtr getEdge(std::string edgeName) const;
TechDraw::FacePtr getFace(std::string faceName) const;
TechDraw::BaseGeomPtr getGeomByIndex(int idx) const; //get existing geom for edge idx in projection
TechDraw::VertexPtr getProjVertexByIndex(int idx) const; //get existing geom for vertex idx in projection
TechDraw::VertexPtr getProjVertexByCosTag(std::string cosTag);
std::vector<TechDraw::BaseGeomPtr>
getFaceEdgesByIndex(int idx) const;//get edges for face idx in projection

View File

@@ -1271,198 +1271,15 @@ bool BSpline::isLine()
//used by DVDim for approximate dims
bool BSpline::isCircle()
{
bool result = false;
double radius;
Base::Vector3d center;
bool isArc = false;
getCircleParms(result, radius, center, isArc);
return result;
}
//used by DVDim for approximate dims
void BSpline::getCircleParms(bool& isCircle, double& radius, Base::Vector3d& center, bool& isArc)
{
double curveLimit = 0.0001;
BRepAdaptor_Curve c(occEdge);
Handle(Geom_BSplineCurve) spline = c.BSpline();
double f, l;
f = c.FirstParameter();
l = c.LastParameter();
double parmRange = fabs(l - f);
int testCount = 6;
double parmStep = parmRange/testCount;
std::vector<double> curvatures;
std::vector<gp_Pnt> centers;
gp_Pnt curveCenter;
double sumCurvature = 0;
Base::Vector3d sumCenter, valueAt;
try {
GeomLProp_CLProps prop(spline, f, 3, Precision::Confusion());
curvatures.push_back(prop.Curvature());
sumCurvature += prop.Curvature();
prop.CentreOfCurvature(curveCenter);
centers.push_back(curveCenter);
sumCenter += Base::Vector3d(curveCenter.X(), curveCenter.Y(), curveCenter.Z());
for (int i = 1; i < (testCount - 1); i++) {
prop.SetParameter(parmStep * i);
curvatures.push_back(prop.Curvature());
sumCurvature += prop.Curvature();
prop.CentreOfCurvature(curveCenter);
centers.push_back(curveCenter);
sumCenter += Base::Vector3d(curveCenter.X(), curveCenter.Y(), curveCenter.Z());
}
prop.SetParameter(l);
curvatures.push_back(prop.Curvature());
sumCurvature += prop.Curvature();
prop.CentreOfCurvature(curveCenter);
centers.push_back(curveCenter);
sumCenter += Base::Vector3d(curveCenter.X(), curveCenter.Y(), curveCenter.Z());
}
catch (Standard_Failure&) {
Base::Console().Log("TechDraw - GEO::BSpline::getCircleParms - CLProps failed\n");
isCircle = false;
return;
}
Base::Vector3d avgCenter = sumCenter/testCount;
double errorCenter = 0;
for (auto& c: centers) {
errorCenter += (avgCenter - Base::Vector3d(c.X(), c.Y(), c.Z())).Length();
}
errorCenter = errorCenter/testCount;
double avgCurve = sumCurvature/testCount;
double errorCurve = 0;
for (auto& cv: curvatures) {
errorCurve += fabs(avgCurve - cv); //fabs???
}
errorCurve = errorCurve/testCount;
isArc = !c.IsClosed();
isCircle = false;
if ( errorCurve < curveLimit ) {
isCircle = true;
radius = 1.0/avgCurve;
center = avgCenter;
}
return GeometryUtils::isCircle(occEdge);
}
// make a circular edge from BSpline
TopoDS_Edge BSpline::asCircle(bool& arc)
{
TopoDS_Edge result;
BRepAdaptor_Curve c(occEdge);
// find the two ends
Handle(Geom_Curve) curve = c.Curve().Curve();
double f = c.FirstParameter();
double l = c.LastParameter();
gp_Pnt s = c.Value(f);
gp_Pnt e = c.Value(l);
if (s.IsEqual(e, 0.001)) { //more reliable
arc = false;
} else {
arc = true;
}
// arc = !c.IsClosed(); //reliable?
Handle(Geom_BSplineCurve) spline = c.BSpline();
if (spline->NbPoles() < 5) { //need 5 poles (s-p1-pm-p2-e) for algo
return result; //how to do with fewer poles?
}
try {
// get three points on curve (non extreme poles)
int nb_poles = spline->NbPoles();
gp_Pnt p1 = spline->Pole(2); //OCC numbering starts at 1!!
gp_Pnt p2 = spline->Pole(nb_poles-1);
gp_Pnt pm;
if (nb_poles == 5) {
pm = spline->Pole(3); //5 poles => 2.5 => 2
} else {
pm = spline->Pole(nb_poles / 2);
}
// project three poles onto the curve
GeomAPI_ProjectPointOnCurve proj1;
GeomAPI_ProjectPointOnCurve proj2;
GeomAPI_ProjectPointOnCurve projm;
proj1.Init(p1, curve, f, l);
proj1.Perform(p1);
proj2.Init(p2, curve, f, l);
proj2.Perform(p2);
projm.Init(pm, curve, f, l);
projm.Perform(pm);
if ( (proj1.NbPoints() == 0) ||
(proj2.NbPoints() == 0) ||
(projm.NbPoints() == 0) ) {
return result;
}
gp_Pnt pc1, pc2, pcm;
// get projected points
pc1 = proj1.NearestPoint();
pc2 = proj2.NearestPoint();
pcm = projm.NearestPoint();
// make 2 circles and find their radii
gce_MakeCirc gce_circ1 = gce_MakeCirc(s, pc1, pcm); //3 point circle
if (gce_circ1.Status() != gce_Done) {
return result;
}
gp_Circ circle1 = gce_circ1.Value();
double radius1 = circle1.Radius();
gp_Pnt center1 = circle1.Location();
Base::Vector3d vc1 = DrawUtil::toVector3d(center1);
gce_MakeCirc gce_circ2 = gce_MakeCirc(pcm, pc2, e);
if (gce_circ2.Status() != gce_Done) {
return result;
}
gp_Circ circle2 = gce_circ2.Value();
double radius2 = circle2.Radius();
gp_Pnt center2 = circle2.Location();
Base::Vector3d vc2 = DrawUtil::toVector3d(center2);
// compare radii & centers
double allowError = 0.001; //mm^-3 good enough for printing
double radius;
Base::Vector3d center;
if ( (DrawUtil::fpCompare(radius2, radius1, allowError)) &&
(vc1.IsEqual(vc2, allowError)) ) {
if (arc) {
GC_MakeArcOfCircle makeArc(s, pcm, e);
Handle(Geom_TrimmedCurve) tCurve = makeArc.Value();
BRepBuilderAPI_MakeEdge newEdge(tCurve);
result = newEdge;
} else {
radius = (radius1 + radius2) / 2.0;
center = (vc1 + vc2) / 2.0;
gp_Pnt gCenter(center.x, center.y, center.z);
gp_Ax2 stdZ(gCenter, gp_Dir(0, 0, 1));
gp_Circ newCirc(stdZ, radius);
BRepBuilderAPI_MakeEdge newEdge(newCirc);
result = newEdge;
}
}
}
catch (const Standard_Failure& e) {
Base::Console().Log("Geom::asCircle - OCC error - %s - while approx spline as circle\n",
e.GetMessageString());
TopoDS_Edge nullReturn;
result = nullReturn;
}
catch (...) {
Base::Console().Log("Geom::asCircle - unknown error occurred while approx spline as circle\n");
TopoDS_Edge nullReturn;
result = nullReturn;
}
return result;
return GeometryUtils::asCircle(occEdge, arc);
}
bool BSpline::intersectsArc(Base::Vector3d p1, Base::Vector3d p2)
{
gp_Pnt pnt1(p1.x, p1.y,p1.z);
@@ -1771,4 +1588,186 @@ TopoDS_Edge GeometryUtils::edgeFromCircleArc(TechDraw::AOCPtr c)
return aMakeEdge.Edge();
}
//used by DVDim for approximate dims
bool GeometryUtils::isCircle(TopoDS_Edge occEdge)
{
double radius;
Base::Vector3d center;
bool isArc = false;
return GeometryUtils::getCircleParms(occEdge, radius, center, isArc);
}
//tries to interpret a BSpline edge as a circle. Used by DVDim for approximate dimensions.
bool GeometryUtils::getCircleParms(TopoDS_Edge occEdge, double& radius, Base::Vector3d& center, bool& isArc)
{
double curveLimit = EWTOLERANCE;
BRepAdaptor_Curve c(occEdge);
Handle(Geom_BSplineCurve) spline = c.BSpline();
double f, l;
f = c.FirstParameter();
l = c.LastParameter();
double parmRange = fabs(l - f);
int testCount = 6;
double parmStep = parmRange/testCount;
std::vector<double> curvatures;
std::vector<gp_Pnt> centers;
gp_Pnt curveCenter;
double sumCurvature = 0;
Base::Vector3d sumCenter, valueAt;
try {
GeomLProp_CLProps prop(spline, f, 3, Precision::Confusion());
curvatures.push_back(prop.Curvature());
sumCurvature += prop.Curvature();
prop.CentreOfCurvature(curveCenter);
centers.push_back(curveCenter);
sumCenter += DrawUtil::toVector3d(curveCenter);
for (int i = 1; i < (testCount - 1); i++) {
prop.SetParameter(parmStep * i);
curvatures.push_back(prop.Curvature());
sumCurvature += prop.Curvature();
prop.CentreOfCurvature(curveCenter);
centers.push_back(curveCenter);
sumCenter += DrawUtil::toVector3d(curveCenter);
}
prop.SetParameter(l);
curvatures.push_back(prop.Curvature());
sumCurvature += prop.Curvature();
prop.CentreOfCurvature(curveCenter);
centers.push_back(curveCenter);
sumCenter += DrawUtil::toVector3d(curveCenter);
}
catch (Standard_Failure&) {
Base::Console().Error("OCC error. Could not interpret BSpline as Circle\n");
return false;
}
Base::Vector3d avgCenter = sumCenter/testCount;
double avgCurve = sumCurvature/testCount;
double errorCurve = 0;
for (auto& cv: curvatures) {
errorCurve += fabs(avgCurve - cv); //fabs???
}
errorCurve = errorCurve/testCount;
isArc = !c.IsClosed();
bool isCircle(false);
if ( errorCurve < curveLimit ) {
isCircle = true;
radius = 1.0/avgCurve;
center = avgCenter;
}
return isCircle;
}
// make a circle or arc of circle Edge from BSpline Edge
TopoDS_Edge GeometryUtils::asCircle(TopoDS_Edge occEdge, bool& arc)
{
TopoDS_Edge result;
BRepAdaptor_Curve c(occEdge);
// find the two ends
Handle(Geom_Curve) curve = c.Curve().Curve();
double f = c.FirstParameter();
double l = c.LastParameter();
gp_Pnt s = c.Value(f);
gp_Pnt e = c.Value(l);
if (s.IsEqual(e, 0.001)) { //more reliable
arc = false;
} else {
arc = true;
}
// arc = !c.IsClosed(); //reliable?
Handle(Geom_BSplineCurve) spline = c.BSpline();
if (spline->NbPoles() < 5) { //need 5 poles (s-p1-pm-p2-e) for algo
return result; //how to do with fewer poles?
}
try {
// get three points on curve (non extreme poles)
int nb_poles = spline->NbPoles();
gp_Pnt p1 = spline->Pole(2); //OCC numbering starts at 1!!
gp_Pnt p2 = spline->Pole(nb_poles-1);
gp_Pnt pm;
if (nb_poles == 5) {
pm = spline->Pole(3); //5 poles => 2.5 => 2
} else {
pm = spline->Pole(nb_poles / 2);
}
// project three poles onto the curve
GeomAPI_ProjectPointOnCurve proj1;
GeomAPI_ProjectPointOnCurve proj2;
GeomAPI_ProjectPointOnCurve projm;
proj1.Init(p1, curve, f, l);
proj1.Perform(p1);
proj2.Init(p2, curve, f, l);
proj2.Perform(p2);
projm.Init(pm, curve, f, l);
projm.Perform(pm);
if ( (proj1.NbPoints() == 0) ||
(proj2.NbPoints() == 0) ||
(projm.NbPoints() == 0) ) {
return result;
}
gp_Pnt pc1, pc2, pcm;
// get projected points
pc1 = proj1.NearestPoint();
pc2 = proj2.NearestPoint();
pcm = projm.NearestPoint();
// make 2 circles and find their radii
gce_MakeCirc gce_circ1 = gce_MakeCirc(s, pc1, pcm); //3 point circle
if (gce_circ1.Status() != gce_Done) {
return result;
}
gp_Circ circle1 = gce_circ1.Value();
double radius1 = circle1.Radius();
gp_Pnt center1 = circle1.Location();
Base::Vector3d vc1 = DrawUtil::toVector3d(center1);
gce_MakeCirc gce_circ2 = gce_MakeCirc(pcm, pc2, e);
if (gce_circ2.Status() != gce_Done) {
return result;
}
gp_Circ circle2 = gce_circ2.Value();
double radius2 = circle2.Radius();
gp_Pnt center2 = circle2.Location();
Base::Vector3d vc2 = DrawUtil::toVector3d(center2);
// compare radii & centers
double allowError = 0.001; //mm^-3 good enough for printing
double radius;
Base::Vector3d center;
if ( (DrawUtil::fpCompare(radius2, radius1, allowError)) &&
(vc1.IsEqual(vc2, allowError)) ) {
if (arc) {
GC_MakeArcOfCircle makeArc(s, pcm, e);
Handle(Geom_TrimmedCurve) tCurve = makeArc.Value();
BRepBuilderAPI_MakeEdge mkEdge(tCurve);
result = mkEdge.Edge();
} else {
radius = (radius1 + radius2) / 2.0;
center = (vc1 + vc2) / 2.0;
gp_Pnt gCenter(center.x, center.y, center.z);
gp_Ax2 stdZ(gCenter, gp_Dir(0, 0, 1));
gp_Circ newCirc(stdZ, radius);
BRepBuilderAPI_MakeEdge mkEdge(newCirc);
result = mkEdge.Edge();
}
}
}
catch (const Standard_Failure& e) {
Base::Console().Error("asCircle - OCC error - %s - while approx spline as circle\n",
e.GetMessageString());
throw Base::RuntimeError("Failed to make circle from bspline");
}
catch (...) {
Base::Console().Error("asCircle - unknown error occurred while approx spline as circle\n");
}
return result;
}

View File

@@ -274,7 +274,7 @@ class TechDrawExport BSpline: public BaseGeom
bool isLine();
bool isCircle();
TopoDS_Edge asCircle(bool& isArc);
void getCircleParms(bool& isCircle, double& radius, Base::Vector3d& center, bool& isArc);
// void getCircleParms(bool& isCircle, double& radius, Base::Vector3d& center, bool& isArc);
bool intersectsArc(Base::Vector3d p1, Base::Vector3d p2);
std::vector<BezierSegment> segments;
};
@@ -390,6 +390,10 @@ class TechDrawExport GeometryUtils
static TopoDS_Edge edgeFromGeneric(TechDraw::GenericPtr g);
static TopoDS_Edge edgeFromCircle(TechDraw::CirclePtr c);
static TopoDS_Edge edgeFromCircleArc(TechDraw::AOCPtr c);
static bool isCircle(TopoDS_Edge occEdge);
static bool getCircleParms(TopoDS_Edge occEdge, double& radius, Base::Vector3d& center, bool& isArc);
static TopoDS_Edge asCircle(TopoDS_Edge occEdge, bool& arc);
};
} //end namespace TechDraw

View File

@@ -143,6 +143,7 @@ void GeometryObject::clear()
void GeometryObject::projectShape(const TopoDS_Shape& inShape, const gp_Ax2& viewAxis)
{
// Base::Console().Message("GO::projectShape()\n");
clear();
Handle(HLRBRep_Algo) brep_hlr;
@@ -251,9 +252,11 @@ void GeometryObject::projectShape(const TopoDS_Shape& inShape, const gp_Ax2& vie
//convert the hlr output into TD Geometry
void GeometryObject::makeTDGeometry()
{
extractGeometry(TechDraw::ecHARD,//always show the hard&outline visible lines
true);
extractGeometry(TechDraw::ecOUTLINE, true);
// Base::Console().Message("GO::makeTDGeometry()\n");
extractGeometry(TechDraw::ecHARD, //always show the hard&outline visible lines
true);
extractGeometry(TechDraw::ecOUTLINE,
true);
const DrawViewPart* dvp = static_cast<const DrawViewPart*>(m_parent);
if (!dvp) {

View File

@@ -87,7 +87,7 @@ short LandmarkDimension::mustExecute() const
App::DocumentObjectExecReturn *LandmarkDimension::execute()
{
// Base::Console().Message("LD::execute() - %s\n", getNameInDocument());
Base::Console().Message("LD::execute() - %s\n", getNameInDocument());
if (!keepUpdated()) {
return App::DocumentObject::StdReturn;
}
@@ -99,6 +99,7 @@ App::DocumentObjectExecReturn *LandmarkDimension::execute()
References2D.setValue(dvp);
std::vector<DocumentObject*> features = References3D.getValues();
Base::Console().Message("LD::execute - features: %d\n", features.size());
//if distance, required size = 2
//if angle, required size = 3; //not implemented yet
unsigned int requiredSize = 2;
@@ -129,17 +130,16 @@ App::DocumentObjectExecReturn *LandmarkDimension::execute()
index++;
}
}
m_linearPoints.first = points.front();
m_linearPoints.second = points.back();
//m_anglePoints.first = //not implemented yet
Base::Console().Message("LD::execute - front: %s back: %s\n",
DrawUtil::formatVector(points.front()).c_str(),
DrawUtil::formatVector(points.back()).c_str());
setLinearPoints(points.front(), points.back());
App::DocumentObjectExecReturn* dvdResult = DrawViewDimension::execute();
// dvp->resetReferenceVerts();
dvp->addReferencesToGeom();
dvp->requestPaint();
dvp->requestPaint();
overrideKeepUpdated(false);
return dvdResult;
}
@@ -159,51 +159,6 @@ Base::Vector3d LandmarkDimension::projectPoint(const Base::Vector3d& pt, DrawVie
return result;
}
std::vector<Base::Vector3d> LandmarkDimension::get2DPoints() const
{
// Base::Console().Message("LD::get2DPoints()\n");
std::vector<Base::Vector3d> result;
std::vector<App::DocumentObject*> refs3 = References3D.getValues();
TechDraw::DrawViewPart* dvp = getViewPart();
for (auto& r: refs3) {
Base::Vector3d loc3d = ShapeExtractor::getLocation3dFromFeat(r);
Base::Vector3d loc2d = projectPoint(loc3d, dvp);
result.push_back(loc2d);
}
return result;
}
//! References2D are only used to store ParentView
bool LandmarkDimension::has2DReferences() const
{
bool result = false;
const std::vector<App::DocumentObject*> &objects = References2D.getValues();
if (!objects.empty()) {
result = true;
}
return result;
}
//! References2D are only used to store ParentView
bool LandmarkDimension::checkReferences2D() const
{
return true;
}
pointPair LandmarkDimension::getPointsTwoVerts()
{
// Base::Console().Message("LD::getPointsTwoVerts() - %s\n", getNameInDocument());
pointPair result;
TechDraw::DrawViewPart* dvp = getViewPart();
if (dvp) {
std::vector<Base::Vector3d> points = get2DPoints();
result.first = points.at(0) * dvp->getScale();
result.second = points.at(1) * dvp->getScale();
}
return result;
}
int LandmarkDimension::getRefType() const
{
//TODO: need changes here when other reference dim types added
@@ -239,18 +194,13 @@ void LandmarkDimension::onDocumentRestored()
}
ReferenceTags.setValues(tags);
m_linearPoints.first = points.front();
m_linearPoints.second = points.back();
setLinearPoints(points.front(), points.back());
DrawViewDimension::onDocumentRestored();
}
void LandmarkDimension::unsetupObject()
{
// bool isRemoving = testStatus(App::ObjectStatus::Remove);
// Base::Console().Message("LD::unsetupObject - isRemove: %d status: %X\n",
// isRemoving, getStatus());
TechDraw::DrawViewPart* dvp = getViewPart();
std::vector<std::string> tags = ReferenceTags.getValues();
@@ -261,14 +211,3 @@ void LandmarkDimension::unsetupObject()
dvp->requestPaint();
}
//??? why does getPyObject work sometimes and no others???
//PyObject *LandmarkDimension::getPyObject(void)
//{
// if (PythonObject.is(Py::_None())) {
// // ref counter is set to 1
// PythonObject = Py::Object(new LandmarkDimensionPy(this), true);
// }
// return Py::new_reference_to(PythonObject);
//}

View File

@@ -28,7 +28,6 @@
#include "DrawViewDimension.h"
class TopoDS_Shape;
class gp_Ax2;
@@ -56,12 +55,7 @@ public:
const char* getViewProviderName() const override {
return "TechDrawGui::ViewProviderDimension"; }
/* virtual PyObject *getPyObject(void) override;*/
bool checkReferences2D() const override;
bool has2DReferences() const override;
pointPair getPointsTwoVerts() override;
std::vector<Base::Vector3d> get2DPoints() const;
DrawViewPart* getViewPart() const override;
int getRefType() const override;

View File

@@ -84,6 +84,8 @@ set(TechDrawGui_UIC_SRCS
TaskMoveView.ui
TaskProjection.ui
TaskComplexSection.ui
TaskDimRepair.ui
)
SET(MRTE_SRCS
@@ -108,6 +110,8 @@ SET(TechDrawGui_SRCS
CommandExtensionDims.cpp
CommandExtensionPack.cpp
CommandStack.cpp
DimensionValidators.cpp
DimensionValidators.h
Resources/TechDraw.qrc
PreCompiled.cpp
PreCompiled.h
@@ -209,9 +213,9 @@ SET(TechDrawGui_SRCS
TaskDetail.h
PreferencesGui.cpp
PreferencesGui.h
TaskCosmeticLine.ui
TaskCosmeticLine.cpp
TaskCosmeticLine.h
TaskCosmeticLine.ui
TaskMoveView.ui
TaskProjection.cpp
TaskProjection.h
@@ -219,6 +223,9 @@ SET(TechDrawGui_SRCS
TaskComplexSection.cpp
TaskComplexSection.h
TaskComplexSection.ui
TaskDimRepair.cpp
TaskDimRepair.h
TaskDimRepair.ui
Widgets/CompassDialWidget.cpp
Widgets/CompassDialWidget.h
Widgets/CompassWidget.cpp
@@ -429,6 +436,7 @@ SET(TechDrawGuiTaskDlgs_SRCS
TaskMoveView.ui
TaskProjection.ui
TaskComplexSection.ui
TaskDimRepair.ui
)
SOURCE_GROUP("MRTE" FILES ${MRTE_SRCS})

File diff suppressed because it is too large Load Diff

View File

@@ -569,8 +569,8 @@ void execPosHorizChainDimension(Gui::Command* cmd) {
for (auto dim : validDimension) {
dim->Y.setValue(yMaster);
pointPair pp = dim->getLinearPoints();
Base::Vector3d p1 = pp.first;
Base::Vector3d p2 = pp.second;
Base::Vector3d p1 = pp.first();
Base::Vector3d p2 = pp.second();
dim->X.setValue((p1.x + p2.x) / 2.0);
}
Gui::Command::commitCommand();
@@ -631,8 +631,8 @@ void execPosVertChainDimension(Gui::Command* cmd) {
for (auto dim : validDimension) {
dim->X.setValue(xMaster);
pointPair pp = dim->getLinearPoints();
Base::Vector3d p1 = pp.first;
Base::Vector3d p2 = pp.second;
Base::Vector3d p1 = pp.first();
Base::Vector3d p2 = pp.second();
dim->Y.setValue((p1.y + p2.y) / -2.0 + 0.5 * fontSize);
}
Gui::Command::commitCommand();
@@ -692,7 +692,7 @@ void execPosObliqueChainDimension(Gui::Command* cmd) {
float yMaster = validDimension[0]->Y.getValue();
Base::Vector3d pMaster(xMaster, yMaster, 0.0);
pointPair pp = validDimension[0]->getLinearPoints();
Base::Vector3d dirMaster = pp.second - pp.first;
Base::Vector3d dirMaster = pp.second() - pp.first();
dirMaster.y = -dirMaster.y;
for (auto dim : validDimension) {
float xDim = dim->X.getValue();
@@ -881,8 +881,8 @@ void execCascadeHorizDimension(Gui::Command* cmd) {
for (auto dim : validDimension) {
dim->Y.setValue(yMaster);
pointPair pp = dim->getLinearPoints();
Base::Vector3d p1 = pp.first;
Base::Vector3d p2 = pp.second;
Base::Vector3d p1 = pp.first();
Base::Vector3d p2 = pp.second();
dim->X.setValue((p1.x + p2.x) / 2.0);
yMaster = yMaster + dimDistance;
}
@@ -948,8 +948,8 @@ void execCascadeVertDimension(Gui::Command* cmd) {
for (auto dim : validDimension) {
dim->X.setValue(xMaster);
pointPair pp = dim->getLinearPoints();
Base::Vector3d p1 = pp.first;
Base::Vector3d p2 = pp.second;
Base::Vector3d p1 = pp.first();
Base::Vector3d p2 = pp.second();
dim->Y.setValue((p1.y + p2.y) / -2.0 + 0.5 * fontSize);
xMaster = xMaster + dimDistance;
}
@@ -1011,7 +1011,7 @@ void execCascadeObliqueDimension(Gui::Command* cmd) {
float yMaster = validDimension[0]->Y.getValue();
Base::Vector3d pMaster(xMaster, yMaster, 0.0);
pointPair pp = validDimension[0]->getLinearPoints();
Base::Vector3d dirMaster = pp.second - pp.first;
Base::Vector3d dirMaster = pp.second() - pp.first();
dirMaster.y = -dirMaster.y;
Base::Vector3d origin(0.0, 0.0, 0.0);
Base::Vector3d ipDelta = _getTrianglePoint(pMaster, dirMaster, origin);
@@ -1206,7 +1206,7 @@ void execCreateHorizChainDimension(Gui::Command* cmd) {
TechDraw::DrawViewDimension* dim;
dim = _createLinDimension(cmd, objFeat, allVertexes[n].name, allVertexes[n + 1].name, "DistanceX");
TechDraw::pointPair pp = dim->getLinearPoints();
Base::Vector3d mid = (pp.first + pp.second) / 2.0;
Base::Vector3d mid = (pp.first() + pp.second()) / 2.0;
dim->X.setValue(mid.x);
if (n == 0)
yMaster = -mid.y;
@@ -1271,7 +1271,7 @@ void execCreateVertChainDimension(Gui::Command* cmd) {
TechDraw::DrawViewDimension* dim;
dim = _createLinDimension(cmd, objFeat, allVertexes[n].name, allVertexes[n + 1].name, "DistanceY");
TechDraw::pointPair pp = dim->getLinearPoints();
Base::Vector3d mid = (pp.first + pp.second) / 2.0;
Base::Vector3d mid = (pp.first() + pp.second()) / 2.0;
if (n == 0)
xMaster = mid.x;
dim->X.setValue(xMaster);
@@ -1363,7 +1363,7 @@ void execCreateObliqueChainDimension(Gui::Command* cmd) {
TechDraw::DrawViewDimension* dim;
dim = _createLinDimension(cmd, objFeat, carrierVertexes[n].name, carrierVertexes[n + 1].name, "Distance");
TechDraw::pointPair pp = dim->getLinearPoints();
Base::Vector3d mid = (pp.first + pp.second) / 2.0 + delta;
Base::Vector3d mid = (pp.first() + pp.second()) / 2.0 + delta;
dim->X.setValue(mid.x);
dim->Y.setValue(-mid.y + 0.5 * fontSize);
}
@@ -1548,7 +1548,7 @@ void execCreateHorizCoordDimension(Gui::Command* cmd) {
TechDraw::DrawViewDimension* dim;
dim = _createLinDimension(cmd, objFeat, allVertexes[0].name, allVertexes[n + 1].name, "DistanceX");
TechDraw::pointPair pp = dim->getLinearPoints();
Base::Vector3d mid = (pp.first + pp.second) / 2.0;
Base::Vector3d mid = (pp.first() + pp.second()) / 2.0;
dim->X.setValue(mid.x);
dim->Y.setValue(-yMaster - dimDistance * n);
}
@@ -1620,7 +1620,7 @@ void execCreateVertCoordDimension(Gui::Command* cmd) {
TechDraw::DrawViewDimension* dim;
dim = _createLinDimension(cmd, objFeat, allVertexes[0].name, allVertexes[n + 1].name, "DistanceY");
TechDraw::pointPair pp = dim->getLinearPoints();
Base::Vector3d mid = (pp.first + pp.second) / 2.0;
Base::Vector3d mid = (pp.first() + pp.second()) / 2.0;
dim->X.setValue(xMaster + dimDistance * n);
dim->Y.setValue(-mid.y + 0.5 * fontSize);
}
@@ -1717,7 +1717,7 @@ void execCreateObliqueCoordDimension(Gui::Command* cmd) {
TechDraw::DrawViewDimension* dim;
dim = _createLinDimension(cmd, objFeat, carrierVertexes[0].name, carrierVertexes[n + 1].name, "Distance");
TechDraw::pointPair pp = dim->getLinearPoints();
Base::Vector3d mid = (pp.first + pp.second) / 2.0 + delta * (n + 1);
Base::Vector3d mid = (pp.first() + pp.second()) / 2.0 + delta * (n + 1);
dim->X.setValue(mid.x);
dim->Y.setValue(-mid.y + 0.5 * fontSize);
}
@@ -1905,7 +1905,7 @@ void execCreateHorizChamferDimension(Gui::Command* cmd) {
if (std::signbit(allVertexes[0].point.y))
yMax = -yMax;
TechDraw::pointPair pp = dim->getLinearPoints();
Base::Vector3d mid = (pp.first + pp.second) / 2.0;
Base::Vector3d mid = (pp.first() + pp.second()) / 2.0;
dim->X.setValue(mid.x);
dim->Y.setValue(-yMax);
float dx = allVertexes[0].point.x - allVertexes[1].point.x;
@@ -1972,7 +1972,7 @@ void execCreateVertChamferDimension(Gui::Command* cmd) {
if (std::signbit(allVertexes[0].point.x))
xMax = -xMax;
TechDraw::pointPair pp = dim->getLinearPoints();
Base::Vector3d mid = (pp.first + pp.second) / 2.0;
Base::Vector3d mid = (pp.first() + pp.second()) / 2.0;
dim->X.setValue(xMax);
dim->Y.setValue(-mid.y);
float dx = allVertexes[0].point.x - allVertexes[1].point.x;
@@ -2169,7 +2169,7 @@ void CmdTechDrawExtensionCreateLengthArc::activated(int iMsg) {
TechDraw::DrawViewDimension* dim;
dim = _createLinDimension(this, objFeat, startName.str(), endName.str(), "Distance");
TechDraw::pointPair pp = dim->getLinearPoints();
Base::Vector3d mid = (pp.first + pp.second) / 2.0;
Base::Vector3d mid = (pp.first() + pp.second()) / 2.0;
dim->X.setValue(mid.x);
dim->Y.setValue(-mid.y);
Base::Vector3d radVec1 = startPt - centerPt;

View File

@@ -0,0 +1,712 @@
/***************************************************************************
* Copyright (c) 2022 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 *
* *
***************************************************************************/
#ifndef _PreComp_
#include <BRepAdaptor_Curve.hxx>
#include <BRep_Tool.hxx>
#include <GeomAbs_CurveType.hxx>
#include <TopAbs_ShapeEnum.hxx>
#include <TopExp.hxx>
#endif //#ifndef _PreComp_
#include <App/DocumentObject.h>
#include <Base/Exception.h>
#include <Base/Console.h>
#include <Gui/Selection.h>
#include <Mod/TechDraw/App/Geometry.h>
#include <Mod/TechDraw/App/DrawUtil.h>
#include <Mod/TechDraw/App/DrawViewPart.h>
#include <Mod/TechDraw/App/ShapeExtractor.h>
#include <Mod/TechDraw/App/ShapeExtractor.h>
#include "DimensionValidators.h"
using namespace TechDraw;
using DU = DrawUtil;
TechDraw::DrawViewPart* TechDraw::getReferencesFromSelection( ReferenceVector& references2d, ReferenceVector& references3d )
{
TechDraw::DrawViewPart* dvp(nullptr);
TechDraw::DrawViewDimension* dim(nullptr);
std::vector<Gui::SelectionObject> selectionAll = Gui::Selection().getSelectionEx();
for (auto& selItem : selectionAll) {
if (selItem.getObject()->isDerivedFrom(TechDraw::DrawViewDimension::getClassTypeId())) {
//we are probably repairing a dimension, but we will check later
dim = static_cast<TechDraw::DrawViewDimension*> (selItem.getObject());
} else if (selItem.getObject()->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) {
//this could be a 2d geometry selection or just a DrawViewPart for context in
//a 3d selection
dvp = static_cast<TechDraw::DrawViewPart*> (selItem.getObject());
if (selItem.getSubNames().empty()) {
//there are no subNames, so we think this is a 3d case,
//and we only need to select the view. We set the reference
//subName to a null string to avoid later misunderstandings.
ReferenceEntry ref(dvp, std::string());
references2d.push_back(ref);
}
for (auto& sub : selItem.getSubNames()) {
ReferenceEntry ref(dvp, sub);
references2d.push_back(ref);
}
} else if ( !selItem.getObject()->isDerivedFrom(TechDraw::DrawView::getClassTypeId()) ) {
//this is not a TechDraw object, so we check to see if it has 3d geometry
std::vector<App::DocumentObject*> links;
links.push_back(selItem.getObject());
if (!ShapeExtractor::getShapes(links).IsNull()) {
//this item has 3d geometry so we are interested
App::DocumentObject* obj3d = selItem.getObject();
if (selItem.getSubNames().empty()) {
if (ShapeExtractor::isPointType(obj3d)) {
//a point object may not have a subName when selected,
//so we need to perform some special handling.
ReferenceEntry ref(obj3d, "Vertex1");
references3d.push_back(ref);
continue;
} else {
//this is a whole object reference, probably for an extent dimension
ReferenceEntry ref(obj3d, std::string());
references3d.push_back(ref);
continue;
}
}
//this is a regular reference in form obj+subelement
for (auto& sub3d : selItem.getSubNames()) {
ReferenceEntry ref(obj3d, sub3d);
references3d.push_back(ref);
}
} else {
Base::Console().Message("DV::getRefsFromSel - %s has no shape!\n", selItem.getObject()->getNameInDocument());
}
}
}
if (dim) {
if (!dvp) {
ReferenceEntry ref(dim->getViewPart(), std::string());
references2d.push_back(ref);
return dim->getViewPart();
}
}
return dvp;
}
//! verify that the proposed references contains valid geometries from a 2d DrawViewPart.
DimensionGeometryType TechDraw::validateDimSelection(ReferenceVector references, //[(dvp*, std::string),...,(dvp*, std::string)]
StringVector acceptableGeometry, //"Edge", "Vertex", etc
std::vector<int> minimumCounts, //how many of each geometry are needed for a good dimension
std::vector<DimensionGeometryType> acceptableDimensionGeometrys) //isVertical, isHorizontal, ...
{
StringVector subNames;
TechDraw::DrawViewPart* dvpSave(nullptr);
for (auto& ref : references) {
TechDraw::DrawViewPart* dvp = dynamic_cast<TechDraw::DrawViewPart *>(ref.getObject());
if ( dvp ) {
dvpSave = dvp;
//TODO: check for non-empty subname?
subNames.push_back(ref.getSubName());
}
}
if (!dvpSave) {
//must have 1 DVP in selection
return isInvalid;
}
if (subNames.front().empty()) {
//no geometry referenced. can not make a dim from this mess. We are being called to validate
//a selection for a 3d reference
return isViewReference;
}
//check for invalid geometry descriptors in the subNames
std::unordered_set<std::string> acceptableGeometrySet(acceptableGeometry.begin(),
acceptableGeometry.end());
if (!TechDraw::validateSubnameList(subNames, acceptableGeometrySet)) {
//can not make a dimension from this
return isInvalid;
}
//check for wrong number of geometry
GeomCountVector foundCounts;
GeomCountMap minimumCountMap = loadRequiredCounts(acceptableGeometry, minimumCounts);
if (!checkGeometryOccurences(subNames, minimumCountMap)) {
//too many or too few geometry descriptors.
return isInvalid;
}
//we have a (potentially valid collection of 2d geometry
ReferenceVector valid2dReferences;
for (auto& sub : subNames) {
ReferenceEntry validEntry(dvpSave, sub);
valid2dReferences.push_back(validEntry);
}
DimensionGeometryType foundGeometry = getGeometryConfiguration(valid2dReferences);
if (acceptableDimensionGeometrys.empty()) {
//if the list is empty, we are accepting anything
return foundGeometry;
}
for (auto& acceptable : acceptableDimensionGeometrys) {
if (foundGeometry == acceptable) {
return foundGeometry;
}
}
return isInvalid;
}
//! verify that the proposed references contains valid geometries from non-TechDraw objects.
DimensionGeometryType TechDraw::validateDimSelection3d(TechDraw::DrawViewPart* dvp,
ReferenceVector references, //[(dvp*, std::string),...,(dvp*, std::string)]
StringVector acceptableGeometry, //"Edge", "Vertex", etc
std::vector<int> minimumCounts, //how many of each geometry are needed for a good dimension
std::vector<DimensionGeometryType> acceptableDimensionGeometrys) //isVertical, isHorizontal, ...
{
// Base::Console().Message("DV::validateDimSelection3d() - references: %d\n", references.size());
StringVector subNames;
for (auto& ref : references) {
if (!ref.getSubName().empty()) {
subNames.push_back(ref.getSubName());
}
}
//check for invalid geometry descriptors in the subNames
std::unordered_set<std::string> acceptableGeometrySet(acceptableGeometry.begin(),
acceptableGeometry.end());
if (!TechDraw::validateSubnameList(subNames, acceptableGeometrySet)) {
//can not make a dimension from this
return isInvalid;
}
//check for wrong number of geometry
GeomCountMap minimumCountMap = loadRequiredCounts(acceptableGeometry, minimumCounts);
if (!checkGeometryOccurences(subNames, minimumCountMap)) {
//too many or too few geometry descriptors.
return isInvalid;
}
//we have a (potentially valid collection of 3d geometry
DimensionGeometryType foundGeometry = getGeometryConfiguration3d(dvp, references);
if (acceptableDimensionGeometrys.empty()) {
//if the list is empty, we are accepting anything
return foundGeometry;
}
for (auto& acceptable : acceptableDimensionGeometrys) {
if (foundGeometry == acceptable) {
return foundGeometry;
}
}
return isInvalid;
}
bool TechDraw::validateSubnameList(StringVector subNames,
GeometrySet acceptableGeometrySet)
{
// Base::Console().Message("DV::validateSubNameList()\n");
for (auto& sub : subNames) {
std::string geometryType = DrawUtil::getGeomTypeFromName(sub);
if (acceptableGeometrySet.count(geometryType) == 0) {
//this geometry type is not allowed
return false;
}
}
return true;
}
//count how many of each "Edge", "Vertex, etc and compare totals to required minimum
bool TechDraw::checkGeometryOccurences(StringVector subNames,
GeomCountMap keyedMinimumCounts)
{
// Base::Console().Message("DV::checkGeometryOccurences() - subNames: %d\n", subNames.size());
//how many of each geometry descriptor are input
GeomCountMap foundCounts;
for (auto& sub : subNames) {
std::string geometryType = DrawUtil::getGeomTypeFromName(sub);
std::map<std::string, int>::iterator it0(foundCounts.find(geometryType));
if (it0 == foundCounts.end()) {
//already have this geometryType
it0->second++;
} else {
//first occurrence of this geometryType
foundCounts[geometryType] = 1;
}
}
//check found geometry counts against required counts
for (auto& foundItem : foundCounts) {
std::string currentKey = foundItem.first;
int foundCount = foundItem.second;
auto itAccept = keyedMinimumCounts.find(currentKey);
if (itAccept == keyedMinimumCounts.end()) {
//not supposed to happen by this point
throw Base::IndexError("Dimension validation counts and geometry do not match");
}
if (foundCount < keyedMinimumCounts[currentKey]) {
//not enough of this type of geom to make a good dimension - ex 1 Vertex
return false;
}
}
//we have no complaints about the input
return true;
}
//return the first valid configuration contained in the already validated references
DimensionGeometryType TechDraw::getGeometryConfiguration(ReferenceVector valid2dReferences)
{
DimensionGeometryType config = isValidMultiEdge(valid2dReferences);
if ( config > isInvalid) {
return config;
}
config = isValidVertexes(valid2dReferences);
if ( config > isInvalid) {
return config;
}
config = isValidSingleEdge(valid2dReferences.front());
if ( config > isInvalid) {
return config;
}
config = isValidHybrid(valid2dReferences);
if ( config > isInvalid) {
return config;
}
// no valid configuration found
return isInvalid;
}
//return the first valid configuration contained in the already validated references
DimensionGeometryType TechDraw::getGeometryConfiguration3d(DrawViewPart* dvp, ReferenceVector valid3dReferences)
{
// Base::Console().Message("DV::getGeometryConfig3d() - refs: %d\n", valid3dReferences.size());
//first we check for whole object references
ReferenceVector wholeObjectRefs;
ReferenceVector subElementRefs;
for (auto& ref : valid3dReferences) {
if (ref.isWholeObject()) {
wholeObjectRefs.push_back(ref);
} else {
subElementRefs.push_back(ref);
}
}
if (subElementRefs.empty()) {
//only whole object references
return isMultiEdge;
}
if (!wholeObjectRefs.empty()) {
//mix of whole object and subelement refs
return isMultiEdge; //??? correct ???
}
//only have subelement refs
DimensionGeometryType config = isValidMultiEdge3d(dvp, valid3dReferences);
if ( config > isInvalid) {
return config;
}
config = isValidVertexes3d(dvp, valid3dReferences);
if ( config > isInvalid) {
return config;
}
config = isValidSingleEdge3d(dvp, valid3dReferences.front());
if ( config > isInvalid) {
return config;
}
config = isValidHybrid3d(dvp, valid3dReferences);
if ( config > isInvalid) {
return config;
}
// no valid configuration found
return isInvalid;
}
//fill the GeomCountMap with pairs made from corresponding items in acceptableGeometry
//and minimumCounts
GeomCountMap TechDraw::loadRequiredCounts(StringVector& acceptableGeometry,
std::vector<int>& minimumCounts)
{
if (acceptableGeometry.size() != minimumCounts.size()) {
throw Base::IndexError("acceptableGeometry and minimum counts have different sizes.");
}
GeomCountMap result;
int iCount = 0;
for (auto& acceptableItem : acceptableGeometry) {
result[acceptableItem] = minimumCounts.at(iCount);
iCount++;
}
return result;
}
//! verify that Selection contains a valid Geometry for a single Edge Dimension
DimensionGeometryType TechDraw::isValidSingleEdge(ReferenceEntry ref)
{
auto objFeat( dynamic_cast<TechDraw::DrawViewPart *>(ref.getObject()) );
if (!objFeat)
return isInvalid;
//the Name starts with "Edge"
std::string geomName = DrawUtil::getGeomTypeFromName(ref.getSubName());
if (geomName != "Edge") {
return isInvalid;
}
//the geometry exists (redundant?)
int GeoId( TechDraw::DrawUtil::getIndexFromName(ref.getSubName()) );
TechDraw::BaseGeomPtr geom = objFeat->getGeomByIndex(GeoId);
if (!geom) {
return isInvalid;
}
if(geom->geomType == TechDraw::GENERIC) {
TechDraw::GenericPtr gen1 = std::static_pointer_cast<TechDraw::Generic>(geom);
if(gen1->points.size() < 2) {
return isInvalid;
}
Base::Vector3d line = gen1->points.at(1) - gen1->points.at(0);
if(fabs(line.y) < FLT_EPSILON ) {
return TechDraw::isHorizontal;
} else if(fabs(line.x) < FLT_EPSILON) {
return TechDraw::isVertical;
} else {
return TechDraw::isDiagonal;
}
} else if (geom->geomType == TechDraw::CIRCLE ||
geom->geomType == TechDraw::ARCOFCIRCLE ) {
return isCircle;
} else if (geom->geomType == TechDraw::ELLIPSE ||
geom->geomType == TechDraw::ARCOFELLIPSE) {
return isEllipse;
} else if (geom->geomType == TechDraw::BSPLINE) {
TechDraw::BSplinePtr spline = std::static_pointer_cast<TechDraw::BSpline> (geom);
if (spline->isCircle()) {
return isBSplineCircle;
} else {
return isBSpline;
}
}
return isInvalid;
}
//! verify that Selection contains a valid Geometry for a single Edge Dimension
DimensionGeometryType TechDraw::isValidSingleEdge3d(DrawViewPart *dvp, ReferenceEntry ref)
{
(void) dvp;
//the Name starts with "Edge"
std::string geomName = DrawUtil::getGeomTypeFromName(ref.getSubName());
if (geomName != "Edge") {
return isInvalid;
}
TopoDS_Shape refShape = ref.getGeometry();
if (refShape.IsNull() || refShape.ShapeType() != TopAbs_EDGE) {
throw Base::RuntimeError("Geometry for reference is not an edge.");
}
TopoDS_Edge occEdge = TopoDS::Edge(refShape);
BRepAdaptor_Curve adapt(occEdge);
if (adapt.GetType() == GeomAbs_Line) {
Base::Vector3d point0 = DU::toVector3d(BRep_Tool::Pnt(TopExp::FirstVertex(occEdge)));
Base::Vector3d point1 = DU::toVector3d(BRep_Tool::Pnt(TopExp::LastVertex(occEdge)));
Base::Vector3d line = point1 - point0;
if(fabs(line.y) < FLT_EPSILON ) {
return TechDraw::isHorizontal;
} else if(fabs(line.x) < FLT_EPSILON) {
return TechDraw::isVertical;
} else if(fabs(line.z) < FLT_EPSILON) {
return TechDraw::isZLimited;
} else {
return TechDraw::isDiagonal;
}
} else if (adapt.GetType() == GeomAbs_Circle) {
return isCircle;
} else if (adapt.GetType() == GeomAbs_Ellipse) {
return isEllipse;
} else if (adapt.GetType() == GeomAbs_BSplineCurve) {
if (GeometryUtils::isCircle(occEdge)) {
return isBSplineCircle;
} else {
return isBSpline;
}
}
return isInvalid;
}
//! verify that the edge references can make a dimension. Currently only extent
//! dimensions support more than 2 edges
DimensionGeometryType TechDraw::isValidMultiEdge(ReferenceVector refs)
{
//there has to be at least 2
if(refs.size() < 2) {
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;
}
int GeoId0( TechDraw::DrawUtil::getIndexFromName(refs.at(0).getSubName()) );
int GeoId1( TechDraw::DrawUtil::getIndexFromName(refs.at(1).getSubName()) );
TechDraw::BaseGeomPtr geom0 = objFeat0->getGeomByIndex(GeoId0);
TechDraw::BaseGeomPtr geom1 = objFeat0->getGeomByIndex(GeoId1);
if(geom0->geomType == TechDraw::GENERIC &&
geom1->geomType == TechDraw::GENERIC) {
TechDraw::GenericPtr gen0 = std::static_pointer_cast<TechDraw::Generic> (geom0);
TechDraw::GenericPtr gen1 = std::static_pointer_cast<TechDraw::Generic> (geom1);
if(gen0->points.size() > 2 ||
gen1->points.size() > 2) { //the edge is a polyline
return isInvalid; //not supported yet
}
Base::Vector3d line0 = gen0->points.at(1) - gen0->points.at(0);
Base::Vector3d line1 = gen1->points.at(1) - gen1->points.at(0);
double xprod = fabs(line0.x * line1.y - line0.y * line1.x);
if (xprod > FLT_EPSILON) { //edges are not parallel
return isAngle; //angle or distance
} else {
return isDiagonal; //distance || line
}
} else {
return isDiagonal; //two edges, not both straight lines
}
return isInvalid;
}
//! verify that the edge references can make a dimension. Currently only extent
//! dimensions support more than 2 edges
DimensionGeometryType TechDraw::isValidMultiEdge3d(DrawViewPart *dvp, ReferenceVector refs)
{
(void) dvp;
//there has to be at least 2
if(refs.size() < 2) {
return isInvalid;
}
std::vector<TopoDS_Edge> edges;
for (auto& ref : refs) {
std::vector<TopoDS_Shape> shapesAll = ShapeExtractor::getShapesFromObject(ref.getObject());
if (shapesAll.empty()) {
//reference has no geometry
return isInvalid;
}
//the Name starts with "Edge"
std::string geomName = DrawUtil::getGeomTypeFromName(ref.getSubName().c_str());
if (geomName != "Edge") {
return isInvalid;
}
}
std::vector<TopoDS_Edge> edgesAll;
std::vector<int> typeAll;
for (auto& ref : refs) {
TopoDS_Shape geometry = ref.getGeometry();
if (geometry.ShapeType() != TopAbs_EDGE) {
return isInvalid;
}
TopoDS_Edge edge = TopoDS::Edge(geometry);
BRepAdaptor_Curve adapt(edge);
if (adapt.GetType() != GeomAbs_Line) {
//not a line, so this must be an extent dim?
return isMultiEdge;
}
edgesAll.push_back(edge);
}
if (edgesAll.size() > 2) {
//must be an extent dimension of lines?
return isMultiEdge;
} else if (edgesAll.size() == 2) {
Base::Vector3d first0 = DU::toVector3d(BRep_Tool::Pnt(TopExp::FirstVertex(edgesAll.at(0))));
Base::Vector3d last0 = DU::toVector3d(BRep_Tool::Pnt(TopExp::LastVertex(edgesAll.at(1))));
Base::Vector3d line0 = last0 - first0;
Base::Vector3d first1 = DU::toVector3d(BRep_Tool::Pnt(TopExp::FirstVertex(edgesAll.at(0))));
Base::Vector3d last1 = DU::toVector3d(BRep_Tool::Pnt(TopExp::LastVertex(edgesAll.at(1))));
Base::Vector3d line1 = last1 - first1;
if (DU::fpCompare(fabs(line0.Dot(line1)), 1)) {
//lines are parallel, must be distance dim
return isDiagonal;
} else {
//lines are skew, could be angle, could be distance?
return isAngle;
}
}
return isInvalid;
}
//! verify that the vertex references can make a dimension
DimensionGeometryType TechDraw::isValidVertexes(ReferenceVector refs)
{
TechDraw::DrawViewPart* dvp( dynamic_cast<TechDraw::DrawViewPart*>(refs.front().getObject()) );
if ( !dvp ) {
//probably redundant
throw Base::RuntimeError("Logic error in isValidMultiEdge");
}
if (refs.size() == 2) {
//2 vertices can only make a distance dimension
TechDraw::VertexPtr v0 = dvp->getVertex(refs.at(0).getSubName());
TechDraw::VertexPtr v1 = dvp->getVertex(refs.at(1).getSubName());
Base::Vector3d line = v1->point() - v0->point();
if(fabs(line.y) < FLT_EPSILON ) {
return isHorizontal;
} else if(fabs(line.x) < FLT_EPSILON) {
return isVertical;
} else {
return isDiagonal;
}
} else if (refs.size() == 3) {
//three vertices make an angle dimension
return isAngle3Pt;
}
// did not find a valid configuration
return isInvalid;
}
//! verify that the vertex references can make a dimension
DimensionGeometryType TechDraw::isValidVertexes3d(DrawViewPart *dvp, ReferenceVector refs)
{
// Base::Console().Message("DV::isValidVertexes3d() - refs: %d\n", refs.size());
(void) dvp;
if (refs.size() == 2) {
//2 vertices can only make a distance dimension
TopoDS_Shape geometry0 = refs.at(0).getGeometry();
TopoDS_Shape geometry1 = refs.at(1).getGeometry();
if (geometry0.IsNull() || geometry1.IsNull() ||
geometry0.ShapeType() != TopAbs_VERTEX ||
geometry1.ShapeType() != TopAbs_VERTEX) {
return isInvalid;
}
Base::Vector3d point0 = DU::toVector3d(BRep_Tool::Pnt(TopoDS::Vertex(geometry0)));
point0 = dvp->projectPoint(point0);
Base::Vector3d point1 = DU::toVector3d(BRep_Tool::Pnt(TopoDS::Vertex(geometry1)));
point1 = dvp->projectPoint(point1);
Base::Vector3d line = point1 - point0;
if(fabs(line.y) < FLT_EPSILON ) {
return isHorizontal;
} else if(fabs(line.x) < FLT_EPSILON) {
return isVertical;
// } else if(fabs(line.z) < FLT_EPSILON) {
// return isZLimited;
} else {
return isDiagonal;
}
} else if (refs.size() == 3) {
//three vertices make an angle dimension
//we could check here that all the geometries are Vertex
return isAngle3Pt;
}
// did not find a valid configuration
return isInvalid;
}
//! verify that the mixed bag (ex Vertex-Edge) of references can make a dimension
DimensionGeometryType TechDraw::isValidHybrid(ReferenceVector refs)
{
if (refs.empty()) {
return isInvalid;
}
int vertexCount(0);
int edgeCount(0);
for (auto& ref : refs) {
if (DU::getGeomTypeFromName(ref.getSubName()) == "Vertex") {
vertexCount++;
}
if (DU::getGeomTypeFromName(ref.getSubName()) == "Edge") {
edgeCount++;
}
}
if (vertexCount > 0 &&
edgeCount > 0) {
//must be a diagonal dim? could it be isHorizontal or isVertical?
return isDiagonal;
}
return isInvalid;
}
//! verify that the mixed bag (ex Vertex-Edge) of references can make a dimension
DimensionGeometryType TechDraw::isValidHybrid3d(DrawViewPart *dvp, ReferenceVector refs)
{
(void) dvp;
//we don't have a special check for 3d in this case
return isValidHybrid(refs);
}
//handle situations where revised geometry type is valid but not suitable for existing dimType
long int TechDraw::mapGeometryTypeToDimType(long int dimType,
DimensionGeometryType geometry2d,
DimensionGeometryType geometry3d)
{
if (geometry2d == isInvalid && geometry3d == isInvalid) {
//probably an error, but we can't do anything with this
return dimType;
}
if (geometry2d == isViewReference && geometry3d != isInvalid) {
switch (geometry3d) {
case isDiagonal:
return DrawViewDimension::Distance;
case isHorizontal:
return DrawViewDimension::DistanceX;
case isVertical:
return DrawViewDimension::DistanceY;
case isAngle:
return DrawViewDimension::Angle;
case isAngle3Pt:
return DrawViewDimension::Angle3Pt;
default:
return dimType;
}
} else if (geometry2d != isViewReference) {
switch (geometry2d) {
case isDiagonal:
return DrawViewDimension::Distance;
case isHorizontal:
return DrawViewDimension::DistanceX;
case isVertical:
return DrawViewDimension::DistanceY;
case isAngle:
return DrawViewDimension::Angle;
case isAngle3Pt:
return DrawViewDimension::Angle3Pt;
default:
return dimType;
}
}
return dimType;
}

View File

@@ -0,0 +1,102 @@
/***************************************************************************
* Copyright (c) 2022 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 *
* *
***************************************************************************/
#ifndef TECHDRAW_DIMENSIONVALIDATORS_H
#define TECHDRAW_DIMENSIONVALIDATORS_H
#include <Mod/TechDraw/TechDrawGlobal.h>
#include <Mod/TechDraw/App/DrawViewDimension.h>
namespace App
{
class Document;
class DocumentObject;
}
using StringVector = std::vector<std::string>;
using GeomCount = std::pair<std::string, int>; //geometry descriptor ("Edge") + counter pair
using GeomCountVector = std::vector<GeomCount>;
using GeomCountMap = std::map<std::string, int>;
using GeometrySet = std::unordered_set<std::string>; //queryable unique set of geometrty descriptors
using DimensionGeometryType = int;
namespace TechDraw
{
class DrawViewPart;
enum DimensionGeometryEnum {
isInvalid,
isHorizontal,
isVertical,
isDiagonal,
isCircle,
isEllipse,
isBSplineCircle,
isBSpline,
isAngle,
isAngle3Pt,
isMultiEdge,
isZLimited,
isViewReference //never needs to be specified in the acceptable list
};
TechDraw::DrawViewPart* TechDrawExport getReferencesFromSelection( ReferenceVector& references2d, ReferenceVector& references3d );
DimensionGeometryType TechDrawExport validateDimSelection(ReferenceVector references,
StringVector acceptableGeometry, //"Edge", "Vertex", etc
std::vector<int> minimumCounts, //how many of each geometry are needed for a good dimension
std::vector<DimensionGeometryType> acceptableDimensionGeometrys); //isVertical, isHorizontal, ...
DimensionGeometryType TechDrawExport validateDimSelection3d(TechDraw::DrawViewPart* dvp,
ReferenceVector references,
StringVector acceptableGeometry, //"Edge", "Vertex", etc
std::vector<int> minimumCounts, //how many of each geometry are needed for a good dimension
std::vector<DimensionGeometryType> acceptableDimensionGeometrys); //isVertical, isHorizontal, ...
bool TechDrawExport validateSubnameList(StringVector subNames,
GeometrySet acceptableGeometrySet);
DimensionGeometryType TechDrawExport getGeometryConfiguration(TechDraw::ReferenceVector valid2dReferences);
DimensionGeometryType TechDrawExport getGeometryConfiguration3d(TechDraw::DrawViewPart* dvp,
TechDraw::ReferenceVector valid3dReferences);
GeomCountMap TechDrawExport loadRequiredCounts(StringVector& acceptableGeometry,
std::vector<int>& minimumCouts);
bool TechDrawExport checkGeometryOccurences(StringVector subNames,
GeomCountMap keyedMinimumCounts);
DimensionGeometryType TechDrawExport isValidVertexes(TechDraw::ReferenceVector refs);
DimensionGeometryType TechDrawExport isValidMultiEdge(TechDraw::ReferenceVector refs);
DimensionGeometryType TechDrawExport isValidSingleEdge(TechDraw::ReferenceEntry ref);
DimensionGeometryType TechDrawExport isValidHybrid(TechDraw::ReferenceVector refs);
DimensionGeometryType TechDrawExport isValidVertexes3d(TechDraw::DrawViewPart* dvp, TechDraw::ReferenceVector refs);
DimensionGeometryType TechDrawExport isValidMultiEdge3d(TechDraw::DrawViewPart* dvp, TechDraw::ReferenceVector refs);
DimensionGeometryType TechDrawExport isValidSingleEdge3d(TechDraw::DrawViewPart* dvp, TechDraw::ReferenceEntry ref);
DimensionGeometryType TechDrawExport isValidHybrid3d(TechDraw::DrawViewPart* dvp, TechDraw::ReferenceVector refs);
long int TechDrawExport mapGeometryTypeToDimType(long int dimType,
DimensionGeometryType geometry2d,
DimensionGeometryType geometry3d);
}
#endif //TECHDRAW_DIMENSIONVALIDATORS_H

View File

@@ -2097,7 +2097,7 @@ void QGIViewDimension::drawDistance(TechDraw::DrawViewDimension* dimension,
lineAngle = M_PI_2;
}
else {
lineAngle = (fromQtApp(linePoints.second) - fromQtApp(linePoints.first)).Angle();
lineAngle = (fromQtApp(linePoints.second()) - fromQtApp(linePoints.first())).Angle();
}
int standardStyle = viewProvider->StandardAndStyle.getValue();
@@ -2106,14 +2106,14 @@ void QGIViewDimension::drawDistance(TechDraw::DrawViewDimension* dimension,
if (dimension->AngleOverride.getValue()) {
drawDistanceOverride(fromQtApp(linePoints.first), fromQtApp(linePoints.second),
drawDistanceOverride(fromQtApp(linePoints.first()), fromQtApp(linePoints.second()),
dimension->LineAngle.getValue() * M_PI / 180.0, labelRectangle,
standardStyle, renderExtent, flipArrows,
dimension->ExtensionAngle.getValue() * M_PI / 180.0);
}
else {
drawDistanceExecutive(fromQtApp(linePoints.first), fromQtApp(linePoints.second), lineAngle,
labelRectangle, standardStyle, renderExtent, flipArrows);
drawDistanceExecutive(fromQtApp(linePoints.first()), fromQtApp(linePoints.second()),
lineAngle, labelRectangle, standardStyle, renderExtent, flipArrows);
}
}
@@ -2127,10 +2127,12 @@ void QGIViewDimension::drawRadius(TechDraw::DrawViewDimension* dimension,
double endAngle;
double startRotation;
if (curvePoints.isArc) {
endAngle = (fromQtApp(curvePoints.arcEnds.second) - fromQtApp(curvePoints.center)).Angle();
endAngle =
(fromQtApp(curvePoints.arcEnds.second()) - fromQtApp(curvePoints.center)).Angle();
startRotation =
(fromQtApp(curvePoints.arcEnds.first) - fromQtApp(curvePoints.center)).Angle()
(fromQtApp(curvePoints.arcEnds.first()) - fromQtApp(curvePoints.center)).Angle()
- endAngle;
if (startRotation != 0.0 && ((startRotation > 0.0) != curvePoints.arcCW)) {
startRotation += curvePoints.arcCW ? +M_2PI : -M_2PI;
}
@@ -2323,9 +2325,9 @@ void QGIViewDimension::drawAngle(TechDraw::DrawViewDimension* dimension,
anglePoints anglePoints = dimension->getAnglePoints();
Base::Vector2d angleVertex = fromQtApp(anglePoints.vertex);
Base::Vector2d startPoint = fromQtApp(anglePoints.ends.first);
Base::Vector2d endPoint = fromQtApp(anglePoints.ends.second);
Base::Vector2d angleVertex = fromQtApp(anglePoints.vertex());
Base::Vector2d startPoint = fromQtApp(anglePoints.first());
Base::Vector2d endPoint = fromQtApp(anglePoints.second());
double endAngle = (endPoint - angleVertex).Angle();
double startAngle = (startPoint - angleVertex).Angle();

View File

@@ -83,6 +83,7 @@
<file>icons/TechDraw_Balloon.svg</file>
<file>icons/TechDraw_DiameterDimension.svg</file>
<file>icons/TechDraw_Dimension.svg</file>
<file>icons/TechDraw_DimensionRepair.svg</file>
<file>icons/TechDraw_ExtensionAreaAnnotation.svg</file>
<file>icons/TechDraw_ExtensionCascadeHorizDimension.svg</file>
<file>icons/TechDraw_ExtensionCascadeObliqueDimension.svg</file>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@@ -0,0 +1,346 @@
/***************************************************************************
* Copyright (c) 2022 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 *
* *
***************************************************************************/
#include "PreCompiled.h"
#include <QMessageBox>
#include <QTableWidgetItem>
#ifndef _PreComp_
#include <cmath>
#endif // #ifndef _PreComp_
#include <Base/Console.h>
#include <Base/Tools.h>
#include <Base/Vector3D.h>
#include <Gui/Application.h>
#include <Gui/BitmapFactory.h>
#include <Gui/Command.h>
#include <Gui/Document.h>
#include <Gui/MainWindow.h>
#include <Gui/Selection.h>
#include <Gui/ViewProvider.h>
#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentObject.h>
#include <Mod/TechDraw/App/DrawView.h>
#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>
using namespace Gui;
using namespace TechDraw;
using namespace TechDrawGui;
TaskDimRepair::TaskDimRepair(TechDraw::DrawViewDimension* inDvd,
ReferenceVector references2d,
ReferenceVector references3d) :
ui(new Ui_TaskDimRepair),
m_dim(inDvd),
m_references2d(references2d),
m_references3d(references3d)
{
ui->setupUi(this);
connect(ui->pbSelection, SIGNAL(clicked(bool)), this, SLOT(slotUseSelection()));
saveDimState();
setUiPrimary();
}
TaskDimRepair::~TaskDimRepair()
{
}
void TaskDimRepair::setUiPrimary()
{
setWindowTitle(QObject::tr("Dimension Repair"));
ui->leName->setReadOnly(true);
ui->leLabel->setReadOnly(true);
ui->leName->setText(Base::Tools::fromStdString(m_dim->getNameInDocument()));
ui->leLabel->setText(Base::Tools::fromStdString(m_dim->Label.getValue()));
std::string objName = m_dim->getViewPart()->getNameInDocument();
std::string objLabel = m_dim->getViewPart()->Label.getValue();
ui->leObject2d->setText(Base::Tools::fromStdString(objName + " / " + objLabel));
const std::vector<std::string>& subElements2d = m_dim->References2D.getSubValues();
std::vector<std::string> noLabels(subElements2d.size());
fillList(ui->lwGeometry2d, subElements2d, noLabels);
const std::vector<App::DocumentObject*>& objs3d = m_dim->References3D.getValues();
QStringList headers;
headers << tr("Object Name")
<< tr("Object Label")
<< tr("SubElement");
ui->twReferences3d->setHorizontalHeaderLabels(headers);
ReferenceVector references3d;
if (!m_references3d.empty()) {
references3d = m_references3d;
} else if (!objs3d.empty()) {
references3d = m_dim->getEffectiveReferences();
}
loadTableWidget(ui->twReferences3d, references3d);
}
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();
}
//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);
}
}
//similar to code in CommandCreateDims.cpp
//use the current selection to replace the references in dim
void TaskDimRepair::slotUseSelection()
{
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
//validators happy
//bool accepted =
static_cast<void> (Gui::Selection().addSelection(m_dim->getDocument()->getName(),
m_dim->getNameInDocument()));
}
ReferenceVector references2d;
ReferenceVector references3d;
TechDraw::DrawViewPart* dvp = TechDraw::getReferencesFromSelection(references2d, references3d);
if (dvp != m_saveDvp) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("Incorrect Selection"),
QObject::tr("Can not use references from a different View"));
return;
}
StringVector acceptableGeometry( { "Edge", "Vertex" } );
std::vector<int> minimumCounts( { 1, 1 } );
std::vector<DimensionGeometryType> acceptableDimensionGeometrys; //accept anything
DimensionGeometryType geometryRefs2d = validateDimSelection(references2d,
acceptableGeometry,
minimumCounts,
acceptableDimensionGeometrys);
if (geometryRefs2d == isInvalid) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("Incorrect Selection"),
QObject::tr("Can not make a dimension from selection"));
return;
}
//what 3d geometry configuration did we receive?
DimensionGeometryType geometryRefs3d(isInvalid);
if (geometryRefs2d == TechDraw::isViewReference &&
!references3d.empty()) {
geometryRefs3d = validateDimSelection3d(dvp,
references3d,
acceptableGeometry,
minimumCounts,
acceptableDimensionGeometrys);
if ( geometryRefs3d == isInvalid) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("Incorrect Selection"),
QObject::tr("Can not make dimension from selection"));
return;
}
}
m_dimType = mapGeometryTypeToDimType(m_dim->Type.getValue(),
geometryRefs2d,
geometryRefs3d);
m_references2d = references2d;
if (references3d.empty()) {
m_references3d.clear();
} else {
m_references3d = references3d;
}
updateUi();
}
void TaskDimRepair::updateUi()
{
// Base::Console().Message("TDR::updateUi()\n");
std::string objName = m_dim->getViewPart()->getNameInDocument();
std::string objLabel = m_dim->getViewPart()->Label.getValue();
ui->leObject2d->setText(Base::Tools::fromStdString(objName + " / " + objLabel));
std::vector<std::string> subElements2d;
for (auto& ref : m_references2d) {
subElements2d.push_back(ref.getSubName());
}
std::vector<std::string> noLabels(subElements2d.size());
fillList(ui->lwGeometry2d, subElements2d, noLabels);
loadTableWidget(ui->twReferences3d, m_references3d);
}
void TaskDimRepair::loadTableWidget(QTableWidget* tw, ReferenceVector refs)
{
// Base::Console().Message("TDR::loadTableWidget() - refs: %d\n", refs.size());
tw->clearContents();
tw->setRowCount(refs.size() + 1);
size_t iRow = 0;
for (auto& ref : refs) {
QString qName = Base::Tools::fromStdString(ref.getObject()->getNameInDocument());
QTableWidgetItem* itemName = new QTableWidgetItem(qName);
itemName->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
tw->setItem(iRow,0, itemName);
QString qLabel = Base::Tools::fromStdString(std::string(ref.getObject()->Label.getValue()));
QTableWidgetItem* itemLabel = new QTableWidgetItem(qLabel);
itemLabel->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
tw->setItem(iRow,1, itemLabel);
QString qSubName = Base::Tools::fromStdString(ref.getSubName());
QTableWidgetItem* itemSubName = new QTableWidgetItem(qSubName);
itemSubName->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
tw->setItem(iRow,2, itemSubName);
iRow++;
}
}
void TaskDimRepair::fillList(QListWidget* lwItems, std::vector<std::string> labels, std::vector<std::string> names)
{
QListWidgetItem* item;
QString qLabel;
QString qName;
QString qText;
int labelCount = labels.size();
int i = 0;
lwItems->clear();
for (; i < labelCount; i++) {
qLabel = Base::Tools::fromStdString(labels[i]);
qName = Base::Tools::fromStdString(names[i]);
qText = QString::fromUtf8("%1 %2").arg(qName, qLabel);
item = new QListWidgetItem(qText, lwItems);
item->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
item->setData(Qt::UserRole, qName);
}
}
void TaskDimRepair::replaceReferences()
{
if (m_dim) {
m_dim->setReferences2d(m_references2d);
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->recomputeFeature();
return true;
}
bool TaskDimRepair::reject()
{
// Base::Console().Message("TDR::reject()\n");
restoreDimState();
Gui::Command::doCommand(Gui::Command::Gui, "Gui.ActiveDocument.resetEdit()");
return false;
}
void TaskDimRepair::changeEvent(QEvent *e)
{
if (e->type() == QEvent::LanguageChange) {
ui->retranslateUi(this);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TaskDlgDimReference::TaskDlgDimReference(TechDraw::DrawViewDimension* inDvd,
ReferenceVector references2d,
ReferenceVector references3d) :
TaskDialog()
{
widget = new TaskDimRepair(inDvd, references2d, references3d);
taskbox = new Gui::TaskView::TaskBox(Gui::BitmapFactory().pixmap("TechDraw_DimensionRepair"),
widget->windowTitle(), true, 0);
taskbox->groupLayout()->addWidget(widget);
Content.push_back(taskbox);
}
TaskDlgDimReference::~TaskDlgDimReference()
{
}
void TaskDlgDimReference::update()
{
//widget->updateTask();
}
//==== calls from the TaskView ===============================================================
void TaskDlgDimReference::open()
{
}
void TaskDlgDimReference::clicked(int i)
{
Q_UNUSED(i);
}
bool TaskDlgDimReference::accept()
{
widget->accept();
return true;
}
bool TaskDlgDimReference::reject()
{
widget->reject();
return true;
}
#include <Mod/TechDraw/Gui/moc_TaskDimRepair.cpp>

View File

@@ -0,0 +1,125 @@
/***************************************************************************
* Copyright (c) 2022 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 *
* *
***************************************************************************/
#ifndef TECHDRAW_TASKDIMREPAIR_H
#define TECHDRAW_TASKDIMREPAIR_H
#include <Mod/TechDraw/TechDrawGlobal.h>
#include <Gui/TaskView/TaskDialog.h>
#include <Gui/TaskView/TaskView.h>
#include <Mod/TechDraw/App/DrawViewDimension.h>
#include <Mod/TechDraw/App/DimensionReferences.h>
#include <Mod/TechDraw/Gui/ui_TaskDimRepair.h>
class Ui_TaskDimRepair;
namespace App
{
class DocumentObject;
}
namespace TechDrawGui
{
class TaskDimRepair : public QWidget
{
Q_OBJECT
public:
TaskDimRepair(TechDraw::DrawViewDimension* inDvd,
TechDraw::ReferenceVector references2d,
TechDraw::ReferenceVector references3d);
~TaskDimRepair();
public:
virtual bool accept();
virtual bool reject();
protected Q_SLOTS:
void slotUseSelection();
protected:
void changeEvent(QEvent *e);
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);
void saveDimState();
void restoreDimState();
private:
std::unique_ptr<Ui_TaskDimRepair> ui;
TechDraw::DrawViewDimension* m_dim;
TechDraw::ReferenceVector m_references2d;
TechDraw::ReferenceVector m_references3d;
long int m_dimType;
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;
};
class TaskDlgDimReference : public Gui::TaskView::TaskDialog
{
Q_OBJECT
public:
TaskDlgDimReference(TechDraw::DrawViewDimension* inDvd,
TechDraw::ReferenceVector references2d,
TechDraw::ReferenceVector references3d);
~TaskDlgDimReference();
public:
/// is called the TaskView when the dialog is opened
virtual void open();
/// is called by the framework if an button is clicked which has no accept or reject role
virtual void clicked(int);
/// is called by the framework if the dialog is accepted (Ok)
virtual bool accept();
/// is called by the framework if the dialog is rejected (Cancel)
virtual bool reject();
/// is called by the framework if the user presses the help button
virtual void helpRequested() { return;}
virtual bool isAllowedAlterDocument(void) const
{ return false; }
void update();
protected:
private:
TaskDimRepair * widget;
Gui::TaskView::TaskBox* taskbox;
};
} //namespace TechDrawGui
#endif // #ifndef TECHDRAW_TASKDIMREPAIR_H

View File

@@ -0,0 +1,211 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TaskDimRepair</class>
<widget class="QWidget" name="TaskDimRepair">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>356</width>
<height>512</height>
</rect>
</property>
<property name="windowTitle">
<string>Dimension Repair</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="gbDimension">
<property name="title">
<string>Dimension</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Label</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="leName">
<property name="enabled">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="leLabel">
<property name="enabled">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="pbSelection">
<property name="text">
<string>Replace References with Current Selection</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gbReferences2D">
<property name="title">
<string>References 2D</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Object</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="leObject2d">
<property name="toolTip">
<string>The View that owns this Dimension</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_6">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>90</height>
</size>
</property>
<property name="text">
<string>Geometry</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QListWidget" name="lwGeometry2d">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>64</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>90</height>
</size>
</property>
<property name="toolTip">
<string>The subelements of the View that define the geometry for this Dimension</string>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="resizeMode">
<enum>QListView::Adjust</enum>
</property>
<property name="itemAlignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gbReferences3d">
<property name="title">
<string>References 3D</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QTableWidget" name="twReferences3d">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="columnCount">
<number>3</number>
</property>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<column/>
<column/>
<column/>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -327,8 +327,8 @@ void TaskDimension::onDimUseDefaultClicked()
{
pointPair points = m_parent->getDimFeat()->getLinearPoints();
//duplicate coordinate conversion logic from QGIViewDimension
Base::Vector2d first2(points.first.x, -points.first.y);
Base::Vector2d second2(points.second.x, -points.second.y);
Base::Vector2d first2(points.first().x, -points.first().y);
Base::Vector2d second2(points.second().x, -points.second().y);
double lineAngle = (second2 - first2).Angle();
ui->dsbDimAngle->setValue(lineAngle * 180.0 / M_PI);
}
@@ -345,8 +345,8 @@ void TaskDimension::onExtUseDefaultClicked()
{
pointPair points = m_parent->getDimFeat()->getLinearPoints();
//duplicate coordinate conversion logic from QGIViewDimension
Base::Vector2d first2(points.first.x, -points.first.y);
Base::Vector2d second2(points.second.x, -points.second.y);
Base::Vector2d first2(points.first().x, -points.first().y);
Base::Vector2d second2(points.second().x, -points.second().y);
Base::Vector2d lineDirection = second2 - first2;
Base::Vector2d extensionDirection(-lineDirection.y, lineDirection.x);
double extensionAngle = extensionDirection.Angle();

View File

@@ -99,7 +99,8 @@ void ViewProviderDimension::attach(App::DocumentObject *pcFeat)
// call parent attach method
ViewProviderDrawingView::attach(pcFeat);
sPixmap = "TechDraw_Dimension";
// sPixmap = "TechDraw_Dimension";
setPixmapForType();
if (getViewObject()->isDerivedFrom(TechDraw::LandmarkDimension::getClassTypeId())) {
sPixmap = "TechDraw_LandmarkDimension";
}
@@ -141,20 +142,7 @@ bool ViewProviderDimension::setEdit(int ModNum)
void ViewProviderDimension::updateData(const App::Property* prop)
{
if (prop == &(getViewObject()->Type)) {
if (getViewObject()->Type.isValue("DistanceX")) {
sPixmap = "TechDraw_HorizontalDimension";
} else if (getViewObject()->Type.isValue("DistanceY")) {
sPixmap = "TechDraw_VerticalDimension";
} else if (getViewObject()->Type.isValue("Radius")) {
sPixmap = "TechDraw_RadiusDimension";
} else if (getViewObject()->Type.isValue("Diameter")) {
sPixmap = "TechDraw_DiameterDimension";
} else if (getViewObject()->Type.isValue("Angle")) {
sPixmap = "TechDraw_AngleDimension";
} else if (getViewObject()->Type.isValue("Angle3Pt")) {
sPixmap = "TechDraw_3PtAngleDimension";
}
return;
setPixmapForType();
}
//Dimension handles X, Y updates differently that other QGIView
@@ -171,7 +159,8 @@ void ViewProviderDimension::updateData(const App::Property* prop)
prop == &(getViewObject()->EqualTolerance) ||
prop == &(getViewObject()->OverTolerance) ||
prop == &(getViewObject()->UnderTolerance) ||
prop == &(getViewObject()->Inverted) ){
prop == &(getViewObject()->Inverted) ) {
QGIView* qgiv = getQView();
if (qgiv) {
qgiv->updateView(true);
@@ -183,6 +172,23 @@ void ViewProviderDimension::updateData(const App::Property* prop)
Gui::ViewProviderDocumentObject::updateData(prop);
}
void ViewProviderDimension::setPixmapForType()
{
if (getViewObject()->Type.isValue("DistanceX")) {
sPixmap = "TechDraw_HorizontalDimension";
} else if (getViewObject()->Type.isValue("DistanceY")) {
sPixmap = "TechDraw_VerticalDimension";
} else if (getViewObject()->Type.isValue("Radius")) {
sPixmap = "TechDraw_RadiusDimension";
} else if (getViewObject()->Type.isValue("Diameter")) {
sPixmap = "TechDraw_DiameterDimension";
} else if (getViewObject()->Type.isValue("Angle")) {
sPixmap = "TechDraw_AngleDimension";
} else if (getViewObject()->Type.isValue("Angle3Pt")) {
sPixmap = "TechDraw_3PtAngleDimension";
}
}
void ViewProviderDimension::onChanged(const App::Property* p)
{
if ((p == &Font) ||

View File

@@ -23,8 +23,8 @@
#ifndef DRAWINGGUI_VIEWPROVIDERDIMENSION_H
#define DRAWINGGUI_VIEWPROVIDERDIMENSION_H
#include <Mod/TechDraw/TechDrawGlobal.h>
#include <Mod/TechDraw/TechDrawGlobal.h>
#include <App/PropertyUnits.h>
@@ -84,6 +84,7 @@ public:
double prefWeight() const;
int prefStandardAndStyle() const;
bool canDelete(App::DocumentObject* obj) const override;
void setPixmapForType();
protected:
void handleChangedPropertyType(Base::XMLReader &reader, const char *TypeName, App::Property * prop) override;

View File

@@ -86,6 +86,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const
*dimensions << "TechDraw_VerticalExtentDimension";
*dimensions << "TechDraw_LinkDimension";
*dimensions << "TechDraw_LandmarkDimension";
*dimensions << "TechDraw_DimensionRepair";
// extension: attributes and modifications
Gui::MenuItem* toolattrib = new Gui::MenuItem;
@@ -269,13 +270,16 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
Gui::ToolBarItem *dims = new Gui::ToolBarItem(root);
dims->setCommand("TechDraw Dimensions");
*dims << "TechDraw_LengthDimension";
*dims << "TechDraw_HorizontalDimension";
*dims << "TechDraw_VerticalDimension";
*dims << "TechDraw_RadiusDimension";
*dims << "TechDraw_DiameterDimension";
*dims << "TechDraw_AngleDimension";
*dims << "TechDraw_3PtAngleDimension";
*dims << "TechDraw_LinearGroup";
// *dims << "TechDraw_LengthDimension";
// *dims << "TechDraw_HorizontalDimension";
// *dims << "TechDraw_VerticalDimension";
*dims << "TechDraw_RadialGroup";
// *dims << "TechDraw_RadiusDimension";
// *dims << "TechDraw_DiameterDimension";
*dims << "TechDraw_AngularGroup";
// *dims << "TechDraw_AngleDimension";
// *dims << "TechDraw_3PtAngleDimension";
*dims << "TechDraw_ExtentGroup";
// *dims << "TechDraw_HorizontalExtentDimension";
// *dims << "TechDraw_VerticalExtentDimension";
@@ -283,6 +287,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
*dims << "TechDraw_Balloon";
*dims << "TechDraw_LandmarkDimension";
// *dims << "TechDraw_Dimension"
*dims << "TechDraw_DimensionRepair";
Gui::ToolBarItem *extattribs = new Gui::ToolBarItem(root);
extattribs->setCommand("TechDraw Attributes");
@@ -416,13 +421,16 @@ Gui::ToolBarItem* Workbench::setupCommandBars() const
Gui::ToolBarItem *dims = new Gui::ToolBarItem(root);
dims->setCommand("TechDraw Dimensions");
*dims << "TechDraw_LengthDimension";
*dims << "TechDraw_HorizontalDimension";
*dims << "TechDraw_VerticalDimension";
*dims << "TechDraw_RadiusDimension";
*dims << "TechDraw_DiameterDimension";
*dims << "TechDraw_AngleDimension";
*dims << "TechDraw_3PtAngleDimension";
*dims << "TechDraw_LinearGroup";
// *dims << "TechDraw_LengthDimension";
// *dims << "TechDraw_HorizontalDimension";
// *dims << "TechDraw_VerticalDimension";
*dims << "TechDraw_RadialGroup";
// *dims << "TechDraw_RadiusDimension";
// *dims << "TechDraw_DiameterDimension";
*dims << "TechDraw_AngularGroup";
// *dims << "TechDraw_AngleDimension";
// *dims << "TechDraw_3PtAngleDimension";
*dims << "TechDraw_ExtentGroup";
// *dims << "TechDraw_HorizontalExtentDimension";
// *dims << "TechDraw_VerticalExtentDimension";
@@ -430,6 +438,7 @@ Gui::ToolBarItem* Workbench::setupCommandBars() const
*dims << "TechDraw_Balloon";
*dims << "TechDraw_LandmarkDimension";
// *dims << "TechDraw_Dimension";
*dims << "TechDraw_DimensionRepair";
Gui::ToolBarItem *extattribs = new Gui::ToolBarItem(root);
extattribs->setCommand("TechDraw Attributes");