[TD]Standard Line Styles - App components
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -883,6 +883,8 @@ void CenterLine::Save(Base::Writer &writer) const
|
||||
writer.decInd();
|
||||
writer.Stream() << writer.ind() << "</CLPoints>" << 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() << "<Style value=\"" << m_format.m_style << "\"/>" << std::endl;
|
||||
writer.Stream() << writer.ind() << "<Weight value=\"" << m_format.m_weight << "\"/>" << std::endl;
|
||||
writer.Stream() << writer.ind() << "<Color value=\"" << m_format.m_color.asHexString() << "\"/>" << 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<int>(m_geometry->getGeomType()));
|
||||
}
|
||||
|
||||
writer.Stream() << writer.ind() << "<LineNumber value=\"" << m_format.getLineNumber() << "\"/>" << 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<int>(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
|
||||
|
||||
@@ -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() << "<GeomIndex value=\"" << m_geomIndex << "\"/>" << 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() << "<Style value=\"" << m_format.m_style << "\"/>" << endl;
|
||||
writer.Stream() << writer.ind() << "<Weight value=\"" << m_format.m_weight << "\"/>" << endl;
|
||||
writer.Stream() << writer.ind() << "<Color value=\"" << m_format.m_color.asHexString() << "\"/>" << endl;
|
||||
writer.Stream() << writer.ind() << "<Visible value=\"" << v << "\"/>" << endl;
|
||||
writer.Stream() << writer.ind() << "<LineNumber value=\"" << m_format.getLineNumber() << "\"/>" << 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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,
|
||||
|
||||
404
src/Mod/TechDraw/App/LineGenerator.cpp
Normal file
404
src/Mod/TechDraw/App/LineGenerator.cpp
Normal file
@@ -0,0 +1,404 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 WandererFan <wandererfan@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
//! 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 <QVector>
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Stream.h>
|
||||
|
||||
#include <Mod/TechDraw/App/Preferences.h>
|
||||
#include <Mod/TechDraw/App/DrawUtil.h>
|
||||
#include <Mod/TechDraw/App/LineNameEnum.h>
|
||||
|
||||
#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<std::string> 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<double> 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<double> qDashPattern = QVector<double>::fromStdVector(dashPattern);
|
||||
#else
|
||||
QVector<double> 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<std::string, int> LineGenerator::loadElements()
|
||||
{
|
||||
// Base::Console().Message("DLG::loadElements()\n");
|
||||
std::map<std::string, int> 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<std::string> 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<std::string> > LineGenerator::getLineDefinitions()
|
||||
{
|
||||
// Base::Console().Message("DLG::loadLineDefinitions()\n");
|
||||
std::vector< std::vector<std::string> > 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<std::string> validTokens;
|
||||
for (auto& token : DU::tokenize(line, ",")) {
|
||||
if (!token.empty()) {
|
||||
validTokens.emplace_back(token);
|
||||
}
|
||||
}
|
||||
std::vector<std::string> 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<std::string> LineGenerator::getAvailableLineStandards()
|
||||
{
|
||||
std::vector<std::string> 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<std::string> LineGenerator::getLoadedDescriptions()
|
||||
{
|
||||
return m_lineDescs;
|
||||
}
|
||||
|
||||
|
||||
//! extract the line description fields from the current definition file
|
||||
std::vector<std::string> LineGenerator::getLineDescriptions()
|
||||
{
|
||||
std::vector<std::string> 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<std::string> 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<std::string> 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<std::string> 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);
|
||||
}
|
||||
86
src/Mod/TechDraw/App/LineGenerator.h
Normal file
86
src/Mod/TechDraw/App/LineGenerator.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 WandererFan <wandererfan@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
//! 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 <Mod/TechDraw/TechDrawGlobal.h>
|
||||
|
||||
#include <QPen>
|
||||
|
||||
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<std::string> getAvailableLineStandards();
|
||||
static std::string getLineStandardsBody();
|
||||
|
||||
//! get line descriptions from memory
|
||||
std::vector<std::string> getLoadedDescriptions();
|
||||
//! get line descriptions from file
|
||||
static std::vector<std::string> getLineDescriptions();
|
||||
|
||||
static bool isProportional(size_t standardIndex);
|
||||
bool isCurrentProportional();
|
||||
static std::string getBodyFromString(std::string inString);
|
||||
|
||||
private:
|
||||
static std::map<std::string, int> loadElements();
|
||||
static std::vector< std::vector<std::string> > getLineDefinitions();
|
||||
|
||||
std::map<std::string, int> m_elementDefs;
|
||||
std::vector< std::vector<std::string> > m_lineDefs;
|
||||
std::vector< std::string > m_lineDescs;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
86
src/Mod/TechDraw/App/LineNameEnum.cpp
Normal file
86
src/Mod/TechDraw/App/LineNameEnum.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 WandererFan <wandererfan@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#include "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};
|
||||
|
||||
}
|
||||
|
||||
115
src/Mod/TechDraw/App/LineNameEnum.h
Normal file
115
src/Mod/TechDraw/App/LineNameEnum.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 WandererFan <wandererfan@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef STDLINEENUMS_H_
|
||||
#define STDLINEENUMS_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <QCoreApplication>
|
||||
|
||||
#include <Mod/TechDraw/TechDrawGlobal.h>
|
||||
|
||||
|
||||
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
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#include <Base/Parameter.h>
|
||||
|
||||
#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/";
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user