[TD]Complex Section - initial implementation

This commit is contained in:
wandererfan
2022-10-10 10:10:42 -04:00
committed by WandererFan
parent f0c61364f3
commit 0ff473a9b6
39 changed files with 4656 additions and 773 deletions

View File

@@ -147,11 +147,13 @@ void MDIView::onRelabel(Gui::Document *pDoc)
// Either with dirty flag ...
QRegularExpression rx(QLatin1String("(\\s\\:\\s\\d+\\[\\*\\])$"));
QRegularExpressionMatch match;
int pos = cap.lastIndexOf(rx, -1, &match);
//int pos =
cap.lastIndexOf(rx, -1, &match);
if (!match.hasMatch()) {
// ... or not
rx.setPattern(QLatin1String("(\\s\\:\\s\\d+)$"));
pos = cap.lastIndexOf(rx, -1, &match);
//pos =
cap.lastIndexOf(rx, -1, &match);
}
if (match.hasMatch()) {
cap = QString::fromUtf8(pDoc->getDocument()->Label.getValue());

View File

@@ -24,8 +24,9 @@
#include <Base/Interpreter.h>
#include <Base/PyObjectBase.h>
#include "Cosmetic.h"
#include "CosmeticExtension.h"
#include "Cosmetic.h"
#include "DrawComplexSection.h"
#include "DrawGeomHatch.h"
#include "DrawHatch.h"
#include "DrawLeaderLine.h"
@@ -37,7 +38,6 @@
#include "DrawSVGTemplate.h"
#include "DrawTile.h"
#include "DrawTileWeld.h"
#include "DrawView.h"
#include "DrawViewAnnotation.h"
#include "DrawViewArch.h"
#include "DrawViewBalloon.h"
@@ -47,8 +47,8 @@
#include "DrawViewDimension.h"
#include "DrawViewDimExtent.h"
#include "DrawViewDraft.h"
#include "DrawView.h"
#include "DrawViewImage.h"
#include "DrawViewMulti.h"
#include "DrawViewPart.h"
#include "DrawViewSection.h"
#include "DrawViewSpreadsheet.h"
@@ -62,6 +62,7 @@
#include "PropertyGeomFormatList.h"
namespace TechDraw {
extern PyObject* initModule();
}
@@ -90,7 +91,7 @@ PyMOD_INIT_FUNC(TechDraw)
TechDraw::DrawViewSpreadsheet ::init();
TechDraw::DrawViewSection ::init();
TechDraw::DrawViewMulti ::init();
TechDraw::DrawComplexSection ::init();
TechDraw::DrawViewDimension ::init();
TechDraw::DrawViewDimExtent ::init();
TechDraw::LandmarkDimension ::init();
@@ -134,7 +135,8 @@ PyMOD_INIT_FUNC(TechDraw)
TechDraw::DrawPagePython ::init();
TechDraw::DrawViewPython ::init();
TechDraw::DrawViewPartPython ::init();
TechDraw::DrawViewMultiPython ::init();
TechDraw::DrawViewSectionPython::init();
TechDraw::DrawComplexSectionPython ::init();
TechDraw::DrawTemplatePython ::init();
TechDraw::DrawViewSymbolPython::init();
TechDraw::DrawLeaderLinePython::init();

View File

@@ -75,6 +75,8 @@ generate_from_xml(CosmeticExtensionPy)
SET(Draw_SRCS
DrawPage.cpp
DrawPage.h
DrawComplexSection.cpp
DrawComplexSection.h
DrawView.cpp
DrawView.h
DrawViewPart.cpp

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,129 @@
/***************************************************************************
* Copyright (c) 2022 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 DrawComplexSection_h_
#define DrawComplexSection_h_
#include <Mod/TechDraw/TechDrawGlobal.h>
#include <gp_Dir.hxx>
#include <gp_Vec.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include "DrawViewSection.h"
namespace TechDraw
{
//changes in direction of complex section line
class ChangePoint
{
public:
ChangePoint(QPointF location, QPointF preDirection, QPointF postDirection);
ChangePoint(gp_Pnt location, gp_Dir preDirection, gp_Dir postDirection);
~ChangePoint() = default;
QPointF getLocation() const { return m_location; }
QPointF getPreDirection() const { return m_preDirection; }
QPointF getPostDirection() const { return m_postDirection; }
void scale(double scaleFactor);
private:
QPointF m_location;
QPointF m_preDirection;
QPointF m_postDirection;
};
using ChangePointVector = std::vector<ChangePoint>;
class TechDrawExport DrawComplexSection : public DrawViewSection
{
PROPERTY_HEADER_WITH_OVERRIDE(Part::DrawComplexSection);
public:
DrawComplexSection();
~DrawComplexSection() = default;
App::PropertyLink CuttingToolWireObject;
App::PropertyEnumeration ProjectionStrategy; //Single or Piecewise
TopoDS_Shape getShapeToCut() override;
TopoDS_Shape makeCuttingTool(double dMax) 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;
void makeSectionCut(TopoDS_Shape &baseShape) override;
TopoDS_Shape getShapeToIntersect() override;
gp_Pln getSectionPlane() const override;
TopoDS_Compound alignSectionFaces(TopoDS_Shape faceIntersections) override;
std::pair<Base::Vector3d, Base::Vector3d>
sectionLineEnds() 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);
TopoDS_Shape extrudeWireToFace(TopoDS_Wire& wire, gp_Dir extrudeDir, double extrudeDist);
TopoDS_Shape makeAlignedPieces(const TopoDS_Shape& rawShape,
const TopoDS_Shape& toolFaceShape,
double extrudeDistance);
TopoDS_Shape distributeAlignedPieces(std::vector<TopoDS_Shape> pieces);
TopoDS_Compound singleToolIntersections(const TopoDS_Shape& cutShape);
TopoDS_Compound piecewiseToolIntersections(const TopoDS_Shape& cutShape);
BaseGeomPtrVector makeSectionLineGeometry();
std::pair<Base::Vector3d, Base::Vector3d>
sectionArrowDirs();
TopoDS_Wire makeSectionLineWire();
TopoDS_Wire makeProfileWire(App::DocumentObject* toolObj);
TopoDS_Wire makeNoseToTailWire(TopoDS_Wire inWire);
gp_Dir projectProfileWire(TopoDS_Wire profileWire, gp_Ax3 paperCS);
ChangePointVector getChangePointsFromSectionLine();
bool validateProfilePosition(TopoDS_Wire profileWire,
gp_Ax2 sectionCS,
gp_Dir& gClosestBasis) const;
bool showSegment(gp_Dir segmentNormal) const;
static bool isProfileObject(App::DocumentObject* obj);
static bool isMultiSegmentProfile(App::DocumentObject* obj);
static bool isLinearProfile(App::DocumentObject* obj);
private:
gp_Dir getFaceNormal(TopoDS_Face& face);
TopoDS_Shape m_toolFaceShape;
TopoDS_Wire m_profileWire;
static const char* ProjectionStrategyEnums[];
};
using DrawComplexSectionPython = App::FeaturePythonT<DrawComplexSection>;
} //namespace TechDraw
#endif

View File

@@ -512,6 +512,12 @@ std::vector<TopoDS_Edge> DrawProjectSplit::scrubEdges(const std::vector<TechDraw
std::vector<TopoDS_Edge> DrawProjectSplit::scrubEdges(std::vector<TopoDS_Edge>& origEdges,
std::vector<TopoDS_Edge> &closedEdges)
{
if (origEdges.empty()) {
//how did this happen? if Scale is zero, all the edges will be zero length,
//but Scale property has constraint, so this shouldn't happen!
// Base::Console().Message("DPS::scrubEdges(2) - origEdges is empty\n"); //debug
return std::vector<TopoDS_Edge>();
}
//HLR usually delivers overlapping edges. We need to refine edge overlaps
//into non-overlapping pieces
std::vector<TopoDS_Edge> noOverlaps;

View File

@@ -23,36 +23,38 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <cmath>
# include <cstdlib>
# include <cstring>
# include <sstream>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <sstream>
# include <boost/regex.hpp>
#include <boost/regex.hpp>
# include <QChar>
# include <QPointF>
# include <QString>
#include <QChar>
#include <QPointF>
#include <QString>
# include <BRep_Builder.hxx>
# include <BRep_Tool.hxx>
# include <BRepAdaptor_Curve.hxx>
# include <BRepAdaptor_Surface.hxx>
# include <BRepExtrema_DistShapeShape.hxx>
# include <BRepLProp_CLProps.hxx>
# include <BRepLProp_CurveTool.hxx>
# include <BRepLProp_SLProps.hxx>
# include <BRepTools.hxx>
# include <GCPnts_AbscissaPoint.hxx>
# include <gp_Ax3.hxx>
# include <gp_Dir.hxx>
# include <gp_Elips.hxx>
# include <gp_Pnt.hxx>
# include <gp_Vec.hxx>
# include <Precision.hxx>
# include <TopExp.hxx>
# include <TopExp_Explorer.hxx>
# include <TopTools_IndexedMapOfShape.hxx>
#include <BRepBndLib.hxx>
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepExtrema_DistShapeShape.hxx>
#include <BRepLProp_CLProps.hxx>
#include <BRepLProp_CurveTool.hxx>
#include <BRepLProp_SLProps.hxx>
#include <BRepTools.hxx>
#include <GCPnts_AbscissaPoint.hxx>
#include <gp_Ax3.hxx>
#include <gp_Dir.hxx>
#include <gp_Elips.hxx>
#include <gp_Pnt.hxx>
#include <gp_Vec.hxx>
#include <Precision.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
#endif
#include <App/Application.h>
@@ -511,6 +513,11 @@ Base::Vector3d DrawUtil::vecRotate(Base::Vector3d vec,
return Base::Vector3d(xForm * (vec));
}
gp_Vec DrawUtil::closestBasis(gp_Vec inVec)
{
return gp_Vec(togp_Dir(closestBasis(toVector3d(inVec))));
}
Base::Vector3d DrawUtil::closestBasis(Base::Vector3d v)
{
Base::Vector3d result(0.0, -1, 0);
@@ -522,11 +529,16 @@ Base::Vector3d DrawUtil::closestBasis(Base::Vector3d v)
Base::Vector3d stdZr(0.0, 0.0, -1.0);
//first check if already a basis
if (checkParallel(v, stdZ) ||
checkParallel(v, stdY) ||
checkParallel(v, stdX)) {
if (v.Dot(stdX) == 1.0 ||
v.Dot(stdY) == 1.0 ||
v.Dot(stdZ) == 1.0) {
return v;
}
if (v.Dot(stdX) == -1.0 ||
v.Dot(stdY) == -1.0 ||
v.Dot(stdZ) == -1.0) {
return -v;
}
//not a basis. find smallest angle with a basis.
double angleX, angleY, angleZ, angleXr, angleYr, angleZr, angleMin;
@@ -537,23 +549,139 @@ Base::Vector3d DrawUtil::closestBasis(Base::Vector3d v)
angleYr = stdYr.GetAngle(v);
angleZr = stdZr.GetAngle(v);
angleMin = angleX;
if (angleY < angleMin) {
return stdY;
angleMin = std::min({angleX, angleY, angleZ, angleXr, angleYr, angleZr});
if (angleX == angleMin) {
return Base::Vector3d(1.0, 0.0, 0.0);
}
if (angleZ < angleMin) {
return stdZ;
if (angleY == angleMin) {
return Base::Vector3d(0.0, 1.0, 0.0);
}
if (angleXr < angleMin) {
return stdXr;
if (angleZ == angleMin) {
return Base::Vector3d(0.0, 0.0, 1.0);
}
if (angleYr < angleMin) {
return stdYr;
if (angleXr == angleMin) {
return Base::Vector3d(1.0, 0.0, 0.0);
}
if (angleZr < angleMin) {
return stdZr;
if (angleYr == angleMin) {
return Base::Vector3d(0.0, 1.0, 0.0);
}
return stdX;
if (angleZr == angleMin) {
return Base::Vector3d(0.0, 0.0, 1.0);
}
//should not get to here
return Base::Vector3d(1.0, 0.0, 0.0);
}
Base::Vector3d DrawUtil::closestBasis(Base::Vector3d vDir, gp_Ax2 coordSys)
{
gp_Dir gDir(vDir.x, vDir.y, vDir.z);
return closestBasis(gDir, coordSys);
}
Base::Vector3d DrawUtil::closestBasis(gp_Dir gDir, gp_Ax2 coordSys)
{
gp_Dir xCS = coordSys.XDirection(); //these are unit vectors?
gp_Dir yCS = coordSys.YDirection();
gp_Dir zCS = coordSys.Direction();
//first check if already a basis
if (gDir.Dot(xCS) == 1.0 ||
gDir.Dot(yCS) == 1.0 ||
gDir.Dot(zCS) == 1.0 ) {
//gDir is parallel with a basis
return Base::Vector3d( gDir.X(), gDir.Y(), gDir.Z()) ;
}
if (gDir.Dot(xCS.Reversed()) == 1.0 ||
gDir.Dot(yCS.Reversed()) == 1.0 ||
gDir.Dot(zCS.Reversed()) == 1.0 ) {
//gDir is anti-parallel with a basis
return Base::Vector3d( -gDir.X(), -gDir.Y(), -gDir.Z());
}
//not a basis. find smallest angle with a basis.
double angleX, angleY, angleZ, angleXr, angleYr, angleZr, angleMin;
angleX = gDir.Angle(xCS);
angleY = gDir.Angle(yCS);
angleZ = gDir.Angle(zCS);
angleXr = gDir.Angle(xCS.Reversed());
angleYr = gDir.Angle(yCS.Reversed());
angleZr = gDir.Angle(zCS.Reversed());
angleMin = std::min({angleX, angleY, angleZ, angleXr, angleYr, angleZr});
if (angleX == angleMin) {
return Base::Vector3d(xCS.X(), xCS.Y(), xCS.Z());
}
if (angleY == angleMin) {
return Base::Vector3d(yCS.X(), yCS.Y(), yCS.Z());
}
if (angleZ == angleMin) {
return Base::Vector3d(zCS.X(), zCS.Y(), zCS.Z()) ;
}
if (angleXr == angleMin) {
return Base::Vector3d(-xCS.X(), -xCS.Y(), -xCS.Z());
}
if (angleYr == angleMin) {
return Base::Vector3d(-yCS.X(), -yCS.Y(), -yCS.Z());
}
if (angleZr == angleMin) {
return Base::Vector3d(-zCS.X(), -zCS.Y(), -zCS.Z());
}
//should not get to here
return Base::Vector3d(xCS.X(), xCS.Y(), xCS.Z());
}
double DrawUtil::getWidthInDirection(gp_Dir direction, TopoDS_Shape& shape)
{
Base::Vector3d stdX(1.0, 0.0, 0.0);
Base::Vector3d stdY(0.0, 1.0, 0.0);
Base::Vector3d stdZ(0.0, 0.0, 1.0);
Base::Vector3d stdXr(-1.0, 0.0, 0.0);
Base::Vector3d stdYr(0.0, -1.0, 0.0);
Base::Vector3d stdZr(0.0, 0.0, -1.0);
Base::Vector3d vClosestBasis = closestBasis(toVector3d(direction));
Bnd_Box shapeBox;
shapeBox.SetGap(0.0);
BRepBndLib::AddOptimal(shape, shapeBox);
double xMin = 0, xMax = 0, yMin = 0, yMax = 0, zMin = 0, zMax = 0;
if (shapeBox.IsVoid()) {
//this really shouldn't happen here as null shapes should have been caught
//long before this
Base::Console().Error("DU::getWidthInDirection - shapeBox is void\n");
return 0.0;
}
shapeBox.Get(xMin, yMin, zMin, xMax, yMax, zMax);
if (vClosestBasis.IsEqual(stdX, EWTOLERANCE) ||
vClosestBasis.IsEqual(stdXr, EWTOLERANCE) ) {
return xMax - xMin;
}
if (vClosestBasis.IsEqual(stdY, EWTOLERANCE) ||
vClosestBasis.IsEqual(stdYr, EWTOLERANCE) ) {
return yMax - yMin;
}
if (vClosestBasis.IsEqual(stdZ, EWTOLERANCE) ||
vClosestBasis.IsEqual(stdZr, EWTOLERANCE) ) {
return zMax - zMin;
}
return 0.0;
}
//based on Function provided by Joe Dowsett, 2014
@@ -873,6 +1001,102 @@ void DrawUtil::encodeXmlSpecialChars(std::string& inoutText)
inoutText.swap(buffer);
}
//Sort edges into nose to tail order. From Part/App/AppPartPy.cpp. gives back a sequence
//of nose to tail edges and a shrunken input sequence of edges (the unconnected left overs)
//struct EdgePoints {
// gp_Pnt v1, v2;
// std::list<TopoDS_Edge>::iterator it;
// TopoDS_Edge edge;
//};
std::list<TopoDS_Edge> DrawUtil::sort_Edges(double tol3d, std::list<TopoDS_Edge>& edges)
{
tol3d = tol3d * tol3d;
std::list<EdgePoints> edge_points;
TopExp_Explorer xp;
for (std::list<TopoDS_Edge>::iterator it = edges.begin(); it != edges.end(); ++it) {
EdgePoints ep;
xp.Init(*it,TopAbs_VERTEX);
ep.v1 = BRep_Tool::Pnt(TopoDS::Vertex(xp.Current()));
xp.Next();
ep.v2 = BRep_Tool::Pnt(TopoDS::Vertex(xp.Current()));
ep.it = it;
ep.edge = *it;
edge_points.push_back(ep);
}
if (edge_points.empty())
return std::list<TopoDS_Edge>();
std::list<TopoDS_Edge> sorted;
gp_Pnt gpChainFirst, gpChainLast;
gpChainFirst = edge_points.front().v1;
gpChainLast = edge_points.front().v2;
sorted.push_back(edge_points.front().edge);
edges.erase(edge_points.front().it);
edge_points.erase(edge_points.begin());
while (!edge_points.empty()) {
// search for adjacent edge
std::list<EdgePoints>::iterator itEdgePoint;
for (itEdgePoint = edge_points.begin(); itEdgePoint != edge_points.end(); ++itEdgePoint) {
if (itEdgePoint->v1.SquareDistance(gpChainLast) <= tol3d) {
//found a connection from end of chain to start of edge
gpChainLast = itEdgePoint->v2;
sorted.push_back(itEdgePoint->edge);
edges.erase(itEdgePoint->it);
edge_points.erase(itEdgePoint);
itEdgePoint = edge_points.begin();
break;
}
else if (itEdgePoint->v2.SquareDistance(gpChainFirst) <= tol3d) {
//found a connection from start of chain to end of edge
gpChainFirst = itEdgePoint->v1;
sorted.push_front(itEdgePoint->edge);
edges.erase(itEdgePoint->it);
edge_points.erase(itEdgePoint);
itEdgePoint = edge_points.begin();
break;
}
else if (itEdgePoint->v2.SquareDistance(gpChainLast) <= tol3d) {
//found a connection from end of chain to end of edge
gpChainLast = itEdgePoint->v1;
Standard_Real firstParam, lastParam;
const Handle(Geom_Curve) & curve = BRep_Tool::Curve(itEdgePoint->edge, firstParam, lastParam);
firstParam = curve->ReversedParameter(firstParam);
lastParam = curve->ReversedParameter(lastParam);
TopoDS_Edge edgeReversed = BRepBuilderAPI_MakeEdge(curve->Reversed(), firstParam, lastParam);
sorted.push_back(edgeReversed);
edges.erase(itEdgePoint->it);
edge_points.erase(itEdgePoint);
itEdgePoint = edge_points.begin();
break;
}
else if (itEdgePoint->v1.SquareDistance(gpChainFirst) <= tol3d) {
//found a connection from start of chain to start of edge
gpChainFirst = itEdgePoint->v2;
Standard_Real firstParam, lastParam;
const Handle(Geom_Curve) & curve = BRep_Tool::Curve(itEdgePoint->edge, firstParam, lastParam);
firstParam = curve->ReversedParameter(firstParam);
lastParam = curve->ReversedParameter(lastParam);
TopoDS_Edge edgeReversed = BRepBuilderAPI_MakeEdge(curve->Reversed(), firstParam, lastParam);
sorted.push_front(edgeReversed);
edges.erase(itEdgePoint->it);
edge_points.erase(itEdgePoint);
itEdgePoint = edge_points.begin();
break;
}
}
if ((itEdgePoint == edge_points.end()) || (gpChainLast.SquareDistance(gpChainFirst) <= tol3d)) {
// no adjacent edge found or polyline is closed
return sorted;
}
}
return sorted;
}
// Supplementary mathematical functions
// ====================================
@@ -1367,7 +1591,7 @@ void DrawUtil::dumpCS3(const char* text,
gp_Dir baseX = CS.XDirection();
gp_Dir baseY = CS.YDirection();
gp_Pnt baseOrg = CS.Location();
Base::Console().Message("DU::dumpCSF - %s Loc: %s Axis: %s X: %s Y: %s\n", text,
Base::Console().Message("DU::dumpCS3 - %s Loc: %s Axis: %s X: %s Y: %s\n", text,
DrawUtil::formatVector(baseOrg).c_str(),
DrawUtil::formatVector(baseAxis).c_str(),
DrawUtil::formatVector(baseX).c_str(),

View File

@@ -70,6 +70,13 @@
namespace TechDraw
{
//used by sort_Edges
struct EdgePoints {
gp_Pnt v1, v2;
std::list<TopoDS_Edge>::iterator it;
TopoDS_Edge edge;
};
/// Convenient utility functions for TechDraw Module
class TechDrawExport DrawUtil {
public:
@@ -122,10 +129,15 @@ class TechDrawExport DrawUtil {
double angle,
Base::Vector3d axis,
Base::Vector3d org = Base::Vector3d(0.0, 0.0, 0.0));
static Base::Vector3d closestBasis(Base::Vector3d v);
static gp_Vec closestBasis(gp_Vec inVec);
static Base::Vector3d closestBasis(Base::Vector3d vDir, gp_Ax2 coordSys);
static Base::Vector3d closestBasis(gp_Dir gDir, gp_Ax2 coordSys);
static double getWidthInDirection(gp_Dir direction, TopoDS_Shape& shape);
static double getDefaultLineWeight(std::string s);
/* static Base::Vector3d vector23(const Base::Vector3d& v2) { return Base::Vector3d(v2.x, v2.y, 0.0); }*/
/* static Base::Vector3d vector32(const Base::Vector3d& v3) { return Base::Vector3d(v3.x, v3.y); }*/
//! is pt between end1 and end2?
static bool isBetween(const Base::Vector3d pt, const Base::Vector3d end1, const Base::Vector3d end2);
//! find intersection in 2d for 2 lines in point+direction form
@@ -133,8 +145,10 @@ class TechDrawExport DrawUtil {
Base::Vector3d p2, Base::Vector3d d2);
static Base::Vector2d Intersect2d(Base::Vector2d p1, Base::Vector2d d1,
Base::Vector2d p2, Base::Vector2d d2);
static Base::Vector3d gpPnt2V3(const gp_Pnt gp) { return Base::Vector3d(gp.X(), gp.Y(), gp.Z()); }
static gp_Pnt V32gpPnt(const Base::Vector3d v) { return gp_Pnt(v.x, v.y, v.z); }
static Base::Vector3d toVector3d(const gp_Pnt gp) { return Base::Vector3d(gp.X(), gp.Y(), gp.Z()); }
static Base::Vector3d toVector3d(const gp_Dir gp) { return Base::Vector3d(gp.X(), gp.Y(), gp.Z()); }
static gp_Pnt togp_Pnt(const Base::Vector3d v) { return gp_Pnt(v.x, v.y, v.z); }
static gp_Dir togp_Dir(const Base::Vector3d v) { return gp_Dir(v.x, v.y, v.z); }
static std::string shapeToString(TopoDS_Shape s);
static TopoDS_Shape shapeFromString(std::string s);
static Base::Vector3d invertY(Base::Vector3d v);
@@ -148,7 +162,7 @@ class TechDrawExport DrawUtil {
static bool circulation(Base::Vector3d A, Base::Vector3d B, Base::Vector3d C);
static int countSubShapes(TopoDS_Shape shape, TopAbs_ShapeEnum subShape);
static void encodeXmlSpecialChars(std::string& inoutText);
static std::list<TopoDS_Edge> sort_Edges(double tol3d, std::list<TopoDS_Edge>& edges);
// Supplementary mathematical functions
static int sgn(double x);

View File

@@ -118,6 +118,15 @@ void DrawView::onChanged(const App::Property* prop)
//Coding note: calling execute, recompute or recomputeFeature inside an onChanged
//method can create infinite loops if the called method changes a property. In general
//don't do this! There are situations where it is OK, but careful analysis is a must.
if (prop == &Scale &&
Scale.getValue() < Precision::Confusion()) {
//this is not supposed to happen since Scale has constraints, but it may
//happen during changes made in PropertyEditor?
Scale.setValue(1.0);
return;
}
if (isRestoring()) {
App::DocumentObject::onChanged(prop);
return;

View File

@@ -25,29 +25,30 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <sstream>
# include <QtConcurrentRun>
# include <Bnd_Box.hxx>
# include <BRep_Tool.hxx>
# include <BRepAlgo_NormalProjection.hxx>
# include <BRepBndLib.hxx>
# include <BRepBuilderAPI_Copy.hxx>
# include <BRepBuilderAPI_MakeFace.hxx>
# include <BRepBuilderAPI_MakeWire.hxx>
# include <BRepTools.hxx>
# include <gp_Ax2.hxx>
# include <gp_Dir.hxx>
# include <gp_Pln.hxx>
# include <gp_Pnt.hxx>
# include <HLRAlgo_Projector.hxx>
# include <ShapeAnalysis.hxx>
# include <TopExp.hxx>
# include <TopoDS.hxx>
# include <TopoDS_Edge.hxx>
# include <TopoDS_Face.hxx>
# include <TopoDS_Shape.hxx>
# include <TopoDS_Vertex.hxx>
# include <TopoDS_Wire.hxx>
#include <sstream>
#include <QtConcurrentRun>
#include <Bnd_Box.hxx>
#include <BRep_Tool.hxx>
#include <BRepAlgo_NormalProjection.hxx>
#include <BRepBndLib.hxx>
#include <BRepBuilderAPI_Copy.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepTools.hxx>
#include <gp_Ax2.hxx>
#include <gp_Dir.hxx>
#include <gp_Pln.hxx>
#include <gp_Pnt.hxx>
#include <HLRAlgo_Projector.hxx>
#include <ShapeAnalysis.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopoDS_Wire.hxx>
#endif
#include <App/Application.h>
@@ -237,7 +238,7 @@ App::DocumentObjectExecReturn *DrawViewPart::execute(void)
TopoDS_Shape shape = getSourceShape();
if (shape.IsNull()) {
Base::Console().Log("DVP::execute - %s - Source shape is Null.\n",
Base::Console().Message("DVP::execute - %s - Source shape is Null.\n",
getNameInDocument());
return DrawView::execute();
}
@@ -345,7 +346,7 @@ GeometryObject* DrawViewPart::makeGeometryForShape(TopoDS_Shape& shape)
}
//create a geometry object and trigger the HLR process in another thread
TechDraw::GeometryObject* DrawViewPart::buildGeometryObject(TopoDS_Shape& shape, gp_Ax2& viewAxis)
TechDraw::GeometryObject* DrawViewPart::buildGeometryObject(TopoDS_Shape& shape, const gp_Ax2 &viewAxis)
{
// Base::Console().Message("DVP::buildGeometryObject() - %s\n", getNameInDocument());
showProgressMessage(getNameInDocument(), "is finding hidden lines");
@@ -468,7 +469,7 @@ void DrawViewPart::extractFaces()
geometryObject->getVisibleFaceEdges(SmoothVisible.getValue(),SeamVisible.getValue());
if (goEdges.empty()) {
Base::Console().Message("DVP::extractFaces - %s - no face edges available!\n", getNameInDocument());
// Base::Console().Message("DVP::extractFaces - %s - no face edges available!\n", getNameInDocument()); //debug
return;
}
@@ -476,6 +477,13 @@ void DrawViewPart::extractFaces()
std::vector<TopoDS_Edge> closedEdges;
std::vector<TopoDS_Edge> cleanEdges = DrawProjectSplit::scrubEdges(goEdges, closedEdges);
if (cleanEdges.empty() &&
closedEdges.empty()) {
//how does this happen? something wrong somewhere
// Base::Console().Message("DVP::extractFaces - no clean or closed wires\n"); //debug
return;
}
//use EdgeWalker to make wires from edges
EdgeWalker eWalker;
std::vector<TopoDS_Wire> sortedWires;
@@ -892,8 +900,27 @@ BaseGeomPtr DrawViewPart::projectEdge(const TopoDS_Edge& e) const
projector.Add(e);
projector.Build();
TopoDS_Shape s = projector.Projection();
// Base::Console().Message("DVP::projectEdge - s.IsNull: %d\n", s.IsNull());
BaseGeomPtr result;
return BaseGeom::baseFactory(TopoDS::Edge(s));
}
//simple projection of inWire with conversion of the result to TD geometry
BaseGeomPtrVector DrawViewPart::projectWire(const TopoDS_Wire& inWire) const
{
// Base::Console().Message("DVP::projectWire() - inWire.IsNull: %d\n", inWire.IsNull());
BaseGeomPtrVector result;
Base::Vector3d stdOrg(0.0, 0.0, 0.0);
TopoDS_Face paper = BRepBuilderAPI_MakeFace(gp_Pln(getProjectionCS(stdOrg)));
BRepAlgo_NormalProjection projector(paper);
projector.Add(inWire);
projector.Build();
BRepTools::Write(projector.Projection(), "DVPprojectedWire.brep"); //debug
TopExp_Explorer expShape(projector.Projection(), TopAbs_EDGE);
for (; expShape.More(); expShape.Next()) {
BaseGeomPtr edge = BaseGeom::baseFactory(TopoDS::Edge(expShape.Current()));
result.push_back(edge);
}
return result;
}

View File

@@ -142,11 +142,12 @@ public:
virtual Base::Vector3d projectPoint(const Base::Vector3d& pt,
bool invert = true) const;
virtual BaseGeomPtr projectEdge(const TopoDS_Edge& e) const;
virtual BaseGeomPtrVector projectWire(const TopoDS_Wire& inWire) const;
virtual gp_Ax2 getViewAxis(const Base::Vector3d& pt,
const Base::Vector3d& direction,
const bool flip=true) const;
virtual gp_Ax2 getProjectionCS(Base::Vector3d pt) const;
virtual gp_Ax2 getProjectionCS(Base::Vector3d pt = Base::Vector3d(0.0, 0.0, 0.0)) const;
virtual Base::Vector3d getXDirection() const; //don't use XDirection.getValue()
virtual Base::Vector3d getOriginalCentroid() const;
virtual Base::Vector3d getCurrentCentroid() const;
@@ -223,7 +224,7 @@ protected:
void onChanged(const App::Property* prop) override;
void unsetupObject() override;
virtual TechDraw::GeometryObject* buildGeometryObject(TopoDS_Shape& shape, gp_Ax2& viewAxis);
virtual TechDraw::GeometryObject* buildGeometryObject(TopoDS_Shape& shape, const gp_Ax2& viewAxis);
virtual TechDraw::GeometryObject* makeGeometryForShape(TopoDS_Shape& shape); //const??
void partExec(TopoDS_Shape& shape);
virtual void addShapes2d(void);

View File

@@ -22,33 +22,55 @@
* *
***************************************************************************/
//DrawViewSection processing overview
//execute
// sectionExec(getShapeToCut())
//sectionExec
// makeSectionCut(baseShape)
//makeSectionCut (separate thread)
// m_cuttingTool = makeCuttingTool (DVSTool.brep)
// m_cutPieces = (baseShape - m_cuttingTool) (DVSCutPieces.brep)
//onSectionCutFinished
// m_preparedShape = prepareShape(m_cutPieces) - centered, scaled, rotated
// geometryObject = DVP::buildGeometryObject(m_preparedShape) (HLR)
//postHlrTasks
// faceIntersections = findSectionPlaneIntersections
// m_sectionTopoDSFaces = alignSectionFaces(faceIntersections)
// m_tdSectionFaces = makeTDSectionFaces(m_sectionTopoDSFaces)
#include "PreCompiled.h"
#ifndef _PreComp_
# include <chrono>
# include <sstream>
# include <QtConcurrentRun>
# include <Bnd_Box.hxx>
# include <BRep_Builder.hxx>
# include <BRepBndLib.hxx>
# include <BRepAdaptor_Surface.hxx>
# include <BRepAlgoAPI_Cut.hxx>
# include <BRepBuilderAPI_Copy.hxx>
# include <BRepBuilderAPI_MakeFace.hxx>
# include <BRepBuilderAPI_Transform.hxx>
# include <BRepPrimAPI_MakePrism.hxx>
# include <BRepTools.hxx>
# include <gp_Ax2.hxx>
# include <gp_Ax3.hxx>
# include <gp_Dir.hxx>
# include <gp_Pln.hxx>
# include <gp_Pnt.hxx>
# include <TopoDS_Shape.hxx>
# include <TopoDS.hxx>
# include <TopoDS_Face.hxx>
# include <TopoDS_Edge.hxx>
# include <TopoDS_Compound.hxx>
# include <TopExp_Explorer.hxx>
#include <chrono>
#include <sstream>
#include <QtConcurrentRun>
#include <Bnd_Box.hxx>
#include <BRep_Builder.hxx>
#include <BRepBndLib.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <BRepBuilderAPI_Copy.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#include <BRepPrimAPI_MakePrism.hxx>
#include <BRepTools.hxx>
#include <gp_Ax2.hxx>
#include <gp_Ax3.hxx>
#include <gp_Dir.hxx>
#include <gp_Pln.hxx>
#include <gp_Pnt.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Compound.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#endif
#include <App/Application.h>
@@ -58,21 +80,32 @@
#include <Base/FileInfo.h>
#include <Base/Parameter.h>
#include "DrawViewSection.h"
#include <Mod/Part/App/PartFeature.h>
#include "DrawGeomHatch.h"
#include "DrawHatch.h"
#include "DrawProjGroupItem.h"
#include "DrawProjGroupItem.h"
#include "DrawUtil.h"
#include "DrawUtil.h"
#include "EdgeWalker.h"
#include "Geometry.h"
#include "Geometry.h"
#include "GeometryObject.h"
#include "GeometryObject.h"
#include "HatchLine.h"
#include "DrawViewSection.h"
using namespace TechDraw;
using DU = DrawUtil;
const char* DrawViewSection::SectionDirEnums[]= {"Right",
"Left",
"Up",
"Down",
"Aligned",
nullptr};
const char* DrawViewSection::CutSurfaceEnums[]= {"Hide",
@@ -88,7 +121,8 @@ const char* DrawViewSection::CutSurfaceEnums[]= {"Hide",
PROPERTY_SOURCE(TechDraw::DrawViewSection, TechDraw::DrawViewPart)
DrawViewSection::DrawViewSection() :
m_waitingForCut(false)
m_waitingForCut(false),
m_shapeSize(0.0)
{
static const char *sgroup = "Section";
static const char *fgroup = "Cut Surface Format";
@@ -200,29 +234,37 @@ void DrawViewSection::onChanged(const App::Property* prop)
DrawView::onChanged(prop);
}
TopoDS_Shape DrawViewSection::getShapeToCut()
{
// Base::Console().Message("DVS::getShapeToCut()\n");
App::DocumentObject* base = BaseView.getValue();
TechDraw::DrawViewPart* dvp = nullptr;
if (!base ||
!base->getTypeId().isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) {
//this can probably only happen with scripting
return TopoDS_Shape();
} else {
dvp = static_cast<TechDraw::DrawViewPart*>(base);
}
TopoDS_Shape shapeToCut = dvp->getSourceShape();
if (FuseBeforeCut.getValue()) {
shapeToCut = dvp->getSourceShapeFused();
}
return shapeToCut;
}
App::DocumentObjectExecReturn *DrawViewSection::execute()
{
// Base::Console().Message("DVS::execute() - %s\n", getNameInDocument());
if (!keepUpdated()) {
return App::DocumentObject::StdReturn;
}
App::DocumentObject* base = BaseView.getValue();
if (!base) {
if (!isBaseValid()) {
return new App::DocumentObjectExecReturn("BaseView object not found");
}
TechDraw::DrawViewPart* dvp = nullptr;
if (!base->getTypeId().isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) {
//this can probably only happen with scripting
return new App::DocumentObjectExecReturn("BaseView object is not a DrawViewPart object");
} else {
dvp = static_cast<TechDraw::DrawViewPart*>(base);
}
TopoDS_Shape baseShape = dvp->getSourceShape();
if (FuseBeforeCut.getValue()) {
baseShape = dvp->getSourceShapeFused();
}
TopoDS_Shape baseShape = getShapeToCut();
if (baseShape.IsNull()) {
return DrawView::execute();
@@ -230,7 +272,6 @@ App::DocumentObjectExecReturn *DrawViewSection::execute()
m_saveShape = baseShape; //save shape for 2nd pass
// checkXDirection();
bool haveX = checkXDirection();
if (!haveX) {
//block touch/onChanged stuff
@@ -246,6 +287,16 @@ App::DocumentObjectExecReturn *DrawViewSection::execute()
return DrawView::execute();
}
bool DrawViewSection::isBaseValid() const
{
App::DocumentObject* base = BaseView.getValue();
if (base &&
base->getTypeId().isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) {
return true;
}
return false;
}
void DrawViewSection::sectionExec(TopoDS_Shape& baseShape)
{
// Base::Console().Message("DVS::sectionExec() - %s baseShape.IsNull: %d\n",
@@ -289,112 +340,128 @@ void DrawViewSection::makeSectionCut(TopoDS_Shape &baseShape)
Bnd_Box centerBox;
BRepBndLib::AddOptimal(baseShape, centerBox);
centerBox.SetGap(0.0);
gp_Pln pln = getSectionPlane();
gp_Dir gpNormal = pln.Axis().Direction();
Base::Vector3d orgPnt = SectionOrigin.getValue();
if(!isReallyInBox(gp_Pnt(orgPnt.x, orgPnt.y, orgPnt.z), centerBox)) {
Base::Console().Warning("DVS: SectionOrigin doesn't intersect part in %s\n", getNameInDocument());
}
// make cutting tool
// Make the extrusion face
double dMax = sqrt(centerBox.SquareExtent());
BRepBuilderAPI_MakeFace mkFace(pln, -dMax, dMax, -dMax, dMax);
TopoDS_Face aProjFace = mkFace.Face();
if(aProjFace.IsNull()) {
Base::Console().Warning("DVS: Section face is NULL in %s\n", getNameInDocument());
return;
}
gp_Vec extrudeDir = dMax * gp_Vec(gpNormal);
TopoDS_Shape prism = BRepPrimAPI_MakePrism(aProjFace, extrudeDir, false, true).Shape();
m_shapeSize = sqrt(centerBox.SquareExtent());
// We need to copy the shape to not modify the BRepstructure
BRepBuilderAPI_Copy BuilderCopy(baseShape);
TopoDS_Shape myShape = BuilderCopy.Shape();
m_saveShape = myShape; //save shape for 2nd pass
if (debugSection()) {
BRepTools::Write(myShape, "DVSCopy.brep"); //debug
}
m_cuttingTool = makeCuttingTool(m_shapeSize);
if (debugSection()) {
BRepTools::Write(m_cuttingTool, "DVSTool.brep"); //debug
}
// perform cut
BRep_Builder builder;
TopoDS_Compound pieces;
builder.MakeCompound(pieces);
TopoDS_Compound cutPieces;
builder.MakeCompound(cutPieces);
TopExp_Explorer expl(myShape, TopAbs_SOLID);
int indb = 0;
int outdb = 0;
for (; expl.More(); expl.Next()) {
indb++;
const TopoDS_Solid& s = TopoDS::Solid(expl.Current());
BRepAlgoAPI_Cut mkCut(s, prism);
BRepAlgoAPI_Cut mkCut(s, m_cuttingTool);
if (!mkCut.IsDone()) {
Base::Console().Warning("DVS: Section cut has failed in %s\n", getNameInDocument());
continue;
}
TopoDS_Shape cut = mkCut.Shape();
builder.Add(pieces, cut);
outdb++;
builder.Add(cutPieces, mkCut.Shape());
}
// pieces contains result of cutting each subshape in baseShape with tool
TopoDS_Shape rawShape = pieces;
// cutPieces contains result of cutting each subshape in baseShape with tool
m_cutPieces = cutPieces;
if (debugSection()) {
BRepTools::Write(myShape, "DVSCopy.brep"); //debug
BRepTools::Write(aProjFace, "DVSFace.brep"); //debug
BRepTools::Write(prism, "DVSTool.brep"); //debug
BRepTools::Write(pieces, "DVSPieces.brep"); //debug
BRepTools::Write(cutPieces, "DVSCutPieces.brep"); //debug
}
// check for error in cut
Bnd_Box testBox;
BRepBndLib::AddOptimal(rawShape, testBox);
BRepBndLib::AddOptimal(m_cutPieces, testBox);
testBox.SetGap(0.0);
if (testBox.IsVoid()) { //prism & input don't intersect. rawShape is garbage, don't bother.
Base::Console().Warning("DVS::makeSectionCut - prism & input don't intersect - %s\n", Label.getValue());
return;
}
// build display geometry as in DVP, with minor mods
TopoDS_Shape centeredShape;
if (debugSection()) {
BRepTools::Write(m_cutPieces, "DVSRawShapeAfter.brep"); //debug
}
waitingForCut(false);
}
//position, scale and rotate shape for buildGeometryObject
TopoDS_Shape DrawViewSection::prepareShape(const TopoDS_Shape& rawShape,
double shapeSize)
{
// Base::Console().Message("DVS::prepareShape - %s - rawShape.IsNull: %d shapeSize: %.3f\n",
// getNameInDocument(), rawShape.IsNull(), shapeSize);
(void) shapeSize; //shapeSize is not used in this base class, but is interesting for
//derived classes
// build display geometry as in DVP, with minor mods
TopoDS_Shape preparedShape;
try {
Base::Vector3d origin(0.0, 0.0, 0.0);
m_viewAxis = getProjectionCS(origin);
m_projectionCS = getProjectionCS(origin);
gp_Pnt inputCenter;
inputCenter = TechDraw::findCentroid(rawShape,
m_viewAxis);
m_projectionCS);
Base::Vector3d centroid(inputCenter.X(),
inputCenter.Y(),
inputCenter.Z());
centeredShape = TechDraw::moveShape(rawShape,
preparedShape = TechDraw::moveShape(rawShape,
centroid * -1.0);
m_cutShape = centeredShape;
m_cutShape = preparedShape;
m_saveCentroid = centroid;
m_scaledShape = TechDraw::scaleShape(centeredShape,
getScale());
preparedShape = TechDraw::scaleShape(preparedShape,
getScale());
if (!DrawUtil::fpCompare(Rotation.getValue(), 0.0)) {
m_scaledShape = TechDraw::rotateShape(m_scaledShape,
m_viewAxis,
preparedShape = TechDraw::rotateShape(preparedShape,
m_projectionCS,
Rotation.getValue());
}
if (debugSection()) {
BRepTools::Write(m_cutShape, "DVSmCutShape.brep"); //debug
BRepTools::Write(m_scaledShape, "DVSScaled.brep"); //debug
// DrawUtil::dumpCS("DVS::makeSectionCut - CS to GO", viewAxis);
}
m_rawShape = rawShape; //save for section face finding
}
catch (Standard_Failure& e1) {
Base::Console().Warning("DVS::makeSectionCut - failed to build base shape %s - %s **\n",
Base::Console().Warning("DVS::prepareShape - failed to build shape %s - %s **\n",
getNameInDocument(), e1.GetMessageString());
return;
}
return preparedShape;
}
waitingForCut(false);
TopoDS_Shape DrawViewSection::makeCuttingTool(double shapeSize)
{
// Base::Console().Message("DVS::makeCuttingTool(%.3f) - %s\n", shapeSize, getNameInDocument());
// Make the extrusion face
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 (debugSection()){
BRepTools::Write(aProjFace, "DVSSectionFace.brep"); //debug
}
gp_Vec extrudeDir = shapeSize * gp_Vec(gpNormal);
return BRepPrimAPI_MakePrism(aProjFace, extrudeDir, false, true).Shape();
}
void DrawViewSection::onSectionCutFinished()
@@ -404,10 +471,15 @@ void DrawViewSection::onSectionCutFinished()
showProgressMessage(getNameInDocument(), "has finished making section cut");
m_preparedShape = prepareShape(getShapeToPrepare(), m_shapeSize);
if (debugSection()) {
BRepTools::Write(m_preparedShape, "DVSPreparedShape.brep"); //debug
}
postSectionCutTasks();
//display geometry for cut shape is in geometryObject as in DVP
m_tempGeometryObject = buildGeometryObject(m_scaledShape, m_viewAxis);
m_tempGeometryObject = buildGeometryObject(m_preparedShape, getSectionCS());
}
//activities that depend on updated geometry object
@@ -430,78 +502,44 @@ void DrawViewSection::postHlrTasks(void)
// build section face geometry
TopoDS_Compound faceIntersections = findSectionPlaneIntersections(m_rawShape);
TopoDS_Compound faceIntersections = findSectionPlaneIntersections(getShapeToIntersect());
if (faceIntersections.IsNull()) {
requestPaint();
return;
}
TopoDS_Shape centeredShapeF = TechDraw::moveShape(faceIntersections,
TopoDS_Shape centeredFaces = TechDraw::moveShape(faceIntersections,
m_saveCentroid * -1.0);
TopoDS_Shape scaledSection = TechDraw::scaleShape(centeredShapeF,
TopoDS_Shape scaledSection = TechDraw::scaleShape(centeredFaces,
getScale());
if (!DrawUtil::fpCompare(Rotation.getValue(), 0.0)) {
scaledSection = TechDraw::rotateShape(scaledSection,
m_viewAxis,
getProjectionCS(),
Rotation.getValue());
}
if (debugSection()) {
BRepTools::Write(scaledSection, "DVSScaledFaces.brep"); //debug
BRepTools::Write(faceIntersections, "DVSFaceIntersections.brep"); //debug
}
// scaledSection is compound of TopoDS_Face intersections, but aligned to pln(origin, sectionNormal)
// needs to be aligned to pln (origin, stdZ);
gp_Ax3 R3;
gp_Ax2 projCS = getSectionCS();
gp_Ax3 proj3 = gp_Ax3(gp_Pnt(0.0, 0.0, 0.0),
projCS.Direction(),
projCS.XDirection());
gp_Trsf fromR3;
fromR3.SetTransformation(R3, proj3);
BRepBuilderAPI_Transform xformer(fromR3);
xformer.Perform(scaledSection, true);
if (xformer.IsDone()) {
sectionTopoDSFaces = TopoDS::Compound(xformer.Shape());
} else {
Base::Console().Message("DVS::sectionExec - face xform failed\n");
m_sectionTopoDSFaces = alignSectionFaces(faceIntersections);
if (debugSection()) {
BRepTools::Write(m_sectionTopoDSFaces, "DVSTopoSectionFaces.brep"); //debug
}
m_tdSectionFaces = makeTDSectionFaces(m_sectionTopoDSFaces);
sectionTopoDSFaces = TopoDS::Compound(GeometryObject::invertGeometry(sectionTopoDSFaces)); //handle Qt -y
//turn section faces into TD geometry
tdSectionFaces.clear();
TopExp_Explorer sectionExpl(sectionTopoDSFaces, TopAbs_FACE);
for (; sectionExpl.More(); sectionExpl.Next()) {
const TopoDS_Face& face = TopoDS::Face(sectionExpl.Current());
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();
const TopoDS_Wire& wire = TopoDS::Wire(expFace.Current());
TopExp_Explorer expWire(wire, TopAbs_EDGE);
for ( ; expWire.More(); expWire.Next()) {
const TopoDS_Edge& edge = TopoDS::Edge(expWire.Current());
TechDraw::BaseGeomPtr e = BaseGeom::baseFactory(edge);
if (e) {
w->geoms.push_back(e);
}
}
sectionFace->wires.push_back(w);
}
tdSectionFaces.push_back(sectionFace);
}
TechDraw::DrawViewPart* dvp = dynamic_cast<TechDraw::DrawViewPart*>(BaseView.getValue());
if (dvp) {
dvp->requestPaint(); //to refresh section line
}
requestPaint();
requestPaint(); //this will be a duplicate paint if we are making a standalone ComplexSection
}
//activities that depend on a valid section cut
void DrawViewSection::postSectionCutTasks()
{
// Base::Console().Message("DVS::postSectionCutTasks()\n");
std::vector<App::DocumentObject*> children = getInList();
for (auto& c: children) {
if (c->getTypeId().isDerivedFrom(DrawViewPart::getClassTypeId())) {
@@ -529,16 +567,24 @@ gp_Pln DrawViewSection::getSectionPlane() const
}
//! tries to find the intersection of the section plane with the shape giving a collection of planar faces
//! the original algo finds the intersections first then transforms them to match the centered, rotated
//! and scaled cut shape. Piecewise complex sections need to intersect the final cut shape (which in this
//! case is a compound of individual cuts) with the "effective" (flattened) section plane.
TopoDS_Compound DrawViewSection::findSectionPlaneIntersections(const TopoDS_Shape& shape)
{
// Base::Console().Message("DVS::findSectionPlaneIntersections() - %s\n", getNameInDocument());
if(shape.IsNull()){
// this shouldn't happen
Base::Console().Warning("DrawViewSection::findSectionPlaneInter - %s - input shape is Null\n", getNameInDocument());
// Base::Console().Warning("DrawViewSection::findSectionPlaneInter - %s - input shape is Null\n", getNameInDocument());
return TopoDS_Compound();
}
gp_Pln plnSection = getSectionPlane();
if (debugSection()) {
BRepBuilderAPI_MakeFace mkFace(plnSection, -m_shapeSize, m_shapeSize, -m_shapeSize, m_shapeSize);
BRepTools::Write(mkFace.Face(), "DVSSectionPlane.brep"); //debug
BRepTools::Write(shape, "DVSShapeToIntersect.brep)");
}
BRep_Builder builder;
TopoDS_Compound result;
builder.MakeCompound(result);
@@ -558,6 +604,109 @@ TopoDS_Compound DrawViewSection::findSectionPlaneIntersections(const TopoDS_Shap
return result;
}
//move section faces to line up with cut shape
TopoDS_Compound DrawViewSection::alignSectionFaces(TopoDS_Shape faceIntersections)
{
// Base::Console().Message("DVS::alignSectionFaces()\n");
TopoDS_Compound sectionFaces;
TopoDS_Shape centeredShape = TechDraw::moveShape(faceIntersections,
getOriginalCentroid() * -1.0);
TopoDS_Shape scaledSection = TechDraw::scaleShape(centeredShape,
getScale());
if (!DrawUtil::fpCompare(Rotation.getValue(), 0.0)) {
scaledSection = TechDraw::rotateShape(scaledSection,
getSectionCS(),
Rotation.getValue());
}
if (debugSection()) {
BRepTools::Write(scaledSection, "DVSScaledFaces.brep"); //debug
}
return mapToPage(scaledSection);
}
TopoDS_Compound DrawViewSection::mapToPage(TopoDS_Shape& shapeToAlign)
{
// shapeToAlign is compound of TopoDS_Face intersections, but aligned to pln(origin, sectionNormal)
// needs to be aligned to paper plane (origin, stdZ);
//project the faces in the shapeToAlign, build new faces from the resulting wires and
//combine everything into a compound of faces
BRep_Builder builder;
TopoDS_Compound result;
builder.MakeCompound(result);
TopExp_Explorer expFace(shapeToAlign, TopAbs_FACE);
for (int iFace = 1; expFace.More(); expFace.Next(), iFace++) {
const TopoDS_Face& face = TopoDS::Face(expFace.Current());
std::vector<TopoDS_Wire> faceWires;
TopExp_Explorer expWires(face, TopAbs_WIRE);
for ( ; expWires.More(); expWires.Next()) {
const TopoDS_Wire& wire = TopoDS::Wire(expWires.Current());
TopoDS_Shape projectedShape = GeometryObject::projectSimpleShape(wire, getSectionCS());
std::vector<TopoDS_Edge> wireEdges;
//projectedShape is just a bunch of edges. we have to rebuild the wire.
TopExp_Explorer expEdges(projectedShape, TopAbs_EDGE);
for ( ; expEdges.More(); expEdges.Next()) {
const TopoDS_Edge& edge = TopoDS::Edge(expEdges.Current());
wireEdges.push_back(edge);
}
TopoDS_Wire cleanWire = EdgeWalker::makeCleanWire(wireEdges, 2.0 * EWTOLERANCE);
faceWires.push_back(cleanWire);
}
if (debugSection()) {
std::stringstream ss;
ss << "DVSFaceWires" << iFace << ".brep";
BRepTools::Write(DrawUtil::vectorToCompound(faceWires), ss.str().c_str()); //debug
}
//first wire should be the outer boundary of the face
BRepBuilderAPI_MakeFace mkFace(faceWires.front());
int wireCount = faceWires.size();
for (int iWire = 1; iWire < wireCount; iWire++) {
//make holes in the face with the rest of the wires
mkFace.Add(faceWires.at(iWire));
}
builder.Add(result, mkFace.Face());
if (debugSection()) {
std::stringstream ss;
ss << "DVSFaceFromWires" << iFace << ".brep";
BRepTools::Write(mkFace.Face(), ss.str().c_str()); //debug
}
}
return result;
}
//turn OCC section faces into TD geometry
std::vector<TechDraw::FacePtr> DrawViewSection::makeTDSectionFaces(TopoDS_Compound topoDSFaces)
{
// Base::Console().Message("DVS::makeTDSectionFaces()\n");
std::vector<TechDraw::FacePtr> tdSectionFaces;
TopExp_Explorer sectionExpl(topoDSFaces, TopAbs_FACE);
for (; sectionExpl.More(); sectionExpl.Next()) {
const TopoDS_Face& face = TopoDS::Face(sectionExpl.Current());
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();
const TopoDS_Wire& wire = TopoDS::Wire(expFace.Current());
TopExp_Explorer expWire(wire, TopAbs_EDGE);
for ( ; expWire.More(); expWire.Next()) {
const TopoDS_Edge& edge = TopoDS::Edge(expWire.Current());
TechDraw::BaseGeomPtr e = BaseGeom::baseFactory(edge);
if (e) {
w->geoms.push_back(e);
}
}
sectionFace->wires.push_back(w);
}
tdSectionFaces.push_back(sectionFace);
}
return tdSectionFaces;
}
//calculate the ends of the section line in BaseView's coords
std::pair<Base::Vector3d, Base::Vector3d> DrawViewSection::sectionLineEnds()
{
@@ -662,8 +811,6 @@ void DrawViewSection::setCSFromBase(const std::string sectionName)
gp_Ax2 DrawViewSection::getCSFromBase(const std::string sectionName) const
{
// Base::Console().Message("DVS::getCSFromBase(%s)\n", sectionName.c_str());
Base::Vector3d sectionNormal;
Base::Vector3d sectionXDir;
Base::Vector3d origin(0.0, 0.0, 0.0);
Base::Vector3d sectOrigin = SectionOrigin.getValue();
@@ -693,6 +840,12 @@ gp_Ax2 DrawViewSection::getCSFromBase(const std::string sectionName) const
} else if (sectionName == "Right") {
dvsDir = dvpRight.Reversed();
dvsXDir = dvpDir;
} else if (sectionName == "Aligned") {
//if aligned, we don't get our direction from the base view
Base::Vector3d sectionNormal = SectionNormal.getValue();
dvsDir = gp_Dir(sectionNormal.x, sectionNormal.y, sectionNormal.z);
Base::Vector3d sectionXDir = XDirection.getValue();
dvsXDir = gp_Dir(sectionXDir.x, sectionXDir.y, sectionXDir.z);
} else {
Base::Console().Log("Error - DVS::getCSFromBase - bad sectionName: %s\n", sectionName.c_str());
dvsDir = dvpRight;
@@ -752,7 +905,7 @@ std::vector<LineSet> DrawViewSection::getDrawableLines(int i)
TopoDS_Face DrawViewSection::getSectionTopoDSFace(int i)
{
TopoDS_Face result;
TopExp_Explorer expl(sectionTopoDSFaces, TopAbs_FACE);
TopExp_Explorer expl(m_sectionTopoDSFaces, TopAbs_FACE);
int count = 1;
for (; expl.More(); expl.Next(), count++) {
if (count == i+1) {

View File

@@ -94,26 +94,37 @@ public:
short mustExecute() const override;
void sectionExec(TopoDS_Shape& s);
void makeSectionCut(TopoDS_Shape &baseShape);
virtual void makeSectionCut(TopoDS_Shape &baseShape);
void postHlrTasks(void) override;
virtual void postSectionCutTasks();
void waitingForCut(bool s) { m_waitingForCut = s; }
bool waitingForCut(void) const { return m_waitingForCut; }
bool waitingForResult() const override;
std::vector<TechDraw::FacePtr> getTDFaceGeometry() {return tdSectionFaces;}
virtual TopoDS_Shape makeCuttingTool(double shapeSize);
virtual TopoDS_Shape getShapeToCut();
virtual bool isBaseValid() const;
virtual TopoDS_Shape prepareShape(const TopoDS_Shape& rawShape,
double shapeSize);
virtual TopoDS_Shape getShapeToPrepare() const { return m_cutPieces; }
//CS related methods
void setCSFromBase(const std::string sectionName);
gp_Ax2 getCSFromBase(const std::string sectionName) const;
virtual gp_Ax2 getCSFromBase(const std::string sectionName) const;
gp_Ax2 getSectionCS() const;
Base::Vector3d getXDirection() const override; //don't use XDirection.getValue()
TechDraw::DrawViewPart* getBaseDVP() const;
TechDraw::DrawProjGroupItem* getBaseDPGI() const;
TopoDS_Compound getSectionTFaces() { return sectionTopoDSFaces;}
//section face related methods
TopoDS_Compound getSectionTFaces() { return m_sectionTopoDSFaces;}
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_Shape getShapeToIntersect() { return m_cutPieces; }
void makeLineSets(void) ;
std::vector<LineSet> getDrawableLines(int i = 0);
std::vector<PATLineSpec> getDecodedSpecsFromFile(std::string fileSpec, std::string myPattern);
@@ -123,7 +134,7 @@ public:
static const char* SectionDirEnums[];
static const char* CutSurfaceEnums[];
std::pair<Base::Vector3d, Base::Vector3d> sectionLineEnds();
virtual std::pair<Base::Vector3d, Base::Vector3d> sectionLineEnds();
bool showSectionEdges(void);
@@ -131,13 +142,13 @@ public Q_SLOTS:
void onSectionCutFinished(void);
protected:
TopoDS_Compound sectionTopoDSFaces; //needed for hatching
TopoDS_Compound m_sectionTopoDSFaces; //needed for hatching
std::vector<LineSet> m_lineSets;
std::vector<TechDraw::FacePtr> tdSectionFaces;
std::vector<TechDraw::FacePtr> m_tdSectionFaces;
gp_Pln getSectionPlane() const;
TopoDS_Compound findSectionPlaneIntersections(const TopoDS_Shape& shape);
virtual gp_Pln getSectionPlane() const;
virtual TopoDS_Compound findSectionPlaneIntersections(const TopoDS_Shape& shape);
void getParameters();
bool debugSection() const;
int prefCutSurface() const;
@@ -151,15 +162,16 @@ protected:
void replaceSvgIncluded(std::string newSvgFile);
void replacePatIncluded(std::string newPatFile);
TopoDS_Shape m_rawShape;
gp_Ax2 m_viewAxis;
TopoDS_Shape m_scaledShape;
TopoDS_Shape m_cutPieces; //the shape after cutting, but before centering & scaling
gp_Ax2 m_projectionCS;
TopoDS_Shape m_preparedShape; //the shape after cutting, centering, scaling etc
QMetaObject::Connection connectCutWatcher;
QFutureWatcher<void> m_cutWatcher;
QFuture<void> m_cutFuture;
bool m_waitingForCut;
TopoDS_Shape m_cuttingTool;
double m_shapeSize;
};
using DrawViewSectionPython = App::FeaturePythonT<DrawViewSection>;

View File

@@ -24,9 +24,9 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <iomanip>
# include <sstream>
# include <boost/regex.hpp>
#include <iomanip>
#include <sstream>
#include <boost/regex.hpp>
#endif
#include <App/Property.h>
@@ -34,10 +34,10 @@
#include <Mod/Spreadsheet/App/Cell.h>
#include <Mod/Spreadsheet/App/Sheet.h>
#include "DrawViewSpreadsheet.h"
#include "DrawUtil.h"
#include "Preferences.h"
#include "DrawViewSpreadsheet.h"
using namespace TechDraw;

View File

@@ -1246,8 +1246,8 @@ bool BSpline::isLine()
return false;
}
Base::Vector3d vs = DrawUtil::gpPnt2V3(s);
Base::Vector3d ve = DrawUtil::gpPnt2V3(e);
Base::Vector3d vs = DrawUtil::toVector3d(s);
Base::Vector3d ve = DrawUtil::toVector3d(e);
double endLength = (vs - ve).Length();
int low = 0;
int high = spline->NbPoles() - 1;
@@ -1256,9 +1256,9 @@ bool BSpline::isLine()
double lenTotal = 0.0;
for (int i = 0; i < high; i++) {
gp_Pnt p1 = poles(i);
Base::Vector3d v1 = DrawUtil::gpPnt2V3(p1);
Base::Vector3d v1 = DrawUtil::toVector3d(p1);
gp_Pnt p2 = poles(i+1);
Base::Vector3d v2 = DrawUtil::gpPnt2V3(p2);
Base::Vector3d v2 = DrawUtil::toVector3d(p2);
lenTotal += (v2-v1).Length();
}
@@ -1415,7 +1415,7 @@ TopoDS_Edge BSpline::asCircle(bool& arc)
gp_Circ circle1 = gce_circ1.Value();
double radius1 = circle1.Radius();
gp_Pnt center1 = circle1.Location();
Base::Vector3d vc1 = DrawUtil::gpPnt2V3(center1);
Base::Vector3d vc1 = DrawUtil::toVector3d(center1);
gce_MakeCirc gce_circ2 = gce_MakeCirc(pcm, pc2, e);
if (gce_circ2.Status() != gce_Done) {
@@ -1424,7 +1424,7 @@ TopoDS_Edge BSpline::asCircle(bool& arc)
gp_Circ circle2 = gce_circ2.Value();
double radius2 = circle2.Radius();
gp_Pnt center2 = circle2.Location();
Base::Vector3d vc2 = DrawUtil::gpPnt2V3(center2);
Base::Vector3d vc2 = DrawUtil::toVector3d(center2);
// compare radii & centers
double allowError = 0.001; //mm^-3 good enough for printing

View File

@@ -24,13 +24,20 @@
#ifndef _PreComp_
#include <Bnd_Box.hxx>
#include <BRep_Builder.hxx>
#include <BRepAlgo_NormalProjection.hxx>
#include <BRepBndLib.hxx>
#include <BRepBuilderAPI_Copy.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#include <BRep_Builder.hxx>
#include <BRep_Builder.hxx>
#include <BRepLib.hxx>
#include <BRepLib.hxx>
#include <BRepLProp_CLProps.hxx>
#include <BRepLProp_CurveTool.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
#include <BRep_Tool.hxx>
#include <BRepTools.hxx>
#include <gp_Ax1.hxx>
#include <gp_Ax2.hxx>
@@ -39,17 +46,17 @@
#include <gp_Pnt.hxx>
#include <gp_Trsf.hxx>
#include <gp_Vec.hxx>
#include <HLRBRep.hxx>
#include <HLRAlgo_Projector.hxx>
#include <HLRBRep_Algo.hxx>
#include <HLRBRep_HLRToShape.hxx>
#include <HLRBRep.hxx>
#include <HLRBRep_PolyAlgo.hxx>
#include <HLRAlgo_Projector.hxx>
#include <HLRBRep_PolyHLRToShape.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopExp.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Vertex.hxx>
#endif // #ifndef _PreComp_
@@ -70,6 +77,8 @@
using namespace TechDraw;
using namespace std;
using DU = DrawUtil;
struct EdgePoints {
gp_Pnt v1, v2;
TopoDS_Edge edge;
@@ -180,6 +189,7 @@ void GeometryObject::projectShape(const TopoDS_Shape& inShape,
visHard = hlrToShape.VCompound();
BRepLib::BuildCurves3d(visHard);
visHard = invertGeometry(visHard);
BRepTools::Write(visHard, "GOvisHard.brep"); //debug
}
if (!hlrToShape.Rg1LineVCompound().IsNull()) {
@@ -417,6 +427,46 @@ void GeometryObject::projectShapeWithPolygonAlgo(const TopoDS_Shape& input,
makeTDGeometry();
}
//project the edges in shape onto XY.mirrored plane of CS. mimics the projection
//of the main hlr routine. Only the visible hard edges are returned, so this method
//is only suitable for simple shapes that have no hidden edges, like faces or wires.
//TODO: allow use of perspective projector
TopoDS_Shape GeometryObject::projectSimpleShape(const TopoDS_Shape &shape,
const gp_Ax2 &CS)
{
// Base::Console().Message("GO::()\n");
if(shape.IsNull()) {
throw Base::ValueError("GO::projectSimpleShape - input shape is NULL");
}
HLRBRep_Algo *brep_hlr = new HLRBRep_Algo();
brep_hlr->Add(shape);
HLRAlgo_Projector projector( CS );
brep_hlr->Projector(projector);
brep_hlr->Update();
brep_hlr->Hide();
HLRBRep_HLRToShape hlrToShape(brep_hlr);
TopoDS_Shape hardEdges = hlrToShape.VCompound();
BRepLib::BuildCurves3d(hardEdges);
hardEdges = invertGeometry(hardEdges);
return hardEdges;
}
//project the edges of a shape onto the XY plane of projCS. This does not give
//the same result as the hlr projections
TopoDS_Shape GeometryObject::simpleProjection(const TopoDS_Shape& shape,
const gp_Ax2& projCS)
{
gp_Pln plane(projCS);
TopoDS_Face paper = BRepBuilderAPI_MakeFace(plane);
BRepAlgo_NormalProjection projector(paper);
projector.Add(shape);
projector.Build();
return projector.Projection();
}
TopoDS_Shape GeometryObject::projectFace(const TopoDS_Shape &face,
const gp_Ax2 &CS)
{
@@ -510,11 +560,11 @@ void GeometryObject::addGeomFromCompound(TopoDS_Shape edgeCompound, edgeClass ca
Base::Console().Log("GO::addGeomFromCompound - edge: %d is NULL\n", i);
continue;
}
if (DrawUtil::isZeroEdge(edge)) {
if (DU::isZeroEdge(edge)) {
Base::Console().Log("GO::addGeomFromCompound - edge: %d is zeroEdge\n", i);
continue;
}
if (DrawUtil::isCrazy(edge)) {
if (DU::isCrazy(edge)) {
Base::Console().Log("GO::addGeomFromCompound - edge: %d is crazy\n", i);
continue;
}
@@ -860,7 +910,7 @@ gp_Ax2 TechDraw::getViewAxis(const Base::Vector3d origin,
Base::Vector3d stdZ(0.0, 0.0, 1.0);
Base::Vector3d stdOrg(0.0, 0.0, 0.0);
Base::Vector3d cross = direction;
if (TechDraw::DrawUtil::checkParallel(direction, stdZ)) {
if (DU::checkParallel(direction, stdZ)) {
cross = Base::Vector3d(1.0, 0.0, 0.0);
} else {
cross.Normalize();
@@ -913,7 +963,7 @@ gp_Ax2 TechDraw::legacyViewAxis1(const Base::Vector3d origin,
}
Base::Vector3d cross = flipDirection;
// //special case
if (TechDraw::DrawUtil::checkParallel(flipDirection, stdZ)) {
if (DU::checkParallel(flipDirection, stdZ)) {
cross = Base::Vector3d(1.0, 0.0, 0.0);
} else {
cross.Normalize();
@@ -940,6 +990,23 @@ gp_Ax2 TechDraw::legacyViewAxis1(const Base::Vector3d origin,
return viewAxis;
}
//! Returns the centroid of shape based on R3
gp_Pnt TechDraw::findCentroid(const TopoDS_Shape& shape)
{
Bnd_Box tBounds;
tBounds.SetGap(0.0);
BRepBndLib::AddOptimal(shape, tBounds, true, false);
Standard_Real xMin, yMin, zMin, xMax, yMax, zMax;
tBounds.Get(xMin, yMin, zMin, xMax, yMax, zMax);
Standard_Real x = (xMin + xMax) / 2.0,
y = (yMin + yMax) / 2.0,
z = (zMin + zMax) / 2.0;
return gp_Pnt(x, y, z);
}
//! Returns the centroid of shape, as viewed according to direction
gp_Pnt TechDraw::findCentroid(const TopoDS_Shape &shape,
const Base::Vector3d &direction)
@@ -955,8 +1022,6 @@ gp_Pnt TechDraw::findCentroid(const TopoDS_Shape &shape,
const gp_Ax2 &viewAxis)
{
// Base::Console().Message("GO::findCentroid() - 2\n");
// Base::Vector3d origin(0.0, 0.0, 0.0);
// gp_Ax2 viewAxis = getViewAxis(origin, direction);
gp_Trsf tempTransform;
tempTransform.SetTransformation(viewAxis);
@@ -1020,7 +1085,7 @@ TopoDS_Shape TechDraw::mirrorShape(const TopoDS_Shape &input,
// mirror about the Y axis
gp_Trsf tempTransform;
//BRepBuilderAPI_Transform will loop forever if asked to use 0.0 as scale
if (!(scale > 0.0)) {
if (scale <= 0.0) {
tempTransform.SetScale(inputCenter, 1.0);
} else {
tempTransform.SetScale(inputCenter, scale);
@@ -1042,8 +1107,8 @@ TopoDS_Shape TechDraw::mirrorShape(const TopoDS_Shape &input,
//!rotates a shape about a viewAxis
TopoDS_Shape TechDraw::rotateShape(const TopoDS_Shape &input,
gp_Ax2& viewAxis,
double rotAngle)
const gp_Ax2 &viewAxis,
double rotAngle)
{
TopoDS_Shape transShape;
if (input.IsNull()) {
@@ -1103,3 +1168,62 @@ TopoDS_Shape TechDraw::moveShape(const TopoDS_Shape &input,
}
return transShape;
}
//!moves a shape with restricts on directions
TopoDS_Shape TechDraw::moveShapeRestricted(const TopoDS_Shape &input,
const Base::Vector3d& motion,
bool allowX,
bool allowY,
bool allowZ)
{
gp_Vec gMotion(allowX ? motion.x : 0.0,
allowY ? motion.y : 0.0,
allowZ ? motion.z : 0.0);
TopoDS_Shape transShape;
try {
gp_Trsf xlate;
xlate.SetTranslation(gMotion);
BRepBuilderAPI_Transform mkTrf(input, xlate);
transShape = mkTrf.Shape();
}
catch (...) {
Base::Console().Log("GeometryObject::moveShapeRestricted - move failed.\n");
return transShape;
}
return transShape;
}
//!moves a shape with restricts on directions
TopoDS_Shape TechDraw::moveShapeRestricted(const TopoDS_Shape &input,
const Base::Vector3d& motion,
const Base::Vector3d& mask)
{
gp_Vec gMotion(mask.x ? motion.x : 0.0,
mask.y ? motion.y : 0.0,
mask.z ? motion.z : 0.0);
TopoDS_Shape transShape;
try {
gp_Trsf xlate;
xlate.SetTranslation(gMotion);
BRepBuilderAPI_Transform mkTrf(input, xlate);
transShape = mkTrf.Shape();
}
catch (...) {
Base::Console().Log("GeometryObject::moveShapeRestricted - move failed.\n");
return transShape;
}
return transShape;
}
TopoDS_Shape TechDraw::moveShapeRestricted(const TopoDS_Shape &input,
const gp_Vec& motion,
const gp_Vec& mask)
{
return moveShapeRestricted(input,
DU::toVector3d(motion),
DU::toVector3d(mask));
}

View File

@@ -67,13 +67,24 @@ TopoDS_Shape TechDrawExport mirrorShape(const TopoDS_Shape &input,
TopoDS_Shape TechDrawExport scaleShape(const TopoDS_Shape &input,
double scale);
TopoDS_Shape TechDrawExport rotateShape(const TopoDS_Shape &input,
gp_Ax2& viewAxis,
double rotAngle);
const gp_Ax2& viewAxis,
double rotAngle);
TopoDS_Shape TechDrawExport moveShape(const TopoDS_Shape &input,
const Base::Vector3d& motion);
TopoDS_Shape TechDrawExport moveShapeRestricted(const TopoDS_Shape &input,
const Base::Vector3d& motion,
bool allowX = true,
bool allowY = true,
bool allowZ = true);
TopoDS_Shape TechDrawExport moveShapeRestricted(const TopoDS_Shape &input,
const Base::Vector3d& motion,
const Base::Vector3d& mask);
TopoDS_Shape TechDrawExport moveShapeRestricted(const TopoDS_Shape &input,
const gp_Vec& motion,
const gp_Vec& mask);
//! Returns the centroid of shape, as viewed according to direction
gp_Pnt TechDrawExport findCentroid(const TopoDS_Shape& shape);
gp_Pnt TechDrawExport findCentroid(const TopoDS_Shape &shape,
const Base::Vector3d &direction);
gp_Pnt TechDrawExport findCentroid(const TopoDS_Shape &shape,
@@ -118,9 +129,12 @@ public:
const gp_Ax2 &viewAxis);
void projectShapeWithPolygonAlgo(const TopoDS_Shape &input,
const gp_Ax2 &viewAxis);
TopoDS_Shape projectFace(const TopoDS_Shape &face,
const gp_Ax2 &CS);
static TopoDS_Shape projectSimpleShape(const TopoDS_Shape &shape,
const gp_Ax2 &CS);
static TopoDS_Shape simpleProjection(const TopoDS_Shape& shape,
const gp_Ax2& projCS);
static TopoDS_Shape projectFace(const TopoDS_Shape &face,
const gp_Ax2 &CS);
void makeTDGeometry();
void extractGeometry(edgeClass category, bool visible);
void addFaceGeom(FacePtr f);

View File

@@ -56,6 +56,7 @@
#include <cassert>
#include <cstdio>
#include <chrono>
#include <fstream>
#include <iomanip>
#include <iostream>

View File

@@ -132,7 +132,28 @@ double Preferences::vertexScale()
return result;
}
int Preferences::scaleType()
{
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/General");
int result = hGrp->GetInt("DefaultScaleType", 0);
return result;
}
double Preferences::scale()
{
int prefScaleType = scaleType();
if (prefScaleType == 0) { //page scale
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/General");
return hGrp->GetFloat("DefaultPageScale", 1.0);
} else if (prefScaleType == 1) { //custom scale
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/General");
return hGrp->GetFloat("DefaultViewScale", 1.0);
}
return 1.0;
}
//lightgray #D3D3D3

View File

@@ -52,7 +52,8 @@ static App::Color selectColor();
static App::Color preselectColor();
static App::Color vertexColor();
static double vertexScale();
static int scaleType();
static double scale();
static bool useGlobalDecimals();
static bool keepPagesUpToDate();

View File

@@ -87,6 +87,7 @@ set(TechDrawGui_UIC_SRCS
SymbolChooser.ui
TaskMoveView.ui
TaskProjection.ui
TaskComplexSection.ui
)
if(BUILD_QT5)
@@ -222,6 +223,9 @@ SET(TechDrawGui_SRCS
TaskProjection.cpp
TaskProjection.h
TaskProjection.ui
TaskComplexSection.cpp
TaskComplexSection.h
TaskComplexSection.ui
)
SET(TechDrawGuiView_SRCS
@@ -419,6 +423,7 @@ SET(TechDrawGuiTaskDlgs_SRCS
TaskCustomizeFormat.ui
TaskMoveView.ui
TaskProjection.ui
TaskComplexSection.ui
)
SOURCE_GROUP("MRTE" FILES ${MRTE_SRCS})

View File

@@ -30,8 +30,10 @@
#include <App/Document.h>
#include <App/DocumentObject.h>
#include <App/Link.h>
#include <Base/Console.h>
#include <Base/Tools.h>
#include <Gui/Action.h>
#include <Gui/Application.h>
#include <Gui/Command.h>
@@ -43,14 +45,18 @@
#include <Gui/SelectionObject.h>
#include <Gui/ViewProvider.h>
#include <Gui/WaitCursor.h>
#include <Mod/Spreadsheet/App/Sheet.h>
#include <Mod/TechDraw/App/DrawComplexSection.h>
#include <Mod/TechDraw/App/DrawPage.h>
#include <Mod/TechDraw/App/DrawProjGroup.h>
#include <Mod/TechDraw/App/DrawUtil.h>
#include <Mod/TechDraw/App/DrawUtil.h>
#include <Mod/TechDraw/App/DrawViewArch.h>
#include <Mod/TechDraw/App/DrawViewClip.h>
#include <Mod/TechDraw/App/DrawViewDetail.h>
#include <Mod/TechDraw/App/DrawViewDraft.h>
#include <Mod/TechDraw/App/DrawViewMulti.h>
#include <Mod/TechDraw/App/DrawViewPart.h>
#include <Mod/TechDraw/App/DrawViewSymbol.h>
#include <Mod/TechDraw/App/Preferences.h>
@@ -62,6 +68,7 @@
#include "QGVPage.h"
#include "Rez.h"
#include "TaskActiveView.h"
#include "TaskComplexSection.h"
#include "TaskDetail.h"
#include "TaskProjGroup.h"
#include "TaskProjection.h"
@@ -512,6 +519,120 @@ bool CmdTechDrawSectionView::isActive()
return (havePage && haveView && !taskInProgress);
}
//===========================================================================
// TechDraw_ComplexSection
//===========================================================================
DEF_STD_CMD_A(CmdTechDrawComplexSection)
CmdTechDrawComplexSection::CmdTechDrawComplexSection()
: Command("TechDraw_ComplexSection")
{
sAppModule = "TechDraw";
sGroup = QT_TR_NOOP("TechDraw");
sMenuText = QT_TR_NOOP("Insert Complex Section");
sToolTipText = QT_TR_NOOP("Insert a Complex Section");
sWhatsThis = "TechDraw_ComplexSection";
sStatusTip = sToolTipText;
sPixmap = "actions/TechDraw_ComplexSection";
}
void CmdTechDrawComplexSection::activated(int iMsg)
{
Q_UNUSED(iMsg);
TechDraw::DrawPage* page = DrawGuiUtil::findPage(this);
if (!page) {
return;
}
std::string PageName = page->getNameInDocument();
TechDraw::DrawViewPart* baseView(nullptr);
std::vector<App::DocumentObject*> shapes;
std::vector<App::DocumentObject*> xShapes;
App::DocumentObject* profileObject(nullptr);
std::vector<std::string> profileSubs;
Gui::ResolveMode resolve = Gui::ResolveMode::OldStyleElement; //mystery
bool single = false; //mystery
auto selection = getSelection().getSelectionEx(nullptr,
App::DocumentObject::getClassTypeId(),
resolve,
single);
for (auto& sel: selection) {
bool is_linked = false;
auto obj = sel.getObject();
if (obj->isDerivedFrom(TechDraw::DrawPage::getClassTypeId())) {
continue;
}
if (obj->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) {
//use the dvp's Sources as sources for this ComplexSection &
//check the subelement(s) to see if they can be used as a profile
baseView = static_cast<TechDraw::DrawViewPart*>(obj);
if (!sel.getSubNames().empty()) {
//need to add profile subs as parameter
profileObject = baseView;
profileSubs = sel.getSubNames();
}
continue;
}
if (obj->isDerivedFrom(App::LinkElement::getClassTypeId()) ||
obj->isDerivedFrom(App::LinkGroup::getClassTypeId()) ||
obj->isDerivedFrom(App::Link::getClassTypeId()) ) {
is_linked = true;
}
// If parent of the obj is a link to another document, we possibly need to treat non-link obj as linked, too
// 1st, is obj in another document?
if (obj->getDocument() != this->getDocument()) {
std::set<App::DocumentObject*> parents = obj->getInListEx(true);
for (auto& parent : parents) {
// Only consider parents in the current document, i.e. possible links in this View's document
if (parent->getDocument() != this->getDocument()) {
continue;
}
// 2nd, do we really have a link to obj?
if (parent->isDerivedFrom(App::LinkElement::getClassTypeId()) ||
parent->isDerivedFrom(App::LinkGroup::getClassTypeId()) ||
parent->isDerivedFrom(App::Link::getClassTypeId())) {
// We have a link chain from this document to obj, and obj is in another document -> it's an XLink target
is_linked = true;
}
}
}
if (is_linked) {
xShapes.push_back(obj);
continue;
}
//not a Link and not null. assume to be drawable. Undrawables will be
// skipped later.
if (TechDraw::DrawComplexSection::isProfileObject(obj)) {
profileObject = obj;
} else {
shapes.push_back(obj);
}
}
if (shapes.empty() &&
xShapes.empty() &&
!baseView) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("No Base View, Shapes, Groups or Links in this selection"));
return;
}
if (!profileObject) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("No profile object found in selection"));
return;
}
Gui::Control().showDialog(new TaskDlgComplexSection(page, baseView,
shapes, xShapes,
profileObject, profileSubs));
}
bool CmdTechDrawComplexSection::isActive()
{
return DrawGuiUtil::needPage(this);
}
//===========================================================================
// TechDraw_DetailView
//===========================================================================
@@ -1510,4 +1631,5 @@ void CreateTechDrawCommands()
rcCmdMgr.addCommand(new CmdTechDrawSpreadsheetView());
rcCmdMgr.addCommand(new CmdTechDrawBalloon());
rcCmdMgr.addCommand(new CmdTechDrawProjectShape());
rcCmdMgr.addCommand(new CmdTechDrawComplexSection());
}

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>440</width>
<height>447</height>
<width>450</width>
<height>541</height>
</rect>
</property>
<property name="sizePolicy">
@@ -33,21 +33,34 @@
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_2" columnstretch="1,0,1">
<item row="0" column="0">
<widget class="QLabel" name="label_10">
<layout class="QGridLayout" name="gridLayout_2" columnstretch="1,0,0">
<item row="5" column="0">
<widget class="QLabel" name="label">
<property name="font">
<font>
<italic>true</italic>
<italic>false</italic>
</font>
</property>
<property name="text">
<string>Section Line Standard</string>
<string>Detail View Outline Shape</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="Gui::PrefComboBox" name="cbSectionLineStd">
<item row="7" column="1">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="13" column="0">
<widget class="Gui::PrefCheckBox" name="cbShowCenterMarks">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
@@ -56,43 +69,137 @@
</property>
<property name="minimumSize">
<size>
<width>184</width>
<height>22</height>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="toolTip">
<string>Show arc center marks in views</string>
</property>
<property name="text">
<string>Show Center Marks</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>ShowCenterMarks</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/TechDraw/Decorations</cstring>
</property>
</widget>
</item>
<item row="13" column="2">
<widget class="Gui::PrefCheckBox" name="cbPrintCenterMarks">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Standard to be used to draw section lines</string>
<string>Show arc centers in printed output</string>
</property>
<property name="currentIndex">
<number>1</number>
<property name="text">
<string>Print Center Marks</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>SectionLineStandard</cstring>
<cstring>PrintCenterMarks</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/TechDraw/Standards</cstring>
<cstring>Mod/TechDraw/Decorations</cstring>
</property>
</widget>
</item>
<item row="9" column="2">
<widget class="Gui::PrefComboBox" name="pcbBalloonArrow">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Style for balloon leader line ends</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>BalloonArrow</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/TechDraw/Decorations</cstring>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="Gui::PrefComboBox" name="pcbMatting">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Outline shape for detail views</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>MattingStyle</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/Decorations</cstring>
</property>
<item>
<property name="text">
<string>ANSI</string>
<string>Circle</string>
</property>
<property name="icon">
<iconset resource="Resources/TechDraw.qrc">
<normaloff>:/icons/circular.svg</normaloff>:/icons/circular.svg</iconset>
</property>
</item>
<item>
<property name="text">
<string>ISO</string>
<string>Square</string>
</property>
<property name="icon">
<iconset resource="Resources/TechDraw.qrc">
<normaloff>:/icons/square.svg</normaloff>:/icons/square.svg</iconset>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_6">
<item row="8" column="0">
<widget class="QLabel" name="label_5">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>Section Line Style</string>
<string>Balloon Shape</string>
</property>
</widget>
</item>
@@ -178,76 +285,87 @@
</item>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_19">
<item row="0" column="0">
<widget class="QLabel" name="label_10">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>Section Cut Surface</string>
<string>Section Line Standard</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="Gui::PrefComboBox" name="cbCutSurface">
<item row="0" column="2">
<widget class="Gui::PrefComboBox" name="cbSectionLineStd">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<width>184</width>
<height>22</height>
</size>
</property>
<property name="toolTip">
<string>Default appearance of cut surface in section view</string>
<string>Standard to be used to draw section lines</string>
</property>
<property name="currentIndex">
<number>2</number>
<number>1</number>
</property>
<property name="prefEntry" stdset="0">
<cstring>CutSurfaceDisplay</cstring>
<cstring>SectionLineStandard</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/Decorations</cstring>
<cstring>Mod/TechDraw/Standards</cstring>
</property>
<item>
<property name="text">
<string>Hide</string>
<string>ANSI</string>
</property>
</item>
<item>
<property name="text">
<string>Solid Color</string>
</property>
</item>
<item>
<property name="text">
<string>SVG Hatch</string>
</property>
</item>
<item>
<property name="text">
<string>PAT Hatch</string>
<string>ISO</string>
</property>
</item>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_13">
<item row="6" column="0">
<widget class="QLabel" name="label_20">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="toolTip">
<string>Line group used to set line widths</string>
<string>Line style of detail highlight on base view</string>
</property>
<property name="text">
<string>Line Width Group</string>
<string>Detail Highlight Style</string>
</property>
</widget>
</item>
<item row="3" column="2">
<item row="10" column="0">
<widget class="QLabel" name="label_18">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="toolTip">
<string>Length of horizontal portion of Balloon leader</string>
</property>
<property name="text">
<string>Ballon Leader Kink Length</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="Gui::PrefComboBox" name="pcbLineGroup">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@@ -272,77 +390,7 @@
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label">
<property name="font">
<font>
<italic>false</italic>
</font>
</property>
<property name="text">
<string>Detail View Outline Shape</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="Gui::PrefComboBox" name="pcbMatting">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Outline shape for detail views</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>MattingStyle</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/Decorations</cstring>
</property>
<item>
<property name="text">
<string>Circle</string>
</property>
<property name="icon">
<iconset resource="Resources/TechDraw.qrc">
<normaloff>:/icons/circular.svg</normaloff>:/icons/circular.svg</iconset>
</property>
</item>
<item>
<property name="text">
<string>Square</string>
</property>
<property name="icon">
<iconset resource="Resources/TechDraw.qrc">
<normaloff>:/icons/square.svg</normaloff>:/icons/square.svg</iconset>
</property>
</item>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_20">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="toolTip">
<string>Line style of detail highlight on base view</string>
</property>
<property name="text">
<string>Detail Highlight Style</string>
</property>
</widget>
</item>
<item row="5" column="2">
<item row="6" column="2">
<widget class="Gui::PrefComboBox" name="pcbHighlightStyle">
<property name="minimumSize">
<size>
@@ -415,33 +463,8 @@
</item>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_4">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>Center Line Style</string>
</property>
</widget>
</item>
<item row="6" column="1">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="6" column="2">
<widget class="Gui::PrefComboBox" name="pcbCenterStyle">
<item row="10" column="2">
<widget class="Gui::PrefUnitSpinBox" name="pdsbBalloonKink">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
@@ -455,86 +478,66 @@
</size>
</property>
<property name="toolTip">
<string>Type for centerlines</string>
<string>Length of balloon leader line kink</string>
</property>
<property name="currentIndex">
<number>2</number>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="value">
<double>5.000000000000000</double>
</property>
<property name="prefEntry" stdset="0">
<cstring>CenterLine</cstring>
<cstring>BalloonKink</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/Decorations</cstring>
<cstring>Mod/TechDraw/Dimensions</cstring>
</property>
<item>
<property name="text">
<string>NeverShow</string>
</property>
<property name="icon">
<iconset resource="Resources/TechDraw.qrc">
<normaloff>:/icons/arrownone.svg</normaloff>:/icons/arrownone.svg</iconset>
</property>
</item>
<item>
<property name="text">
<string>Continuous</string>
</property>
<property name="icon">
<iconset resource="Resources/TechDraw.qrc">
<normaloff>:/icons/continuous-line.svg</normaloff>:/icons/continuous-line.svg</iconset>
</property>
</item>
<item>
<property name="text">
<string>Dash</string>
</property>
<property name="icon">
<iconset resource="Resources/TechDraw.qrc">
<normaloff>:/icons/dash-line.svg</normaloff>:/icons/dash-line.svg</iconset>
</property>
</item>
<item>
<property name="text">
<string>Dot</string>
</property>
<property name="icon">
<iconset resource="Resources/TechDraw.qrc">
<normaloff>:/icons/dot-line.svg</normaloff>:/icons/dot-line.svg</iconset>
</property>
</item>
<item>
<property name="text">
<string>DashDot</string>
</property>
<property name="icon">
<iconset resource="Resources/TechDraw.qrc">
<normaloff>:/icons/dashDot-line.svg</normaloff>:/icons/dashDot-line.svg</iconset>
</property>
</item>
<item>
<property name="text">
<string>DashDotDot</string>
</property>
<property name="icon">
<iconset resource="Resources/TechDraw.qrc">
<normaloff>:/icons/dashDotDot-line.svg</normaloff>:/icons/dashDotDot-line.svg</iconset>
</property>
</item>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_5">
<item row="9" column="0">
<widget class="QLabel" name="label_3">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>Balloon Shape</string>
<string>Balloon Leader End</string>
</property>
</widget>
</item>
<item row="7" column="2">
<item row="11" column="0">
<widget class="Gui::PrefCheckBox" name="cbPyramidOrtho">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Restrict Filled Triangle line end to vertical or horizontal directions</string>
</property>
<property name="text">
<string>Balloon Orthogonal Triangle</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>PyramidOrtho</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/TechDraw/Decorations</cstring>
</property>
</widget>
</item>
<item row="8" column="2">
<widget class="Gui::PrefComboBox" name="pcbBalloonShape">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@@ -631,121 +634,101 @@
</item>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_3">
<item row="7" column="2">
<widget class="Gui::PrefComboBox" name="pcbCenterStyle">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Type for centerlines</string>
</property>
<property name="currentIndex">
<number>2</number>
</property>
<property name="prefEntry" stdset="0">
<cstring>CenterLine</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/Decorations</cstring>
</property>
<item>
<property name="text">
<string>NeverShow</string>
</property>
<property name="icon">
<iconset resource="Resources/TechDraw.qrc">
<normaloff>:/icons/arrownone.svg</normaloff>:/icons/arrownone.svg</iconset>
</property>
</item>
<item>
<property name="text">
<string>Continuous</string>
</property>
<property name="icon">
<iconset resource="Resources/TechDraw.qrc">
<normaloff>:/icons/continuous-line.svg</normaloff>:/icons/continuous-line.svg</iconset>
</property>
</item>
<item>
<property name="text">
<string>Dash</string>
</property>
<property name="icon">
<iconset resource="Resources/TechDraw.qrc">
<normaloff>:/icons/dash-line.svg</normaloff>:/icons/dash-line.svg</iconset>
</property>
</item>
<item>
<property name="text">
<string>Dot</string>
</property>
<property name="icon">
<iconset resource="Resources/TechDraw.qrc">
<normaloff>:/icons/dot-line.svg</normaloff>:/icons/dot-line.svg</iconset>
</property>
</item>
<item>
<property name="text">
<string>DashDot</string>
</property>
<property name="icon">
<iconset resource="Resources/TechDraw.qrc">
<normaloff>:/icons/dashDot-line.svg</normaloff>:/icons/dashDot-line.svg</iconset>
</property>
</item>
<item>
<property name="text">
<string>DashDotDot</string>
</property>
<property name="icon">
<iconset resource="Resources/TechDraw.qrc">
<normaloff>:/icons/dashDotDot-line.svg</normaloff>:/icons/dashDotDot-line.svg</iconset>
</property>
</item>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_19">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>Balloon Leader End</string>
<string>Section Cut Surface</string>
</property>
</widget>
</item>
<item row="8" column="2">
<widget class="Gui::PrefComboBox" name="pcbBalloonArrow">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Style for balloon leader line ends</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>BalloonArrow</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/TechDraw/Decorations</cstring>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_18">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="toolTip">
<string>Length of horizontal portion of Balloon leader</string>
</property>
<property name="text">
<string>Ballon Leader Kink Length</string>
</property>
</widget>
</item>
<item row="9" column="2">
<widget class="Gui::PrefUnitSpinBox" name="pdsbBalloonKink">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Length of balloon leader line kink</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="value">
<double>5.000000000000000</double>
</property>
<property name="prefEntry" stdset="0">
<cstring>BalloonKink</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/TechDraw/Dimensions</cstring>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="Gui::PrefCheckBox" name="cbPyramidOrtho">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Restrict Filled Triangle line end to vertical or horizontal directions</string>
</property>
<property name="text">
<string>Balloon Orthogonal Triangle</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>PyramidOrtho</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/TechDraw/Decorations</cstring>
</property>
</widget>
</item>
<item row="10" column="2">
<item row="11" column="2">
<widget class="Gui::PrefCheckBox" name="cbAutoHoriz">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@@ -776,71 +759,112 @@
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="Gui::PrefCheckBox" name="cbShowCenterMarks">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<item row="1" column="0">
<widget class="QLabel" name="label_6">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>Section Line Style</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_4">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>Center Line Style</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="Gui::PrefComboBox" name="cbCutSurface">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
<height>22</height>
</size>
</property>
<property name="toolTip">
<string>Default appearance of cut surface in section view</string>
</property>
<property name="currentIndex">
<number>2</number>
</property>
<property name="prefEntry" stdset="0">
<cstring>CutSurfaceDisplay</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>/Mod/TechDraw/Decorations</cstring>
</property>
<item>
<property name="text">
<string>Hide</string>
</property>
</item>
<item>
<property name="text">
<string>Solid Color</string>
</property>
</item>
<item>
<property name="text">
<string>SVG Hatch</string>
</property>
</item>
<item>
<property name="text">
<string>PAT Hatch</string>
</property>
</item>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_13">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="toolTip">
<string>Show arc center marks in views</string>
<string>Line group used to set line widths</string>
</property>
<property name="text">
<string>Show Center Marks</string>
<string>Line Width Group</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="Gui::PrefCheckBox" name="cbComplexMarks">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="toolTip">
<string>Show or hide marks at direction changes on ComplexSection lines.</string>
</property>
<property name="text">
<string>Complex Section Line Marks</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>ShowCenterMarks</cstring>
<cstring>SectionLineMarks</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/TechDraw/Decorations</cstring>
</property>
</widget>
</item>
<item row="12" column="2">
<widget class="Gui::PrefCheckBox" name="cbPrintCenterMarks">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Show arc centers in printed output</string>
</property>
<property name="text">
<string>Print Center Marks</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>PrintCenterMarks</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/TechDraw/Decorations</cstring>
</property>
</widget>
</item>
</layout>
</layout>
</item>
</layout>
</widget>
@@ -854,7 +878,7 @@
</font>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=" font-weight:600;"&gt;Note:&lt;/span&gt; Items in &lt;span style=" font-style:italic;"&gt;italics&lt;/span&gt; are default values for new objects. They have no effect on existing objects.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Note:&lt;/span&gt; Items in &lt;span style=&quot; font-style:italic;&quot;&gt;italics&lt;/span&gt; are default values for new objects. They have no effect on existing objects.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>

View File

@@ -62,6 +62,7 @@ void DlgPrefsTechDrawAnnotationImp::saveSettings()
ui->cbPrintCenterMarks->onSave();
ui->cbPyramidOrtho->onSave();
ui->cbSectionLineStd->onSave();
ui->cbComplexMarks->onSave();
ui->cbShowCenterMarks->onSave();
ui->pcbLineGroup->onSave();
ui->pcbBalloonArrow->onSave();
@@ -100,6 +101,7 @@ void DlgPrefsTechDrawAnnotationImp::loadSettings()
ui->cbPrintCenterMarks->onRestore();
ui->cbPyramidOrtho->onRestore();
ui->cbSectionLineStd->onRestore();
ui->cbComplexMarks->onRestore();
ui->cbShowCenterMarks->onRestore();
ui->pcbLineGroup->onRestore();
ui->pcbBalloonArrow->onRestore();

View File

@@ -181,6 +181,13 @@ Qt::PenStyle PreferencesGui::sectionLineStyle()
return sectStyle;
}
bool PreferencesGui::sectionLineMarks()
{
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter().
GetGroup("BaseApp")->GetGroup("Preferences")->
GetGroup("Mod/TechDraw/Decorations");
return hGrp->GetBool("SectionLineMarks", true);
}
QString PreferencesGui::weldingDirectory()
{

View File

@@ -62,6 +62,7 @@ static double dimArrowSize();
static double edgeFuzz();
static Qt::PenStyle sectionLineStyle();
static bool sectionLineMarks();
static QString weldingDirectory();

View File

@@ -55,6 +55,7 @@ public:
virtual void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = nullptr );
virtual void draw();
void setWidth(double w);
double getWidth() { return m_width; }
void setStyle(Qt::PenStyle s);
void setColor(QColor c);
QColor getColor(void) { return m_colNormal; }

View File

@@ -23,6 +23,7 @@
#include "PreCompiled.h"
#ifndef _PreComp_
#include <qmath.h>
#include <QGraphicsScene>
#include <QPainter>
#include <QPainterPath>
#include <QPainterPathStroker>
@@ -43,23 +44,30 @@
#include "QGIView.h"
#include "PreferencesGui.h"
#include "Rez.h"
#include "ZVALUE.h"
#define ANSISTANDARD 0
#define ISOSTANDARD 1
#define SINGLEDIRECTIONMODE 0 //both arrows point along the section normal
#define MULTIDIRECTIONMODE 1 //the arrows point along the normal of their section line segment
using namespace TechDrawGui;
using namespace TechDraw;
QGISectionLine::QGISectionLine()
QGISectionLine::QGISectionLine() :
m_pathMode(false),
m_arrowMode()
{
m_symbol = "";
m_symSize = 0.0;
m_extLen = 1.5 * Rez::guiX(QGIArrow::getPrefArrowSize());
m_extLen = 1.5 * Rez::guiX(QGIArrow::getPrefArrowSize()); //is there a standard for this??
m_arrowSize = QGIArrow::getPrefArrowSize();
m_line = new QGraphicsPathItem();
addToGroup(m_line);
m_extend = new QGraphicsPathItem();
addToGroup(m_extend);
m_arrow1 = new QGIArrow();
addToGroup(m_arrow1);
m_arrow2 = new QGIArrow();
@@ -69,7 +77,7 @@ QGISectionLine::QGISectionLine()
m_symbol2 = new QGCustomText();
addToGroup(m_symbol2);
setWidth(Rez::guiX(0.75));
setWidth(Rez::guiX(0.75)); //a default?
setStyle(getSectionStyle());
setColor(getSectionColor());
@@ -85,14 +93,25 @@ void QGISectionLine::draw()
extensionEndsISO();
}
makeLine();
if (!pathMode()) {
makeSectionLine();
}
makeExtensionLine();
makeArrows();
makeSymbols();
makeChangePointMarks();
update();
}
void QGISectionLine::makeLine()
void QGISectionLine::makeExtensionLine()
{
QPen extendPen;
extendPen.setWidthF(getWidth());
extendPen.setColor(getSectionColor());
extendPen.setStyle(Qt::SolidLine);
extendPen.setCapStyle(Qt::FlatCap);
m_extend->setPen(extendPen);
QPainterPath pp;
pp.moveTo(m_beginExt1);
@@ -100,7 +119,13 @@ void QGISectionLine::makeLine()
pp.moveTo(m_beginExt2);
pp.lineTo(m_endExt2);
m_extend->setPath(pp);
}
//make the traditional straight section line
void QGISectionLine::makeSectionLine()
{
QPainterPath pp;
pp.moveTo(m_start);
pp.lineTo(m_end);
m_line->setPath(pp);
@@ -119,62 +144,56 @@ void QGISectionLine::makeArrows()
//make Euro (ISO) Arrows
void QGISectionLine::makeArrowsISO()
{
double arrowRotation = 0.0;
m_arrowDir.Normalize();
double angle = atan2f(m_arrowDir.y, m_arrowDir.x);
if (angle < 0.0) {
angle = 2 * M_PI + angle;
}
arrowRotation = 360.0 - angle * (180.0/M_PI); //convert to Qt rotation (clockwise degrees)
m_arrow1->setStyle(0);
m_arrow1->setSize(QGIArrow::getPrefArrowSize());
m_arrow1->setPos(m_start);
m_arrow1->draw();
m_arrow1->setRotation(arrowRotation); //rotation = 0 ==> -> horizontal, pointing right
m_arrow2->setStyle(0);
m_arrow2->setSize(QGIArrow::getPrefArrowSize());
m_arrow2->setPos(m_end);
if (m_arrowMode == SINGLEDIRECTIONMODE) {
double arrowRotation = getArrowRotation(m_arrowDir);
m_arrow1->setRotation(arrowRotation); //rotation = 0 ==> -> horizontal, pointing right
m_arrow2->setRotation(arrowRotation);
} else {
double arrowRotation1 = getArrowRotation(m_arrowDir1);
m_arrow1->setRotation(arrowRotation1);
double arrowRotation2 = getArrowRotation(m_arrowDir2);
m_arrow2->setRotation(arrowRotation2);
}
m_arrow1->draw();
m_arrow2->draw();
m_arrow2->setRotation(arrowRotation);
}
//make traditional (ASME) section arrows
void QGISectionLine::makeArrowsTrad()
{
double arrowRotation = 0.0;
m_arrowDir.Normalize();
double angle = atan2f(m_arrowDir.y, m_arrowDir.x);
if (angle < 0.0) {
angle = 2 * M_PI + angle;
}
arrowRotation = 360.0 - angle * (180.0/M_PI); //convert to Qt rotation (clockwise degrees)
QPointF posArrow1, posArrow2;
QPointF offsetDir(m_arrowDir.x, -m_arrowDir.y); //remember Y dir is flipped
double oblique = 1.0;
if ( !DrawUtil::fpCompare((m_arrowDir.x + m_arrowDir.y), 1.0) ) {
oblique = 1.25;
}
double offsetLength = (m_extLen * oblique) + Rez::guiX(QGIArrow::getPrefArrowSize());
QPointF offsetVec = offsetLength * offsetDir;
posArrow1 = m_start + offsetVec;
posArrow2 = m_end + offsetVec;
m_arrow1->setStyle(0);
m_arrow1->setSize(QGIArrow::getPrefArrowSize());
m_arrow1->setPos(posArrow1);
m_arrow1->draw();
m_arrow1->setRotation(arrowRotation); //rotation = 0 ==> -> horizontal, pointing right
m_arrow2->setStyle(0);
m_arrow2->setSize(QGIArrow::getPrefArrowSize());
m_arrow2->setPos(posArrow2);
if (m_arrowMode == SINGLEDIRECTIONMODE) {
double arrowRotation = getArrowRotation(m_arrowDir);
m_arrow1->setRotation(arrowRotation); //rotation = 0 ==> -> horizontal, pointing right
m_arrow2->setRotation(arrowRotation);
m_arrowPos1 = getArrowPosition(m_arrowDir, m_start);
m_arrow1->setPos(m_arrowPos1);
m_arrowPos2 = getArrowPosition(m_arrowDir, m_end);
m_arrow2->setPos(m_arrowPos2);
} else {
double arrowRotation1 = getArrowRotation(m_arrowDir1);
m_arrow1->setRotation(arrowRotation1);
m_arrowPos1 = getArrowPosition(m_arrowDir1, m_start);
m_arrow1->setPos(m_arrowPos1);
double arrowRotation2 = getArrowRotation(m_arrowDir2);
m_arrow2->setRotation(arrowRotation2);
m_arrowPos2 = getArrowPosition(m_arrowDir2, m_end);
m_arrow2->setPos(m_arrowPos2);
}
m_arrow1->draw();
m_arrow2->draw();
m_arrow2->setRotation(arrowRotation);
}
void QGISectionLine::makeSymbols()
@@ -187,10 +206,10 @@ void QGISectionLine::makeSymbols()
}
}
//arrows go at arrowhead position.
void QGISectionLine::makeSymbolsTrad()
{
prepareGeometryChange();
// m_symFont.setPixelSize(QGIView::calculateFontPixelSize(m_symSize));
int fontSize = QGIView::exactFontSize(Base::Tools::toStdString(m_symFont.family()), m_symSize);
m_symFont.setPixelSize(fontSize);
m_symbol1->setFont(m_symFont);
@@ -199,33 +218,28 @@ void QGISectionLine::makeSymbolsTrad()
m_symbol2->setPlainText(QString::fromUtf8(m_symbol));
QRectF symRect = m_symbol1->boundingRect();
double symWidth = symRect.width();
double symHeight = symRect.height();
double symbolFudge = 0.75;
double angle = atan2f(m_arrowDir.y, m_arrowDir.x);
if (angle < 0.0) {
angle = 2 * M_PI + angle;
}
Base::Vector3d adjustVector(cos(angle) * symWidth, sin(angle) * symHeight, 0.0);
adjustVector = DrawUtil::invertY(adjustVector) * symbolFudge;
QPointF qAdjust(adjustVector.x, adjustVector.y);
double gap = 0.5 * symHeight; //symHeight as surrogate for char box
QPointF posSymbol1 = m_arrow1->pos() + qAdjust;
m_symbol1->centerAt(posSymbol1);
QPointF motion1(m_arrowDir1.x, -m_arrowDir1.y); //move in same direction as arrow
QPointF motion2(m_arrowDir2.x, -m_arrowDir2.y); //Qt y coords!
QPointF posSymbol2 = m_arrow2->pos() + qAdjust;
m_symbol2->centerAt(posSymbol2);
QPointF symPos1 = m_arrowPos1 + motion1 * gap;
QPointF symPos2 = m_arrowPos2 + motion2 * gap;
m_symbol1->setTransformOriginPoint(m_symbol1->mapFromParent(posSymbol1));
m_symbol1->setRotation(360.0 - rotation());
m_symbol2->setTransformOriginPoint(m_symbol2->mapFromParent(posSymbol2));
m_symbol1->centerAt(symPos1);
m_symbol2->centerAt(symPos2);
m_symbol1->setTransformOriginPoint(m_symbol1->mapFromParent(symPos1));
m_symbol1->setRotation(360.0 - rotation()); //to Qt angle
m_symbol2->setTransformOriginPoint(m_symbol2->mapFromParent(symPos2));
m_symbol2->setRotation(360.0 - rotation());
}
//symbols go at ends of extensions
void QGISectionLine::makeSymbolsISO()
{
prepareGeometryChange();
// m_symFont.setPixelSize(QGIView::calculateFontPixelSize(m_symSize));
int fontSize = QGIView::exactFontSize(Base::Tools::toStdString(m_symFont.family()), m_symSize);
m_symFont.setPixelSize(fontSize);
m_symbol1->setFont(m_symFont);
@@ -233,79 +247,111 @@ void QGISectionLine::makeSymbolsISO()
m_symbol2->setFont(m_symFont);
m_symbol2->setPlainText(QString::fromUtf8(m_symbol));
QPointF symPosStart, symPosEnd;
//no normalize() for QPointF
QPointF dist = (m_start - m_end);
double lenDist = sqrt(dist.x()*dist.x() + dist.y()*dist.y());
QPointF offsetDir = dist / lenDist;
QRectF symRect = m_symbol1->boundingRect();
double symWidth = symRect.width();
double symHeight = symRect.height();
double gap = 0.5 * symHeight; //symHeight as surrogate for char box
double symbolFudge = 0.75;
double angle = atan2f(offsetDir.y(), offsetDir.x());
if (angle < 0.0) {
angle = 2.0 * M_PI + angle;
}
Base::Vector3d adjustVector(cos(angle) * symWidth, sin(angle) * symHeight, 0.0);
adjustVector = adjustVector * symbolFudge;
QPointF qAdjust(adjustVector.x, adjustVector.y);
QPointF motion1(-m_arrowDir1.x, m_arrowDir1.y); //move away from extension end
QPointF motion2(-m_arrowDir2.x, m_arrowDir2.y); //Qt y coords!
symPosStart = m_start + qAdjust;
symPosEnd = m_end - qAdjust;
QPointF symPos1 = m_endExt1 + motion1 * gap;
QPointF symPos2 = m_endExt2 + motion2 * gap;
m_symbol1->centerAt(symPosStart);
m_symbol2->centerAt(symPosEnd);
m_symbol1->centerAt(symPos1);
m_symbol2->centerAt(symPos2);
m_symbol1->setTransformOriginPoint(m_symbol1->mapFromParent(symPosStart));
m_symbol1->setTransformOriginPoint(m_symbol1->mapFromParent(symPos1));
m_symbol1->setRotation(360.0 - rotation());
m_symbol2->setTransformOriginPoint(m_symbol2->mapFromParent(symPosEnd));
m_symbol2->setTransformOriginPoint(m_symbol2->mapFromParent(symPos2));
m_symbol2->setRotation(360.0 - rotation());
}
//extension lines are on the stock side of the section line
void QGISectionLine::extensionEndsTrad()
{
QPointF offsetDir(m_arrowDir.x, -m_arrowDir.y);
if (m_arrowMode == SINGLEDIRECTIONMODE) {
QPointF offsetDir(m_arrowDir.x, -m_arrowDir.y); //inverted Y
offsetDir = normalizeQPointF(offsetDir);
//extensions for oblique section line needs to be a bit longer
double oblique = 1.0;
if ( !DrawUtil::fpCompare((m_arrowDir.x + m_arrowDir.y), 1.0) ) {
oblique = 1.25;
//draw from section line endpoint
QPointF offsetEnd = m_extLen * offsetDir;
m_beginExt1 = m_start;
m_endExt1 = m_start + offsetEnd;
m_beginExt2 = m_end;
m_endExt2 = m_end + offsetEnd;
} else {
//extension lines run from point on section line to arrowhead
m_beginExt1 = m_start;
m_endExt1 = getArrowPosition(m_arrowDir1, m_start);
m_beginExt2 = m_end;
m_endExt2 = getArrowPosition(m_arrowDir2, m_end);
}
//draw from section line endpoint
QPointF offsetEnd = oblique * m_extLen * offsetDir;
m_beginExt1 = m_start;
m_endExt1 = m_start + offsetEnd;
m_beginExt2 = m_end;
m_endExt2 = m_end + offsetEnd;
}
//the extension lines are on the waste side of the section line!
void QGISectionLine::extensionEndsISO()
{
//lines are offset to other side of section line!
QPointF offsetDir(m_arrowDir.x, -m_arrowDir.y);
offsetDir = offsetDir * -1.0;
if (m_arrowMode == SINGLEDIRECTIONMODE) {
QPointF offsetDir(-m_arrowDir.x, m_arrowDir.y); //reversed and inverted y
offsetDir = normalizeQPointF(offsetDir);
//extensions for oblique section line needs to be a bit longer?
//this is just esthetics
double oblique = 1.0;
if ( !DrawUtil::fpCompare((m_arrowDir.x + m_arrowDir.y), 1.0) ) {
oblique = 1.10;
//draw from section line endpoint less arrow length
QPointF offsetStart = offsetDir * Rez::guiX(QGIArrow::getPrefArrowSize());
QPointF offsetEnd = m_extLen * offsetDir;
m_beginExt1 = m_start + offsetStart;
m_endExt1 = m_start + offsetStart + offsetEnd;
m_beginExt2 = m_end + offsetStart;
m_endExt2 = m_end + offsetStart + offsetEnd;
} else {
//extension lines run in reverse of arrow direction from base of arrowhead for distance m_extLen
QPointF offsetDir1(-m_arrowDir1.x, m_arrowDir1.y); //reversed and inverted y
offsetDir1 = normalizeQPointF(offsetDir1);
QPointF offsetStart1 = offsetDir1 * Rez::guiX(QGIArrow::getPrefArrowSize());
QPointF offsetEnd1 = m_extLen * offsetDir1;
m_beginExt1 = m_start + offsetStart1;
m_endExt1 = m_start + offsetStart1 + offsetEnd1;
QPointF offsetDir2(-m_arrowDir2.x, m_arrowDir2.y); //reversed and inverted y
offsetDir2 = normalizeQPointF(offsetDir2);
QPointF offsetStart2 = offsetDir2 * Rez::guiX(QGIArrow::getPrefArrowSize());
QPointF offsetEnd2 = m_extLen * offsetDir2;
m_beginExt2 = m_end + offsetStart2;
m_endExt2 = m_end + offsetStart2 + offsetEnd2;
}
//draw from section line endpoint less arrow length
QPointF offsetStart = offsetDir * Rez::guiX(QGIArrow::getPrefArrowSize());
QPointF offsetEnd = oblique * m_extLen * offsetDir;
m_beginExt1 = m_start + offsetStart;
m_endExt1 = m_start + offsetStart + offsetEnd;
m_beginExt2 = m_end + offsetStart;
m_endExt2 = m_end + offsetStart + offsetEnd;
}
void QGISectionLine::makeChangePointMarks()
{
// Base::Console().Message("QGISL::makeChangePointMarks()\n");
double segmentLength = 0.50 * QGIArrow::getPrefArrowSize();
QPen cPointPen;
//TODO: this should really be 2.0 * thickLineWidth, but we only have one
//width available (which should be 'thin', for the section line)
cPointPen.setWidthF(2.0 * getWidth());
cPointPen.setColor(getSectionColor());
cPointPen.setStyle(Qt::SolidLine);
for (auto& cPoint : m_changePointData) {
QGraphicsPathItem* cPointItem = new QGraphicsPathItem();
addToGroup(cPointItem);
QPainterPath pPath;
QPointF location = cPoint.getLocation();
QPointF start = location + cPoint.getPreDirection() * segmentLength;
QPointF end = location + cPoint.getPostDirection() * segmentLength;
pPath.moveTo(Rez::guiPt(start));
pPath.lineTo(Rez::guiPt(location));
pPath.lineTo(Rez::guiPt(end));
cPointItem->setPath(pPath);
cPointItem->setPen(cPointPen);
cPointItem->setZValue(ZVALUE::SECTIONLINE + 1);
cPointItem->setPos(0.0, 0.0);
m_changePointMarks.push_back(cPointItem);
}
}
void QGISectionLine::setEnds(Base::Vector3d l1, Base::Vector3d l2)
{
m_l1 = l1;
@@ -333,8 +379,46 @@ void QGISectionLine::setDirection(double xDir, double yDir)
void QGISectionLine::setDirection(Base::Vector3d dir)
{
m_arrowMode = SINGLEDIRECTIONMODE;
m_arrowDir = dir;
m_arrowDir.Normalize();
m_arrowDir1 = dir;
m_arrowDir1.Normalize();
m_arrowDir2 = dir;
m_arrowDir2.Normalize();
}
void QGISectionLine::setArrowDirections(Base::Vector3d dir1, Base::Vector3d dir2)
{
m_arrowMode = MULTIDIRECTIONMODE;
m_arrowDir1 = dir1;
m_arrowDir1.Normalize();
m_arrowDir2 = dir2;
m_arrowDir2.Normalize();
}
//convert an arrow direction vector into a Qt rotation angle degrees
double QGISectionLine::getArrowRotation(Base::Vector3d arrowDir)
{
arrowDir.Normalize();
double angle = atan2f(arrowDir.y, arrowDir.x);
if (angle < 0.0) {
angle = 2 * M_PI + angle;
}
double arrowRotation = 360.0 - angle * (180.0/M_PI); //convert to Qt rotation (clockwise degrees)
return arrowRotation;
}
QPointF QGISectionLine::getArrowPosition(Base::Vector3d arrowDir, QPointF refPoint)
{
QPointF qArrowDir(arrowDir.x, -arrowDir.y); //remember Y dir is flipped
qArrowDir = normalizeQPointF(qArrowDir);
double offsetLength = m_extLen + Rez::guiX(QGIArrow::getPrefArrowSize());
QPointF offsetVec = offsetLength * qArrowDir;
QPointF arrowPos = refPoint + offsetVec;
return arrowPos;
}
void QGISectionLine::setFont(QFont f, double fsize)
@@ -343,6 +427,44 @@ void QGISectionLine::setFont(QFont f, double fsize)
m_symSize = fsize;
}
void QGISectionLine::setPath(QPainterPath& path)
{
m_line->setPath(path);
}
void QGISectionLine::setChangePoints(TechDraw::ChangePointVector changePointData)
{
m_changePointData = changePointData;
clearChangePointMarks();
}
void QGISectionLine::clearChangePoints()
{
clearChangePointMarks();
m_changePointData.clear();
}
void QGISectionLine::clearChangePointMarks()
{
if (!m_changePointMarks.empty()) {
for (auto& cPoint : m_changePointMarks) {
cPoint->hide();
scene()->removeItem(cPoint);
delete cPoint;
}
m_changePointMarks.clear();
}
}
//QPointF does not have length or normalize methods
QPointF QGISectionLine::normalizeQPointF(QPointF inPoint)
{
double x2 = inPoint.x() * inPoint.x();
double y2 = inPoint.y() * inPoint.y();
double root = sqrt(x2 + y2);
return inPoint / root;
}
void QGISectionLine::setSectionColor(QColor c)
{
setColor(c);
@@ -416,11 +538,6 @@ void QGISectionLine::setTools()
m_line->setPen(m_pen);
// m_arrow1->setPen(m_pen);
// m_arrow2->setPen(m_pen);
// m_arrow1->setBrush(m_brush);
// m_arrow2->setBrush(m_brush);
m_arrow1->setNormalColor(m_colCurrent);
m_arrow1->setFillColor(m_colCurrent);
m_arrow1->setPrettyNormal();

View File

@@ -28,9 +28,12 @@
#include <QColor>
#include <QFont>
#include <QPointF>
#include <QPainterPath>
#include <Base/Vector3D.h>
#include <Mod/TechDraw/App/DrawComplexSection.h>
#include "QGCustomText.h"
#include "QGIDecoration.h"
@@ -53,34 +56,46 @@ public:
void setEnds(Base::Vector3d l1, Base::Vector3d l2);
void setBounds(double x1, double y1, double x2, double y2);
void setPath(QPainterPath& path);
void setSymbol(char* sym);
void setDirection(double xDir, double yDir);
void setDirection(Base::Vector3d dir);
void setArrowDirections(Base::Vector3d dir1, Base::Vector3d dir2);
void setFont(QFont f, double fsize);
void setSectionStyle(int style);
void setSectionColor(QColor c);
void setPathMode(bool mode) { m_pathMode = mode; }
bool pathMode() { return m_pathMode; }
void setChangePoints(TechDraw::ChangePointVector changePoints);
void clearChangePoints();
virtual void draw();
protected:
QColor getSectionColor();
Qt::PenStyle getSectionStyle();
void makeLine();
void makeSectionLine();
void makeExtensionLine();
void makeArrows();
void makeArrowsTrad();
void makeArrowsISO();
void makeSymbols();
void makeSymbolsTrad();
void makeSymbolsISO();
void makeChangePointMarks();
void setTools();
int getPrefSectionStandard();
void extensionEndsISO();
void extensionEndsTrad();
double getArrowRotation(Base::Vector3d arrowDir);
QPointF getArrowPosition(Base::Vector3d arrowDir, QPointF refPoint);
void clearChangePointMarks();
static QPointF normalizeQPointF(QPointF inPoint);
private:
char* m_symbol;
QGraphicsPathItem* m_line; //primpath?
QGraphicsPathItem* m_line;
QGraphicsPathItem* m_extend;
QGIArrow* m_arrow1;
QGIArrow* m_arrow2;
QGCustomText* m_symbol1;
@@ -92,15 +107,21 @@ private:
QFont m_symFont;
double m_symSize;
double m_arrowSize;
//QColor m_color;
double m_extLen;
// int m_sectionFormat; //0 = ASME, 1 = ISO
Base::Vector3d m_l1; //end of main section line
Base::Vector3d m_l2; //end of main section line
QPointF m_beginExt1; //start of extension line 1
QPointF m_endExt1; //end of extension line 1
QPointF m_beginExt2; //start of extension line 2
QPointF m_endExt2; //end of extension line 1
bool m_pathMode; //use external path for line
int m_arrowMode; //0 = 1 direction for both arrows, 1 = direction for each arrow
Base::Vector3d m_arrowDir1;
Base::Vector3d m_arrowDir2;
QPointF m_arrowPos1;
QPointF m_arrowPos2;
std::vector<QGraphicsPathItem*> m_changePointMarks;
TechDraw::ChangePointVector m_changePointData;
};
}

View File

@@ -56,6 +56,7 @@
#include <Mod/TechDraw/App/DrawUtil.h>
#include <Mod/TechDraw/App/DrawViewPart.h>
#include <Mod/TechDraw/App/DrawViewSection.h>
#include <Mod/TechDraw/App/DrawComplexSection.h>
#include <Mod/TechDraw/App/DrawHatch.h>
#include <Mod/TechDraw/App/DrawGeomHatch.h>
#include <Mod/TechDraw/App/DrawViewDetail.h>
@@ -446,10 +447,10 @@ void QGIViewPart::drawViewPart()
if (!vp)
return;
float lineWidth = vp->LineWidth.getValue() * lineScaleFactor;
float lineWidthHid = vp->HiddenWidth.getValue() * lineScaleFactor;
float lineWidthIso = vp->IsoWidth.getValue() * lineScaleFactor;
// float lineWidthExtra = viewPart->ExtraWidth.getValue() * lineScaleFactor;
float lineWidth = vp->LineWidth.getValue() * lineScaleFactor; //thick
float lineWidthHid = vp->HiddenWidth.getValue() * lineScaleFactor; //thin
float lineWidthIso = vp->IsoWidth.getValue() * lineScaleFactor; //graphic
// float lineWidthExtra = viewPart->ExtraWidth.getValue() * lineScaleFactor; //extra
bool showAll = vp->ShowAllEdges.getValue();
prepareGeometryChange();
@@ -803,7 +804,11 @@ void QGIViewPart::drawAllSectionLines()
if (vp->ShowSectionLine.getValue()) {
auto refs = viewPart->getSectionRefs();
for (auto& r:refs) {
drawSectionLine(r, true);
if (r->isDerivedFrom(DrawComplexSection::getClassTypeId())) {
drawComplexSectionLine(r, true);
} else {
drawSectionLine(r, true);
}
}
}
}
@@ -820,8 +825,10 @@ void QGIViewPart::drawSectionLine(TechDraw::DrawViewSection* viewSection, bool b
return;
auto vp = static_cast<ViewProviderViewPart*>(getViewProvider(getViewObject()));
if (!vp)
if (!vp) {
return;
}
float lineWidthThin = vp->HiddenWidth.getValue() * lineScaleFactor; //thin
if (b) {
QGISectionLine* sectionLine = new QGISectionLine();
@@ -829,7 +836,7 @@ void QGIViewPart::drawSectionLine(TechDraw::DrawViewSection* viewSection, bool b
sectionLine->setSymbol(const_cast<char*>(viewSection->SectionSymbol.getValue()));
sectionLine->setSectionStyle(vp->SectionLineStyle.getValue());
sectionLine->setSectionColor(vp->SectionLineColor.getValue().asValue<QColor>());
sectionLine->setPathMode(false);
//find the ends of the section line
double scale = viewPart->getScale();
std::pair<Base::Vector3d, Base::Vector3d> sLineEnds = viewSection->sectionLineEnds();
@@ -839,11 +846,8 @@ void QGIViewPart::drawSectionLine(TechDraw::DrawViewSection* viewSection, bool b
//which way to the arrows point?
Base::Vector3d lineDir = l2 - l1;
lineDir.Normalize();
Base::Vector3d normalDir = viewSection->SectionNormal.getValue();
Base::Vector3d projNormal = viewPart->projectPoint(normalDir);
projNormal.Normalize();
Base::Vector3d arrowDir = viewSection->SectionNormal.getValue();
arrowDir = - viewPart->projectPoint(arrowDir); //arrows point reverse of sectionNormal(extrusion dir)
arrowDir = - viewPart->projectPoint(arrowDir); //arrows point reverse of sectionNormal
sectionLine->setDirection(arrowDir.x, -arrowDir.y); //invert Y
//make the section line a little longer
@@ -853,7 +857,7 @@ void QGIViewPart::drawSectionLine(TechDraw::DrawViewSection* viewSection, bool b
//set the general parameters
sectionLine->setPos(0.0, 0.0);
sectionLine->setWidth(Rez::guiX(vp->LineWidth.getValue()));
sectionLine->setWidth(lineWidthThin);
double fontSize = Preferences::dimFontSizeMM();
sectionLine->setFont(getFont(), fontSize);
sectionLine->setZValue(ZVALUE::SECTIONLINE);
@@ -862,6 +866,73 @@ void QGIViewPart::drawSectionLine(TechDraw::DrawViewSection* viewSection, bool b
}
}
void QGIViewPart::drawComplexSectionLine(TechDraw::DrawViewSection* viewSection, bool b)
{
Q_UNUSED(b);
TechDraw::DrawViewPart *viewPart = static_cast<TechDraw::DrawViewPart *>(getViewObject());
if (!viewPart)
return;
if (!viewSection)
return;
auto vp = static_cast<ViewProviderViewPart*>(getViewProvider(getViewObject()));
if (!vp) {
return;
}
float lineWidthThin = vp->HiddenWidth.getValue() * lineScaleFactor; //thin
auto dcs = static_cast<DrawComplexSection*>(viewSection);
BaseGeomPtrVector edges = dcs->makeSectionLineGeometry();
QPainterPath wirePath;
QPainterPath firstSeg = drawPainterPath(edges.front());
wirePath.connectPath(firstSeg);
int edgeCount = edges.size();
//NOTE: if the edges are not in nose to tail order, Qt will insert extra segments
//that will overlap the segments we add. for interupted line styles, this
//will make the line look continuous. This is prevented in
//DrawComplexSection::makeSectionLineGeometry by calling makeNoseToTailWire
for (int i = 1; i < edgeCount; i++) {
QPainterPath edgePath = drawPainterPath(edges.at(i));
wirePath.connectPath(edgePath);
}
std::pair<Base::Vector3d, Base::Vector3d> ends = dcs->sectionLineEnds();
Base::Vector3d vStart = Rez::guiX(ends.first); //already scaled by dcs
Base::Vector3d vEnd = Rez::guiX(ends.second);
QGISectionLine* sectionLine = new QGISectionLine();
addToGroup(sectionLine);
sectionLine->setSymbol(const_cast<char*>(viewSection->SectionSymbol.getValue()));
sectionLine->setSectionStyle(vp->SectionLineStyle.getValue());
sectionLine->setSectionColor(vp->SectionLineColor.getValue().asValue<QColor>());
sectionLine->setPathMode(true);
sectionLine->setPath(wirePath);
sectionLine->setEnds(vStart, vEnd);
if (vp->SectionLineMarks.getValue()) {
sectionLine->setChangePoints(dcs->getChangePointsFromSectionLine());
} else {
sectionLine->clearChangePoints();
}
if (dcs->ProjectionStrategy.isValue("Single")) {
Base::Vector3d arrowDirSingle = viewSection->SectionNormal.getValue();
arrowDirSingle = - viewPart->projectPoint(arrowDirSingle); //arrows are opposite section normal
sectionLine->setDirection(arrowDirSingle.x, -arrowDirSingle.y); //invert y for Qt
} else {
std::pair<Base::Vector3d, Base::Vector3d> dirsPiecewise = dcs->sectionArrowDirs();
dirsPiecewise.first = DrawUtil::invertY(dirsPiecewise.first);
dirsPiecewise.second = DrawUtil::invertY(dirsPiecewise.second);
sectionLine->setArrowDirections(dirsPiecewise.first, dirsPiecewise.second);
}
//set the general parameters
sectionLine->setPos(0.0, 0.0);
sectionLine->setWidth(lineWidthThin);
double fontSize = Preferences::dimFontSizeMM();
sectionLine->setFont(getFont(), fontSize);
sectionLine->setZValue(ZVALUE::SECTIONLINE);
sectionLine->setRotation(- viewPart->Rotation.getValue());
sectionLine->draw();
}
//TODO: use Cosmetic::CenterLine object for this to make it usable for dims.
void QGIViewPart::drawCenterLines(bool b)
{
@@ -885,35 +956,28 @@ void QGIViewPart::drawCenterLines(bool b)
centerLine = new QGICenterLine();
addToGroup(centerLine);
centerLine->setPos(0.0, 0.0);
//this should work from the viewPart's bbox, not the border
// double scale = viewPart->getScale();
double width = Rez::guiX(viewPart->getBoxX());
sectionSpan = width + sectionFudge;
// sectionSpan = m_border->rect().width() + sectionFudge;
xVal = sectionSpan / 2.0;
yVal = 0.0;
centerLine->setIntersection(horiz && vert);
centerLine->setBounds(-xVal, -yVal, xVal, yVal);
centerLine->setWidth(Rez::guiX(vp->HiddenWidth.getValue()));
centerLine->setZValue(ZVALUE::SECTIONLINE);
// centerLine->setRotation(viewPart->Rotation.getValue());
centerLine->draw();
}
if (vert) {
centerLine = new QGICenterLine();
addToGroup(centerLine);
centerLine->setPos(0.0, 0.0);
// double scale = viewPart->getScale();
double height = Rez::guiX(viewPart->getBoxY());
sectionSpan = height + sectionFudge;
// sectionSpan = (m_border->rect().height() - m_label->boundingRect().height()) + sectionFudge;
xVal = 0.0;
yVal = sectionSpan / 2.0;
centerLine->setIntersection(horiz && vert);
centerLine->setBounds(-xVal, -yVal, xVal, yVal);
centerLine->setWidth(Rez::guiX(vp->HiddenWidth.getValue()));
centerLine->setZValue(ZVALUE::SECTIONLINE);
// centerLine->setRotation(viewPart->Rotation.getValue());
centerLine->draw();
}
}

View File

@@ -68,6 +68,7 @@ public:
QRectF boundingRect() const override;
virtual void drawAllSectionLines();
virtual void drawSectionLine(TechDraw::DrawViewSection* s, bool b);
virtual void drawComplexSectionLine(TechDraw::DrawViewSection* viewSection, bool b);
virtual void drawCenterLines(bool b);
virtual void drawHighlight(TechDraw::DrawViewDetail* viewDetail, bool b);
virtual void drawMatting();

View File

@@ -51,6 +51,7 @@
<file>icons/actions/TechDraw_View.svg</file>
<file>icons/actions/TechDraw_WeldSymbol.svg</file>
<file>icons/actions/TechDraw_SurfaceFinishSymbols.svg</file>
<file>icons/actions/TechDraw_ComplexSection.svg</file>
<file>icons/arrow-ccw.svg</file>
<file>icons/arrow-cw.svg</file>
<file>icons/arrow-down.svg</file>
@@ -180,6 +181,8 @@
<!-- main wb icon and preferences icons -->
<file>icons/preferences-techdraw.svg</file>
<!-- bitmap images -->
<!-- translations -->
<file>translations/TechDraw_af.qm</file>
<file>translations/TechDraw_ar.qm</file>

View File

@@ -0,0 +1,767 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
id="svg249"
height="64"
width="64"
version="1.1">
<defs
id="defs3">
<marker
style="overflow:visible;"
id="Arrow2Mend"
refX="0.0"
refY="0.0"
orient="auto">
<path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path5645" />
</marker>
<marker
style="overflow:visible;"
id="marker7794"
refX="0.0"
refY="0.0"
orient="auto">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path7792" />
</marker>
<marker
style="overflow:visible;"
id="marker7676"
refX="0.0"
refY="0.0"
orient="auto">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path7674" />
</marker>
<marker
style="overflow:visible;"
id="marker7510"
refX="0.0"
refY="0.0"
orient="auto">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path7508" />
</marker>
<marker
style="overflow:visible;"
id="marker7386"
refX="0.0"
refY="0.0"
orient="auto">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path7384" />
</marker>
<marker
style="overflow:visible;"
id="Arrow1Mend"
refX="0.0"
refY="0.0"
orient="auto">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path5627" />
</marker>
<marker
style="overflow:visible"
id="marker7236"
refX="0.0"
refY="0.0"
orient="auto">
<path
transform="scale(0.6) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path7234" />
</marker>
<marker
style="overflow:visible"
id="marker7190"
refX="0.0"
refY="0.0"
orient="auto">
<path
transform="scale(0.6) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path7188" />
</marker>
<marker
style="overflow:visible"
id="Arrow1Sstart"
refX="0.0"
refY="0.0"
orient="auto">
<path
transform="scale(0.2) translate(6,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path5630" />
</marker>
<marker
style="overflow:visible"
id="Arrow2Lstart"
refX="0.0"
refY="0.0"
orient="auto">
<path
transform="scale(1.1) translate(1,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path5636" />
</marker>
<marker
style="overflow:visible"
id="Arrow2Mstart"
refX="0.0"
refY="0.0"
orient="auto">
<path
transform="scale(0.6) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
id="path5642" />
</marker>
<marker
style="overflow:visible"
id="Arrow1Lstart"
refX="0.0"
refY="0.0"
orient="auto">
<path
transform="scale(0.8) translate(12.5,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path5618" />
</marker>
<linearGradient
id="linearGradient3999">
<stop
id="stop4001"
offset="0"
style="stop-color:#34e0e2;stop-opacity:1" />
<stop
id="stop4003"
offset="1"
style="stop-color:#06989a;stop-opacity:1" />
</linearGradient>
<radialGradient
gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
gradientUnits="userSpaceOnUse"
xlink:href="#linearGradient5060"
id="radialGradient5031"
fy="486.64789"
fx="605.71429"
r="117.14286"
cy="486.64789"
cx="605.71429" />
<linearGradient
id="linearGradient5060">
<stop
offset="0"
style="stop-color:#000000;stop-opacity:1"
id="stop5062" />
<stop
offset="1"
style="stop-color:#000000;stop-opacity:0"
id="stop5064" />
</linearGradient>
<radialGradient
gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
gradientUnits="userSpaceOnUse"
xlink:href="#linearGradient5060"
id="radialGradient5029"
fy="486.64789"
fx="605.71429"
r="117.14286"
cy="486.64789"
cx="605.71429" />
<linearGradient
id="linearGradient5048">
<stop
offset="0"
style="stop-color:#000000;stop-opacity:0"
id="stop5050" />
<stop
offset="0.5"
style="stop-color:#000000;stop-opacity:1"
id="stop5056" />
<stop
offset="1"
style="stop-color:#000000;stop-opacity:0"
id="stop5052" />
</linearGradient>
<linearGradient
gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
gradientUnits="userSpaceOnUse"
xlink:href="#linearGradient5048"
id="linearGradient5027"
y2="609.50507"
x2="302.85715"
y1="366.64789"
x1="302.85715" />
<linearGradient
id="linearGradient4542">
<stop
offset="0"
style="stop-color:#000000;stop-opacity:1"
id="stop4544" />
<stop
offset="1"
style="stop-color:#000000;stop-opacity:0"
id="stop4546" />
</linearGradient>
<radialGradient
gradientTransform="matrix(1,0,0,0.284916,0,30.08928)"
gradientUnits="userSpaceOnUse"
xlink:href="#linearGradient4542"
id="radialGradient4548"
fy="42.07798"
fx="24.306795"
r="15.821514"
cy="42.07798"
cx="24.306795" />
<linearGradient
id="linearGradient15662">
<stop
offset="0"
style="stop-color:#ffffff;stop-opacity:1"
id="stop15664" />
<stop
offset="1"
style="stop-color:#f8f8f8;stop-opacity:1"
id="stop15666" />
</linearGradient>
<radialGradient
gradientUnits="userSpaceOnUse"
id="aigrd3"
fy="64.567902"
fx="20.892099"
r="5.257"
cy="64.567902"
cx="20.892099">
<stop
offset="0"
style="stop-color:#f0f0f0;stop-opacity:1"
id="stop15573" />
<stop
offset="1"
style="stop-color:#9a9a9a;stop-opacity:1"
id="stop15575" />
</radialGradient>
<radialGradient
gradientUnits="userSpaceOnUse"
id="aigrd2"
fy="114.5684"
fx="20.892099"
r="5.256"
cy="114.5684"
cx="20.892099">
<stop
offset="0"
style="stop-color:#f0f0f0;stop-opacity:1"
id="stop15566" />
<stop
offset="1"
style="stop-color:#9a9a9a;stop-opacity:1"
id="stop15568" />
</radialGradient>
<linearGradient
id="linearGradient269">
<stop
offset="0"
style="stop-color:#a3a3a3;stop-opacity:1"
id="stop270" />
<stop
offset="1"
style="stop-color:#4c4c4c;stop-opacity:1"
id="stop271" />
</linearGradient>
<linearGradient
id="linearGradient259">
<stop
offset="0"
style="stop-color:#fafafa;stop-opacity:1"
id="stop260" />
<stop
offset="1"
style="stop-color:#bbbbbb;stop-opacity:1"
id="stop261" />
</linearGradient>
<linearGradient
id="linearGradient12512">
<stop
offset="0"
style="stop-color:#ffffff;stop-opacity:1"
id="stop12513" />
<stop
offset="0.5"
style="stop-color:#fff520;stop-opacity:0.89108908"
id="stop12517" />
<stop
offset="1"
style="stop-color:#fff300;stop-opacity:0"
id="stop12514" />
</linearGradient>
<radialGradient
gradientTransform="matrix(0.968273,0,0,1.032767,3.4281936,-47.492271)"
gradientUnits="userSpaceOnUse"
xlink:href="#linearGradient269"
id="radialGradient15656"
fy="3.7561285"
fx="8.824419"
r="37.751713"
cy="3.7561285"
cx="8.824419" />
<radialGradient
gradientTransform="matrix(0.960493,0,0,1.041132,0.07464063,-48.138718)"
gradientUnits="userSpaceOnUse"
xlink:href="#linearGradient259"
id="radialGradient15658"
fy="35.736916"
fx="33.966679"
r="86.70845"
cy="35.736916"
cx="33.966679" />
<radialGradient
gradientTransform="matrix(0.968273,0,0,1.032767,3.4281936,-47.492271)"
gradientUnits="userSpaceOnUse"
xlink:href="#linearGradient15662"
id="radialGradient15668"
fy="7.2678967"
fx="8.1435566"
r="38.158695"
cy="7.2678967"
cx="8.1435566" />
<radialGradient
gradientTransform="matrix(0.229703,0,0,0.229703,4.613529,3.979808)"
gradientUnits="userSpaceOnUse"
xlink:href="#aigrd2"
id="radialGradient2283"
fy="114.5684"
fx="20.892099"
r="5.256"
cy="114.5684"
cx="20.892099" />
<radialGradient
gradientTransform="matrix(0.229703,0,0,0.229703,4.613529,3.979808)"
gradientUnits="userSpaceOnUse"
xlink:href="#aigrd3"
id="radialGradient2285"
fy="64.567902"
fx="20.892099"
r="5.257"
cy="64.567902"
cx="20.892099" />
<linearGradient
gradientUnits="userSpaceOnUse"
xlink:href="#linearGradient3377-76"
id="linearGradient4343"
y2="41.792759"
x2="44.524982"
y1="14.452502"
x1="18.971846" />
<linearGradient
id="linearGradient3377-76">
<stop
offset="0"
style="stop-color:#faff2b;stop-opacity:1"
id="stop3379-5" />
<stop
offset="0.5"
style="stop-color:#fcb915;stop-opacity:1"
id="stop4345" />
<stop
offset="1"
style="stop-color:#c68708;stop-opacity:1"
id="stop3381-7" />
</linearGradient>
<linearGradient
gradientUnits="userSpaceOnUse"
xlink:href="#linearGradient3377-76"
id="linearGradient4349"
y2="108.75008"
x2="175.6825"
y1="79.160103"
x1="145.64697" />
<linearGradient
id="linearGradient4482">
<stop
offset="0"
style="stop-color:#faff2b;stop-opacity:1"
id="stop4484" />
<stop
offset="0.5"
style="stop-color:#fcb915;stop-opacity:1"
id="stop4486" />
<stop
offset="1"
style="stop-color:#c68708;stop-opacity:1"
id="stop4488" />
</linearGradient>
<radialGradient
gradientTransform="matrix(0.97435,0.2250379,-0.4623105,2.0016728,48.487554,-127.99883)"
gradientUnits="userSpaceOnUse"
xlink:href="#linearGradient3377"
id="radialGradient4351"
fy="97.369568"
fx="135.38333"
r="19.467436"
cy="97.369568"
cx="135.38333" />
<linearGradient
id="linearGradient3377">
<stop
offset="0"
style="stop-color:#faff2b;stop-opacity:1"
id="stop3379" />
<stop
offset="1"
style="stop-color:#ffaa00;stop-opacity:1"
id="stop3381" />
</linearGradient>
<radialGradient
gradientUnits="userSpaceOnUse"
xlink:href="#linearGradient3377"
id="radialGradient4353"
fy="28.869568"
fx="45.883327"
r="19.467436"
cy="28.869568"
cx="45.883327" />
<linearGradient
id="linearGradient4495">
<stop
offset="0"
style="stop-color:#faff2b;stop-opacity:1"
id="stop4497" />
<stop
offset="1"
style="stop-color:#ffaa00;stop-opacity:1"
id="stop4499" />
</linearGradient>
<radialGradient
r="5.256"
fy="114.5684"
fx="20.892099"
cy="114.5684"
cx="20.892099"
gradientTransform="matrix(0.229703,0,0,0.229703,4.613529,3.979808)"
gradientUnits="userSpaceOnUse"
id="radialGradient2283-4"
xlink:href="#aigrd2-2" />
<radialGradient
id="aigrd2-2"
cx="20.892099"
cy="114.5684"
r="5.256"
fx="20.892099"
fy="114.5684"
gradientUnits="userSpaceOnUse">
<stop
offset="0"
style="stop-color:#F0F0F0"
id="stop15566-3" />
<stop
offset="1.0000000"
style="stop-color:#9a9a9a;stop-opacity:1.0000000;"
id="stop15568-2" />
</radialGradient>
<radialGradient
r="5.257"
fy="64.567902"
fx="20.892099"
cy="64.567902"
cx="20.892099"
gradientTransform="matrix(0.229703,0,0,0.229703,4.613529,3.979808)"
gradientUnits="userSpaceOnUse"
id="radialGradient2285-2"
xlink:href="#aigrd3-1" />
<radialGradient
id="aigrd3-1"
cx="20.892099"
cy="64.567902"
r="5.257"
fx="20.892099"
fy="64.567902"
gradientUnits="userSpaceOnUse">
<stop
offset="0"
style="stop-color:#F0F0F0"
id="stop15573-6" />
<stop
offset="1.0000000"
style="stop-color:#9a9a9a;stop-opacity:1.0000000;"
id="stop15575-8" />
</radialGradient>
<radialGradient
xlink:href="#linearGradient15662-7"
id="radialGradient15668-2"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.2992848,0,0,1.4315068,3.2140525,-64.437909)"
cx="8.1435566"
cy="7.2678967"
fx="8.1435566"
fy="7.2678967"
r="38.158695" />
<linearGradient
id="linearGradient15662-7">
<stop
id="stop15664-6"
offset="0.0000000"
style="stop-color:#ffffff;stop-opacity:1.0000000;" />
<stop
id="stop15666-1"
offset="1.0000000"
style="stop-color:#f8f8f8;stop-opacity:1.0000000;" />
</linearGradient>
<radialGradient
xlink:href="#linearGradient259-5"
id="radialGradient15658-4"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.3214205,0,0,1.4752426,-2.0839021,-66.146883)"
cx="33.966679"
cy="35.736916"
fx="33.966679"
fy="35.736916"
r="86.70845" />
<linearGradient
id="linearGradient259-5">
<stop
id="stop260-5"
offset="0.0000000"
style="stop-color:#fafafa;stop-opacity:1.0000000;" />
<stop
id="stop261-1"
offset="1.0000000"
style="stop-color:#bbbbbb;stop-opacity:1.0000000;" />
</linearGradient>
<radialGradient
xlink:href="#linearGradient269-1"
id="radialGradient15656-7"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.3321242,0,0,1.4633899,2.5298271,-65.230893)"
cx="3.3431637"
cy="37.388847"
fx="3.3431637"
fy="37.388847"
r="37.751713" />
<linearGradient
id="linearGradient269-1">
<stop
id="stop270-1"
offset="0.0000000"
style="stop-color:#a3a3a3;stop-opacity:1.0000000;" />
<stop
id="stop271-5"
offset="1.0000000"
style="stop-color:#4c4c4c;stop-opacity:1.0000000;" />
</linearGradient>
<linearGradient
y2="609.50507"
x2="302.85715"
y1="366.64789"
x1="302.85715"
gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
gradientUnits="userSpaceOnUse"
id="linearGradient5027-1"
xlink:href="#linearGradient5048-7" />
<linearGradient
id="linearGradient5048-7">
<stop
id="stop5050-4"
offset="0"
style="stop-color:black;stop-opacity:0;" />
<stop
style="stop-color:black;stop-opacity:1;"
offset="0.5"
id="stop5056-0" />
<stop
id="stop5052-9"
offset="1"
style="stop-color:black;stop-opacity:0;" />
</linearGradient>
<radialGradient
r="117.14286"
fy="486.64789"
fx="605.71429"
cy="486.64789"
cx="605.71429"
gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
gradientUnits="userSpaceOnUse"
id="radialGradient5029-4"
xlink:href="#linearGradient5060-8" />
<linearGradient
id="linearGradient5060-8">
<stop
id="stop5062-8"
offset="0"
style="stop-color:black;stop-opacity:1;" />
<stop
id="stop5064-2"
offset="1"
style="stop-color:black;stop-opacity:0;" />
</linearGradient>
<radialGradient
xlink:href="#linearGradient5060-8"
id="radialGradient3663"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
cx="605.71429"
cy="486.64789"
fx="605.71429"
fy="486.64789"
r="117.14286" />
<radialGradient
xlink:href="#linearGradient5060-8"
id="radialGradient4227"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
cx="605.71429"
cy="486.64789"
fx="605.71429"
fy="486.64789"
r="117.14286" />
<radialGradient
gradientTransform="matrix(0.35714269,0.7142857,-1.3537553,0.6768774,100.50163,-81.878026)"
gradientUnits="userSpaceOnUse"
r="11.846154"
fy="17.566746"
fx="118.58249"
cy="17.566746"
cx="118.58249"
id="radialGradient4005"
xlink:href="#linearGradient3999" />
</defs>
<metadata
id="metadata4">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<dc:creator>
<cc:Agent>
<dc:title>[agryson] Alexander Gryson</dc:title>
</cc:Agent>
</dc:creator>
<dc:source>http://agryson.net</dc:source>
<cc:license
rdf:resource="https://www.gnu.org/copyleft/lesser.html" />
<dc:title>TechDraw_View</dc:title>
<dc:date>2016-01-14</dc:date>
<dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation>
<dc:publisher>
<cc:Agent>
<dc:title>FreeCAD</dc:title>
</cc:Agent>
</dc:publisher>
<dc:identifier>FreeCAD/src/Mod/TechDraw/Gui/Resources/icons/actions/TechDraw_View.svg</dc:identifier>
<dc:rights>
<cc:Agent>
<dc:title>FreeCAD LGPL2+</dc:title>
</cc:Agent>
</dc:rights>
<dc:contributor>
<cc:Agent>
<dc:title>[agryson] Alexander Gryson</dc:title>
</cc:Agent>
</dc:contributor>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
<cc:permits
rdf:resource="http://web.resource.org/cc/Reproduction" />
<cc:permits
rdf:resource="http://web.resource.org/cc/Distribution" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Notice" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Attribution" />
<cc:permits
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
<cc:requires
rdf:resource="http://web.resource.org/cc/ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
transform="translate(0,16)"
style="display:inline"
id="layer4" />
<g
id="g5194">
<g
transform="translate(1.0000002)"
id="g9787">
<g
id="g5200"
transform="matrix(0.83344344,1.4435664,-1.4435664,0.83344344,27.489822,-46.272055)">
<g
id="g5186">
<path
transform="matrix(1.2727273,0,0,1.2727273,-115.54545,-3.7272729)"
d="m 134,21 a 11,11 0 0 1 -8.9962,10.81595 11,11 0 0 1 -12.27376,-6.8754 11,11 0 0 1 4.52453,-13.320849 L 123,21 Z"
id="path3211"
style="fill:url(#radialGradient4005);fill-opacity:1;stroke:#042a2a;stroke-width:1.57142854;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4.07999992;stroke-opacity:1" />
<path
transform="matrix(1.090909,0,0,1.0909091,-93.181808,0.090909)"
d="M 134,21 A 11,11 0 0 1 125.00406,31.815903 11,11 0 0 1 112.73023,24.941037 11,11 0 0 1 117.2539,11.62011 L 123,21 Z"
id="path3211-1"
style="fill:none;stroke:#34e0e2;stroke-width:1.83333313;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4.07999992;stroke-opacity:1" />
</g>
<path
style="fill:none;stroke:#042a2a;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 35.152416,10.111524 42.230483,21.41264 55.018587,21.35316"
id="path5188" />
</g>
<g
id="g9774"
transform="translate(-2)">
<path
style="fill:#babdb6;stroke:#042a2a;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 44.883046,58.135162 4.044609,-3.211896 v 6.185873 z"
id="path9722" />
<g
id="g9767">
<path
style="fill:none;stroke:#042a2a;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 49.165573,5.9715929 h 9.873606 V 58.194641 h -9.992565"
id="path9698" />
<path
style="fill:#babdb6;stroke:#042a2a;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 45.120964,6.1500317 49.165573,2.9381358 V 9.1240094 Z"
id="path9720" />
<path
style="fill:none;stroke:#babdb6;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 46.905351,5.9715929 H 59.03918 V 58.194641 H 47.381187"
id="path9696" />
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -0,0 +1,360 @@
/***************************************************************************
* Copyright (c) 2022 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"
#ifndef _PreComp_
#endif // #ifndef _PreComp_
#include <QPushButton>
#include <BRep_Tool.hxx>
#include <gp_Pnt.hxx>
#include <App/Document.h>
#include <App/DocumentObject.h>
#include <App/Link.h>
#include <Base/Console.h>
#include <Base/Tools.h>
#include <Base/Quantity.h>
#include <Base/UnitsApi.h>
#include <Gui/Application.h>
#include <Gui/BitmapFactory.h>
#include <Gui/Command.h>
#include <Gui/Control.h>
#include <Gui/Document.h>
#include <Gui/MainWindow.h>
#include <Gui/Selection.h>
#include <Gui/ViewProvider.h>
#include <Gui/WaitCursor.h>
#include <Mod/TechDraw/App/DrawPage.h>
#include <Mod/TechDraw/App/DrawUtil.h>
#include <Mod/TechDraw/App/DrawView.h>
#include <Mod/TechDraw/App/DrawViewPart.h>
#include <Mod/TechDraw/App/DrawComplexSection.h>
#include <Mod/TechDraw/App/Preferences.h>
#include <Mod/TechDraw/Gui/ui_TaskComplexSection.h>
#include "DrawGuiUtil.h"
#include "TaskComplexSection.h"
using namespace Gui;
using namespace TechDraw;
using namespace TechDrawGui;
TaskComplexSection::TaskComplexSection(TechDraw::DrawPage* page,
TechDraw::DrawViewPart* baseView,
std::vector<App::DocumentObject*> shapes,
std::vector<App::DocumentObject*> xShapes,
App::DocumentObject* profileObject,
std::vector<std::string> profileSubs) :
ui(new Ui_TaskComplexSection),
m_page(page),
m_baseView(baseView),
m_section(nullptr),
m_shapes(shapes),
m_xShapes(xShapes),
m_profileObject(profileObject),
m_profileSubs(profileSubs),
m_sectionName(std::string())
{
ui->setupUi(this);
setUiPrimary();
connect(ui->pbSectionObjects, SIGNAL(clicked()), this, SLOT(onSectionObjectsUseSelectionClicked()));
connect(ui->pbProfileObject, SIGNAL(clicked()), this, SLOT(onProfileObjectsUseSelectionClicked()));
}
void TaskComplexSection::changeEvent(QEvent* event)
{
if (event->type() == QEvent::LanguageChange) {
ui->retranslateUi(this);
}
}
void TaskComplexSection::setUiPrimary()
{
setWindowTitle(QObject::tr("New Complex Section"));
ui->dsbXNormal->setEnabled(true);
ui->dsbYNormal->setEnabled(true);
ui->dsbZNormal->setEnabled(true);
std::pair<Base::Vector3d, Base::Vector3d> dirs = DrawGuiUtil::get3DDirAndRot();
ui->dsbXNormal->setValue(dirs.first.x);
ui->dsbYNormal->setValue(dirs.first.y);
ui->dsbZNormal->setValue(dirs.first.z);
m_saveXDir = dirs.second;
ui->leSectionObjects->setText(sourcesToString());
ui->leProfileObject->setText(Base::Tools::fromStdString(m_profileObject->getNameInDocument()) +
QString::fromUtf8(" / ") +
Base::Tools::fromStdString(m_profileObject->Label.getValue()));
if (m_baseView) {
ui->dsbScale->setValue(m_baseView->getScale());
ui->cmbScaleType->setCurrentIndex(m_baseView->ScaleType.getValue());
} else {
ui->dsbScale->setValue(Preferences::scale());
ui->cmbScaleType->setCurrentIndex(Preferences::scaleType());
}
}
void TaskComplexSection::onSectionObjectsUseSelectionClicked()
{
std::vector<Gui::SelectionObject> selection = Gui::Selection().getSelectionEx();
std::vector<App::DocumentObject*> newSelection;
std::vector<App::DocumentObject*> newXSelection;
for (auto& sel : selection) {
if (sel.getObject()->isDerivedFrom(App::LinkElement::getClassTypeId()) ||
sel.getObject()->isDerivedFrom(App::LinkGroup::getClassTypeId()) ||
sel.getObject()->isDerivedFrom(App::Link::getClassTypeId()) ) {
newXSelection.push_back(sel.getObject());
} else {
newSelection.push_back(sel.getObject());
}
}
m_shapes = newSelection;
m_xShapes = newXSelection;
ui->leSectionObjects->setText(sourcesToString());
}
void TaskComplexSection::onProfileObjectsUseSelectionClicked()
{
std::vector<Gui::SelectionObject> selection = Gui::Selection().getSelectionEx();
//check for single selection and ability to make profile from selected object
if (!selection.empty()) {
m_profileObject = selection.front().getObject();
ui->leProfileObject->setText(Base::Tools::fromStdString(m_profileObject->getNameInDocument()) +
QString::fromUtf8(" / ") +
Base::Tools::fromStdString(m_profileObject->Label.getValue()));
}
}
QString TaskComplexSection::sourcesToString()
{
QString result;
if (m_baseView) {
for (auto& obj : m_baseView->Source.getValues()) {
result += Base::Tools::fromStdString(obj->getNameInDocument()) +
QString::fromUtf8(" / ") +
Base::Tools::fromStdString(obj->Label.getValue()) +
QString::fromUtf8(", ");
}
for (auto& obj : m_baseView->XSource.getValues()) {
result += Base::Tools::fromStdString(obj->getNameInDocument()) +
QString::fromUtf8(" / ") +
Base::Tools::fromStdString(obj->Label.getValue()) +
QString::fromUtf8(", ");
}
} else {
for (auto& obj : m_shapes) {
result += Base::Tools::fromStdString(obj->getNameInDocument()) +
QString::fromUtf8(" / ") +
Base::Tools::fromStdString(obj->Label.getValue()) +
QString::fromUtf8(", ");
}
for (auto& obj : m_xShapes) {
result += Base::Tools::fromStdString(obj->getNameInDocument()) +
QString::fromUtf8(" / ") +
Base::Tools::fromStdString(obj->Label.getValue()) +
QString::fromUtf8(", ");
}
}
return result;
}
void TaskComplexSection::updateUi()
{
}
//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) {
m_sectionName = m_page->getDocument()->getUniqueObjectName("ComplexSection");
std::string sectionType = "TechDraw::DrawComplexSection";
Command::doCommand(Command::Doc, "App.ActiveDocument.addObject('%s', '%s')",
sectionType.c_str(), m_sectionName.c_str());
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.addView(App.ActiveDocument.%s)",
m_page->getNameInDocument(), m_sectionName.c_str());
QString qTemp = ui->leSymbol->text();
std::string temp = Base::Tools::toStdString(qTemp);
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.SectionSymbol = '%s'",
m_sectionName.c_str(),
temp.c_str());
std::string lblText = "Section " +
temp +
" - " +
temp;
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.Label = '%s'",
m_sectionName.c_str(),
lblText.c_str());
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.Scale = %0.6f",
m_sectionName.c_str(),
ui->dsbScale->value());
int scaleType = ui->cmbScaleType->currentIndex();
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.ScaleType = %d",
m_sectionName.c_str(), scaleType);
int projectionStrategy = ui->cmbStrategy->currentIndex();
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.ProjectionStrategy = %d",
m_sectionName.c_str(), projectionStrategy);
Command::doCommand(Command::Doc, "App.activeDocument().%s.Direction = FreeCAD.Vector(%.3f, %.3f, %.3f)",
m_sectionName.c_str(), ui->dsbXNormal->value(),
ui->dsbYNormal->value(), ui->dsbZNormal->value());
Command::doCommand(Command::Doc, "App.activeDocument().%s.SectionNormal = FreeCAD.Vector(%.3f, %.3f, %.3f)",
m_sectionName.c_str(), ui->dsbXNormal->value(),
ui->dsbYNormal->value(), ui->dsbZNormal->value());
Command::doCommand(Command::Doc, "App.activeDocument().%s.XDirection = FreeCAD.Vector(%.3f, %.3f, %.3f)",
m_sectionName.c_str(), m_saveXDir.x, m_saveXDir.y, m_saveXDir.z);
Command::doCommand(Command::Doc, "App.activeDocument().%s.SectionOrigin = FreeCAD.Vector(0.0, 0.0, 0.0)",
m_sectionName.c_str());
Command::doCommand(Command::Doc, "App.activeDocument().%s.SectionDirection = 'Aligned'",
m_sectionName.c_str());
App::DocumentObject* newObj = m_page->getDocument()->getObject(m_sectionName.c_str());
m_section = dynamic_cast<TechDraw::DrawComplexSection*>(newObj);
if (!newObj || !m_section) {
throw Base::RuntimeError("TaskComplexSection - new section object not found");
}
if (m_baseView) {
m_section->Source.setValues(m_baseView->Source.getValues());
m_section->XSource.setValues(m_baseView->XSource.getValues());
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.BaseView = App.ActiveDocument.%s",
m_sectionName.c_str(), m_baseView->getNameInDocument());
} else {
m_section->Source.setValues(m_shapes);
m_section->XSource.setValues(m_xShapes);
}
m_section->CuttingToolWireObject.setValue(m_profileObject);
}
Gui::Command::commitCommand();
if (m_section) {
m_section->recomputeFeature();
}
return;
}
void TaskComplexSection::saveButtons(QPushButton* btnOK,
QPushButton* btnCancel)
{
m_btnOK = btnOK;
m_btnCancel = btnCancel;
}
void TaskComplexSection::enableTaskButtons(bool button)
{
m_btnOK->setEnabled(button);
m_btnCancel->setEnabled(button);
}
//******************************************************************************
bool TaskComplexSection::accept()
{
Gui::Document* doc = Gui::Application::Instance->getDocument(m_page->getDocument());
if (!doc)
return false;
createComplexSection();
Gui::Command::doCommand(Gui::Command::Gui, "Gui.ActiveDocument.resetEdit()");
return true;
}
bool TaskComplexSection::reject()
{
Gui::Document* doc = Gui::Application::Instance->getDocument(m_page->getDocument());
if (!doc)
return false;
//make sure any dangling objects are cleaned up
Gui::Command::doCommand(Gui::Command::Gui, "App.activeDocument().recompute()");
Gui::Command::doCommand(Gui::Command::Gui, "Gui.ActiveDocument.resetEdit()");
return false;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TaskDlgComplexSection::TaskDlgComplexSection(TechDraw::DrawPage* page,
TechDraw::DrawViewPart *baseView,
std::vector<App::DocumentObject*> shapes,
std::vector<App::DocumentObject*> xShapes,
App::DocumentObject* profileObject,
std::vector<std::string> profileSubs)
: TaskDialog()
{
widget = new TaskComplexSection(page, baseView, shapes, xShapes, profileObject, profileSubs);
taskbox = new Gui::TaskView::TaskBox(Gui::BitmapFactory().pixmap("actions/TechDraw_ComplexSection"),
widget->windowTitle(), true, nullptr);
taskbox->groupLayout()->addWidget(widget);
Content.push_back(taskbox);
}
TaskDlgComplexSection::~TaskDlgComplexSection()
{
}
void TaskDlgComplexSection::update()
{
// widget->updateTask();
}
void TaskDlgComplexSection::modifyStandardButtons(QDialogButtonBox* box)
{
QPushButton* btnOK = box->button(QDialogButtonBox::Ok);
QPushButton* btnCancel = box->button(QDialogButtonBox::Cancel);
widget->saveButtons(btnOK, btnCancel);
}
//==== calls from the TaskView ===============================================================
void TaskDlgComplexSection::open()
{
}
void TaskDlgComplexSection::clicked(int)
{
}
bool TaskDlgComplexSection::accept()
{
widget->accept();
return true;
}
bool TaskDlgComplexSection::reject()
{
widget->reject();
return true;
}
#include <Mod/TechDraw/Gui/moc_TaskComplexSection.cpp>

View File

@@ -0,0 +1,137 @@
/***************************************************************************
* Copyright (c) 2022 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 TECHDRAWGUI_TASKCOMPLEXSECTION_H
#define TECHDRAWGUI_TASKCOMPLEXSECTION_H
#include <Mod/TechDraw/TechDrawGlobal.h>
#include <QString>
#include <Base/Vector3D.h>
#include <Gui/TaskView/TaskDialog.h>
#include <Gui/TaskView/TaskView.h>
namespace App
{
class DocumentObject;
}
namespace TechDraw
{
class DrawPage;
class DrawView;
class DrawViewPart;
class DrawComplexSection;
}
namespace TechDrawGui
{
class Ui_TaskComplexSection;
class TaskComplexSection : public QWidget
{
Q_OBJECT
public:
TaskComplexSection(TechDraw::DrawPage* page,
TechDraw::DrawViewPart* baseView,
std::vector<App::DocumentObject*> shapes,
std::vector<App::DocumentObject*> xShapes,
App::DocumentObject* profileObject,
std::vector<std::string> profileSubs);
~TaskComplexSection() = default;
virtual bool accept();
virtual bool reject();
void saveButtons(QPushButton* btnOK,
QPushButton* btnCancel);
void enableTaskButtons(bool button);
public Q_SLOTS:
void onSectionObjectsUseSelectionClicked();
void onProfileObjectsUseSelectionClicked();
protected:
void changeEvent(QEvent *event) override;
void setUiPrimary();
void updateUi();
private:
void createComplexSection();
QString sourcesToString();
std::unique_ptr<Ui_TaskComplexSection> ui;
TechDraw::DrawPage* m_page;
TechDraw::DrawViewPart* m_baseView;
TechDraw::DrawComplexSection* m_section;
std::vector<App::DocumentObject*> m_shapes;
std::vector<App::DocumentObject*> m_xShapes;
App::DocumentObject* m_profileObject;
std::vector<std::string> m_profileSubs;
std::string m_sectionName;
Base::Vector3d m_saveXDir;
QPushButton* m_btnOK;
QPushButton* m_btnCancel;
};
class TaskDlgComplexSection : public Gui::TaskView::TaskDialog
{
Q_OBJECT
public:
TaskDlgComplexSection(TechDraw::DrawPage* page,
TechDraw::DrawViewPart* baseView,
std::vector<App::DocumentObject*> shapes,
std::vector<App::DocumentObject*> xShapes,
App::DocumentObject* profileObject,
std::vector<std::string> profileSubs);
~TaskDlgComplexSection() override;
public:
/// is called the TaskView when the dialog is opened
void open() override;
/// is called by the framework if an button is clicked which has no accept or reject role
void clicked(int) override;
/// is called by the framework if the dialog is accepted (Ok)
bool accept() override;
/// is called by the framework if the dialog is rejected (Cancel)
bool reject() override;
/// is called by the framework if the user presses the help button
bool isAllowedAlterDocument() const override
{ return false; }
void update();
void modifyStandardButtons(QDialogButtonBox* box) override;
protected:
private:
TaskComplexSection * widget;
Gui::TaskView::TaskBox* taskbox;
};
} //namespace TechDrawGui
#endif // #ifndef TECHDRAWGUI_TASKCOMPLEXSECTION_H

View File

@@ -0,0 +1,296 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TechDrawGui::TaskComplexSection</class>
<widget class="QWidget" name="TechDrawGui::TaskComplexSection">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>370</width>
<height>478</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Complex Section</string>
</property>
<property name="windowIcon">
<iconset resource="Resources/TechDraw.qrc">
<normaloff>:/icons/actions/TechDraw_ComplexSection.svg</normaloff>:/icons/actions/TechDraw_ComplexSection.svg</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Object Selection</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Objects to section</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="pbSectionObjects">
<property name="text">
<string>Use Selection</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Profile object</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="leProfileObject">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="leSectionObjects">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QPushButton" name="pbProfileObject">
<property name="text">
<string>Use Selection</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Section Parameters</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QGridLayout" name="gridLayout_4" columnstretch="1,1">
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Identifier</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="cmbScaleType">
<property name="minimumSize">
<size>
<width>0</width>
<height>26</height>
</size>
</property>
<property name="toolTip">
<string>Scale Page/Auto/Custom</string>
</property>
<item>
<property name="text">
<string>Page</string>
</property>
</item>
<item>
<property name="text">
<string>Automatic</string>
</property>
</item>
<item>
<property name="text">
<string>Custom</string>
</property>
</item>
</widget>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="dsbScale">
<property name="minimumSize">
<size>
<width>0</width>
<height>26</height>
</size>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Scale Type</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Scale</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="leSymbol">
<property name="minimumSize">
<size>
<width>0</width>
<height>26</height>
</size>
</property>
<property name="toolTip">
<string>Identifier for this section</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Projection Strategy</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="cmbStrategy">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>26</height>
</size>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="currentText">
<string>Single</string>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<item>
<property name="text">
<string>Single</string>
</property>
</item>
<item>
<property name="text">
<string>Piecewise</string>
</property>
</item>
<item>
<property name="text">
<string>NoParallel</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Section Normal</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Z</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>X</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Y</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="dsbXNormal">
<property name="minimum">
<double>-2147483647.000000000000000</double>
</property>
<property name="maximum">
<double>2147483647.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="dsbYNormal">
<property name="minimum">
<double>-2147483647.000000000000000</double>
</property>
<property name="maximum">
<double>2147483647.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="dsbZNormal">
<property name="minimum">
<double>-2147483647.000000000000000</double>
</property>
<property name="maximum">
<double>2147483647.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="Resources/TechDraw.qrc"/>
</resources>
<connections/>
</ui>

View File

@@ -76,6 +76,7 @@ ViewProviderViewPart::ViewProviderViewPart()
static const char *group = "Lines";
static const char *dgroup = "Decoration";
static const char *hgroup = "Highlight";
static const char *sgroup = "Section Line";
//default line weights
@@ -104,12 +105,14 @@ ViewProviderViewPart::ViewProviderViewPart()
ADD_PROPERTY_TYPE(CenterScale, (defScale), dgroup, App::Prop_None, "Center mark size adjustment, if enabled");
//properties that affect Section Line
ADD_PROPERTY_TYPE(ShowSectionLine ,(true) ,dgroup, App::Prop_None, "Show/hide section line if applicable");
ADD_PROPERTY_TYPE(ShowSectionLine ,(true) ,sgroup, App::Prop_None, "Show/hide section line if applicable");
SectionLineStyle.setEnums(LineStyleEnums);
ADD_PROPERTY_TYPE(SectionLineStyle, (PreferencesGui::sectionLineStyle()), dgroup, App::Prop_None,
ADD_PROPERTY_TYPE(SectionLineStyle, (PreferencesGui::sectionLineStyle()), sgroup, App::Prop_None,
"Set section line style if applicable");
ADD_PROPERTY_TYPE(SectionLineColor, (prefSectionColor()), dgroup, App::Prop_None,
ADD_PROPERTY_TYPE(SectionLineColor, (prefSectionColor()), sgroup, App::Prop_None,
"Set section line color if applicable");
ADD_PROPERTY_TYPE(SectionLineMarks, (PreferencesGui::sectionLineMarks()), sgroup, App::Prop_None,
"Show marks at direction changes for ComplexSection");
//properties that affect Detail Highlights
HighlightLineStyle.setEnums(LineStyleEnums);
@@ -139,6 +142,7 @@ void ViewProviderViewPart::onChanged(const App::Property* prop)
prop == &(ShowSectionLine) ||
prop == &(SectionLineStyle) ||
prop == &(SectionLineColor) ||
prop == &(SectionLineMarks) ||
prop == &(HighlightLineStyle) ||
prop == &(HighlightLineColor) ||
prop == &(HorizCenterLine) ||

View File

@@ -22,8 +22,8 @@
#ifndef DRAWINGGUI_VIEWPROVIDERVIEWPART_H
#define DRAWINGGUI_VIEWPROVIDERVIEWPART_H
#include <Mod/TechDraw/TechDrawGlobal.h>
#include <Mod/TechDraw/TechDrawGlobal.h>
#include <App/PropertyUnits.h>
@@ -55,6 +55,7 @@ public:
App::PropertyBool ShowSectionLine;
App::PropertyEnumeration SectionLineStyle;
App::PropertyColor SectionLineColor;
App::PropertyBool SectionLineMarks;
App::PropertyEnumeration HighlightLineStyle;
App::PropertyColor HighlightLineColor;
App::PropertyFloat HighlightAdjust;

View File

@@ -189,6 +189,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const
*draw << "TechDraw_ActiveView";
*draw << "TechDraw_ProjectionGroup";
*draw << "TechDraw_SectionView";
*draw << "TechDraw_ComplexSection";
*draw << "TechDraw_DetailView";
*draw << "Separator";
*draw << "TechDraw_DraftView";
@@ -246,6 +247,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
*views << "TechDraw_ActiveView";
*views << "TechDraw_ProjectionGroup";
*views << "TechDraw_SectionView";
*views << "TechDraw_ComplexSection";
*views << "TechDraw_DetailView";
*views << "TechDraw_DraftView";
*views << "TechDraw_ArchView";
@@ -392,6 +394,7 @@ Gui::ToolBarItem* Workbench::setupCommandBars() const
// *views << "TechDraw_NewMulti"; //deprecated
*views << "TechDraw_ProjectionGroup";
*views << "TechDraw_SectionView";
*views << "TechDraw_ComplexSection";
*views << "TechDraw_DetailView";
*views << "TechDraw_DraftView";
*views << "TechDraw_SpreadsheetView";