[TD]implement BrokenView

This commit is contained in:
wandererfan
2024-03-14 21:04:23 -04:00
committed by WandererFan
parent efa3a7e6ef
commit 43fc04309a
31 changed files with 2749 additions and 32 deletions

View File

@@ -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);
}

View File

@@ -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})

View File

@@ -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)
{

View File

@@ -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:

File diff suppressed because it is too large Load Diff

View 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

View 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>

View 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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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();

View File

@@ -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());

View File

@@ -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;

View File

@@ -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>

View File

@@ -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)
{

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);
};
}

View File

@@ -335,6 +335,8 @@ SET(TechDrawGuiView_SRCS
QGIGhostHighlight.h
PathBuilder.cpp
PathBuilder.h
QGIBreakLine.cpp
QGIBreakLine.h
)
SET(TechDrawGuiNav_SRCS

View File

@@ -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;
}
}
}
}

View File

@@ -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));

View File

@@ -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();

View 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;
}

View 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

View File

@@ -47,6 +47,7 @@ QGIMatting: 205
QGTracker: 210
QGILeaderLine: 232
QGIRichAnno: 233
QGIBreakLine: 250
QGMText: 300
QGEPath: 301
QGMarker: 302

View File

@@ -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;

View File

@@ -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);

View File

@@ -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>

View 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

View File

@@ -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";