[TD]implement BrokenView
This commit is contained in:
@@ -61,6 +61,7 @@
|
||||
#include "PropertyCosmeticEdgeList.h"
|
||||
#include "PropertyCosmeticVertexList.h"
|
||||
#include "PropertyGeomFormatList.h"
|
||||
#include "DrawBrokenViewPy.h"
|
||||
|
||||
|
||||
|
||||
@@ -116,6 +117,7 @@ PyMOD_INIT_FUNC(TechDraw)
|
||||
TechDraw::DrawTile ::init();
|
||||
TechDraw::DrawTileWeld ::init();
|
||||
TechDraw::DrawWeldSymbol ::init();
|
||||
TechDraw::DrawBrokenView ::init();
|
||||
|
||||
TechDraw::PropertyGeomFormatList::init();
|
||||
TechDraw::GeomFormat ::init();
|
||||
@@ -145,6 +147,7 @@ PyMOD_INIT_FUNC(TechDraw)
|
||||
TechDraw::DrawTilePython ::init();
|
||||
TechDraw::DrawTileWeldPython ::init();
|
||||
TechDraw::DrawWeldSymbolPython::init();
|
||||
TechDraw::DrawBrokenViewPython::init();
|
||||
|
||||
PyMOD_Return(mod);
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ generate_from_xml(DrawTilePy)
|
||||
generate_from_xml(DrawTileWeldPy)
|
||||
generate_from_xml(DrawWeldSymbolPy)
|
||||
generate_from_xml(CosmeticExtensionPy)
|
||||
generate_from_xml(DrawBrokenViewPy)
|
||||
|
||||
SET(Draw_SRCS
|
||||
DrawPage.cpp
|
||||
@@ -104,10 +105,10 @@ SET(Draw_SRCS
|
||||
DimensionReferences.h
|
||||
DimensionFormatter.cpp
|
||||
DimensionFormatter.h
|
||||
GeometryMatcher.cpp
|
||||
GeometryMatcher.h
|
||||
DimensionAutoCorrect.cpp
|
||||
DimensionAutoCorrect.h
|
||||
GeometryMatcher.cpp
|
||||
GeometryMatcher.h
|
||||
DrawViewBalloon.cpp
|
||||
DrawViewBalloon.h
|
||||
DrawViewSection.cpp
|
||||
@@ -138,7 +139,9 @@ SET(Draw_SRCS
|
||||
DrawWeldSymbol.h
|
||||
FeatureProjection.cpp
|
||||
FeatureProjection.h
|
||||
)
|
||||
DrawBrokenView.cpp
|
||||
DrawBrokenView.h
|
||||
)
|
||||
|
||||
SET(TechDraw_SRCS
|
||||
AppTechDraw.cpp
|
||||
@@ -253,7 +256,9 @@ SET(Python_SRCS
|
||||
DrawWeldSymbolPyImp.cpp
|
||||
CosmeticExtensionPy.xml
|
||||
CosmeticExtensionPyImp.cpp
|
||||
)
|
||||
DrawBrokenViewPy.xml
|
||||
DrawBrokenViewPyImp.cpp
|
||||
)
|
||||
|
||||
SOURCE_GROUP("Mod" FILES ${TechDraw_SRCS})
|
||||
SOURCE_GROUP("Features" FILES ${Draw_SRCS})
|
||||
|
||||
@@ -60,6 +60,15 @@ void pointPair::move(const Base::Vector3d& offset)
|
||||
m_overrideSecond = m_overrideSecond - offset;
|
||||
}
|
||||
|
||||
//move the points by factor
|
||||
void pointPair::scale(double factor)
|
||||
{
|
||||
m_first = m_first * factor;
|
||||
m_second = m_second * factor;
|
||||
m_overrideFirst = m_overrideFirst * factor;
|
||||
m_overrideSecond = m_overrideSecond * factor;
|
||||
}
|
||||
|
||||
// project the points onto the dvp's paper plane.
|
||||
void pointPair::project(const DrawViewPart* dvp)
|
||||
{
|
||||
|
||||
@@ -76,6 +76,7 @@ public:
|
||||
void project(const DrawViewPart* dvp);
|
||||
void mapToPage(const DrawViewPart* dvp);
|
||||
void invertY();
|
||||
void scale(double factor);
|
||||
void dump(const std::string& text) const;
|
||||
|
||||
private:
|
||||
|
||||
1098
src/Mod/TechDraw/App/DrawBrokenView.cpp
Normal file
1098
src/Mod/TechDraw/App/DrawBrokenView.cpp
Normal file
File diff suppressed because it is too large
Load Diff
145
src/Mod/TechDraw/App/DrawBrokenView.h
Normal file
145
src/Mod/TechDraw/App/DrawBrokenView.h
Normal file
@@ -0,0 +1,145 @@
|
||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 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 *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
//! DrawBrokenView produces a view of the Source shapes after a portion of the shapes
|
||||
//! has been removed.
|
||||
|
||||
#ifndef DRAWBROKENVIEW_H_
|
||||
#define DRAWBROKENVIEW_H_
|
||||
|
||||
#include <Mod/TechDraw/TechDrawGlobal.h>
|
||||
|
||||
#include <TopoDS_Shape.hxx>
|
||||
|
||||
#include <Base/Vector3D.h>
|
||||
|
||||
#include "DrawViewPart.h"
|
||||
|
||||
namespace TechDraw
|
||||
{
|
||||
|
||||
struct BreakListEntry {
|
||||
App::DocumentObject* breakObj;
|
||||
double lowLimit; // the value to use for shifting shapes (the low end of the break)
|
||||
double highLimit; // the other end of the break (the high end)
|
||||
double netRemoved; // the removed amount of the break, less the gap size
|
||||
// TODO: can the gap size change during the lifetime of BreakListEntry? if
|
||||
// so, we need to save the gap size @ creation time?
|
||||
};
|
||||
|
||||
using BreakList = std::vector<BreakListEntry>;
|
||||
|
||||
class TechDrawExport DrawBrokenView: public TechDraw::DrawViewPart
|
||||
{
|
||||
PROPERTY_HEADER_WITH_OVERRIDE(TechDraw::DrawBrokenView);
|
||||
|
||||
public:
|
||||
DrawBrokenView();
|
||||
~DrawBrokenView() override;
|
||||
|
||||
App::PropertyLinkList Breaks;
|
||||
App::PropertyLength Gap;
|
||||
|
||||
App::DocumentObjectExecReturn* execute() override;
|
||||
short mustExecute() const override;
|
||||
PyObject *getPyObject(void) override;
|
||||
// void onChanged(const App::Property* prop) override;
|
||||
const char* getViewProviderName() const override
|
||||
{
|
||||
return "TechDrawGui::ViewProviderViewPart";
|
||||
}
|
||||
|
||||
std::pair<Base::Vector3d, Base::Vector3d>
|
||||
breakPointsFromObj(const App::DocumentObject& breakObj) const;
|
||||
std::pair<Base::Vector3d, Base::Vector3d>
|
||||
breakBoundsFromObj(const App::DocumentObject& breakObj) const;
|
||||
Base::Vector3d directionFromObj(const App::DocumentObject& breakObj) const;
|
||||
|
||||
static bool isBreakObject(const App::DocumentObject& breakObj);
|
||||
static bool isBreakObjectSketch(const App::DocumentObject& breakObj);
|
||||
static std::vector<App::DocumentObject*> removeBreakObjects(std::vector<App::DocumentObject*> breaks, std::vector<App::DocumentObject*> shapes);
|
||||
static std::vector<TopoDS_Edge> edgesFromCompound(TopoDS_Shape compound);
|
||||
|
||||
Base::Vector3d mapPoint3dToView(Base::Vector3d point3d) const;
|
||||
Base::Vector3d mapPoint2dFromView(Base::Vector3d point2d) const;
|
||||
|
||||
Base::Vector3d getCompressedCentroid() const;
|
||||
double breaklineLength(const App::DocumentObject& breakObj) const;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
TopoDS_Shape breakShape(const TopoDS_Shape& shapeToBreak) const;
|
||||
TopoDS_Shape compressShape(const TopoDS_Shape& shapeToCompress) const;
|
||||
TopoDS_Shape apply1Break(const App::DocumentObject& breakObj, const TopoDS_Shape& inShape) const;
|
||||
TopoDS_Shape makeHalfSpace(Base::Vector3d point, Base::Vector3d direction, Base::Vector3d pointInSpace) const;
|
||||
std::pair<Base::Vector3d, Base::Vector3d>
|
||||
breakPointsFromSketch(const App::DocumentObject& breakObj) const;
|
||||
std::pair<Base::Vector3d, Base::Vector3d>
|
||||
breakPointsFromEdge(const App::DocumentObject& breakObj) const;
|
||||
std::pair<Base::Vector3d, Base::Vector3d>
|
||||
breakBoundsFromSketch(const App::DocumentObject& breakObj) const;
|
||||
std::pair<Base::Vector3d, Base::Vector3d>
|
||||
breakBoundsFromEdge(const App::DocumentObject& breakObj) const;
|
||||
double removedLengthFromObj(const App::DocumentObject& breakObj) const;
|
||||
double breaklineLengthFromSketch(const App::DocumentObject& breakObj) const;
|
||||
double breaklineLengthFromEdge(const App::DocumentObject& breakObj) const;
|
||||
|
||||
|
||||
bool isVertical(TopoDS_Edge edge, bool projected = false) const;
|
||||
bool isVertical(std::pair<Base::Vector3d, Base::Vector3d>, bool projected = false) const;
|
||||
bool isHorizontal(TopoDS_Edge edge, bool projected = false) const;
|
||||
|
||||
TopoDS_Shape compressHorizontal(const TopoDS_Shape& inShape) const;
|
||||
TopoDS_Shape compressVertical(const TopoDS_Shape& inShape) const;
|
||||
|
||||
static std::vector<double> getPieceUpperLimits(const std::vector<TopoDS_Shape>& pieces, Base::Vector3d direction);
|
||||
|
||||
BreakList makeSortedBreakList(const std::vector<App::DocumentObject*>& breaks, Base::Vector3d direction, bool descend = false) const;
|
||||
BreakList makeSortedBreakListCompressed(const std::vector<App::DocumentObject*>& breaks, Base::Vector3d moveDirection, bool descend = false) const;
|
||||
static std::vector<TopoDS_Shape> getPieces(TopoDS_Shape brokenShape);
|
||||
static BreakList sortBreaks(BreakList& inList, bool descend = false);
|
||||
static bool breakLess(const BreakListEntry& entry0, const BreakListEntry& entry1);
|
||||
|
||||
// double pointToLimit(const Base::Vector3d& inPoint, const Base::Vector3d& direction) const;
|
||||
double shiftAmountShrink(double pointCoord, const BreakList& sortedBreaks) const;
|
||||
double shiftAmountExpand(double pointCoord, const BreakList& sortedBreaks) const;
|
||||
|
||||
void printBreakList(const std::string& text, const BreakList& inBreaks) const;
|
||||
|
||||
std::pair<Base::Vector3d, Base::Vector3d>
|
||||
scalePair(std::pair<Base::Vector3d, Base::Vector3d> inPair) const;
|
||||
Base::Vector3d makePerpendicular(Base::Vector3d inDir) const;
|
||||
|
||||
Base::Vector3d m_unbrokenCenter;
|
||||
TopoDS_Shape m_compressedShape;
|
||||
|
||||
};
|
||||
|
||||
using DrawBrokenViewPython = App::FeaturePythonT<DrawBrokenView>;
|
||||
|
||||
}//namespace TechDraw
|
||||
|
||||
#endif
|
||||
|
||||
33
src/Mod/TechDraw/App/DrawBrokenViewPy.xml
Normal file
33
src/Mod/TechDraw/App/DrawBrokenViewPy.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
|
||||
<PythonExport
|
||||
Father="DrawViewPartPy"
|
||||
Name="DrawBrokenViewPy"
|
||||
Twin="DrawBrokenView"
|
||||
TwinPointer="DrawBrokenView"
|
||||
Include="Mod/TechDraw/App/DrawBrokenView.h"
|
||||
Namespace="TechDraw"
|
||||
FatherInclude="Mod/TechDraw/App/DrawViewPartPy.h"
|
||||
FatherNamespace="TechDraw">
|
||||
<Documentation>
|
||||
<Author Licence="LGPL" Name="WandererFan" EMail="wandererfan@gmail.com" />
|
||||
<UserDocu>Feature for creating and manipulating Technical Drawing broken views</UserDocu>
|
||||
</Documentation>
|
||||
<Methode Name="mapPoint3dToView">
|
||||
<Documentation>
|
||||
<UserDocu>point2d = mapPoint3dToView(point3d) - returns the position of the 3d point within the broken view.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="mapPoint2dFromView">
|
||||
<Documentation>
|
||||
<UserDocu>point2d = mapPoint2dFromView(point3d) - returns the position of the 2d point within an unbroken view.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="getCompressedCenter">
|
||||
<Documentation>
|
||||
<UserDocu>point3d = getCompressedCenter() - returns the geometric center of the source shapes after break cuts and gap compression.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<CustomAttributes />
|
||||
</PythonExport>
|
||||
</GenerateModel>
|
||||
93
src/Mod/TechDraw/App/DrawBrokenViewPyImp.cpp
Normal file
93
src/Mod/TechDraw/App/DrawBrokenViewPyImp.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 WandererFan <wandererfan@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Vector3D.h>
|
||||
#include <Base/VectorPy.h>
|
||||
|
||||
#include "DrawBrokenView.h"
|
||||
#include "DrawViewPart.h"
|
||||
// inclusion of the generated files
|
||||
#include <Mod/TechDraw/App/DrawViewPartPy.h>
|
||||
#include <Mod/TechDraw/App/DrawBrokenViewPy.h>
|
||||
#include <Mod/TechDraw/App/DrawBrokenViewPy.cpp>
|
||||
|
||||
|
||||
using namespace TechDraw;
|
||||
|
||||
// returns a string which represents the object e.g. when printed in python
|
||||
std::string DrawBrokenViewPy::representation() const
|
||||
{
|
||||
return std::string("<DrawBrokenView object>");
|
||||
}
|
||||
|
||||
PyObject* DrawBrokenViewPy::mapPoint3dToView(PyObject *args)
|
||||
{
|
||||
PyObject* pPoint3d = nullptr;
|
||||
if (!PyArg_ParseTuple(args, "O!", &(Base::VectorPy::Type), &pPoint3d)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DrawBrokenView* dvp = getDrawBrokenViewPtr();
|
||||
Base::Vector3d point3d = static_cast<Base::VectorPy*>(pPoint3d)->value();
|
||||
Base::Vector3d point2d = dvp->mapPoint3dToView(point3d);
|
||||
|
||||
return new Base::VectorPy(new Base::Vector3d(point2d));
|
||||
}
|
||||
|
||||
PyObject* DrawBrokenViewPy::mapPoint2dFromView(PyObject *args)
|
||||
{
|
||||
PyObject* pPoint2d = nullptr;
|
||||
if (!PyArg_ParseTuple(args, "O!", &(Base::VectorPy::Type), &pPoint2d)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DrawBrokenView* dvp = getDrawBrokenViewPtr();
|
||||
Base::Vector3d pointIn = static_cast<Base::VectorPy*>(pPoint2d)->value();
|
||||
Base::Vector3d pointOut = dvp->mapPoint2dFromView(pointIn);
|
||||
|
||||
return new Base::VectorPy(new Base::Vector3d(pointOut));
|
||||
}
|
||||
|
||||
PyObject* DrawBrokenViewPy::getCompressedCenter(PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, "")) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DrawBrokenView* dvp = getDrawBrokenViewPtr();
|
||||
Base::Vector3d pointOut = dvp->getCompressedCentroid();
|
||||
return new Base::VectorPy(new Base::Vector3d(pointOut));
|
||||
}
|
||||
|
||||
|
||||
PyObject *DrawBrokenViewPy::getCustomAttributes(const char* /*attr*/) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int DrawBrokenViewPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -642,6 +642,7 @@ gp_Vec DrawUtil::closestBasis(gp_Vec inVec)
|
||||
return gp_Vec(togp_Dir(closestBasis(toVector3d(inVec))));
|
||||
}
|
||||
|
||||
//! returns stdX, stdY or stdZ.
|
||||
Base::Vector3d DrawUtil::closestBasis(Base::Vector3d v)
|
||||
{
|
||||
Base::Vector3d result(0.0, -1, 0);
|
||||
@@ -698,6 +699,63 @@ Base::Vector3d DrawUtil::closestBasis(Base::Vector3d v)
|
||||
return Base::Vector3d(1.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
//! returns +/- stdX, stdY or stdZ.
|
||||
Base::Vector3d DrawUtil::closestBasisOriented(Base::Vector3d v)
|
||||
{
|
||||
Base::Vector3d result(0.0, -1, 0);
|
||||
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);
|
||||
|
||||
//first check if already a basis
|
||||
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;
|
||||
angleX = stdX.GetAngle(v);
|
||||
angleY = stdY.GetAngle(v);
|
||||
angleZ = stdZ.GetAngle(v);
|
||||
angleXr = stdXr.GetAngle(v);
|
||||
angleYr = stdYr.GetAngle(v);
|
||||
angleZr = stdZr.GetAngle(v);
|
||||
|
||||
angleMin = std::min({angleX, angleY, angleZ, angleXr, angleYr, angleZr});
|
||||
if (angleX == angleMin) {
|
||||
return Base::Vector3d(1.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
if (angleY == angleMin) {
|
||||
return Base::Vector3d(0.0, 1.0, 0.0);
|
||||
}
|
||||
|
||||
if (angleZ == angleMin) {
|
||||
return Base::Vector3d(0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
if (angleXr == angleMin) {
|
||||
return Base::Vector3d(-1.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
if (angleYr == angleMin) {
|
||||
return Base::Vector3d(0.0, -1.0, 0.0);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -150,6 +150,7 @@ public:
|
||||
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 Base::Vector3d closestBasisOriented(Base::Vector3d v);
|
||||
|
||||
static double getWidthInDirection(gp_Dir direction, TopoDS_Shape& shape);
|
||||
static gp_Vec maskDirection(gp_Vec inVec, gp_Dir directionToMask);
|
||||
|
||||
@@ -74,6 +74,7 @@
|
||||
#include "GeometryMatcher.h"
|
||||
#include "Preferences.h"
|
||||
#include "DimensionAutoCorrect.h"
|
||||
#include "DrawBrokenView.h"
|
||||
|
||||
using namespace TechDraw;
|
||||
using namespace Part;
|
||||
@@ -648,7 +649,21 @@ double DrawViewDimension::getDimValue()
|
||||
return result;
|
||||
}
|
||||
if (Type.isValue("Distance") || Type.isValue("DistanceX") || Type.isValue("DistanceY")) {
|
||||
// linear points are inverted? +Y down? scaled!
|
||||
pointPair pts = getLinearPoints();
|
||||
auto dbv = dynamic_cast<DrawBrokenView*>(getViewPart());
|
||||
if (dbv) {
|
||||
// pts are inverted Y, so we need to un-invert them before mapping
|
||||
// pts are scaled, so we need to unscale them for mapPoint2dFromView
|
||||
// then rescale them for the distance calculation below
|
||||
// centers are right side up
|
||||
pts.invertY();
|
||||
pts.scale(1.0 / getViewPart()->getScale());
|
||||
pts.first(dbv->mapPoint2dFromView(pts.first()));
|
||||
pts.second(dbv->mapPoint2dFromView(pts.second()));
|
||||
pts.invertY();
|
||||
pts.scale(getViewPart()->getScale());
|
||||
}
|
||||
Base::Vector3d dimVec = pts.first() - pts.second();
|
||||
if (Type.isValue("Distance")) {
|
||||
result = dimVec.Length() / getViewPart()->getScale();
|
||||
|
||||
@@ -317,7 +317,7 @@ GeometryObjectPtr DrawViewPart::makeGeometryForShape(TopoDS_Shape& shape)
|
||||
}
|
||||
|
||||
//! Modify a shape by centering, scaling and rotating and return the centered (but not rotated) shape
|
||||
TopoDS_Shape DrawViewPart::centerScaleRotate(DrawViewPart* dvp, TopoDS_Shape& inOutShape,
|
||||
TopoDS_Shape DrawViewPart::centerScaleRotate(const DrawViewPart *dvp, TopoDS_Shape& inOutShape,
|
||||
Base::Vector3d centroid)
|
||||
{
|
||||
// Base::Console().Message("DVP::centerScaleRotate() - %s\n", dvp->getNameInDocument());
|
||||
|
||||
@@ -116,7 +116,7 @@ public:
|
||||
const char* getViewProviderName() const override { return "TechDrawGui::ViewProviderViewPart"; }
|
||||
PyObject* getPyObject() override;
|
||||
|
||||
static TopoDS_Shape centerScaleRotate(DrawViewPart* dvp, TopoDS_Shape& inOutShape,
|
||||
static TopoDS_Shape centerScaleRotate(const DrawViewPart* dvp, TopoDS_Shape& inOutShape,
|
||||
Base::Vector3d centroid);
|
||||
|
||||
std::vector<TechDraw::DrawHatch*> getHatches() const;
|
||||
|
||||
@@ -165,8 +165,12 @@
|
||||
result.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
|
||||
<Methode Name="requestPaint">
|
||||
<Methode Name="getGeometricCenter">
|
||||
<Documentation>
|
||||
<UserDocu>point3d = getGeometricCenter() - returns the geometric center of the source shapes.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="requestPaint">
|
||||
<Documentation>
|
||||
<UserDocu>requestPaint(). Redraw the graphic for this View.</UserDocu>
|
||||
</Documentation>
|
||||
|
||||
@@ -110,6 +110,18 @@ PyObject* DrawViewPartPy::requestPaint(PyObject *args)
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
PyObject* DrawViewPartPy::getGeometricCenter(PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, "")) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DrawViewPart* dvp = getDrawViewPartPtr();
|
||||
Base::Vector3d pointOut = dvp->getCurrentCentroid();
|
||||
return new Base::VectorPy(new Base::Vector3d(pointOut));
|
||||
}
|
||||
|
||||
|
||||
// remove all cosmetics
|
||||
PyObject* DrawViewPartPy::clearCosmeticVertices(PyObject *args)
|
||||
{
|
||||
|
||||
@@ -355,16 +355,9 @@ TopoDS_Shape ShapeExtractor::stripInfiniteShapes(TopoDS_Shape inShape)
|
||||
return TopoDS_Shape(std::move(comp));
|
||||
}
|
||||
|
||||
bool ShapeExtractor::is2dObject(App::DocumentObject* obj)
|
||||
bool ShapeExtractor::is2dObject(const App::DocumentObject* obj)
|
||||
{
|
||||
// TODO:: the check for an object being a sketch should be done as in the commented
|
||||
// if statement below. To do this, we need to include Mod/Sketcher/SketchObject.h,
|
||||
// but that makes TechDraw dependent on Eigen libraries which we don't use. As a
|
||||
// workaround we will inspect the object's class name.
|
||||
// if (obj->isDerivedFrom(Sketcher::SketchObject::getClassTypeId())) {
|
||||
std::string objTypeName = obj->getTypeId().getName();
|
||||
std::string sketcherToken("Sketcher");
|
||||
if (objTypeName.find(sketcherToken) != std::string::npos) {
|
||||
if (isSketchObject(obj)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -375,7 +368,7 @@ bool ShapeExtractor::is2dObject(App::DocumentObject* obj)
|
||||
}
|
||||
|
||||
// just these for now
|
||||
bool ShapeExtractor::isEdgeType(App::DocumentObject* obj)
|
||||
bool ShapeExtractor::isEdgeType(const App::DocumentObject* obj)
|
||||
{
|
||||
bool result = false;
|
||||
Base::Type t = obj->getTypeId();
|
||||
@@ -391,7 +384,7 @@ bool ShapeExtractor::isEdgeType(App::DocumentObject* obj)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ShapeExtractor::isPointType(App::DocumentObject* obj)
|
||||
bool ShapeExtractor::isPointType(const App::DocumentObject* obj)
|
||||
{
|
||||
// Base::Console().Message("SE::isPointType(%s)\n", obj->getNameInDocument());
|
||||
if (obj) {
|
||||
@@ -407,7 +400,7 @@ bool ShapeExtractor::isPointType(App::DocumentObject* obj)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ShapeExtractor::isDraftPoint(App::DocumentObject* obj)
|
||||
bool ShapeExtractor::isDraftPoint(const App::DocumentObject* obj)
|
||||
{
|
||||
// Base::Console().Message("SE::isDraftPoint()\n");
|
||||
//if the docObj doesn't have a Proxy property, it definitely isn't a Draft point
|
||||
@@ -422,7 +415,7 @@ bool ShapeExtractor::isDraftPoint(App::DocumentObject* obj)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ShapeExtractor::isDatumPoint(App::DocumentObject* obj)
|
||||
bool ShapeExtractor::isDatumPoint(const App::DocumentObject* obj)
|
||||
{
|
||||
std::string objTypeName = obj->getTypeId().getName();
|
||||
std::string pointToken("Point");
|
||||
@@ -434,7 +427,7 @@ bool ShapeExtractor::isDatumPoint(App::DocumentObject* obj)
|
||||
|
||||
|
||||
//! get the location of a point object
|
||||
Base::Vector3d ShapeExtractor::getLocation3dFromFeat(App::DocumentObject* obj)
|
||||
Base::Vector3d ShapeExtractor::getLocation3dFromFeat(const App::DocumentObject* obj)
|
||||
{
|
||||
// Base::Console().Message("SE::getLocation3dFromFeat()\n");
|
||||
if (!isPointType(obj)) {
|
||||
@@ -444,7 +437,7 @@ Base::Vector3d ShapeExtractor::getLocation3dFromFeat(App::DocumentObject* obj)
|
||||
// //Draft Points are not necc. Part::PartFeature??
|
||||
// //if Draft option "use part primitives" is not set are Draft points still PartFeature?
|
||||
|
||||
Part::Feature* pf = dynamic_cast<Part::Feature*>(obj);
|
||||
const Part::Feature* pf = dynamic_cast<const Part::Feature*>(obj);
|
||||
if (pf) {
|
||||
Part::TopoShape pts = pf->Shape.getShape();
|
||||
pts.setPlacement(pf->globalPlacement());
|
||||
@@ -471,3 +464,18 @@ TopoDS_Shape ShapeExtractor::getLocatedShape(const App::DocumentObject* docObj)
|
||||
return shape.getShape();
|
||||
}
|
||||
|
||||
bool ShapeExtractor::isSketchObject(const App::DocumentObject* obj)
|
||||
{
|
||||
// TODO:: the check for an object being a sketch should be done as in the commented
|
||||
// if statement below. To do this, we need to include Mod/Sketcher/SketchObject.h,
|
||||
// but that makes TechDraw dependent on Eigen libraries which we don't use. As a
|
||||
// workaround we will inspect the object's class name.
|
||||
// if (obj->isDerivedFrom(Sketcher::SketchObject::getClassTypeId())) {
|
||||
std::string objTypeName = obj->getTypeId().getName();
|
||||
std::string sketcherToken("Sketcher");
|
||||
if (objTypeName.find(sketcherToken) != std::string::npos) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,12 +46,13 @@ public:
|
||||
static TopoDS_Shape getShapesFused(const std::vector<App::DocumentObject*> links);
|
||||
static TopoDS_Shape getShapeFromXLink(const App::Link* xLink);
|
||||
|
||||
static bool is2dObject(App::DocumentObject* obj);
|
||||
static bool isEdgeType(App::DocumentObject* obj);
|
||||
static bool isPointType(App::DocumentObject* obj);
|
||||
static bool isDraftPoint(App::DocumentObject* obj);
|
||||
static bool isDatumPoint(App::DocumentObject* obj);
|
||||
static Base::Vector3d getLocation3dFromFeat(App::DocumentObject *obj);
|
||||
static bool is2dObject(const App::DocumentObject* obj);
|
||||
static bool isEdgeType(const App::DocumentObject* obj);
|
||||
static bool isPointType(const App::DocumentObject* obj);
|
||||
static bool isDraftPoint(const App::DocumentObject* obj);
|
||||
static bool isDatumPoint(const App::DocumentObject* obj);
|
||||
static bool isSketchObject(const App::DocumentObject* obj);
|
||||
static Base::Vector3d getLocation3dFromFeat(const App::DocumentObject *obj);
|
||||
|
||||
static TopoDS_Shape stripInfiniteShapes(TopoDS_Shape inShape);
|
||||
|
||||
|
||||
@@ -63,9 +63,6 @@
|
||||
#include <gp_Vec.hxx>
|
||||
#endif// #ifndef _PreComp_
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
|
||||
#include <Base/Console.h>
|
||||
|
||||
#include "DrawUtil.h"
|
||||
@@ -345,3 +342,20 @@ bool ShapeUtils::isShapeReallyNull(TopoDS_Shape shape)
|
||||
return shape.IsNull() || !TopoDS_Iterator(shape).More();
|
||||
}
|
||||
|
||||
bool ShapeUtils::edgesAreParallel(TopoDS_Edge edge0, TopoDS_Edge edge1)
|
||||
{
|
||||
std::pair<Base::Vector3d, Base::Vector3d> ends0 = getEdgeEnds(edge0);
|
||||
Base::Vector3d vec0 = ends0.second - ends0.first;
|
||||
vec0.Normalize();
|
||||
std::pair<Base::Vector3d, Base::Vector3d> ends1 = getEdgeEnds(edge1);
|
||||
Base::Vector3d vec1 = ends1.second - ends1.first;
|
||||
vec1.Normalize();
|
||||
double dot = fabs(vec0.Dot(vec1));
|
||||
if (DU::fpCompare(dot, 1.0, EWTOLERANCE)) {
|
||||
// parallel vectors
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -108,6 +108,8 @@ public:
|
||||
static std::pair<Base::Vector3d, Base::Vector3d> getEdgeEnds(TopoDS_Edge edge);
|
||||
|
||||
static bool isShapeReallyNull(TopoDS_Shape shape);
|
||||
|
||||
static bool edgesAreParallel(TopoDS_Edge edge0, TopoDS_Edge edge1);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -335,6 +335,8 @@ SET(TechDrawGuiView_SRCS
|
||||
QGIGhostHighlight.h
|
||||
PathBuilder.cpp
|
||||
PathBuilder.h
|
||||
QGIBreakLine.cpp
|
||||
QGIBreakLine.h
|
||||
)
|
||||
|
||||
SET(TechDrawGuiNav_SRCS
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
#include <Mod/TechDraw/App/DrawViewPart.h>
|
||||
#include <Mod/TechDraw/App/DrawViewSymbol.h>
|
||||
#include <Mod/TechDraw/App/Preferences.h>
|
||||
#include <Mod/TechDraw/App/DrawBrokenView.h>
|
||||
|
||||
#include "DrawGuiUtil.h"
|
||||
#include "MDIViewPage.h"
|
||||
@@ -79,6 +80,12 @@
|
||||
|
||||
void execSimpleSection(Gui::Command* cmd);
|
||||
void execComplexSection(Gui::Command* cmd);
|
||||
void getSelectedShapes(Gui::Command* cmd,
|
||||
std::vector<App::DocumentObject*>& shapes,
|
||||
std::vector<App::DocumentObject*>& xShapes,
|
||||
App::DocumentObject* faceObj,
|
||||
std::string& faceName);
|
||||
|
||||
|
||||
class Vertex;
|
||||
using namespace TechDrawGui;
|
||||
@@ -419,6 +426,111 @@ void CmdTechDrawView::activated(int iMsg)
|
||||
|
||||
bool CmdTechDrawView::isActive() { return DrawGuiUtil::needPage(this); }
|
||||
|
||||
//===========================================================================
|
||||
// TechDraw_BrokenView
|
||||
//===========================================================================
|
||||
|
||||
DEF_STD_CMD_A(CmdTechDrawBrokenView)
|
||||
|
||||
CmdTechDrawBrokenView::CmdTechDrawBrokenView()
|
||||
: Command("TechDraw_BrokenView")
|
||||
{
|
||||
sAppModule = "TechDraw";
|
||||
sGroup = QT_TR_NOOP("TechDraw");
|
||||
sMenuText = QT_TR_NOOP("Insert Broken View");
|
||||
sToolTipText = QT_TR_NOOP("Insert Broken View");
|
||||
sWhatsThis = "TechDraw_BrokenView";
|
||||
sStatusTip = sToolTipText;
|
||||
sPixmap = "actions/TechDraw_BrokenView";
|
||||
}
|
||||
|
||||
void CmdTechDrawBrokenView::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
TechDraw::DrawPage* page = DrawGuiUtil::findPage(this);
|
||||
if (!page) {
|
||||
return;
|
||||
}
|
||||
std::string PageName = page->getNameInDocument();
|
||||
|
||||
// get the shape objects from the selection
|
||||
std::vector<App::DocumentObject*> shapes;
|
||||
std::vector<App::DocumentObject*> xShapes;
|
||||
App::DocumentObject* faceObj = nullptr;
|
||||
std::string faceName;
|
||||
getSelectedShapes(this, shapes, xShapes, faceObj, faceName);
|
||||
|
||||
// pick the Break objects out of the selected pile
|
||||
std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx(
|
||||
nullptr, App::DocumentObject::getClassTypeId(), Gui::ResolveMode::NoResolve);
|
||||
std::vector<App::DocumentObject*> breakObjects;
|
||||
for (auto& selObj : selection) {
|
||||
auto temp = selObj.getObject();
|
||||
if (DrawBrokenView::isBreakObject(*temp)) {
|
||||
breakObjects.push_back(selObj.getObject());
|
||||
}
|
||||
}
|
||||
if (breakObjects.empty()) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("No Break objects found in this selection"));
|
||||
return;
|
||||
}
|
||||
|
||||
// remove Break objects from shape pile
|
||||
shapes = DrawBrokenView::removeBreakObjects(breakObjects, shapes);
|
||||
xShapes = DrawBrokenView::removeBreakObjects(breakObjects, xShapes);
|
||||
if (shapes.empty() &&
|
||||
xShapes.empty()) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("No Shapes, Groups or Links in this selection"));
|
||||
return;
|
||||
}
|
||||
|
||||
Gui::WaitCursor wc;
|
||||
openCommand(QT_TRANSLATE_NOOP("Command", "Create broken view"));
|
||||
getDocument()->setStatus(App::Document::Status::SkipRecompute, true);
|
||||
std::string FeatName = getUniqueObjectName("BrokenView");
|
||||
doCommand(Doc, "App.activeDocument().addObject('TechDraw::DrawBrokenView','%s')", FeatName.c_str());
|
||||
doCommand(Doc, "App.activeDocument().%s.addView(App.activeDocument().%s)", PageName.c_str(), FeatName.c_str());
|
||||
|
||||
App::DocumentObject* docObj = getDocument()->getObject(FeatName.c_str());
|
||||
TechDraw::DrawBrokenView* dbv = dynamic_cast<TechDraw::DrawBrokenView*>(docObj);
|
||||
if (!dbv) {
|
||||
throw Base::TypeError("CmdTechDrawBrokenView DBV not found\n");
|
||||
}
|
||||
dbv->Source.setValues(shapes);
|
||||
dbv->XSource.setValues(xShapes);
|
||||
dbv->Breaks.setValues(breakObjects);
|
||||
|
||||
//set projection direction from selected Face
|
||||
std::pair<Base::Vector3d, Base::Vector3d> dirs;
|
||||
if (faceName.size()) {
|
||||
dirs = DrawGuiUtil::getProjDirFromFace(faceObj, faceName);
|
||||
}
|
||||
else {
|
||||
dirs = DrawGuiUtil::get3DDirAndRot();
|
||||
}
|
||||
|
||||
Base::Vector3d projDir = dirs.first;
|
||||
doCommand(Doc, "App.activeDocument().%s.Direction = FreeCAD.Vector(%.3f,%.3f,%.3f)",
|
||||
FeatName.c_str(), projDir.x, projDir.y, projDir.z);
|
||||
doCommand(Doc, "App.activeDocument().%s.XDirection = FreeCAD.Vector(%.3f,%.3f,%.3f)",
|
||||
FeatName.c_str(), dirs.second.x, dirs.second.y, dirs.second.z);
|
||||
getDocument()->setStatus(App::Document::Status::SkipRecompute, true);
|
||||
|
||||
commitCommand();
|
||||
|
||||
// Gui::Control().showDialog(new TaskDlgBrokenView(dbv));
|
||||
|
||||
dbv->recomputeFeature();
|
||||
}
|
||||
|
||||
bool CmdTechDrawBrokenView::isActive(void)
|
||||
{
|
||||
return DrawGuiUtil::needPage(this);
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
// TechDraw_ActiveView
|
||||
//===========================================================================
|
||||
@@ -1680,4 +1792,72 @@ void CreateTechDrawCommands()
|
||||
rcCmdMgr.addCommand(new CmdTechDrawSpreadsheetView());
|
||||
rcCmdMgr.addCommand(new CmdTechDrawBalloon());
|
||||
rcCmdMgr.addCommand(new CmdTechDrawProjectShape());
|
||||
rcCmdMgr.addCommand(new CmdTechDrawBrokenView());
|
||||
|
||||
}
|
||||
|
||||
//****************************************
|
||||
|
||||
|
||||
//! extract the selected shapes and xShapes and determine if a face has been
|
||||
//! selected to define the projection direction
|
||||
void getSelectedShapes(Gui::Command* cmd,
|
||||
std::vector<App::DocumentObject*>& shapes,
|
||||
std::vector<App::DocumentObject*>& xShapes,
|
||||
App::DocumentObject* faceObj,
|
||||
std::string& faceName)
|
||||
{
|
||||
Gui::ResolveMode resolve = Gui::ResolveMode::OldStyleElement;//mystery
|
||||
bool single = false; //mystery
|
||||
auto selection = cmd->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(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() != cmd->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() != cmd->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 is 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.
|
||||
shapes.push_back(obj);
|
||||
if (faceObj) {
|
||||
continue;
|
||||
}
|
||||
//don't know if this works for an XLink
|
||||
for (auto& sub : sel.getSubNames()) {
|
||||
if (TechDraw::DrawUtil::getGeomTypeFromName(sub) == "Face") {
|
||||
faceName = sub;
|
||||
//
|
||||
faceObj = obj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,6 +96,21 @@ QColor PreferencesGui::sectionLineQColor()
|
||||
return fcColor.asValue<QColor>();
|
||||
}
|
||||
|
||||
App::Color PreferencesGui::breaklineColor()
|
||||
{
|
||||
App::Color fcColor;
|
||||
fcColor.setPackedValue(Preferences::getPreferenceGroup("Decorations")->GetUnsigned("BreaklineColor", 0x000000FF));
|
||||
return fcColor;
|
||||
}
|
||||
|
||||
QColor PreferencesGui::breaklineQColor()
|
||||
{
|
||||
//if the App::Color version has already lightened the color, we don't want to do it again
|
||||
App::Color fcColor;
|
||||
fcColor.setPackedValue(Preferences::getPreferenceGroup("Decorations")->GetUnsigned("BreaklineColor", 0x000000FF));
|
||||
return fcColor.asValue<QColor>();
|
||||
}
|
||||
|
||||
App::Color PreferencesGui::centerColor()
|
||||
{
|
||||
return App::Color((uint32_t) Preferences::getPreferenceGroup("Decorations")->GetUnsigned("CenterColor", 0x000000FF));
|
||||
|
||||
@@ -27,6 +27,14 @@
|
||||
|
||||
#include <QColor>
|
||||
|
||||
class QColor;
|
||||
class QString;
|
||||
|
||||
namespace App
|
||||
{
|
||||
class Color;
|
||||
}
|
||||
|
||||
class QFont;
|
||||
class QString;
|
||||
|
||||
@@ -57,6 +65,8 @@ static App::Color dimColor();
|
||||
static QColor dimQColor();
|
||||
static App::Color pageColor();
|
||||
static QColor pageQColor();
|
||||
static App::Color breaklineColor();
|
||||
static QColor breaklineQColor();
|
||||
|
||||
static int dimArrowStyle();
|
||||
static double dimArrowSize();
|
||||
|
||||
213
src/Mod/TechDraw/Gui/QGIBreakLine.cpp
Normal file
213
src/Mod/TechDraw/Gui/QGIBreakLine.cpp
Normal file
@@ -0,0 +1,213 @@
|
||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 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_
|
||||
# include <QGraphicsScene>
|
||||
# include <QPainter>
|
||||
# include <QPainterPath>
|
||||
# include <QStyleOptionGraphicsItem>
|
||||
#endif
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Parameter.h>
|
||||
#include <Base/Tools.h>
|
||||
|
||||
#include <Mod/TechDraw/App/Preferences.h>
|
||||
#include <Mod/TechDraw/App/DrawUtil.h>
|
||||
|
||||
#include "QGIBreakLine.h"
|
||||
#include "PreferencesGui.h"
|
||||
|
||||
using namespace TechDrawGui;
|
||||
using namespace TechDraw;
|
||||
|
||||
using DU = DrawUtil;
|
||||
|
||||
constexpr double zigzagWidth{30.0};
|
||||
constexpr double segments{8};
|
||||
|
||||
QGIBreakLine::QGIBreakLine()
|
||||
{
|
||||
setFlag(QGraphicsItem::ItemIsSelectable, false);
|
||||
setFlag(QGraphicsItem::ItemIsMovable, false);
|
||||
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
|
||||
|
||||
m_background = new QGraphicsRectItem();
|
||||
addToGroup(m_background);
|
||||
m_line0 = new QGraphicsPathItem();
|
||||
addToGroup(m_line0);
|
||||
m_line1 = new QGraphicsPathItem();
|
||||
addToGroup(m_line1);
|
||||
|
||||
|
||||
setColor(PreferencesGui::sectionLineQColor());
|
||||
|
||||
// setFill(Qt::NoBrush);
|
||||
setFill(Qt::SolidPattern);
|
||||
}
|
||||
|
||||
void QGIBreakLine::draw()
|
||||
{
|
||||
// Base::Console().Message("QGIBL::draw()\n");
|
||||
Base::Vector3d horizontal{1.0, 0.0, 0.0};
|
||||
prepareGeometryChange();
|
||||
if (m_direction.IsEqual(horizontal, EWTOLERANCE)) {
|
||||
// m_direction connects the two cut points. The zigzags have
|
||||
// to be perpendicular to m_direction
|
||||
// 2x vertical zigzag from upper to lower
|
||||
Base::Vector3d start = Base::Vector3d(m_left, m_bottom, 0.0);
|
||||
m_line0->setPath(makeVerticalZigZag(start));
|
||||
|
||||
start = Base::Vector3d(m_right - zigzagWidth, m_bottom, 0.0);
|
||||
m_line1->setPath(makeVerticalZigZag(start));
|
||||
} else {
|
||||
// m_top is lower than m_bottom due to Qt Y+ down coords
|
||||
// the higher break line
|
||||
// 2x horizontal zigszg from left to right
|
||||
Base::Vector3d start = Base::Vector3d(m_left, m_bottom, 0.0);
|
||||
m_line0->setPath(makeHorizontalZigZag(start));
|
||||
|
||||
// the lower break line
|
||||
start = Base::Vector3d(m_left, m_top - zigzagWidth, 0.0);
|
||||
m_line1->setPath(makeHorizontalZigZag(start));
|
||||
}
|
||||
|
||||
QRectF backgroundRect(m_left, m_bottom, std::fabs(m_right - m_left), std::fabs(m_top - m_bottom));
|
||||
m_background->setRect(backgroundRect);
|
||||
|
||||
m_line0->show();
|
||||
m_line1->show();
|
||||
m_background->show();
|
||||
update();
|
||||
}
|
||||
|
||||
// start needs to be Rez'd and +Y up
|
||||
QPainterPath QGIBreakLine::makeHorizontalZigZag(Base::Vector3d start) const
|
||||
{
|
||||
// Base::Console().Message("QGIBL::makeHorizontalZigZag(%s)\n", DU::formatVector(start).c_str());
|
||||
QPainterPath pPath;
|
||||
double step = (m_right - m_left) / segments;
|
||||
Base::Vector3d xOffset = Base::Vector3d(step, 0.0, 0.0); // 1/2 wave length
|
||||
Base::Vector3d yOffset = Base::Vector3d(0.0, zigzagWidth, 0.0); // amplitude
|
||||
|
||||
pPath.moveTo(DU::toQPointF(start));
|
||||
Base::Vector3d current = start;
|
||||
int iSegment = 0;
|
||||
double flipflop = 1.0;
|
||||
for (; iSegment < segments; iSegment++) {
|
||||
current = current + xOffset;
|
||||
current = current + yOffset * flipflop;
|
||||
pPath.lineTo(DU::toQPointF(current));
|
||||
flipflop *= -1.0;
|
||||
}
|
||||
return pPath;
|
||||
}
|
||||
|
||||
QPainterPath QGIBreakLine::makeVerticalZigZag(Base::Vector3d start) const
|
||||
{
|
||||
// Base::Console().Message("QGIBL::makeVerticalZigZag(%s)\n", DU::formatVector(start).c_str());
|
||||
QPainterPath pPath;
|
||||
double step = (m_top - m_bottom) / segments;
|
||||
Base::Vector3d xOffset = Base::Vector3d(zigzagWidth, 0.0, 0.0); // amplitude
|
||||
Base::Vector3d yOffset = Base::Vector3d(0.0, step, 0.0); // 1/2 wave length
|
||||
|
||||
pPath.moveTo(DU::toQPointF(start));
|
||||
Base::Vector3d current = start;
|
||||
int iSegment = 0;
|
||||
double flipflop = 1.0;
|
||||
for (; iSegment < segments; iSegment++) {
|
||||
current = current + xOffset * flipflop;
|
||||
current = current + yOffset;
|
||||
pPath.lineTo(DU::toQPointF(current));
|
||||
flipflop *= -1.0;
|
||||
}
|
||||
return pPath;
|
||||
}
|
||||
|
||||
void QGIBreakLine::setBounds(double left, double top, double right, double bottom)
|
||||
{
|
||||
// Base::Console().Message("QGIBL::setBounds(%.3f, %.3f, %.3f, %.3f\n", left, top, right, bottom);
|
||||
m_left = left;
|
||||
m_right = right;
|
||||
m_top = top;
|
||||
m_bottom = bottom;
|
||||
}
|
||||
|
||||
void QGIBreakLine::setBounds(Base::Vector3d topLeft, Base::Vector3d bottomRight)
|
||||
{
|
||||
double left = std::min(topLeft.x, bottomRight.x);
|
||||
double right = std::max(topLeft.x, bottomRight.x);
|
||||
double bottom = std::min(topLeft.y, bottomRight.y);
|
||||
double top = std::max(topLeft.y, bottomRight.y);
|
||||
|
||||
setBounds(left, top, right, bottom);
|
||||
}
|
||||
|
||||
void QGIBreakLine::setDirection(Base::Vector3d dir)
|
||||
{
|
||||
m_direction = dir;
|
||||
}
|
||||
|
||||
|
||||
void QGIBreakLine::setBreakColor(QColor c)
|
||||
{
|
||||
setColor(c);
|
||||
}
|
||||
|
||||
void QGIBreakLine::paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) {
|
||||
QStyleOptionGraphicsItem myOption(*option);
|
||||
myOption.state &= ~QStyle::State_Selected;
|
||||
|
||||
setTools();
|
||||
|
||||
// painter->setPen(Qt::blue);
|
||||
// painter->drawRect(boundingRect()); //good for debugging
|
||||
|
||||
QGIDecoration::paint (painter, &myOption, widget);
|
||||
}
|
||||
|
||||
void QGIBreakLine::setTools()
|
||||
{
|
||||
m_pen.setWidthF(m_width);
|
||||
m_pen.setColor(m_colCurrent);
|
||||
m_brush.setStyle(m_brushCurrent);
|
||||
m_brush.setColor(PreferencesGui::pageQColor());
|
||||
|
||||
m_line0->setPen(m_pen);
|
||||
m_line0->setBrush(Qt::NoBrush);
|
||||
m_line1->setPen(m_pen);
|
||||
m_line1->setBrush(Qt::NoBrush);
|
||||
|
||||
m_background->setBrush(m_brush);
|
||||
m_background->setPen(Qt::NoPen);
|
||||
}
|
||||
|
||||
|
||||
void QGIBreakLine::setLinePen(QPen isoPen)
|
||||
{
|
||||
m_pen = isoPen;
|
||||
}
|
||||
|
||||
84
src/Mod/TechDraw/Gui/QGIBreakLine.h
Normal file
84
src/Mod/TechDraw/Gui/QGIBreakLine.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 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_QGIBREAKLINE_H
|
||||
#define TECHDRAWGUI_QGIBREAKLINE_H
|
||||
|
||||
#include <Mod/TechDraw/TechDrawGlobal.h>
|
||||
|
||||
#include <QColor>
|
||||
#include <QFont>
|
||||
#include <QPainterPath>
|
||||
#include <QPointF>
|
||||
|
||||
#include <Base/Vector3D.h>
|
||||
#include <Mod/TechDraw/App/DrawBrokenView.h>
|
||||
|
||||
#include "QGCustomText.h"
|
||||
#include "QGIDecoration.h"
|
||||
|
||||
|
||||
namespace TechDrawGui
|
||||
{
|
||||
|
||||
class TechDrawGuiExport QGIBreakLine : public QGIDecoration
|
||||
{
|
||||
public:
|
||||
explicit QGIBreakLine();
|
||||
~QGIBreakLine() override = default;
|
||||
|
||||
enum {Type = QGraphicsItem::UserType + 250};
|
||||
int type() const override { return Type;}
|
||||
|
||||
void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = nullptr ) override;
|
||||
|
||||
void setBounds(double left, double top, double right, double bottom);
|
||||
void setBounds(Base::Vector3d topLeft, Base::Vector3d bottomRight);
|
||||
void setDirection(Base::Vector3d dir); // horizontal(1,0,0) vertical(0,1,0);
|
||||
void draw() override;
|
||||
|
||||
void setLinePen(QPen isoPen);
|
||||
void setBreakColor(QColor c);
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
QPainterPath makeHorizontalZigZag(Base::Vector3d start) const;
|
||||
QPainterPath makeVerticalZigZag(Base::Vector3d start) const;
|
||||
void setTools();
|
||||
|
||||
QGraphicsPathItem* m_line0;
|
||||
QGraphicsPathItem* m_line1;
|
||||
QGraphicsRectItem* m_background;
|
||||
|
||||
Base::Vector3d m_direction;
|
||||
|
||||
double m_top;
|
||||
double m_bottom;
|
||||
double m_left;
|
||||
double m_right;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // TECHDRAWGUI_QGIBREAKLINE_H
|
||||
|
||||
@@ -47,6 +47,7 @@ QGIMatting: 205
|
||||
QGTracker: 210
|
||||
QGILeaderLine: 232
|
||||
QGIRichAnno: 233
|
||||
QGIBreakLine: 250
|
||||
QGMText: 300
|
||||
QGEPath: 301
|
||||
QGMarker: 302
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <Mod/TechDraw/App/DrawViewPart.h>
|
||||
#include <Mod/TechDraw/App/DrawViewSection.h>
|
||||
#include <Mod/TechDraw/App/Geometry.h>
|
||||
#include <Mod/TechDraw/App/DrawBrokenView.h>
|
||||
|
||||
#include "DrawGuiUtil.h"
|
||||
#include "MDIViewPage.h"
|
||||
@@ -64,6 +65,7 @@
|
||||
#include "ViewProviderViewPart.h"
|
||||
#include "ZVALUE.h"
|
||||
#include "PathBuilder.h"
|
||||
#include "QGIBreakLine.h"
|
||||
|
||||
using namespace TechDraw;
|
||||
using namespace TechDrawGui;
|
||||
@@ -240,6 +242,7 @@ void QGIViewPart::draw()
|
||||
|
||||
drawViewPart();
|
||||
drawAllHighlights();
|
||||
drawBreakLines();
|
||||
drawMatting();
|
||||
//this is old C/L
|
||||
drawCenterLines(true);//have to draw centerlines after border to get size correct.
|
||||
@@ -1032,6 +1035,48 @@ void QGIViewPart::drawMatting()
|
||||
mat->show();
|
||||
}
|
||||
|
||||
|
||||
//! if this is a broken view, draw the break lines.
|
||||
void QGIViewPart::drawBreakLines()
|
||||
{
|
||||
// Base::Console().Message("QGIVP::drawBreakLines()\n");
|
||||
|
||||
auto dbv = dynamic_cast<TechDraw::DrawBrokenView*>(getViewObject());
|
||||
if (!dbv) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto vp = static_cast<ViewProviderViewPart*>(getViewProvider(getViewObject()));
|
||||
if (!vp) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto breaks = dbv->Breaks.getValues();
|
||||
for (auto& breakObj : breaks) {
|
||||
QGIBreakLine* breakLine = new QGIBreakLine();
|
||||
addToGroup(breakLine);
|
||||
|
||||
Base::Vector3d direction = dbv->directionFromObj(*breakObj);
|
||||
direction.Normalize();
|
||||
breakLine->setDirection(direction);
|
||||
std::pair<Base::Vector3d, Base::Vector3d> bounds = dbv->breakBoundsFromObj(*breakObj);
|
||||
// the bounds are in 3d form, so we need to invert & rez them
|
||||
Base::Vector3d topLeft = Rez::guiX(DU::invertY(bounds.first));
|
||||
Base::Vector3d bottomRight = Rez::guiX(DU::invertY(bounds.second));
|
||||
breakLine->setBounds(topLeft, bottomRight);
|
||||
breakLine->setPos(0.0, 0.0);
|
||||
breakLine->setLinePen(
|
||||
m_dashedLineGenerator->getLinePen(1, vp->HiddenWidth.getValue()));
|
||||
breakLine->setWidth(Rez::guiX(vp->HiddenWidth.getValue()));
|
||||
breakLine->setZValue(ZVALUE::SECTIONLINE);
|
||||
App::Color color = prefBreaklineColor();
|
||||
breakLine->setBreakColor(color.asValue<QColor>());
|
||||
breakLine->setRotation(-dbv->Rotation.getValue());
|
||||
breakLine->draw();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void QGIViewPart::toggleCache(bool state)
|
||||
{
|
||||
QList<QGraphicsItem*> items = childItems();
|
||||
@@ -1158,6 +1203,11 @@ bool QGIViewPart::prefPrintCenters()
|
||||
return printCenters;
|
||||
}
|
||||
|
||||
App::Color QGIViewPart::prefBreaklineColor()
|
||||
{
|
||||
return Preferences::getAccessibleColor(PreferencesGui::breaklineColor());
|
||||
}
|
||||
|
||||
QGraphicsItem *QGIViewPart::getQGISubItemByName(const std::string &subName) const
|
||||
{
|
||||
int scanType = 0;
|
||||
|
||||
@@ -33,6 +33,11 @@
|
||||
|
||||
#include "QGIView.h"
|
||||
|
||||
class QColor;
|
||||
|
||||
namespace App {
|
||||
class Color;
|
||||
}
|
||||
|
||||
namespace TechDraw {
|
||||
class DrawViewPart;
|
||||
@@ -86,6 +91,7 @@ public:
|
||||
virtual void drawAllHighlights();
|
||||
virtual void drawHighlight(TechDraw::DrawViewDetail* viewDetail, bool b);
|
||||
virtual void drawMatting();
|
||||
virtual void drawBreakLines();
|
||||
bool showSection;
|
||||
|
||||
void draw() override;
|
||||
@@ -132,6 +138,7 @@ protected:
|
||||
void removeDecorations();
|
||||
bool prefFaceEdges();
|
||||
bool prefPrintCenters();
|
||||
App::Color prefBreaklineColor();
|
||||
|
||||
bool formatGeomFromCosmetic(std::string cTag, QGIEdge* item);
|
||||
bool formatGeomFromCenterLine(std::string cTag, QGIEdge* item);
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
<file>icons/actions/TechDraw_SurfaceFinishSymbols.svg</file>
|
||||
<file>icons/actions/TechDraw_ComplexSection.svg</file>
|
||||
<file>icons/actions/TechDraw_CosmeticCircle.svg</file>
|
||||
<file>icons/actions/TechDraw_BrokenView.svg</file>
|
||||
<file>icons/arrow-ccw.svg</file>
|
||||
<file>icons/arrow-cw.svg</file>
|
||||
<file>icons/arrow-down.svg</file>
|
||||
|
||||
@@ -0,0 +1,650 @@
|
||||
<?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">
|
||||
<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>
|
||||
<linearGradient
|
||||
gradientTransform="matrix(1.0625,0,0,1.1065089,-87.687497,0.78106561)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="30"
|
||||
x2="115"
|
||||
y1="43"
|
||||
x1="121"
|
||||
id="linearGradient4027"
|
||||
xlink:href="#linearGradient4029" />
|
||||
<linearGradient
|
||||
id="linearGradient4029">
|
||||
<stop
|
||||
style="stop-color:#06989a;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop4031" />
|
||||
<stop
|
||||
style="stop-color:#16d0d2;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop4033" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientTransform="matrix(1.0625,0,0,1.1065089,-87.687497,0.78106561)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="30"
|
||||
x2="99"
|
||||
y1="45.629101"
|
||||
x1="102.22456"
|
||||
id="linearGradient4001"
|
||||
xlink:href="#linearGradient3995" />
|
||||
<linearGradient
|
||||
id="linearGradient3995">
|
||||
<stop
|
||||
id="stop3997"
|
||||
offset="0"
|
||||
style="stop-color:#16d0d2;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop3999"
|
||||
offset="1"
|
||||
style="stop-color:#34e0e2;stop-opacity:1" />
|
||||
</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" />
|
||||
</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="g1216">
|
||||
<g
|
||||
id="g1164"
|
||||
transform="matrix(1.5,0,0,1.5,-7.0000008,-24.999981)">
|
||||
<path
|
||||
id="path3185"
|
||||
d="M 9,49.769231 V 28.846153 l 18.307692,5.230771 V 55 Z"
|
||||
style="fill:url(#linearGradient4001);fill-opacity:1;stroke:#042a2a;stroke-width:1.99999988;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
|
||||
<path
|
||||
id="path3973"
|
||||
d="M 9,28.846153 24.692308,21 43.000001,26.230769 27.307692,34.076924 Z"
|
||||
style="fill:#34e0e2;stroke:#042a2a;stroke-width:1.99999988;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
|
||||
<path
|
||||
id="path3975"
|
||||
d="M 27.307692,34.076924 V 55 L 43.000001,47.153847 V 26.230769 Z"
|
||||
style="fill:url(#linearGradient4027);fill-opacity:1;stroke:#042a2a;stroke-width:1.99999988;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
|
||||
<path
|
||||
id="path3185-7"
|
||||
d="M 10.999999,48.247271 V 31.536724 l 14.224332,4.001147 0.0875,16.81772 z"
|
||||
style="fill:none;stroke:#34e0e2;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
id="path3975-4"
|
||||
d="M 29.290031,35.305198 29.27232,51.999998 41,46.247429 40.960479,29.607759 Z"
|
||||
style="fill:none;stroke:#16d0d2;stroke-width:1.99999988;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
</g>
|
||||
<path
|
||||
style="fill:#ffffff;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 18.168282,59.640013 32.150309,47.612463 18.318626,31.826303 32.150309,15.438766 18.168282,3.5615599 H 31.999965 L 45.831653,15.58911 32.300654,31.826303 45.230273,47.311774 31.999965,59.640013 Z"
|
||||
id="path1194" />
|
||||
<g
|
||||
id="g1188"
|
||||
transform="translate(4.0519604,0.42144337)">
|
||||
<g
|
||||
transform="translate(-65.037321,-0.58242377)"
|
||||
id="g1174">
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 79.986197,60.117175 94.158509,47.886276 79.986197,31.966693 93.964368,15.852969 79.792056,4.2044933"
|
||||
id="path1168" />
|
||||
<path
|
||||
id="path1170"
|
||||
d="M 79.986197,60.117175 94.158509,47.886276 79.986197,31.966693 93.964368,15.852969 79.792056,4.2044933"
|
||||
style="fill:none;stroke:#babdb6;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
<g
|
||||
id="g1180"
|
||||
transform="translate(-53.000563,-0.58252127)">
|
||||
<path
|
||||
id="path1176"
|
||||
d="M 79.986197,60.117175 94.158509,47.886276 79.986197,31.966693 93.964368,15.852969 79.792056,4.2044933"
|
||||
style="fill:none;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;stroke:#babdb6;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 79.986197,60.117175 94.158509,47.886276 79.986197,31.966693 93.964368,15.852969 79.792056,4.2044933"
|
||||
id="path1178" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 20 KiB |
@@ -212,6 +212,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const
|
||||
Gui::MenuItem* views = new Gui::MenuItem;
|
||||
views->setCommand("TechDraw Views");
|
||||
*views << "TechDraw_View";
|
||||
*views << "TechDraw_BrokenView";
|
||||
*views << "TechDraw_SectionView";
|
||||
*views << "TechDraw_ComplexSection";
|
||||
*views << "TechDraw_DetailView";
|
||||
@@ -291,6 +292,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
|
||||
Gui::ToolBarItem* views = new Gui::ToolBarItem(root);
|
||||
views->setCommand("TechDraw Views");
|
||||
*views << "TechDraw_View";
|
||||
*views << "TechDraw_BrokenView";
|
||||
*views << "TechDraw_ActiveView";
|
||||
*views << "TechDraw_ProjectionGroup";
|
||||
*views << "TechDraw_SectionGroup";
|
||||
|
||||
Reference in New Issue
Block a user