[TD]fix pathological centerline for points
This commit is contained in:
@@ -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<Base::Vector3d, Base::Vector3d> ends;
|
||||
std::vector<std::string> faces;
|
||||
std::vector<std::string> edges;
|
||||
@@ -405,7 +405,6 @@ std::pair<Base::Vector3d, Base::Vector3d> 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<Base::Vector3d, Base::Vector3d> 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<Base::Vector3d, Base::Vector3d> 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<Base::Vector3d, Base::Vector3d>();
|
||||
@@ -606,17 +604,41 @@ std::pair<Base::Vector3d, Base::Vector3d> 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<Base::Vector3d, Base::Vector3d> 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);
|
||||
|
||||
@@ -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<QColor>(ui->cpLineColor->color());
|
||||
m_cl->m_format.m_color.setValue<QColor>(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);
|
||||
|
||||
@@ -89,6 +89,7 @@ protected:
|
||||
double getExtendBy();
|
||||
|
||||
int checkPathologicalEdges(int inMode);
|
||||
int checkPathologicalVertices(int inMode);
|
||||
void setUiOrientation(int orientation);
|
||||
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user