Merge pull request #21051 from WandererFan/ComplexSectionCrash

[TD]Complex section crash (fix #20155)
This commit is contained in:
Chris Hennes
2025-05-04 20:53:05 -05:00
committed by GitHub
9 changed files with 858 additions and 549 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -35,38 +35,52 @@
namespace TechDraw
{
class TechDrawExport AlignedSizeResponse
{
public:
AlignedSizeResponse(const TopoDS_Shape& piece, Base::Vector3d size, double zvalue) :
alignedPiece(piece),
pieceSize(size),
zMax(zvalue) {}
TopoDS_Shape alignedPiece;
Base::Vector3d pieceSize;
double zMax;
};
//NOLINTBEGIN
class TechDrawExport DrawComplexSection: public DrawViewSection
{
PROPERTY_HEADER_WITH_OVERRIDE(TechDraw::DrawComplexSection);
//NOLINTEND
public:
DrawComplexSection();
~DrawComplexSection() override = default;
//NOLINTBEGIN
App::PropertyLink CuttingToolWireObject;
App::PropertyEnumeration ProjectionStrategy;//Offset or Aligned
//NOLINTEND
TopoDS_Shape makeCuttingTool(double dMax) override;
gp_Ax2 getCSFromBase(const std::string sectionName) const override;
gp_Ax2 getCSFromBase(const std::string& sectionName) const override;
bool isBaseValid() const override;
TopoDS_Compound findSectionPlaneIntersections(const TopoDS_Shape& cutShape) override;
TopoDS_Shape prepareShape(const TopoDS_Shape& cutShape, double shapeSize) override;
TopoDS_Shape getShapeToPrepare() const override;
TopoDS_Shape getShapeToIntersect() override;
gp_Pln getSectionPlane() const override;
TopoDS_Compound alignSectionFaces(TopoDS_Shape faceIntersections) override;
TopoDS_Compound alignSectionFaces(const TopoDS_Shape& faceIntersections) override;
std::pair<Base::Vector3d, Base::Vector3d> sectionLineEnds() override;
void makeSectionCut(const TopoDS_Shape& baseShape) override;
void waitingForAlign(bool s) { m_waitingForAlign = s; }
bool waitingForAlign(void) const { return m_waitingForAlign; }
bool waitingForAlign() const { return m_waitingForAlign; }
TopoDS_Shape getShapeForDetail() const override;
public Q_SLOTS:
void onSectionCutFinished(void) override;
bool boxesIntersect(TopoDS_Face& face, TopoDS_Shape& shape);
TopoDS_Shape shapeShapeIntersect(const TopoDS_Shape& shape0, const TopoDS_Shape& shape1);
std::vector<TopoDS_Face> faceShapeIntersect(const TopoDS_Face& face, const TopoDS_Shape& shape);
@@ -81,26 +95,65 @@ public Q_SLOTS:
ChangePointVector getChangePointsFromSectionLine() override;
bool validateProfilePosition(TopoDS_Wire profileWire, gp_Ax2 sectionCS,
gp_Dir& gClosestBasis) const;
bool validateProfilePosition(const TopoDS_Wire& profileWire, const gp_Ax2& sectionCS) const;
bool showSegment(gp_Dir segmentNormal) const;
gp_Vec projectVector(const gp_Vec& vec) const;
TopoDS_Wire makeProfileWire() const;
static TopoDS_Wire makeProfileWire(App::DocumentObject* toolObj);
static TopoDS_Wire makeNoseToTailWire(TopoDS_Wire inWire);
static gp_Vec makeProfileVector(TopoDS_Wire profileWire);
static TopoDS_Wire makeNoseToTailWire(const TopoDS_Wire& inWire);
static gp_Vec makeProfileVector(const TopoDS_Wire& profileWire);
static bool isProfileObject(App::DocumentObject* obj);
static bool isMultiSegmentProfile(App::DocumentObject* obj);
static bool isLinearProfile(App::DocumentObject* obj);
static bool isTrulyEmpty(TopoDS_Shape inShape);
static bool isTrulyEmpty(const TopoDS_Shape& inShape);
static bool canBuild(gp_Ax2 sectionCS, App::DocumentObject* profileObject);
static gp_Vec projectVector(const gp_Vec& vec, gp_Ax2 sectionCS);
static std::pair<Base::Vector3d, Base::Vector3d> getSegmentEnds(const TopoDS_Edge& segment);
static std::pair<Base::Vector3d, Base::Vector3d> getWireEnds(const TopoDS_Wire& wire);
public Q_SLOTS:
void onSectionCutFinished() override;
private:
gp_Dir getFaceNormal(TopoDS_Face& face);
bool validateOffsetProfile(TopoDS_Wire profile, Base::Vector3d direction, double angleThresholdDeg) const;
std::pair<Base::Vector3d, Base::Vector3d> getSegmentEnds(TopoDS_Edge segment) const;
Base::Vector3d getReferenceAxis();
// methods refactored out of makeAlignedPieces
bool getReversers(const gp_Vec& gProfileVector, double& horizReverser, double& verticalReverser);
AlignedSizeResponse getAlignedSize(const TopoDS_Shape& pieceRotated, int iPiece) const;
TopoDS_Shape cutAndRotatePiece(const TopoDS_Shape& rawShape,
const TopoDS_Face& segmentFace,
int iPiece,
Base::Vector3d uOrientedSegmentNormal,
Base::Vector3d uRotateAxis,
double& pieceVertical);
TopoDS_Shape movePieceToPaperPlane(const TopoDS_Shape& piece, double sizeMax);
TopoDS_Shape distributePiece(const TopoDS_Shape& piece,
double pieceSize,
double verticalDisplace,
const gp_Vec& alignmentAxis,
const gp_Vec& gMovementVector,
double baseDistance);
std::vector<std::pair<int, Base::Vector3d> >
getSegmentViewDirections(const TopoDS_Wire& profileWire,
Base::Vector3d sectionNormal,
Base::Vector3d referenceAxis) const;
std::vector<Base::Vector3d> getPointsForClosingProfile(const TopoDS_Wire& profileWire,
double dMax);
static std::vector<TopoDS_Edge> getUniqueEdges(const TopoDS_Wire& wireIn);
static TopoDS_Shape removeEmptyShapes(const TopoDS_Shape& roughTool);
static gp_Dir getFaceNormal(TopoDS_Face& face);
static bool faceContainsEndpoints(const TopoDS_Edge& edgeToMatch,
const TopoDS_Face& faceToSearch);
static bool normalLess(const std::pair<int, Base::Vector3d>& n1,
const std::pair<int, Base::Vector3d>& n2);
static TopoDS_Wire closeProfile(const TopoDS_Wire& profileWire, Base::Vector3d referenceAxis, double dMax);
static TopoDS_Shape profileToSolid(const TopoDS_Wire& closedProfileWire, Base::Vector3d referenceAxis, double dMax);
TopoDS_Shape m_toolFaceShape;
TopoDS_Shape m_alignResult;
@@ -111,7 +164,7 @@ private:
QFuture<void> m_alignFuture;
bool m_waitingForAlign;
static const char* ProjectionStrategyEnums[];
static const char* ProjectionStrategyEnums[]; //NOLINT
};
using DrawComplexSectionPython = App::FeaturePythonT<DrawComplexSection>;

View File

@@ -119,7 +119,7 @@ DrawViewPart::DrawViewPart()
ADD_PROPERTY_TYPE(Direction, (0.0, -1.0, 0.0), group, App::Prop_None,
"Projection Plane normal. The direction you are looking from.");
ADD_PROPERTY_TYPE(XDirection, (0.0, 0.0, 0.0), group, App::Prop_None,
ADD_PROPERTY_TYPE(XDirection, (1.0, 0.0, 0.0), group, App::Prop_None,
"Projection Plane X Axis in R3. Rotates/Mirrors View");
ADD_PROPERTY_TYPE(Perspective, (false), group, App::Prop_None,
"Perspective(true) or Orthographic(false) projection");
@@ -170,17 +170,17 @@ DrawViewPart::~DrawViewPart()
//! returns a compound of all the shapes from the DocumentObjects in the Source &
//! XSource property lists
TopoDS_Shape DrawViewPart::getSourceShape(bool fuse) const
TopoDS_Shape DrawViewPart::getSourceShape(bool fuse, bool allow2d) const
{
// Base::Console().Message("DVP::getSourceShape()\n");
const std::vector<App::DocumentObject*>& links = getAllSources();
if (links.empty()) {
return TopoDS_Shape();
return {};
}
if (fuse) {
return ShapeExtractor::getShapesFused(links);
}
return ShapeExtractor::getShapes(links);
return ShapeExtractor::getShapes(links, allow2d);
}
//! deliver a shape appropriate for making a detail view based on this view
@@ -278,8 +278,14 @@ void DrawViewPart::onChanged(const App::Property* prop)
// Otherwise bad things will happen because there'll be a normalization for direction calculations later.
Base::Vector3d dir = Direction.getValue();
if (DrawUtil::fpCompare(dir.Length(), 0.0)) {
Base::Console().Warning("%s Direction is null. Using (0, -1, 0).\n", Label.getValue());
Direction.setValue(Base::Vector3d(0.0, -1.0, 0.0));
}
Base::Vector3d xdir = XDirection.getValue();
if (DrawUtil::fpCompare(xdir.Length(), 0.0)) {
Base::Console().Warning("%s XDirection is null. Using (1, 0, 0).\n", Label.getValue());
XDirection.setValue(Base::Vector3d(1.0, 0.0, 0.0));
}
DrawView::onChanged(prop);
}

View File

@@ -212,7 +212,7 @@ public:
bool newFaceFinder();
bool isUnsetting() { return nowUnsetting; }
virtual TopoDS_Shape getSourceShape(bool fuse = false) const;
virtual TopoDS_Shape getSourceShape(bool fuse = false, bool allow2d = true) const;
virtual TopoDS_Shape getShapeForDetail() const;
std::vector<App::DocumentObject*> getAllSources() const;

View File

@@ -100,11 +100,11 @@ using namespace TechDraw;
using DU = DrawUtil;
// class to store geometry of points where the section line changes direction
ChangePoint::ChangePoint(QPointF location, QPointF preDirection, QPointF postDirection)
ChangePoint::ChangePoint(QPointF location, QPointF preDirection, QPointF postDirection) :
m_location(location),
m_preDirection(preDirection),
m_postDirection(postDirection)
{
m_location = location;
m_preDirection = preDirection;
m_postDirection = postDirection;
}
ChangePoint::ChangePoint(gp_Pnt location, gp_Dir preDirection, gp_Dir postDirection)
@@ -122,10 +122,12 @@ void ChangePoint::scale(double scaleFactor)
m_location = m_location * scaleFactor;
}
//NOLINTBEGIN
const char* DrawViewSection::SectionDirEnums[] =
{"Right", "Left", "Up", "Down", "Aligned", nullptr};
const char* DrawViewSection::CutSurfaceEnums[] = {"Hide", "Color", "SvgHatch", "PatHatch", nullptr};
//NOLINTEND
constexpr double stretchMinimum{EWTOLERANCE};
constexpr double stretchMaximum{std::numeric_limits<double>::max()};
@@ -161,8 +163,10 @@ DrawViewSection::DrawViewSection()
App::Prop_None,
"2D View source for this Section");
BaseView.setScope(App::LinkScope::Global);
// default of (0, -1, 0) matches 'Front' direction in DVP
ADD_PROPERTY_TYPE(SectionNormal,
(0, 0, 1.0),
(0, -1, 0),
sgroup,
App::Prop_None,
"Section Plane normal direction");// direction of extrusion
@@ -172,7 +176,7 @@ DrawViewSection::DrawViewSection()
// TODO: SectionDirection is a legacy from when SectionViews were only
// available along cardinal directions. It should be made obsolete and
// replaced with Aligned sections and local unit vectors.
SectionDirection.setEnums(SectionDirEnums);
SectionDirection.setEnums(SectionDirEnums); //NOLINT
ADD_PROPERTY_TYPE(SectionDirection,
((long)0),
sgroup,
@@ -197,7 +201,7 @@ DrawViewSection::DrawViewSection()
"Use the cut shape from the base view instead of the original object");
// properties related to the display of the cut surface
CutSurfaceDisplay.setEnums(CutSurfaceEnums);
CutSurfaceDisplay.setEnums(CutSurfaceEnums); //NOLINT
ADD_PROPERTY_TYPE(CutSurfaceDisplay,
(prefCutSurface()),
fgroup,
@@ -250,8 +254,11 @@ DrawViewSection::DrawViewSection()
SvgIncluded.setStatus(App::Property::ReadOnly, true);
PatIncluded.setStatus(App::Property::ReadOnly, true);
// SectionNormal is used instead to Direction
Direction.setStatus(App::Property::ReadOnly, true);
Direction.setValue(SectionNormal.getValue());
SectionDirection.setStatus(App::Property::Hidden, true);
SectionDirection.setStatus(App::Property::ReadOnly, true);
}
@@ -260,7 +267,6 @@ DrawViewSection::~DrawViewSection()
{
// don't destroy this object while it has dependent threads running
if (m_cutFuture.isRunning()) {
Base::Console().Message("%s is waiting for tasks to complete\n", Label.getValue());
m_cutFuture.waitForFinished();
}
}
@@ -268,7 +274,7 @@ DrawViewSection::~DrawViewSection()
short DrawViewSection::mustExecute() const
{
if (isRestoring()) {
return TechDraw::DrawView::mustExecute();
return TechDraw::DrawView::mustExecute(); //NOLINT
}
if (Scale.isTouched() || Direction.isTouched() || BaseView.isTouched()
@@ -276,7 +282,7 @@ short DrawViewSection::mustExecute() const
return 1;
}
return TechDraw::DrawView::mustExecute();
return TechDraw::DrawView::mustExecute(); //NOLINT
}
void DrawViewSection::onChanged(const App::Property* prop)
@@ -293,40 +299,47 @@ void DrawViewSection::onChanged(const App::Property* prop)
return;
}
if (prop == &SectionNormal) {
if (prop == &SectionNormal ||
prop == &XDirection) {
Direction.setValue(SectionNormal.getValue());
return;
}
else if (prop == &SectionSymbol) {
if (prop == &SectionSymbol) {
if (getBaseDVP()) {
getBaseDVP()->requestPaint();
}
return;
}
else if (prop == &CutSurfaceDisplay) {
if (prop == &CutSurfaceDisplay) {
if (CutSurfaceDisplay.isValue("PatHatch")) {
makeLineSets();
}
requestPaint();
return;
}
else if (prop == &FileHatchPattern) {
if (prop == &FileHatchPattern) {
replaceSvgIncluded(FileHatchPattern.getValue());
requestPaint();
return;
}
else if (prop == &FileGeomPattern) {
if (prop == &FileGeomPattern) {
replacePatIncluded(FileGeomPattern.getValue());
makeLineSets();
requestPaint();
return;
}
else if (prop == &NameGeomPattern) {
if (prop == &NameGeomPattern) {
makeLineSets();
requestPaint();
return;
}
else if (prop == &BaseView) {
if (prop == &BaseView) {
// if the BaseView is a Section, then the option of using UsePreviousCut is
// valid.
if (BaseView.getValue() && BaseView.getValue()->isDerivedFrom<TechDraw::DrawViewSection>()) {
@@ -335,23 +348,23 @@ void DrawViewSection::onChanged(const App::Property* prop)
else {
UsePreviousCut.setStatus(App::Property::ReadOnly, true);
}
} else if (prop == &SectionLineStretch) {
}
if (prop == &SectionLineStretch) {
BaseView.getValue()->touch();
}
DrawView::onChanged(prop);
DrawView::onChanged(prop); //NOLINT
}
TopoDS_Shape DrawViewSection::getShapeToCut()
{
// Base::Console().Message("DVS::getShapeToCut() - %s\n",
// getNameInDocument());
App::DocumentObject* base = BaseView.getValue();
TechDraw::DrawViewPart* dvp = nullptr;
TechDraw::DrawViewSection* dvs = nullptr;
TechDraw::DrawViewDetail* dvd = nullptr;
if (!base) {
return TopoDS_Shape();
return {};
}
TopoDS_Shape shapeToCut;
@@ -368,14 +381,16 @@ TopoDS_Shape DrawViewSection::getShapeToCut()
}
else if (base->isDerivedFrom<TechDraw::DrawViewPart>()) {
dvp = static_cast<TechDraw::DrawViewPart*>(base);
shapeToCut = dvp->getSourceShape();
constexpr bool fuseBefore{true};
constexpr bool allow2d{false};
shapeToCut = dvp->getSourceShape(!fuseBefore, allow2d);
if (FuseBeforeCut.getValue()) {
shapeToCut = dvp->getSourceShape(true);
shapeToCut = dvp->getSourceShape(fuseBefore);
}
}
else {
Base::Console().Message("DVS::getShapeToCut - base is weird\n");
return TopoDS_Shape();
return {};
}
return shapeToCut;
}
@@ -387,7 +402,6 @@ TopoDS_Shape DrawViewSection::getShapeForDetail() const
App::DocumentObjectExecReturn* DrawViewSection::execute()
{
// Base::Console().Message("DVS::execute() - %s\n", Label.getValue());
if (!keepUpdated()) {
return App::DocumentObject::StdReturn;
}
@@ -397,13 +411,13 @@ App::DocumentObjectExecReturn* DrawViewSection::execute()
}
if (waitingForCut() || waitingForHlr()) {
return DrawView::execute();
return DrawView::execute(); //NOLINT
}
TopoDS_Shape baseShape = getShapeToCut();
if (baseShape.IsNull()) {
return DrawView::execute();
return DrawView::execute(); //NOLINT
}
// is SectionOrigin valid?
@@ -433,16 +447,13 @@ App::DocumentObjectExecReturn* DrawViewSection::execute()
sectionExec(baseShape);
addPoints();
return DrawView::execute();
return DrawView::execute(); //NOLINT
}
bool DrawViewSection::isBaseValid() const
{
App::DocumentObject* base = BaseView.getValue();
if (base && base->isDerivedFrom<TechDraw::DrawViewPart>()) {
return true;
}
return false;
return base && base->isDerivedFrom<TechDraw::DrawViewPart>();
}
void DrawViewSection::sectionExec(TopoDS_Shape& baseShape)
@@ -601,15 +612,14 @@ TopoDS_Shape DrawViewSection::makeCuttingTool(double shapeSize)
gp_Pln pln = getSectionPlane();
gp_Dir gpNormal = pln.Axis().Direction();
BRepBuilderAPI_MakeFace mkFace(pln, -shapeSize, shapeSize, -shapeSize, shapeSize);
TopoDS_Face aProjFace = mkFace.Face();
if (aProjFace.IsNull()) {
return TopoDS_Shape();
if (mkFace.Face().IsNull()) {
return {};
}
if (debugSection()) {
BRepTools::Write(aProjFace, "DVSSectionFace.brep");// debug
BRepTools::Write(mkFace.Face(), "DVSSectionFace.brep");// debug
}
gp_Vec extrudeDir = shapeSize * gp_Vec(gpNormal);
return BRepPrimAPI_MakePrism(aProjFace, extrudeDir, false, true).Shape();
return BRepPrimAPI_MakePrism(mkFace.Face(), extrudeDir, false, true).Shape();
}
void DrawViewSection::onSectionCutFinished()
@@ -634,7 +644,7 @@ void DrawViewSection::onSectionCutFinished()
}
// activities that depend on updated geometry object
void DrawViewSection::postHlrTasks(void)
void DrawViewSection::postHlrTasks()
{
DrawViewPart::postHlrTasks();
@@ -671,7 +681,7 @@ void DrawViewSection::postHlrTasks(void)
}
m_tdSectionFaces = makeTDSectionFaces(m_sectionTopoDSFaces);
TechDraw::DrawViewPart* dvp = dynamic_cast<TechDraw::DrawViewPart*>(BaseView.getValue());
auto* dvp = dynamic_cast<TechDraw::DrawViewPart*>(BaseView.getValue());
if (dvp) {
dvp->requestPaint();// to refresh section line
}
@@ -693,10 +703,7 @@ void DrawViewSection::postSectionCutTasks()
bool DrawViewSection::waitingForResult() const
{
if (DrawViewPart::waitingForResult() || waitingForCut()) {
return true;
}
return false;
return DrawViewPart::waitingForResult() || waitingForCut();
}
gp_Pln DrawViewSection::getSectionPlane() const
@@ -704,7 +711,7 @@ gp_Pln DrawViewSection::getSectionPlane() const
gp_Ax2 viewAxis = getSectionCS();
gp_Ax3 viewAxis3(viewAxis);
return gp_Pln(viewAxis3);
return {viewAxis3};
}
//! tries to find the intersection of the section plane with the shape giving a
@@ -720,7 +727,7 @@ TopoDS_Compound DrawViewSection::findSectionPlaneIntersections(const TopoDS_Shap
Base::Console().Warning(
"DrawViewSection::findSectionPlaneInter - %s - input shape is Null\n",
getNameInDocument());
return TopoDS_Compound();
return {};
}
gp_Pln plnSection = getSectionPlane();
@@ -753,7 +760,7 @@ TopoDS_Compound DrawViewSection::findSectionPlaneIntersections(const TopoDS_Shap
}
// move section faces to line up with cut shape
TopoDS_Compound DrawViewSection::alignSectionFaces(TopoDS_Shape faceIntersections)
TopoDS_Compound DrawViewSection::alignSectionFaces(const TopoDS_Shape& faceIntersections)
{
TopoDS_Compound sectionFaces;
TopoDS_Shape centeredShape =
@@ -772,7 +779,7 @@ TopoDS_Compound DrawViewSection::alignSectionFaces(TopoDS_Shape faceIntersection
return mapToPage(scaledSection);
}
TopoDS_Compound DrawViewSection::mapToPage(TopoDS_Shape& shapeToAlign)
TopoDS_Compound DrawViewSection::mapToPage(const TopoDS_Shape& shapeToAlign)
{
// shapeToAlign is compound of TopoDS_Face intersections, but aligned to
// pln(origin, sectionNormal) needs to be aligned to paper plane (origin,
@@ -817,7 +824,7 @@ TopoDS_Compound DrawViewSection::mapToPage(TopoDS_Shape& shapeToAlign)
wireEdges.push_back(edge);
}
TopoDS_Wire cleanWire = EdgeWalker::makeCleanWire(wireEdges, 2.0 * EWTOLERANCE);
TopoDS_Wire cleanWire = EdgeWalker::makeCleanWire(wireEdges, 2 * EWTOLERANCE);
faceWires.push_back(cleanWire);
}
@@ -878,14 +885,14 @@ TopoDS_Shape DrawViewSection::makeFaceFromWires(std::vector<TopoDS_Wire>& inWire
TopoDS_Wire orientedWire = TopoDS::Wire(orientedShape);
orientedWire.Orientation(TopAbs_FORWARD);
TopoDS_Face blankFace = BRepBuilderAPI_MakeFace(orientedWire);
int wireCount = goodWires.size();
size_t wireCount = goodWires.size();
if (wireCount < 2) {
faceToFix = blankFace;
}
else {
// add the holes
BRepBuilderAPI_MakeFace mkFace(blankFace);
for (int iWire = 1; iWire < wireCount; iWire++) {
for (size_t iWire = 1; iWire < wireCount; iWire++) {
// make holes in the face with the rest of the wires
orientedShape = goodWires.at(iWire).Oriented(TopAbs_REVERSED);
orientedWire = TopoDS::Wire(orientedShape);
@@ -895,7 +902,7 @@ TopoDS_Shape DrawViewSection::makeFaceFromWires(std::vector<TopoDS_Wire>& inWire
if (!mkFace.IsDone()) {
Base::Console().Warning("DVS::makeFaceFromWires - %s - failed to make section face.\n",
getNameInDocument());
return TopoDS_Shape();
return {};
}
faceToFix = mkFace.Face();
}
@@ -909,7 +916,7 @@ TopoDS_Shape DrawViewSection::makeFaceFromWires(std::vector<TopoDS_Wire>& inWire
}
// turn OCC section faces into TD geometry
std::vector<TechDraw::FacePtr> DrawViewSection::makeTDSectionFaces(TopoDS_Compound topoDSFaces)
std::vector<TechDraw::FacePtr> DrawViewSection::makeTDSectionFaces(const TopoDS_Compound& topoDSFaces)
{
// Base::Console().Message("DVS::makeTDSectionFaces()\n");
std::vector<TechDraw::FacePtr> tdSectionFaces;
@@ -919,7 +926,7 @@ std::vector<TechDraw::FacePtr> DrawViewSection::makeTDSectionFaces(TopoDS_Compou
TechDraw::FacePtr sectionFace(std::make_shared<TechDraw::Face>());
TopExp_Explorer expFace(face, TopAbs_WIRE);
for (; expFace.More(); expFace.Next()) {
TechDraw::Wire* w = new TechDraw::Wire();
auto* w = new TechDraw::Wire();
const TopoDS_Wire& wire = TopoDS::Wire(expFace.Current());
TopExp_Explorer expWire(wire, TopAbs_EDGE);
for (; expWire.More(); expWire.Next()) {
@@ -946,7 +953,7 @@ std::pair<Base::Vector3d, Base::Vector3d> DrawViewSection::sectionLineEnds()
Base::Vector3d sectionOrg = SectionOrigin.getValue() - getBaseDVP()->getOriginalCentroid();
sectionOrg = getBaseDVP()->projectPoint(sectionOrg);// convert to base view CS
double halfSize = (getBaseDVP()->getSizeAlongVector(dir) / 2.0) * SectionLineStretch.getValue();
double halfSize = (getBaseDVP()->getSizeAlongVector(dir) / 2) * SectionLineStretch.getValue();
result.first = sectionOrg + dir * halfSize;
result.second = sectionOrg - dir * halfSize;
@@ -972,14 +979,14 @@ ChangePointVector DrawViewSection::getChangePointsFromSectionLine()
// Base::Console().Message("Dvs::getChangePointsFromSectionLine()\n");
ChangePointVector result;
std::vector<gp_Pnt> allPoints;
DrawViewPart* baseDvp = freecad_cast<DrawViewPart*>(BaseView.getValue());
auto* baseDvp = freecad_cast<DrawViewPart*>(BaseView.getValue());
if (baseDvp) {
std::pair<Base::Vector3d, Base::Vector3d> lineEnds = sectionLineEnds();
// make start and end marks
gp_Pnt location0 = Base::convertTo<gp_Pnt>(lineEnds.first);
gp_Pnt location1 = Base::convertTo<gp_Pnt>(lineEnds.second);
gp_Dir postDir = gp_Dir(location1.XYZ() - location0.XYZ());
gp_Dir preDir = postDir.Reversed();
auto location0 = Base::convertTo<gp_Pnt>(lineEnds.first);
auto location1 = Base::convertTo<gp_Pnt>(lineEnds.second);
auto postDir = gp_Dir(location1.XYZ() - location0.XYZ());
auto preDir = postDir.Reversed();
ChangePoint startPoint(location0, preDir, postDir);
result.push_back(startPoint);
preDir = gp_Dir(location0.XYZ() - location1.XYZ());
@@ -993,29 +1000,27 @@ ChangePointVector DrawViewSection::getChangePointsFromSectionLine()
// this should really be in BoundBox.h
//! check if point is in box or on boundary of box
//! compare to isInBox which doesn't allow on boundary
bool DrawViewSection::isReallyInBox(const Base::Vector3d v, const Base::BoundBox3d bb) const
bool DrawViewSection::isReallyInBox(const Base::Vector3d& vec, const Base::BoundBox3d& bb) const
{
if (v.x <= bb.MinX || v.x >= bb.MaxX) {
if (vec.x <= bb.MinX || vec.x >= bb.MaxX) {
return false;
}
if (v.y <= bb.MinY || v.y >= bb.MaxY) {
if (vec.y <= bb.MinY || vec.y >= bb.MaxY) {
return false;
}
if (v.z <= bb.MinZ || v.z >= bb.MaxZ) {
if (vec.z <= bb.MinZ || vec.z >= bb.MaxZ) {
return false;
}
return true;
}
bool DrawViewSection::isReallyInBox(const gp_Pnt p, const Bnd_Box& bb) const
bool DrawViewSection::isReallyInBox(const gp_Pnt& point, const Bnd_Box& bb) const
{
return !bb.IsOut(p);
return !bb.IsOut(point);
}
Base::Vector3d DrawViewSection::getXDirection() const
{
// Base::Console().Message("DVS::getXDirection() - %s\n",
// Label.getValue());
App::Property* prop = getPropertyByName("XDirection");
if (!prop) {
// No XDirection property. can this happen?
@@ -1038,10 +1043,8 @@ Base::Vector3d DrawViewSection::getXDirection() const
return XDirection.getValue();
}
void DrawViewSection::setCSFromBase(const std::string sectionName)
void DrawViewSection::setCSFromBase(const std::string& sectionName)
{
// Base::Console().Message("DVS::setCSFromBase(%s)\n",
// sectionName.c_str());
gp_Dir gDir = getCSFromBase(sectionName).Direction();
Base::Vector3d vDir(gDir.X(), gDir.Y(), gDir.Z());
Direction.setValue(vDir);
@@ -1052,10 +1055,8 @@ void DrawViewSection::setCSFromBase(const std::string sectionName)
}
// set the section CS based on an XY vector in BaseViews CS
void DrawViewSection::setCSFromBase(const Base::Vector3d localUnit)
void DrawViewSection::setCSFromBase(const Base::Vector3d& localUnit)
{
// Base::Console().Message("DVS::setCSFromBase(%s)\n",
// DrawUtil::formatVector(localUnit).c_str());
gp_Ax2 newSectionCS = getBaseDVP()->localVectorToCS(localUnit);
Base::Vector3d vDir(newSectionCS.Direction().X(),
@@ -1070,24 +1071,20 @@ void DrawViewSection::setCSFromBase(const Base::Vector3d localUnit)
}
// reset the section CS based on an XY vector in current section CS
void DrawViewSection::setCSFromLocalUnit(const Base::Vector3d localUnit)
void DrawViewSection::setCSFromLocalUnit(const Base::Vector3d& localUnit)
{
// Base::Console().Message("DVS::setCSFromLocalUnit(%s)\n",
// DrawUtil::formatVector(localUnit).c_str());
gp_Dir verticalDir = getSectionCS().YDirection();
auto verticalDir = getSectionCS().YDirection();
gp_Ax1 verticalAxis(Base::convertTo<gp_Pnt>(SectionOrigin.getValue()), verticalDir);
gp_Dir oldNormal = getSectionCS().Direction();
gp_Dir newNormal = Base::convertTo<gp_Dir>(projectPoint(localUnit));
double angle = oldNormal.AngleWithRef(newNormal, verticalDir);
gp_Ax2 newCS = getSectionCS().Rotated(verticalAxis, angle);
auto oldNormal = getSectionCS().Direction();
auto newNormal = Base::convertTo<gp_Dir>(projectPoint(localUnit));
auto angle = oldNormal.AngleWithRef(newNormal, verticalDir);
auto newCS = getSectionCS().Rotated(verticalAxis, angle);
SectionNormal.setValue(Base::convertTo<Base::Vector3d>(newCS.Direction()));
XDirection.setValue(Base::convertTo<Base::Vector3d>(newCS.XDirection()));
}
gp_Ax2 DrawViewSection::getCSFromBase(const std::string sectionName) const
gp_Ax2 DrawViewSection::getCSFromBase(const std::string& sectionName) const
{
// Base::Console().Message("DVS::getCSFromBase(%s)\n",
// sectionName.c_str());
Base::Vector3d origin(0.0, 0.0, 0.0);
Base::Vector3d sectOrigin = SectionOrigin.getValue();
@@ -1143,7 +1140,6 @@ gp_Ax2 DrawViewSection::getCSFromBase(const std::string sectionName) const
// returns current section cs
gp_Ax2 DrawViewSection::getSectionCS() const
{
// Base::Console().Message("DVS::getSectionCS()\n");
Base::Vector3d vNormal = SectionNormal.getValue();
gp_Dir gNormal(vNormal.x, vNormal.y, vNormal.z);
Base::Vector3d vXDir = getXDirection();
@@ -1172,7 +1168,6 @@ Base::Vector3d DrawViewSection::getCutCentroid() const
std::vector<LineSet> DrawViewSection::getDrawableLines(int i)
{
// Base::Console().Message("DVS::getDrawableLines(%d) - lineSets: %d\n", i, m_lineSets.size());
if (m_lineSets.empty()) {
makeLineSets();
}
@@ -1194,14 +1189,14 @@ TopoDS_Face DrawViewSection::getSectionTopoDSFace(int i)
return TopoDS::Face(expl.Current());
}
}
return TopoDS_Face();
return {};
}
TechDraw::DrawViewPart* DrawViewSection::getBaseDVP() const
{
App::DocumentObject* base = BaseView.getValue();
if (base && base->isDerivedFrom<TechDraw::DrawViewPart>()) {
TechDraw::DrawViewPart* baseDVP = static_cast<TechDraw::DrawViewPart*>(base);
auto* baseDVP = static_cast<TechDraw::DrawViewPart*>(base);
return baseDVP;
}
return nullptr;
@@ -1260,12 +1255,35 @@ void DrawViewSection::handleChangedPropertyType(Base::XMLReader &reader, const c
}
}
// checks that SectionNormal and XDirection are perpendicular and that Direction is the same as
// SectionNormal
bool DrawViewSection::checkSectionCS() const
{
auto vNormal = SectionNormal.getValue();
vNormal.Normalize();
auto vXDirection = XDirection.getValue();
vXDirection.Normalize();
auto vDirection = Direction.getValue();
if (vNormal.Length() == 0 ||
vXDirection.Length() == 0 ||
vDirection.Length() == 0) {
return false;
}
if (!vNormal.IsEqual(vDirection, EWTOLERANCE)) {
return false;
}
auto orthoDot = std::fabs(vNormal.Dot(vXDirection));
return orthoDot <= EWTOLERANCE;
}
// hatch file routines
// create geometric hatch lines
void DrawViewSection::makeLineSets(void)
void DrawViewSection::makeLineSets()
{
// Base::Console().Message("DVS::makeLineSets()\n");
if (PatIncluded.isEmpty()) {
return;
}
@@ -1287,10 +1305,8 @@ void DrawViewSection::makeLineSets(void)
}
}
void DrawViewSection::replaceSvgIncluded(std::string newSvgFile)
void DrawViewSection::replaceSvgIncluded(const std::string& newSvgFile)
{
// Base::Console().Message("DVS::replaceSvgIncluded(%s)\n",
// newSvgFile.c_str());
if (newSvgFile.empty()) {
return;
}
@@ -1304,9 +1320,8 @@ void DrawViewSection::replaceSvgIncluded(std::string newSvgFile)
}
}
void DrawViewSection::replacePatIncluded(std::string newPatFile)
void DrawViewSection::replacePatIncluded(const std::string& newPatFile)
{
// Base::Console().Message("DVS::replacePatIncluded(%s)\n", newPatFile.c_str());
if (newPatFile.empty()) {
return;
}
@@ -1324,25 +1339,23 @@ void DrawViewSection::replacePatIncluded(std::string newPatFile)
void DrawViewSection::getParameters()
{
// Base::Console().Message("DVS::getParameters()\n");
bool fuseFirst = Preferences::getPreferenceGroup("General")->GetBool("SectionFuseFirst", false);
FuseBeforeCut.setValue(fuseFirst);
}
bool DrawViewSection::debugSection(void) const
bool DrawViewSection::debugSection() const
{
return Preferences::getPreferenceGroup("debug")->GetBool("debugSection", false);
}
int DrawViewSection::prefCutSurface(void) const
int DrawViewSection::prefCutSurface() const
{
// Base::Console().Message("DVS::prefCutSurface()\n");
//NOLINTNEXTLINE
return Preferences::getPreferenceGroup("Decorations")
->GetInt("CutSurfaceDisplay", 2);// default to SvgHatch
}
bool DrawViewSection::showSectionEdges(void)
bool DrawViewSection::showSectionEdges()
{
return Preferences::getPreferenceGroup("General")->GetBool("ShowSectionEdges", true);
}

View File

@@ -75,14 +75,17 @@ private:
using ChangePointVector = std::vector<ChangePoint>;
//NOLINTBEGIN
class TechDrawExport DrawViewSection: public DrawViewPart
{
PROPERTY_HEADER_WITH_OVERRIDE(TechDraw::DrawViewSection);
//NOLINTEND
public:
DrawViewSection();
~DrawViewSection() override;
//NOLINTBEGIN
App::PropertyLink BaseView;
App::PropertyDirection SectionNormal;
App::PropertyPosition SectionOrigin;
@@ -105,10 +108,10 @@ public:
App::PropertyBool UsePreviousCut; // new v022
App::PropertyFloatConstraint SectionLineStretch; // new v022
//NOLINTEND
bool isReallyInBox(const Base::Vector3d v, const Base::BoundBox3d bb) const;
bool isReallyInBox(const gp_Pnt p, const Bnd_Box& bb) const;
bool isReallyInBox(const Base::Vector3d& vec, const Base::BoundBox3d& bb) const;
bool isReallyInBox(const gp_Pnt& point, const Bnd_Box& bb) const;
App::DocumentObjectExecReturn* execute() override;
void onChanged(const App::Property* prop) override;
@@ -123,10 +126,10 @@ public:
void sectionExec(TopoDS_Shape& s);
virtual void makeSectionCut(const TopoDS_Shape& baseShape);
void postHlrTasks(void) override;
void postHlrTasks() override;
virtual void postSectionCutTasks();
void waitingForCut(bool s) { m_waitingForCut = s; }
bool waitingForCut(void) const { return m_waitingForCut; }
bool waitingForCut() const { return m_waitingForCut; }
bool waitingForResult() const override;
virtual TopoDS_Shape makeCuttingTool(double shapeSize);
@@ -136,10 +139,10 @@ public:
virtual TopoDS_Shape getShapeToPrepare() const { return m_cutPieces; }
//CS related methods
void setCSFromBase(const std::string sectionName);
void setCSFromBase(Base::Vector3d localUnit);
void setCSFromLocalUnit(const Base::Vector3d localUnit);
virtual gp_Ax2 getCSFromBase(const std::string sectionName) const;
void setCSFromBase(const std::string& sectionName);
void setCSFromBase(const Base::Vector3d& localUnit);
void setCSFromLocalUnit(const Base::Vector3d& localUnit);
virtual gp_Ax2 getCSFromBase(const std::string& sectionName) const;
gp_Ax2 getSectionCS() const;
Base::Vector3d getXDirection() const override;//don't use XDirection.getValue()
@@ -148,12 +151,12 @@ public:
//section face related methods
std::vector<TechDraw::FacePtr> getTDFaceGeometry() { return m_tdSectionFaces; }
TopoDS_Face getSectionTopoDSFace(int i);
virtual TopoDS_Compound alignSectionFaces(TopoDS_Shape faceIntersections);
TopoDS_Compound mapToPage(TopoDS_Shape& shapeToAlign);
virtual std::vector<TechDraw::FacePtr> makeTDSectionFaces(TopoDS_Compound topoDSFaces);
virtual TopoDS_Compound alignSectionFaces(const TopoDS_Shape& faceIntersections);
TopoDS_Compound mapToPage(const TopoDS_Shape& shapeToAlign);
virtual std::vector<TechDraw::FacePtr> makeTDSectionFaces(const TopoDS_Compound& topoDSFaces);
virtual TopoDS_Shape getShapeToIntersect() { return m_cutPieces; }
void makeLineSets(void);
void makeLineSets();
std::vector<LineSet> getDrawableLines(int i = 0);
std::vector<PATLineSpec> getDecodedSpecsFromFile(std::string fileSpec, std::string myPattern);
@@ -169,14 +172,15 @@ public:
Base::Vector3d getSectionDirectionOnBaseView();
virtual ChangePointVector getChangePointsFromSectionLine();
bool showSectionEdges(void);
bool showSectionEdges();
TopoDS_Shape makeFaceFromWires(std::vector<TopoDS_Wire> &inWires);
Base::Vector3d getCutCentroid() const;
bool checkSectionCS() const;
public Q_SLOTS:
virtual void onSectionCutFinished(void);
virtual void onSectionCutFinished();
protected:
TopoDS_Compound m_sectionTopoDSFaces;//needed for hatching
@@ -196,8 +200,8 @@ protected:
void onDocumentRestored() override;
void setupObject() override;
void replaceSvgIncluded(std::string newSvgFile);
void replacePatIncluded(std::string newPatFile);
void replaceSvgIncluded(const std::string& newSvgFile);
void replacePatIncluded(const std::string& newPatFile);
TopoDS_Shape m_cutPieces;//the shape after cutting, but before centering & scaling
gp_Ax2 m_projectionCS;

View File

@@ -836,8 +836,6 @@ void QGIViewPart::drawComplexSectionLine(TechDraw::DrawViewSection* viewSection,
}
else {
std::pair<Base::Vector3d, Base::Vector3d> dirsAligned = dcs->sectionArrowDirs();
dirsAligned.first = DrawUtil::invertY(dirsAligned.first);
dirsAligned.second = DrawUtil::invertY(dirsAligned.second);
sectionLine->setArrowDirections(dirsAligned.first, dirsAligned.second);
}

View File

@@ -24,7 +24,6 @@
#ifndef _PreComp_
#include <QMessageBox>
#include <gp_Pnt.hxx>
#include <numbers>
#endif// #ifndef _PreComp_
#include <App/Document.h>
@@ -104,6 +103,8 @@ TaskComplexSection::TaskComplexSection(TechDraw::DrawComplexSection* complexSect
m_section(complexSection),
m_profileObject(nullptr),
m_dirName("Aligned"),
m_sectionName(m_section->getNameInDocument()),
m_savePageName(m_section->findParentPage()->getNameInDocument()),
m_createMode(false),
m_applyDeferred(0),
m_angle(0.0),
@@ -111,10 +112,8 @@ TaskComplexSection::TaskComplexSection(TechDraw::DrawComplexSection* complexSect
m_modelIsDirty(false),
m_scaleEdited(false)
{
m_sectionName = m_section->getNameInDocument();
m_doc = m_section->getDocument();
m_page = m_section->findParentPage();
m_savePageName = m_page->getNameInDocument();
m_baseView = dynamic_cast<TechDraw::DrawViewPart*>(m_section->BaseView.getValue());
if (m_baseView) {
@@ -167,7 +166,7 @@ void TaskComplexSection::setUiPrimary()
std::pair<Base::Vector3d, Base::Vector3d> dirs = DrawGuiUtil::get3DDirAndRot();
m_saveNormal = dirs.first;
m_saveXDir = dirs.second;
m_viewDirectionWidget->setValue(m_saveNormal * -1.0);//this will propagate to m_compass
m_viewDirectionWidget->setValue(m_saveNormal * -1);//this will propagate to m_compass
}
//don't allow updates until a direction is picked
@@ -196,7 +195,7 @@ void TaskComplexSection::setUiEdit()
Base::Vector3d projectedViewDirection = m_baseView->projectPoint(sectionNormalVec, false);
double viewAngle = atan2(-projectedViewDirection.y, -projectedViewDirection.x);
m_compass->setDialAngle(Base::toDegrees(viewAngle));
m_viewDirectionWidget->setValueNoNotify(projectedViewDirection * -1.0);
m_viewDirectionWidget->setValueNoNotify(projectedViewDirection * -1);
}
else {
//no local angle makes sense if there is no baseView?
@@ -244,7 +243,6 @@ void TaskComplexSection::setUiCommon()
//save the start conditions
void TaskComplexSection::saveSectionState()
{
// Base::Console().Message("TCS::saveSectionState()\n");
if (m_section) {
m_saveSymbol = m_section->SectionSymbol.getValue();
m_saveScale = m_section->getScale();
@@ -265,9 +263,9 @@ void TaskComplexSection::saveSectionState()
//restore the start conditions
void TaskComplexSection::restoreSectionState()
{
// Base::Console().Message("TCS::restoreSectionState()\n");
if (!m_section)
if (!m_section){
return;
}
m_section->SectionSymbol.setValue(m_saveSymbol);
m_section->Scale.setValue(m_saveScale);
@@ -302,8 +300,6 @@ void TaskComplexSection::onSectionObjectsUseSelectionClicked()
//the VectorEditWidget reports a change in direction
void TaskComplexSection::slotViewDirectionChanged(Base::Vector3d newDirection)
{
// Base::Console().Message("TCS::slotViewDirectionChanged(%s)\n",
// DrawUtil::formatVector(newDirection).c_str());
Base::Vector3d projectedViewDirection = newDirection;
if (m_baseView) {
projectedViewDirection = m_baseView->projectPoint(newDirection, false);
@@ -319,7 +315,6 @@ void TaskComplexSection::slotViewDirectionChanged(Base::Vector3d newDirection)
//SectionNormal
void TaskComplexSection::slotChangeAngle(double newAngle)
{
// Base::Console().Message("TCS::slotAngleChanged(%.3f)\n", newAngle);
double angleRadians = Base::toRadians(newAngle);
double unitX = cos(angleRadians);
double unitY = sin(angleRadians);
@@ -331,7 +326,6 @@ void TaskComplexSection::slotChangeAngle(double newAngle)
void TaskComplexSection::onUpClicked()
{
// Base::Console().Message("TCS::onUpClicked()\n");
checkAll(false);
m_compass->setToNorth();
m_viewDirectionWidget->setValueNoNotify(Base::Vector3d(0.0, 1.0, 0.0));
@@ -340,7 +334,6 @@ void TaskComplexSection::onUpClicked()
void TaskComplexSection::onDownClicked()
{
// Base::Console().Message("TCS::onDownClicked()\n");
checkAll(false);
m_compass->setToSouth();
m_viewDirectionWidget->setValueNoNotify(Base::Vector3d(0.0, -1.0, 0.0));
@@ -349,7 +342,6 @@ void TaskComplexSection::onDownClicked()
void TaskComplexSection::onLeftClicked()
{
// Base::Console().Message("TCS::onLeftClicked()\n");
checkAll(false);
m_compass->setToWest();
m_viewDirectionWidget->setValueNoNotify(Base::Vector3d(-1.0, 0.0, 0.0));
@@ -358,7 +350,6 @@ void TaskComplexSection::onLeftClicked()
void TaskComplexSection::onRightClicked()
{
// Base::Console().Message("TCS::onRightClicked()\n");
checkAll(false);
m_compass->setToEast();
m_viewDirectionWidget->setValueNoNotify(Base::Vector3d(1.0, 0.0, 0.0));
@@ -481,13 +472,11 @@ QString TaskComplexSection::sourcesToString()
//******************************************************************************
bool TaskComplexSection::apply(bool forceUpdate)
{
// Base::Console().Message("TCS::apply() - liveUpdate: %d force: %d\n",
// ui->cbLiveUpdate->isChecked(), forceUpdate);
if (!ui->cbLiveUpdate->isChecked() && !forceUpdate) {
//nothing to do
m_applyDeferred++;
QString msgLiteral =
QString::fromUtf8(QT_TRANSLATE_NOOP("TaskPojGroup", " updates pending"));
QString::fromUtf8(QT_TRANSLATE_NOOP("TaskComplexSection", " updates pending"));
QString msgNumber = QString::number(m_applyDeferred);
ui->lPendingUpdates->setText(msgNumber + msgLiteral);
return false;
@@ -518,6 +507,9 @@ bool TaskComplexSection::apply(bool forceUpdate)
if (!m_section) {
createComplexSection();
if (!isSectionValid()) {
return false;
}
}
if (isSectionValid()) {
@@ -531,6 +523,11 @@ bool TaskComplexSection::apply(bool forceUpdate)
if (isBaseValid()) {
m_baseView->requestPaint();
}
if (!m_section->checkSectionCS()) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Possible Coordinate System Error"),
QObject::tr("Check SectionNormal, Direction and/or XDirection."));
}
enableAll(true);
checkAll(false);
@@ -543,7 +540,6 @@ bool TaskComplexSection::apply(bool forceUpdate)
void TaskComplexSection::applyAligned()
{
// Base::Console().Message("TCS::applyAligned()\n");
m_dirName = "Aligned";
enableAll(true);
m_directionIsSet = true;
@@ -557,8 +553,6 @@ void TaskComplexSection::applyAligned()
//pointer to created view is not returned, but stored in m_section
void TaskComplexSection::createComplexSection()
{
// Base::Console().Message("TCS::createComplexSection()\n");
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Create ComplexSection"));
if (!m_section) {
const std::string objectName{QT_TR_NOOP("ComplexSection")};
@@ -571,6 +565,7 @@ void TaskComplexSection::createComplexSection()
// unique Labels
QString qTemp = ui->leSymbol->text();
std::string temp = qTemp.toStdString();
//NOLINTBEGIN
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.SectionSymbol = '%s'",
m_sectionName.c_str(), temp.c_str());
@@ -583,8 +578,6 @@ void TaskComplexSection::createComplexSection()
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.Scale = %0.6f",
m_sectionName.c_str(), ui->sbScale->value());
std::string baseName = m_baseView->getNameInDocument();
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.Scale = %0.7f",
m_sectionName.c_str(), ui->sbScale->value());
@@ -600,6 +593,7 @@ void TaskComplexSection::createComplexSection()
m_sectionName.c_str());
Command::doCommand(Command::Doc, "App.activeDocument().%s.SectionDirection = 'Aligned'",
m_sectionName.c_str());
//NOLINTEND
App::DocumentObject* newObj = m_page->getDocument()->getObject(m_sectionName.c_str());
m_section = dynamic_cast<TechDraw::DrawComplexSection*>(newObj);
@@ -608,6 +602,7 @@ void TaskComplexSection::createComplexSection()
}
Base::Vector3d localUnit = m_viewDirectionWidget->value();
if (m_baseView) {
//NOLINTNEXTLINE
Command::doCommand(Command::Doc,
"App.ActiveDocument.%s.BaseView = App.ActiveDocument.%s",
m_sectionName.c_str(), m_baseView->getNameInDocument());
@@ -624,6 +619,7 @@ void TaskComplexSection::createComplexSection()
//if we have not changed the direction, we should use the 3d directions saved in the
//constructor
m_section->SectionNormal.setValue(m_saveNormal);
m_section->Direction.setValue(m_saveNormal);
m_section->XDirection.setValue(m_saveXDir);
}
m_section->Source.setValues(m_shapes);
@@ -637,6 +633,7 @@ void TaskComplexSection::createComplexSection()
//auto orientation of view relative to base view
double viewDirectionAngle = m_compass->positiveValue();
double rotation = requiredRotation(viewDirectionAngle);
//NOLINTNEXTLINE
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.Rotation = %.6f",
m_sectionName.c_str(), rotation);
@@ -646,7 +643,6 @@ void TaskComplexSection::createComplexSection()
void TaskComplexSection::updateComplexSection()
{
// Base::Console().Message("TCS:;updateComplexSection()\n");
if (!isSectionValid()) {
failNoObject();
return;
@@ -656,6 +652,7 @@ void TaskComplexSection::updateComplexSection()
if (m_section) {
QString qTemp = ui->leSymbol->text();
std::string temp = qTemp.toStdString();
//NOLINTBEGIN
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.SectionSymbol = '%s'",
m_sectionName.c_str(), temp.c_str());
@@ -665,8 +662,6 @@ void TaskComplexSection::updateComplexSection()
Command::doCommand(Command::Doc, "App.activeDocument().%s.translateLabel('DrawViewSection', 'Section', '%s')",
m_sectionName.c_str(), makeSectionLabel(qTemp).c_str());
std::string baseName = m_baseView->getNameInDocument();
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.Scale = %0.7f",
m_sectionName.c_str(), ui->sbScale->value());
@@ -678,6 +673,8 @@ void TaskComplexSection::updateComplexSection()
m_sectionName.c_str(), projectionStrategy);
Command::doCommand(Command::Doc, "App.activeDocument().%s.SectionDirection = 'Aligned'",
m_sectionName.c_str());
//NOLINTEND
m_section->CuttingToolWireObject.setValue(m_profileObject);
m_section->SectionDirection.setValue("Aligned");
Base::Vector3d localUnit = m_viewDirectionWidget->value();
@@ -695,13 +692,15 @@ void TaskComplexSection::updateComplexSection()
//auto orientation of view relative to base view
double viewDirectionAngle = m_compass->positiveValue();
double rotation = requiredRotation(viewDirectionAngle);
//NOLINTNEXTLINE
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.Rotation = %.6f",
m_sectionName.c_str(), rotation);
}
Gui::Command::commitCommand();
}
std::string TaskComplexSection::makeSectionLabel(QString symbol)
std::string TaskComplexSection::makeSectionLabel(const QString& symbol)
{
const std::string objectName{QT_TR_NOOP("ComplexSection")};
std::string uniqueSuffix{m_sectionName.substr(objectName.length(), std::string::npos)};
@@ -710,7 +709,7 @@ std::string TaskComplexSection::makeSectionLabel(QString symbol)
return ( uniqueLabel + " " + temp + " - " + temp );
}
void TaskComplexSection::failNoObject(void)
void TaskComplexSection::failNoObject()
{
QString qsectionName = QString::fromStdString(m_sectionName);
QString qbaseName = QString::fromStdString(m_saveBaseName);
@@ -721,34 +720,32 @@ void TaskComplexSection::failNoObject(void)
bool TaskComplexSection::isBaseValid()
{
if (!m_baseView)
if (!m_baseView) {
return false;
}
App::DocumentObject* baseObj = m_doc->getObject(m_saveBaseName.c_str());
if (!baseObj)
return false;
return true;
return baseObj != nullptr;
}
bool TaskComplexSection::isSectionValid()
{
if (!m_section)
if (!m_section) {
return false;
}
App::DocumentObject* sectionObj = m_doc->getObject(m_sectionName.c_str());
if (!sectionObj)
return false;
return true;
return sectionObj != nullptr;
}
//get required rotation from input angle in [0, 360]
//NOTE: shared code with simple section - reuse opportunity
double TaskComplexSection::requiredRotation(double inputAngle)
double TaskComplexSection::requiredRotation(double inputAngleDeg)
{
double rotation = inputAngle - 90.0;
if (rotation == 180.0) {
constexpr double PiOver4Degrees{90};
constexpr double PiOver2Degrees{180};
double rotation = inputAngleDeg - PiOver4Degrees;
if (rotation == PiOver2Degrees) {
//if the view direction is 90/270, then the section is drawn properly and no
//rotation is needed. 90.0 becomes 0.0, but 270.0 needs special handling.
rotation = 0.0;
@@ -759,16 +756,15 @@ double TaskComplexSection::requiredRotation(double inputAngle)
//******************************************************************************
bool TaskComplexSection::accept()
{
// Base::Console().Message("TCS::accept()\n");
apply(true);
Gui::Command::doCommand(Gui::Command::Gui, "Gui.ActiveDocument.resetEdit()");
Gui::Command::doCommand(Gui::Command::Gui, "Gui.ActiveDocument.resetEdit()"); //NOLINT
return true;
}
bool TaskComplexSection::reject()
{
if (!m_section) {//no section created, nothing to undo
Gui::Command::doCommand(Gui::Command::Gui, "Gui.ActiveDocument.resetEdit()");
Gui::Command::doCommand(Gui::Command::Gui, "Gui.ActiveDocument.resetEdit()"); //NOLINT
return false;
}
@@ -776,17 +772,19 @@ bool TaskComplexSection::reject()
if (isBaseValid()) {
m_baseView->requestPaint();
}
Gui::Command::doCommand(Gui::Command::Gui, "Gui.ActiveDocument.resetEdit()");
Gui::Command::doCommand(Gui::Command::Gui, "Gui.ActiveDocument.resetEdit()"); //NOLINT
return false;
}
if (m_createMode) {
std::string SectionName = m_section->getNameInDocument();
//NOLINTBEGIN
Gui::Command::doCommand(Gui::Command::Gui,
"App.ActiveDocument.%s.removeView(App.ActiveDocument.%s)",
m_savePageName.c_str(), SectionName.c_str());
Gui::Command::doCommand(Gui::Command::Gui, "App.ActiveDocument.removeObject('%s')",
SectionName.c_str());
//NOLINTEND
} else {
if (m_modelIsDirty) {
restoreSectionState();
@@ -799,7 +797,7 @@ bool TaskComplexSection::reject()
m_baseView->requestPaint();
}
Gui::Command::updateActive();
Gui::Command::doCommand(Gui::Command::Gui, "Gui.ActiveDocument.resetEdit()");
Gui::Command::doCommand(Gui::Command::Gui, "Gui.ActiveDocument.resetEdit()"); //NOLINT
return false;
}
@@ -818,7 +816,6 @@ TaskDlgComplexSection::TaskDlgComplexSection(TechDraw::DrawPage* page,
std::vector<App::DocumentObject*> xShapes,
App::DocumentObject* profileObject,
std::vector<std::string> profileSubs)
: TaskDialog()
{
widget = new TaskComplexSection(page, baseView, shapes, xShapes, profileObject, profileSubs);
taskbox =
@@ -829,9 +826,8 @@ TaskDlgComplexSection::TaskDlgComplexSection(TechDraw::DrawPage* page,
}
TaskDlgComplexSection::TaskDlgComplexSection(TechDraw::DrawComplexSection* complexSection)
: TaskDialog()
: widget(new TaskComplexSection(complexSection))
{
widget = new TaskComplexSection(complexSection);
taskbox =
new Gui::TaskView::TaskBox(Gui::BitmapFactory().pixmap("actions/TechDraw_ComplexSection"),
widget->windowTitle(), true, nullptr);
@@ -839,8 +835,6 @@ TaskDlgComplexSection::TaskDlgComplexSection(TechDraw::DrawComplexSection* compl
Content.push_back(taskbox);
}
TaskDlgComplexSection::~TaskDlgComplexSection() {}
void TaskDlgComplexSection::update()
{
// widget->updateTask();
@@ -861,4 +855,5 @@ bool TaskDlgComplexSection::reject()
return true;
}
//NOLINTNEXTLINE
#include <Mod/TechDraw/Gui/moc_TaskComplexSection.cpp>

View File

@@ -107,7 +107,7 @@ protected Q_SLOTS:
private:
double requiredRotation(double inputAngle);
std::string makeSectionLabel(QString symbol);
std::string makeSectionLabel(const QString& symbol);
void createComplexSection();
void updateComplexSection();
@@ -161,8 +161,8 @@ public:
std::vector<App::DocumentObject*> xShapes,
App::DocumentObject* profileObject,
std::vector<std::string> profileSubs);
TaskDlgComplexSection(TechDraw::DrawComplexSection* page);
~TaskDlgComplexSection() override;
explicit TaskDlgComplexSection(TechDraw::DrawComplexSection* page) ;
~TaskDlgComplexSection() override = default;
public:
/// is called the TaskView when the dialog is opened