diff --git a/src/Mod/TechDraw/App/CMakeLists.txt b/src/Mod/TechDraw/App/CMakeLists.txt
index fd3d66475e..c1602a200c 100644
--- a/src/Mod/TechDraw/App/CMakeLists.txt
+++ b/src/Mod/TechDraw/App/CMakeLists.txt
@@ -10,7 +10,6 @@ include_directories(
${ZLIB_INCLUDE_DIR}
${PYTHON_INCLUDE_DIRS}
${XercesC_INCLUDE_DIRS}
- ${QT_QTCORE_INCLUDE_DIR}
)
set(TechDrawLIBS
@@ -29,10 +28,15 @@ endif()
include_directories(
${QtConcurrent_INCLUDE_DIRS}
+ ${QtCore_INCLUDE_DIR}
+ ${QtGui_INCLUDE_DIR}
+ ${QtWidgets_INCLUDE_DIRS}
)
set(QtXmlPatternsLib ${QtXmlPatterns_LIBRARIES})
list(APPEND TechDrawLIBS
${QtConcurrent_LIBRARIES}
+ ${QtCore_LIBRARIES}
+ ${QtWidgets_LIBRARIES}
)
link_directories(${OCC_LIBRARY_DIR})
@@ -159,6 +163,8 @@ SET(TechDraw_SRCS
DrawProjectSplit.h
LineGroup.cpp
LineGroup.h
+ LineNameEnum.cpp
+ LineNameEnum.h
ArrowPropEnum.cpp
ArrowPropEnum.h
Preferences.cpp
@@ -169,6 +175,8 @@ SET(TechDraw_SRCS
ProjectionAlgos.h
XMLQuery.cpp
XMLQuery.h
+ LineGenerator.cpp
+ LineGenerator.h
)
SET(Geometry_SRCS
diff --git a/src/Mod/TechDraw/App/CenterLine.cpp b/src/Mod/TechDraw/App/CenterLine.cpp
index bb68b56319..1f24e57d43 100644
--- a/src/Mod/TechDraw/App/CenterLine.cpp
+++ b/src/Mod/TechDraw/App/CenterLine.cpp
@@ -883,6 +883,8 @@ void CenterLine::Save(Base::Writer &writer) const
writer.decInd();
writer.Stream() << writer.ind() << "" << std::endl ;
+ // style is deprecated in favour of line number, but we still save and restore it
+ // to avoid problems with old documents.
writer.Stream() << writer.ind() << "" << std::endl;
writer.Stream() << writer.ind() << "" << std::endl;
writer.Stream() << writer.ind() << "" << std::endl;
@@ -907,6 +909,9 @@ void CenterLine::Save(Base::Writer &writer) const
} else {
Base::Console().Message("CL::Save - unimplemented geomType: %d\n", static_cast(m_geometry->getGeomType()));
}
+
+ writer.Stream() << writer.ind() << "" << std::endl;
+
}
void CenterLine::Restore(Base::XMLReader &reader)
@@ -976,6 +981,8 @@ void CenterLine::Restore(Base::XMLReader &reader)
}
reader.readEndElement("CLPoints");
+ // style is deprecated in favour of line number, but we still save and restore it
+ // to avoid problems with old documents.
reader.readElement("Style");
m_format.m_style = reader.getAttributeAsInteger("value");
reader.readElement("Weight");
@@ -1007,6 +1014,22 @@ void CenterLine::Restore(Base::XMLReader &reader)
} else {
Base::Console().Warning("CL::Restore - unimplemented geomType: %d\n", static_cast(gType));
}
+
+ // older documents may not have the LineNumber element, so we need to check the
+ // next entry. if it is a start element, then we check if it is a start element
+ // for LineNumber.
+ // test for ISOLineNumber can be removed after testing. It is a left over for the earlier
+ // ISO only line handling.
+ if (reader.readNextElement()) {
+ if(strcmp(reader.localName(),"LineNumber") == 0 ||
+ strcmp(reader.localName(),"ISOLineNumber") == 0 ) {
+ // this centerline has an LineNumber attribute
+ m_format.setLineNumber(reader.getAttributeAsInteger("value"));
+ } else {
+ // LineNumber not found.
+ m_format.setLineNumber(LineFormat::InvalidLine);
+ }
+ }
}
CenterLine* CenterLine::copy() const
diff --git a/src/Mod/TechDraw/App/Cosmetic.cpp b/src/Mod/TechDraw/App/Cosmetic.cpp
index 9654b30747..f227199fce 100644
--- a/src/Mod/TechDraw/App/Cosmetic.cpp
+++ b/src/Mod/TechDraw/App/Cosmetic.cpp
@@ -54,6 +54,7 @@ LineFormat::LineFormat()
m_weight = getDefEdgeWidth();
m_color= getDefEdgeColor();
m_visible = true;
+ m_lineNumber = InvalidLine;
}
LineFormat::LineFormat(const int style,
@@ -63,7 +64,8 @@ LineFormat::LineFormat(const int style,
m_style(style),
m_weight(weight),
m_color(color),
- m_visible(visible)
+ m_visible(visible),
+ m_lineNumber(InvalidLine)
{
}
@@ -96,7 +98,7 @@ App::Color LineFormat::getDefEdgeColor()
int LineFormat::getDefEdgeStyle()
{
- return Preferences::getPreferenceGroup("Decorations")->GetInt("CosmoCLStyle", 2); //dashed
+ return Preferences::getPreferenceGroup("Decorations")->GetInt("CenterLineStyle", 2); //dashed
}
//******************************************
@@ -378,6 +380,7 @@ GeomFormat::GeomFormat() :
m_format.m_weight = LineFormat::getDefEdgeWidth();
m_format.m_color = LineFormat::getDefEdgeColor();
m_format.m_visible = true;
+ m_format.setLineNumber(LineFormat::InvalidLine);
createNewTag();
}
@@ -389,6 +392,7 @@ GeomFormat::GeomFormat(const GeomFormat* gf)
m_format.m_weight = gf->m_format.m_weight;
m_format.m_color = gf->m_format.m_color;
m_format.m_visible = gf->m_format.m_visible;
+ m_format.setLineNumber(gf->m_format.getLineNumber());
createNewTag();
}
@@ -401,6 +405,7 @@ GeomFormat::GeomFormat(const int idx,
m_format.m_weight = fmt.m_weight;
m_format.m_color = fmt.m_color;
m_format.m_visible = fmt.m_visible;
+ m_format.setLineNumber(fmt.getLineNumber());
createNewTag();
}
@@ -433,10 +438,13 @@ void GeomFormat::Save(Base::Writer &writer) const
{
const char v = m_format.m_visible?'1':'0';
writer.Stream() << writer.ind() << "" << endl;
+ // style is deprecated in favour of line number, but we still save and restore it
+ // to avoid problems with old documents.
writer.Stream() << writer.ind() << "" << endl;
writer.Stream() << writer.ind() << "" << endl;
writer.Stream() << writer.ind() << "" << endl;
writer.Stream() << writer.ind() << "" << endl;
+ writer.Stream() << writer.ind() << "" << endl;
}
void GeomFormat::Restore(Base::XMLReader &reader)
@@ -449,6 +457,8 @@ void GeomFormat::Restore(Base::XMLReader &reader)
// get the value of my Attribute
m_geomIndex = reader.getAttributeAsInteger("value");
+ // style is deprecated in favour of line number, but we still save and restore it
+ // to avoid problems with old documents.
reader.readElement("Style");
m_format.m_style = reader.getAttributeAsInteger("value");
reader.readElement("Weight");
@@ -458,6 +468,22 @@ void GeomFormat::Restore(Base::XMLReader &reader)
m_format.m_color.fromHexString(temp);
reader.readElement("Visible");
m_format.m_visible = (int)reader.getAttributeAsInteger("value")==0?false:true;
+ // older documents may not have the LineNumber element, so we need to check the
+ // next entry. if it is a start element, then we check if it is a start element
+ // for LineNumber.
+ // test for ISOLineNumber can be removed after testing. It is a left over for the earlier
+ // ISO only line handling.
+ if (reader.readNextElement()) {
+ if(strcmp(reader.localName(),"LineNumber") == 0 ||
+ strcmp(reader.localName(),"ISOLineNumber") == 0 ) { // this GeomFormat has an LineNumber attribute
+ m_format.setLineNumber(reader.getAttributeAsInteger("value"));
+ } else {
+ // LineNumber not found.
+ // TODO: line number should be set to DashedLineGenerator.fromQtStyle(m_format.m_style),
+ // but DashedLineGenerator lives on the gui side, and is not accessible here.
+ m_format.setLineNumber(LineFormat::InvalidLine);
+ }
+ }
}
boost::uuids::uuid GeomFormat::getTag() const
@@ -508,6 +534,7 @@ GeomFormat* GeomFormat::copy() const
newFmt->m_format.m_weight = m_format.m_weight;
newFmt->m_format.m_color = m_format.m_color;
newFmt->m_format.m_visible = m_format.m_visible;
+ newFmt->m_format.setLineNumber(m_format.getLineNumber());
return newFmt;
}
diff --git a/src/Mod/TechDraw/App/Cosmetic.h b/src/Mod/TechDraw/App/Cosmetic.h
index 095ef3cea8..a65441485d 100644
--- a/src/Mod/TechDraw/App/Cosmetic.h
+++ b/src/Mod/TechDraw/App/Cosmetic.h
@@ -40,6 +40,8 @@ class DrawViewPart;
class TechDrawExport LineFormat
{
public:
+ static constexpr size_t InvalidLine{0};
+
LineFormat();
LineFormat(const int style,
const double weight,
@@ -47,10 +49,14 @@ public:
const bool visible);
~LineFormat() = default;
+ int getLineNumber() const { return m_lineNumber; }
+ void setLineNumber(int number) { m_lineNumber = number; }
+
int m_style;
double m_weight;
App::Color m_color;
bool m_visible;
+ int m_lineNumber {1};
static double getDefEdgeWidth();
static App::Color getDefEdgeColor();
diff --git a/src/Mod/TechDraw/App/DrawViewPart.cpp b/src/Mod/TechDraw/App/DrawViewPart.cpp
index 17b605da75..c45f485769 100644
--- a/src/Mod/TechDraw/App/DrawViewPart.cpp
+++ b/src/Mod/TechDraw/App/DrawViewPart.cpp
@@ -222,7 +222,6 @@ void DrawViewPart::addShapes2d(void)
geometryObject->addVertex(v1);
}
else if (s.ShapeType() == TopAbs_EDGE) {
- Base::Console().Message("DVP::add2dShapes - found loose edge - isNull: %d\n", s.IsNull());
TopoDS_Shape sTrans = ShapeUtils::moveShape(s,
m_saveCentroid * -1.0);
TopoDS_Shape sScale = ShapeUtils::scaleShape(sTrans,
diff --git a/src/Mod/TechDraw/App/LineGenerator.cpp b/src/Mod/TechDraw/App/LineGenerator.cpp
new file mode 100644
index 0000000000..29a601efaf
--- /dev/null
+++ b/src/Mod/TechDraw/App/LineGenerator.cpp
@@ -0,0 +1,404 @@
+/***************************************************************************
+ * Copyright (c) 2023 WandererFan *
+ * *
+ * This file is part of the FreeCAD CAx development system. *
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 2 of the License, or (at your option) any later version. *
+ * *
+ * This library is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU Library General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this library; see the file COPYING.LIB. If not, *
+ * write to the Free Software Foundation, Inc., 59 Temple Place, *
+ * Suite 330, Boston, MA 02111-1307, USA *
+ * *
+ ***************************************************************************/
+
+//! a class for handling standard ISO128, ANSI Y14.2 line types and their dash
+//! patterns. Additional standards can be added.
+//! ISO standard lines are defined by a sequence of graphical elements as in
+//! the dotted line (line type 7): DOT, GAP
+//! each graphical element (DOT, GAP, DASH, etc) has a standard length in units
+//! of the line's width.
+//! the graphical elements and line definitions are stored in csv files.
+//! ANSI lines standards are not numbered, but we assign a number as a convenient
+//! reference.
+//! ANSI standard lines are defined similarly to ISO, but the element lengths
+//! are defined in mm, and do not vary with pen width.
+
+//! the graphical elements and line definitions are stored in csv files.
+//! these values only change if ISO128.20 or ANSI Y14.2 change
+
+#include "PreCompiled.h"
+#ifndef _PreComp_
+#endif
+
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+
+#include "Preferences.h"
+#include "LineGenerator.h"
+
+using namespace TechDraw;
+using DU = DrawUtil;
+
+LineGenerator::LineGenerator()
+{
+ m_elementDefs = loadElements();
+ m_lineDefs = getLineDefinitions();
+ m_lineDescs = getLineDescriptions();
+}
+
+//! figure out an appropriate QPen from an iso line number and a Qt PenStyle
+//! we prefer to use the ISO Line Number if available.
+QPen LineGenerator::getBestPen(size_t isoNumber, Qt::PenStyle qtStyle, double width)
+{
+// Base::Console().Message("DLG::getBestPen((%d, %d, %.3f)\n",
+// isoNumber, qtStyle, width);
+ // TODO: use TechDraw::LineFormat::InvalidLine here
+ if (isoNumber > 0 &&
+ isoNumber < m_lineDefs.size()) {
+ // we have a valid line number, so use it
+ return getLinePen(isoNumber, width);
+ }
+ int qtline = fromQtStyle(qtStyle);
+ if (qtline > 0) {
+ // we have a reasonable approximation of a Qt Style
+ return getLinePen(qtline, width);
+ }
+ // no valid line and the qtStyle doesn't convert to a line numb45r
+ // so we'll just make it continuous.
+ return getLinePen(1, width);
+}
+
+//! create a QPen for a given line number and line width. ISO lines are numbered
+//! 1-15 and ANSI lines are 1-4(?) The line width is the nominal width in mm.
+QPen LineGenerator::getLinePen(size_t lineNumber, double nominalLineWidth)
+{
+// Base::Console().Message("LG::getLinePen(%d, %.3f)\n",
+// lineNumber, nominalLineWidth);
+ QPen linePen;
+ linePen.setWidthF(nominalLineWidth);
+
+ // Note: if the cap style is Round or Square, the lengths of the lines, or
+ // dots/dashes within the line, will be wrong by 1 pen width. To get the
+ // exact line lengths or dash pattern, you must use Flat caps. Flat caps
+ // look terrible at the corners.
+ linePen.setCapStyle((Qt::PenCapStyle)Preferences::LineCapStyle());
+
+ double proportionalAdjust{1.0};
+ if (!isCurrentProportional()) {
+ // ANSI.Y14.2M.1992 lines are specified in actual element lengths, but Qt will draw
+ // them as proportional to the line width.
+ proportionalAdjust = nominalLineWidth;
+ }
+
+ // Note: if the cap style is Round or Square, the lengths of the lines, or
+ // dots/dashes within the line, will be wrong by 1 pen width. To get the
+ // exact line lengths or dash pattern, you must use Flat caps. Flat caps
+ // look terrible at the corners.
+ linePen.setCapStyle((Qt::PenCapStyle)Preferences::LineCapStyle());
+
+ // valid line numbers are [1, number of line definitions]
+ // line 1 is always (?) continuous
+ // 0 substitutes for LineFormat::InvalidLine here
+ if (lineNumber < 2 ||
+ lineNumber > m_lineDefs.size()) {
+ // plain boring solid line (or possibly an invalid line number)
+ linePen.setStyle(Qt::SolidLine);
+ return linePen;
+ }
+
+ int lineIndex = lineNumber - 1;
+ std::vector elements = m_lineDefs.at(lineIndex);
+
+ // there are some lines with numbers >1 that are also continuous, and
+ // a dash pattern is not applicable.
+ std::string naToken{"n/a"};
+ if (elements.empty() or elements.front() == naToken) {
+ // plain boring solid line (or possibly an invalid line number)
+ linePen.setStyle(Qt::SolidLine);
+ return linePen;
+ }
+
+ // there is at least one line style (ASME #11 Other) that is "invisible"
+ std::string noLineToken{"noline"};
+ if (elements.front() == noLineToken) {
+ linePen.setStyle(Qt::NoPen);
+ return linePen;
+ }
+
+ // interesting line styles
+ linePen.setStyle(Qt::CustomDashLine);
+ std::vector dashPattern;
+ bool firstElement(true);
+ for (auto& entry : elements) {
+ if (firstElement &&
+ (entry == "Gap" || entry == "Space") ) {
+ // some dash patterns MAY begin with a gap/space, but Qt dash patterns are always
+ // "mark, space, mark, space", so we handle this by offsetting the pattern
+ // and skipping the first element.
+ linePen.setDashOffset(static_cast< double >(m_elementDefs[entry]) / proportionalAdjust);
+ firstElement = false;
+ continue;
+ }
+ firstElement = false;
+ dashPattern.push_back(static_cast< double >(m_elementDefs[entry]) / proportionalAdjust);
+ }
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
+ QVector qDashPattern = QVector::fromStdVector(dashPattern);
+#else
+ QVector qDashPattern(dashPattern.begin(), dashPattern.end());
+#endif
+
+ linePen.setDashPattern(qDashPattern);
+ linePen.setWidthF(nominalLineWidth);
+ return linePen;
+}
+
+
+//! convert Qt line style to closest ISO line number
+int LineGenerator::fromQtStyle(Qt::PenStyle style) const
+{
+// Base::Console().Message("DLG::fromQtStyle(%d)\n", style);
+
+ int result { 0 };
+ // the 4 standard Qt::PenStyles and ISO128 equivalents
+ int dashed = 2;
+ int dotted = 7;
+ int dashDot = 10;
+ int dashDotDot = 12;
+ if (Preferences::lineStandard() == ANSI) {
+ dashed = 2;
+ dotted = 2; // no dotted line in Ansi Y14.2?
+ dashDot = 2;
+ dashDotDot = 2;
+ }
+ if (Preferences::lineStandard() == ASME) {
+ dashed = 2;
+ dotted = 16;
+ dashDot = 17;
+ dashDotDot = 14;
+ }
+
+ switch (style) {
+ case Qt::NoPen:
+ case Qt::SolidLine:
+ result = 1;
+ break;
+ case Qt::DashLine:
+ result = dashed;
+ break;
+ case Qt::DotLine:
+ result = dotted;
+ break;
+ case Qt::DashDotLine:
+ result = dashDot;
+ break;
+ case Qt::DashDotDotLine:
+ result = dashDotDot;
+ break;
+ case Qt::CustomDashLine:
+ // not sure what to do here. we would have to match the custom pattern
+ // to the patterns of the ISO lines and set the dash pattern accordingly.
+ result = 2;
+ break;
+ default:
+ result = 0;
+ }
+ return result;
+}
+
+
+//! return the standard lengths for the various graphical elements described in ISO128,
+//! ANSI Y14.2 standards file
+std::map LineGenerator::loadElements()
+{
+// Base::Console().Message("DLG::loadElements()\n");
+ std::map result;
+ // open file, for each record, parse element name and length, then insert into
+ // the output map.
+
+ std::string parmFile = Preferences::currentElementDefFile();
+ std::string record;
+ Base::FileInfo fi(parmFile);
+ Base::ifstream inFile(fi, std::ifstream::in);
+ if(!inFile.is_open()) {
+ Base::Console().Message( "Cannot open line element def file: %s\n", parmFile.c_str());
+ return result;
+ }
+ std::string line;
+ while ( std::getline(inFile, line) ){
+ if ( line.empty() || line.at(0) == '#' ) {
+ // this is a comment or a blank line, ignore it
+ continue;
+ }
+ std::vector tokens = DU::tokenize(line, ",");
+ // should be 2 tokens: elementName, elementLength
+ result[tokens.front()] = std::stoi(tokens.back(), nullptr);
+ }
+ inFile.close();
+ return result;
+}
+
+
+//! load the line definition file into memory
+std::vector< std::vector > LineGenerator::getLineDefinitions()
+{
+// Base::Console().Message("DLG::loadLineDefinitions()\n");
+ std::vector< std::vector > lineDefs;
+ std::string record;
+ Base::FileInfo fi(Preferences::currentLineDefFile());
+ Base::ifstream inFile(fi, std::ifstream::in);
+ if(!inFile.is_open()) {
+ Base::Console().Message( "Cannot open line def file: %s\n", fi.filePath().c_str());
+ return lineDefs;
+ }
+
+ std::string line;
+ while ( std::getline(inFile, line) ) {
+ if (line.empty() ||
+ line.at(0) == '#') {
+ // this is a comment or a blank line, ignore it
+ continue;
+ }
+ // strip out any null tokens that may be caused by trailing ',' in the input
+ std::vector validTokens;
+ for (auto& token : DU::tokenize(line, ",")) {
+ if (!token.empty()) {
+ validTokens.emplace_back(token);
+ }
+ }
+ std::vector lineDefRow;
+ lineDefRow.insert(lineDefRow.end(), validTokens.begin()+2, validTokens.end());
+ lineDefs.push_back(lineDefRow);
+ }
+
+ inFile.close();
+ return lineDefs;
+}
+
+//! retrieve a sorted list of available line definition files.
+std::vector LineGenerator::getAvailableLineStandards()
+{
+ std::vector result;
+ std::string lineDefToken{"LineDef"};
+ Base::FileInfo fi(Preferences::lineDefinitionLocation());
+ auto fiAll = fi.getDirectoryContent();
+ for (auto& entry : fiAll) {
+ if (!entry.isFile()) {
+ continue;
+ }
+ auto fileName = entry.fileNamePure();
+ size_t position = fileName.find(lineDefToken);
+ if (position != std::string::npos) {
+ result.emplace_back(fileName.substr(0, position - 1));
+ }
+ }
+ std::sort(result.begin(),result.end());
+ return result;
+}
+
+
+//! get the descriptions of the lines already loaded into this LineGenerator object
+std::vector LineGenerator::getLoadedDescriptions()
+{
+ return m_lineDescs;
+}
+
+
+//! extract the line description fields from the current definition file
+std::vector LineGenerator::getLineDescriptions()
+{
+ std::vector lineDescs;
+ std::string record;
+ Base::FileInfo fi(Preferences::currentLineDefFile());
+ Base::ifstream inFile(fi, std::ifstream::in);
+ if(!inFile.is_open()) {
+ Base::Console().Message( "Cannot open line def file: %s\n", fi.filePath().c_str());
+ return lineDescs;
+ }
+
+ std::string line;
+ while ( std::getline(inFile, line) ) {
+ if (line.empty() ||
+ line.at(0) == '#') {
+ // this is a comment or a blank line, ignore it
+ continue;
+ }
+ // strip out any null tokens that may be caused by trailing ',' in the input
+ std::vector validTokens;
+ for (auto& token : DU::tokenize(line, ",")) {
+ if (!token.empty()) {
+ validTokens.emplace_back(token);
+ }
+ }
+ lineDescs.push_back(validTokens.at(1));
+ }
+
+ inFile.close();
+ return lineDescs;
+}
+
+
+//! returns a string identifying the standards body which issued the active line
+//! standard
+std::string LineGenerator::getLineStandardsBody()
+{
+ int activeStandard = Preferences::lineStandard();
+ std::vector choices = getAvailableLineStandards();
+ return getBodyFromString(choices.at(activeStandard));
+}
+
+
+//! returns true if line elements of the current standard are proportional
+//! to line width (as in ISO), or false if the elements have a constant length
+//! (as in ANSI)
+bool LineGenerator::isCurrentProportional()
+{
+ return isProportional(Preferences::lineStandard());
+}
+
+
+//! returns true if line elements of the specified standard are proportional
+//! to line width (as in ISO), or false if the elements have a constant length
+//! (as in ANSI)
+bool LineGenerator::isProportional(size_t standardIndex)
+{
+ std::vector choices = getAvailableLineStandards();
+ if (standardIndex > choices.size()) {
+ // we don't have a standard for the specified index.
+ return true;
+ }
+ std::string bodyName = getBodyFromString(choices.at(standardIndex));
+ if (bodyName == "ANSI") {
+ return false;
+ }
+ return true;
+}
+
+
+//! returns the standards body name from a standard name in the form
+//! body.standard.section.revision
+std::string LineGenerator::getBodyFromString(std::string inString)
+{
+ size_t firstDot = inString.find(".");
+ if (firstDot == std::string::npos) {
+ // something has gone very wrong if an entry in choices does not contain a dot.
+ throw Base::RuntimeError("Malformed standard name found. Could not determine standards body.");
+ }
+ return inString.substr(0, firstDot);
+}
diff --git a/src/Mod/TechDraw/App/LineGenerator.h b/src/Mod/TechDraw/App/LineGenerator.h
new file mode 100644
index 0000000000..6546488292
--- /dev/null
+++ b/src/Mod/TechDraw/App/LineGenerator.h
@@ -0,0 +1,86 @@
+/***************************************************************************
+ * Copyright (c) 2023 WandererFan *
+ * *
+ * This file is part of the FreeCAD CAx development system. *
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 2 of the License, or (at your option) any later version. *
+ * *
+ * This library is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU Library General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this library; see the file COPYING.LIB. If not, *
+ * write to the Free Software Foundation, Inc., 59 Temple Place, *
+ * Suite 330, Boston, MA 02111-1307, USA *
+ * *
+ ***************************************************************************/
+
+//! a class for handling standard ISO128 and ANSI Y14.2 line types and their dash
+//! patterns
+//! ISO standard lines are defined by a sequence of graphical elements as in
+//! the dotted line (line type 7): DOT, GAP
+//! each graphical element (DOT, GAP, DASH, etc) has a standard length in units
+//! of the line's width.
+//! the graphical elements and line definitions are stored in csv files.
+//! ANSI lines standards are not numbered, but we assign a number as a convenient
+//! reference.
+//! ANSI standard lines are defined similarly to ISO, but the element lengths
+//! are defined in mm, and do not vary with pen width.
+//! ASME standard lines do not specify the element lengths at all, so we have
+//! chosen values generally equal to those for ISO128
+
+
+#ifndef DASHEDLINEGENERATOR_H
+#define DASHEDLINEGENERATOR_H
+
+#include
+
+#include
+
+namespace TechDraw {
+
+class LineGenerator {
+public:
+ LineGenerator();
+ ~LineGenerator() = default;
+
+ enum LINESTANDARD
+ {
+ ANSI,
+ ISO,
+ ASME
+ };
+
+ QPen getBestPen(size_t lineNumber, Qt::PenStyle qtStyle, double width);
+ QPen getLinePen(size_t lineNumber, double nominalLineWidth);
+ int fromQtStyle(Qt::PenStyle style) const;
+
+ static std::vector getAvailableLineStandards();
+ static std::string getLineStandardsBody();
+
+ //! get line descriptions from memory
+ std::vector getLoadedDescriptions();
+ //! get line descriptions from file
+ static std::vector getLineDescriptions();
+
+ static bool isProportional(size_t standardIndex);
+ bool isCurrentProportional();
+ static std::string getBodyFromString(std::string inString);
+
+private:
+ static std::map loadElements();
+ static std::vector< std::vector > getLineDefinitions();
+
+ std::map m_elementDefs;
+ std::vector< std::vector > m_lineDefs;
+ std::vector< std::string > m_lineDescs;
+};
+
+}
+
+#endif
diff --git a/src/Mod/TechDraw/App/LineNameEnum.cpp b/src/Mod/TechDraw/App/LineNameEnum.cpp
new file mode 100644
index 0000000000..5211292e9b
--- /dev/null
+++ b/src/Mod/TechDraw/App/LineNameEnum.cpp
@@ -0,0 +1,86 @@
+/***************************************************************************
+ * Copyright (c) 2023 WandererFan *
+ * *
+ * 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 "LineNameEnum.h"
+
+
+namespace TechDraw {
+
+//! line numbers begin at 1, not 0
+
+const int ISOLineName::ISOLineNameCount = 15;
+const char* ISOLineName::ISOLineNameEnums[]= {
+ QT_TRANSLATE_NOOP("ISOLineTypeEnum", "NoLine"),
+ QT_TRANSLATE_NOOP("ISOLineTypeEnum", "Continuous"),
+ QT_TRANSLATE_NOOP("ISOLineTypeEnum", "Dashed"),
+ QT_TRANSLATE_NOOP("ISOLineTypeEnum", "DashedSpaced"),
+ QT_TRANSLATE_NOOP("ISOLineTypeEnum", "LongDashedDotted"),
+ QT_TRANSLATE_NOOP("ISOLineTypeEnum", "LongDashedDoubleDotted"),
+ QT_TRANSLATE_NOOP("ISOLineTypeEnum", "LongDashedTripleDotted"),
+ QT_TRANSLATE_NOOP("ISOLineTypeEnum", "Dotted"),
+ QT_TRANSLATE_NOOP("ISOLineTypeEnum", "LongDashShortDash"),
+ QT_TRANSLATE_NOOP("ISOLineTypeEnum", "LongDashDoubleShortDash"),
+ QT_TRANSLATE_NOOP("ISOLineTypeEnum", "DashedDotted"),
+ QT_TRANSLATE_NOOP("ISOLineTypeEnum", "DoubleDashedDotted"),
+ QT_TRANSLATE_NOOP("ISOLineTypeEnum", "DashedDoubleDotted"),
+ QT_TRANSLATE_NOOP("ISOLineTypeEnum", "DoubleDashedDoubleDotted"),
+ QT_TRANSLATE_NOOP("ISOLineTypeEnum", "DashedTripleDotted"),
+ QT_TRANSLATE_NOOP("ISOLineTypeEnum", "DoubleDashedTripleDotted"),
+ nullptr};
+
+
+const int ANSILineName::ANSILineNameCount = 4;
+const char* ANSILineName::ANSILineNameEnums[]= {
+ QT_TRANSLATE_NOOP("ANSILineTypeEnum", "NoLine"),
+ QT_TRANSLATE_NOOP("ANSILineTypeEnum", "Continuous"),
+ QT_TRANSLATE_NOOP("ANSILineTypeEnum", "Dashed"),
+ QT_TRANSLATE_NOOP("ANSILineTypeEnum", "LongDashDashed"),
+ QT_TRANSLATE_NOOP("ANSILineTypeEnum", "LongDashDoubleDashed"),
+ nullptr};
+
+
+const int ASMELineName::ASMELineNameCount = 18;
+const char* ASMELineName::ASMELineNameEnums[]= {
+ QT_TRANSLATE_NOOP("ASMELineTypeEnum", "NoLine"),
+ QT_TRANSLATE_NOOP("ASMELineTypeEnum", "Visible"),
+ QT_TRANSLATE_NOOP("ASMELineTypeEnum", "Hidden"),
+ QT_TRANSLATE_NOOP("ASMELineTypeEnum", "Section"),
+ QT_TRANSLATE_NOOP("ASMELineTypeEnum", "Center"),
+ QT_TRANSLATE_NOOP("ASMELineTypeEnum", "Symmetry"),
+ QT_TRANSLATE_NOOP("ASMELineTypeEnum", "Dimension"),
+ QT_TRANSLATE_NOOP("ASMELineTypeEnum", "Extension"),
+ QT_TRANSLATE_NOOP("ASMELineTypeEnum", "Leader"),
+ QT_TRANSLATE_NOOP("ASMELineTypeEnum", "CuttingPlane"),
+ QT_TRANSLATE_NOOP("ASMELineTypeEnum", "ViewingPlane"),
+ QT_TRANSLATE_NOOP("ASMELineTypeEnum", "OtherPlane"),
+ QT_TRANSLATE_NOOP("ASMELineTypeEnum", "Break1"),
+ QT_TRANSLATE_NOOP("ASMELineTypeEnum", "Break2"),
+ QT_TRANSLATE_NOOP("ASMELineTypeEnum", "Phantom"),
+ QT_TRANSLATE_NOOP("ASMELineTypeEnum", "Stitch1"),
+ QT_TRANSLATE_NOOP("ASMELineTypeEnum", "Stitch2"),
+ QT_TRANSLATE_NOOP("ASMELineTypeEnum", "Chain"),
+ nullptr};
+
+}
+
diff --git a/src/Mod/TechDraw/App/LineNameEnum.h b/src/Mod/TechDraw/App/LineNameEnum.h
new file mode 100644
index 0000000000..b62c19f80e
--- /dev/null
+++ b/src/Mod/TechDraw/App/LineNameEnum.h
@@ -0,0 +1,115 @@
+/***************************************************************************
+ * Copyright (c) 2023 WandererFan *
+ * *
+ * 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 STDLINEENUMS_H_
+#define STDLINEENUMS_H_
+
+#include
+#include
+#include
+
+#include
+
+
+namespace TechDraw
+{
+
+//! common definitions for line numbers, names and lineicon names
+
+class TechDrawExport ISOLineName {
+ Q_DECLARE_TR_FUNCTIONS(TechDraw::ISOLineName)
+
+public:
+ enum ISOLineType { NOLINE = 0,
+ Continuous,
+ Dashed,
+ DashedSpaced,
+ LongDashedDotted,
+ LongDashedDoubleDotted,
+ LongDashedTripleDotted,
+ Dotted,
+ LongDashShortDash,
+ LongDashDoubleShortDash,
+ DashedDotted,
+ DoubleDashedDotted,
+ DashedDoubleDotted,
+ DoubleDashedDoubleDotted,
+ DashedTripleDotted,
+ DoubleDashedTripleDotted };
+
+ static const char* ISOLineNameEnums[];
+ static const int ISOLineNameCount;
+
+private:
+
+};
+
+class TechDrawExport ANSILineName {
+ Q_DECLARE_TR_FUNCTIONS(TechDraw::ANSILineName)
+
+public:
+ enum ANSILineType { NOLINE = 0,
+ Continuous,
+ Dashed,
+ LongDashedDashed,
+ LongDashedDoubleDashed };
+
+ static const char* ANSILineNameEnums[];
+ static const int ANSILineNameCount;
+
+private:
+
+};
+
+class TechDrawExport ASMELineName {
+ Q_DECLARE_TR_FUNCTIONS(TechDraw::ASMELineName)
+
+public:
+ enum ASMELineType { NOLINE = 0,
+ Visible,
+ Hidden,
+ Section,
+ Center,
+ Symmetry,
+ Dimension,
+ Extension,
+ Leader,
+ CuttingPlane,
+ ViewingPlane,
+ OtherPlane,
+ Break1,
+ Break2,
+ Phantom,
+ Stitch1,
+ Stitch2,
+ Chain
+ };
+
+ static const char* ASMELineNameEnums[];
+ static const int ASMELineNameCount;
+
+private:
+
+};
+} //end namespace TechDraw
+#endif
+
diff --git a/src/Mod/TechDraw/App/Preferences.cpp b/src/Mod/TechDraw/App/Preferences.cpp
index e60c233681..fcfbeaba7c 100644
--- a/src/Mod/TechDraw/App/Preferences.cpp
+++ b/src/Mod/TechDraw/App/Preferences.cpp
@@ -34,7 +34,7 @@
#include
#include "Preferences.h"
-
+#include "LineGenerator.h"
//getters for parameters used in multiple places.
//ensure this is in sync with preference page user interfaces
@@ -240,6 +240,16 @@ int Preferences::mattingStyle()
return getPreferenceGroup("Decorations")->GetInt("MattingStyle", 0);
}
+bool Preferences::showDetailMatting()
+{
+ return getPreferenceGroup("General")->GetBool("ShowDetailMatting", true);
+}
+
+bool Preferences::showDetailHighlight()
+{
+ return getPreferenceGroup("General")->GetBool("ShowDetailHighLight", true);
+}
+
std::string Preferences::svgFile()
{
std::string defaultDir = App::Application::getResourceDir() + "Mod/TechDraw/Patterns/";
diff --git a/src/Mod/TechDraw/App/Preferences.h b/src/Mod/TechDraw/App/Preferences.h
index 38475ccf21..9fc75da93c 100644
--- a/src/Mod/TechDraw/App/Preferences.h
+++ b/src/Mod/TechDraw/App/Preferences.h
@@ -81,6 +81,8 @@ public:
static int altDecimals();
static int mattingStyle();
+ static bool showDetailMatting();
+ static bool showDetailHighlight();
static std::string svgFile();
static std::string patFile();
@@ -105,6 +107,24 @@ public:
static double svgHatchFactor();
static bool SectionUsePreviousCut();
+
+ static int lineStandard();
+ static std::string lineDefinitionLocation();
+ static std::string lineElementsLocation();
+
+ static std::string lineGroupFile();
+ static int lineGroup();
+ static int SectionLineStyle();
+ static int CenterLineStyle();
+ static int HighlightLineStyle();
+ static int HiddenLineStyle();
+ static int LineCapStyle();
+ static int LineCapIndex();
+
+ static int LineSpacingISO();
+
+ static std::string currentLineDefFile();
+ static std::string currentElementDefFile();
};