From 6a0d3dedfbe6e9459fb0318da5b14742e7228e79 Mon Sep 17 00:00:00 2001 From: wandererfan Date: Thu, 6 Jul 2023 15:56:05 -0400 Subject: [PATCH] [TD]fix pathological centerline for points --- src/Mod/TechDraw/App/CenterLine.cpp | 49 ++++++++----- src/Mod/TechDraw/Gui/TaskCenterLine.cpp | 97 +++++++++++++++++++++++-- src/Mod/TechDraw/Gui/TaskCenterLine.h | 1 + 3 files changed, 121 insertions(+), 26 deletions(-) diff --git a/src/Mod/TechDraw/App/CenterLine.cpp b/src/Mod/TechDraw/App/CenterLine.cpp index 80b7c02d62..c03fd66a11 100644 --- a/src/Mod/TechDraw/App/CenterLine.cpp +++ b/src/Mod/TechDraw/App/CenterLine.cpp @@ -159,7 +159,7 @@ CenterLine* CenterLine::CenterLineBuilder(DrawViewPart* partFeat, int mode, bool flip) { -// Base::Console().Message("CL::CLBuilder()\n - subNames: %d", subNames.size()); +// Base::Console().Message("CL::CLBuilder()\n - subNames: %d\n", subNames.size()); std::pair ends; std::vector faces; std::vector edges; @@ -405,7 +405,6 @@ std::pair CenterLine::calcEndPoints(DrawViewPart if (faceBox.IsVoid()) { Base::Console().Error("CL::calcEndPoints - faceBox is void!\n"); -// return result; throw Base::IndexError("CenterLine wrong number of faces."); } @@ -527,7 +526,6 @@ std::pair CenterLine::calcEndPoints2Lines(DrawVi // if the proposed end points prevent the creation of a vertical or horizontal centerline, we need // to prevent the "orientation" code below from creating identical endpoints. This would create a // zero length edge and cause problems later. - // this should probably be prevented in the creation task? bool inhibitVertical = false; bool inhibitHorizontal = false; if (DU::fpCompare(p1.y, p2.y, EWTOLERANCE)) { @@ -586,7 +584,7 @@ std::pair CenterLine::calcEndPoints2Points(DrawV double rotate, bool flip) { -// Base::Console().Message("CL::calc2Points()\n"); +// Base::Console().Message("CL::calc2Points() - mode: %d\n", mode); if (vertNames.empty()) { Base::Console().Warning("CL::calcEndPoints2Points - no points!\n"); return std::pair(); @@ -606,17 +604,41 @@ std::pair CenterLine::calcEndPoints2Points(DrawV } } if (points.size() != 2) { - //this should fail harder. maybe be in a try/catch. -// Base::Console().Message("CL::calcEndPoints2Points - wrong number of points!\n"); -// return result; throw Base::IndexError("CenterLine wrong number of points."); } Base::Vector3d v1 = points.front()->point(); Base::Vector3d v2 = points.back()->point(); - Base::Vector3d mid = (v1 + v2) / 2.0; Base::Vector3d dir = v2 - v1; + + // if the proposed end points prevent the creation of a vertical or horizontal centerline, we need + // to prevent the "orientation" code below from creating identical endpoints. This would create a + // zero length edge and cause problems later. + + bool inhibitVertical = false; + bool inhibitHorizontal = false; + if (DU::fpCompare(v1.y, v2.y, EWTOLERANCE)) { + // proposed end points are aligned horizontally, can not draw horizontal CL + inhibitHorizontal = true; + } + if (DU::fpCompare(v1.x, v2.x, EWTOLERANCE)) { + // proposed end points are aligned vertically, can not draw vertical CL + inhibitVertical = true; + } + + if (mode == 0 && !inhibitVertical) { + //Vertical + v1.x = mid.x; + v2.x = mid.x; + } else if (mode == 1 && !inhibitHorizontal) { + //Horizontal + v1.y = mid.y; + v2.y = mid.y; + } else if (mode == 2) { //Aligned + // no op + } + double length = dir.Length(); dir.Normalize(); Base::Vector3d clDir(dir.y, -dir.x, dir.z); @@ -630,17 +652,6 @@ std::pair CenterLine::calcEndPoints2Points(DrawV p2 = temp; } - if (mode == 0) { //Vertical - p1.x = mid.x; - p2.x = mid.x; - } else if (mode == 1) { //Horizontal - p1.y = mid.y; - p2.y = mid.y; - } else if (mode == 2) { //Aligned - // no op - } - - //extend p1 = p1 + (clDir * ext); p2 = p2 - (clDir * ext); diff --git a/src/Mod/TechDraw/Gui/TaskCenterLine.cpp b/src/Mod/TechDraw/Gui/TaskCenterLine.cpp index 94eae46cee..d21491f209 100644 --- a/src/Mod/TechDraw/Gui/TaskCenterLine.cpp +++ b/src/Mod/TechDraw/Gui/TaskCenterLine.cpp @@ -192,8 +192,14 @@ void TaskCenterLine::setUiPrimary() int precision = Base::UnitsApi::getDecimals(); ui->qsbRotate->setDecimals(precision); - int orientation = checkPathologicalEdges(m_mode); - setUiOrientation(orientation); + if (m_type == 1) { + int orientation = checkPathologicalEdges(m_mode); + setUiOrientation(orientation); + } + if (m_type == 2) { + int orientation = checkPathologicalVertices(m_mode); + setUiOrientation(orientation); + } } void TaskCenterLine::setUiEdit() @@ -238,6 +244,9 @@ void TaskCenterLine::setUiEdit() void TaskCenterLine::onOrientationChanged() { + if (!m_cl) { + return; + } if (ui->rbVertical->isChecked()) m_cl->m_mode = CenterLine::CLMODE::VERTICAL; else if (ui->rbHorizontal->isChecked()) @@ -254,30 +263,50 @@ void TaskCenterLine::onOrientationChanged() void TaskCenterLine::onShiftHorizChanged() { + if (!m_cl) { + return; + } + m_cl->m_hShift = ui->qsbHorizShift->rawValue(); m_partFeat->recomputeFeature(); } void TaskCenterLine::onShiftVertChanged() { + if (!m_cl) { + return; + } + m_cl->m_vShift = ui->qsbVertShift->rawValue(); m_partFeat->recomputeFeature(); } void TaskCenterLine::onRotationChanged() { + if (!m_cl) { + return; + } + m_cl->m_rotate = ui->qsbRotate->rawValue(); m_partFeat->recomputeFeature(); } void TaskCenterLine::onExtendChanged() { + if (!m_cl) { + return; + } + m_cl->m_extendBy = ui->qsbExtend->rawValue(); m_partFeat->recomputeFeature(); } void TaskCenterLine::onColorChanged() { + if (!m_cl) { + return; + } + App::Color ac; ac.setValue(ui->cpLineColor->color()); m_cl->m_format.m_color.setValue(ui->cpLineColor->color()); @@ -286,12 +315,20 @@ void TaskCenterLine::onColorChanged() void TaskCenterLine::onWeightChanged() { + if (!m_cl) { + return; + } + m_cl->m_format.m_weight = ui->dsbWeight->value().getValue(); m_partFeat->recomputeFeature(); } void TaskCenterLine::onStyleChanged() { + if (!m_cl) { + return; + } + m_cl->m_format.m_style = ui->cboxStyle->currentIndex() + 1; m_partFeat->recomputeFeature(); } @@ -326,12 +363,47 @@ int TaskCenterLine::checkPathologicalEdges(int inMode) return inMode; } +// check that we are not trying to create an impossible centerline (ex a vertical centerline +// between 2 vertices aligned vertically) +int TaskCenterLine::checkPathologicalVertices(int inMode) +{ + if (m_type != 2) { + // not a vertex based centerline, this doesn't apply + return inMode; + } + + TechDraw::VertexPtr vert1 = m_partFeat->getVertex(m_subNames.front()); + Base::Vector3d point1 = vert1->point(); + TechDraw::VertexPtr vert2 = m_partFeat->getVertex(m_subNames.back()); + Base::Vector3d point2 = vert2->point(); + + if (DU::fpCompare(point1.x, point2.x, EWTOLERANCE)) { + // points are aligned vertically, CL must be horizontal + return CenterLine::CLMODE::HORIZONTAL; + } + + if (DU::fpCompare(point1.y, point2.y, EWTOLERANCE)) { + // points are aligned horizontally, CL must be vertical + return CenterLine::CLMODE::VERTICAL; + } + + // not pathological case, just return the input mode + return inMode; +} + //****************************************************************************** void TaskCenterLine::createCenterLine() { Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Create CenterLine")); - m_mode = checkPathologicalEdges(m_mode); + // check for illogical parameters + if (m_type == 1) { + // between lines + m_mode = checkPathologicalEdges(m_mode); + } else if (m_type == 2) { + // between points + m_mode = checkPathologicalVertices(m_mode); + } CenterLine* cl = CenterLine::CenterLineBuilder(m_partFeat, m_subNames, m_mode, false); @@ -367,6 +439,7 @@ void TaskCenterLine::createCenterLine() void TaskCenterLine::updateOrientation() { +// Base::Console().Message("TCL::updateOrientation()\n"); if (!m_cl) { return; } @@ -375,10 +448,20 @@ void TaskCenterLine::updateOrientation() // https://forum.freecad.org/viewtopic.php?f=35&t=44255&start=20#p503220 // The centerline creation can fail if m_type is edge and both selected edges are vertical or horizontal. int orientation = m_cl->m_mode; - if (!m_edgeName.empty() && !m_cl->m_edges.empty()) { - // we have an existing centerline, not a freshly created one, and it is a centerline between edges - m_subNames = m_cl->m_edges; - orientation = checkPathologicalEdges(orientation); + if (m_type == 1) { + // between lines + if (!m_edgeName.empty() && !m_cl->m_edges.empty()) { + // we have an existing centerline, not a freshly created one, and it is a centerline between edges + m_subNames = m_cl->m_edges; + orientation = checkPathologicalEdges(orientation); + } + } else if (m_type == 2) { + // between points + if (!m_edgeName.empty() && !m_cl->m_verts.empty()) { + // we have an existing centerline, not a freshly created one, and it is a centerline between points + m_subNames = m_cl->m_verts; + orientation = checkPathologicalVertices(orientation); + } } setUiOrientation(orientation); diff --git a/src/Mod/TechDraw/Gui/TaskCenterLine.h b/src/Mod/TechDraw/Gui/TaskCenterLine.h index b725d79b17..0316838c36 100644 --- a/src/Mod/TechDraw/Gui/TaskCenterLine.h +++ b/src/Mod/TechDraw/Gui/TaskCenterLine.h @@ -89,6 +89,7 @@ protected: double getExtendBy(); int checkPathologicalEdges(int inMode); + int checkPathologicalVertices(int inMode); void setUiOrientation(int orientation); private: