Merge branch 'FreeCAD:master' into draft_patharray
This commit is contained in:
@@ -147,11 +147,13 @@ void MDIView::onRelabel(Gui::Document *pDoc)
|
||||
// Either with dirty flag ...
|
||||
QRegularExpression rx(QLatin1String("(\\s\\:\\s\\d+\\[\\*\\])$"));
|
||||
QRegularExpressionMatch match;
|
||||
int pos = cap.lastIndexOf(rx, -1, &match);
|
||||
//int pos =
|
||||
cap.lastIndexOf(rx, -1, &match);
|
||||
if (!match.hasMatch()) {
|
||||
// ... or not
|
||||
rx.setPattern(QLatin1String("(\\s\\:\\s\\d+)$"));
|
||||
pos = cap.lastIndexOf(rx, -1, &match);
|
||||
//pos =
|
||||
cap.lastIndexOf(rx, -1, &match);
|
||||
}
|
||||
if (match.hasMatch()) {
|
||||
cap = QString::fromUtf8(pDoc->getDocument()->Label.getValue());
|
||||
|
||||
@@ -24,8 +24,9 @@
|
||||
#include <Base/Interpreter.h>
|
||||
#include <Base/PyObjectBase.h>
|
||||
|
||||
#include "Cosmetic.h"
|
||||
#include "CosmeticExtension.h"
|
||||
#include "Cosmetic.h"
|
||||
#include "DrawComplexSection.h"
|
||||
#include "DrawGeomHatch.h"
|
||||
#include "DrawHatch.h"
|
||||
#include "DrawLeaderLine.h"
|
||||
@@ -37,7 +38,6 @@
|
||||
#include "DrawSVGTemplate.h"
|
||||
#include "DrawTile.h"
|
||||
#include "DrawTileWeld.h"
|
||||
#include "DrawView.h"
|
||||
#include "DrawViewAnnotation.h"
|
||||
#include "DrawViewArch.h"
|
||||
#include "DrawViewBalloon.h"
|
||||
@@ -47,8 +47,8 @@
|
||||
#include "DrawViewDimension.h"
|
||||
#include "DrawViewDimExtent.h"
|
||||
#include "DrawViewDraft.h"
|
||||
#include "DrawView.h"
|
||||
#include "DrawViewImage.h"
|
||||
#include "DrawViewMulti.h"
|
||||
#include "DrawViewPart.h"
|
||||
#include "DrawViewSection.h"
|
||||
#include "DrawViewSpreadsheet.h"
|
||||
@@ -62,6 +62,7 @@
|
||||
#include "PropertyGeomFormatList.h"
|
||||
|
||||
|
||||
|
||||
namespace TechDraw {
|
||||
extern PyObject* initModule();
|
||||
}
|
||||
@@ -90,7 +91,7 @@ PyMOD_INIT_FUNC(TechDraw)
|
||||
TechDraw::DrawViewSpreadsheet ::init();
|
||||
|
||||
TechDraw::DrawViewSection ::init();
|
||||
TechDraw::DrawViewMulti ::init();
|
||||
TechDraw::DrawComplexSection ::init();
|
||||
TechDraw::DrawViewDimension ::init();
|
||||
TechDraw::DrawViewDimExtent ::init();
|
||||
TechDraw::LandmarkDimension ::init();
|
||||
@@ -134,7 +135,8 @@ PyMOD_INIT_FUNC(TechDraw)
|
||||
TechDraw::DrawPagePython ::init();
|
||||
TechDraw::DrawViewPython ::init();
|
||||
TechDraw::DrawViewPartPython ::init();
|
||||
TechDraw::DrawViewMultiPython ::init();
|
||||
TechDraw::DrawViewSectionPython::init();
|
||||
TechDraw::DrawComplexSectionPython ::init();
|
||||
TechDraw::DrawTemplatePython ::init();
|
||||
TechDraw::DrawViewSymbolPython::init();
|
||||
TechDraw::DrawLeaderLinePython::init();
|
||||
|
||||
@@ -75,6 +75,8 @@ generate_from_xml(CosmeticExtensionPy)
|
||||
SET(Draw_SRCS
|
||||
DrawPage.cpp
|
||||
DrawPage.h
|
||||
DrawComplexSection.cpp
|
||||
DrawComplexSection.h
|
||||
DrawView.cpp
|
||||
DrawView.h
|
||||
DrawViewPart.cpp
|
||||
|
||||
1179
src/Mod/TechDraw/App/DrawComplexSection.cpp
Normal file
1179
src/Mod/TechDraw/App/DrawComplexSection.cpp
Normal file
File diff suppressed because it is too large
Load Diff
123
src/Mod/TechDraw/App/DrawComplexSection.h
Normal file
123
src/Mod/TechDraw/App/DrawComplexSection.h
Normal file
@@ -0,0 +1,123 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2022 WandererFan <wandererfan@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef DrawComplexSection_h_
|
||||
#define DrawComplexSection_h_
|
||||
|
||||
#include <Mod/TechDraw/TechDrawGlobal.h>
|
||||
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
|
||||
#include "DrawViewSection.h"
|
||||
|
||||
namespace TechDraw
|
||||
{
|
||||
|
||||
//changes in direction of complex section line
|
||||
class ChangePoint
|
||||
{
|
||||
public:
|
||||
ChangePoint(QPointF location, QPointF preDirection, QPointF postDirection);
|
||||
ChangePoint(gp_Pnt location, gp_Dir preDirection, gp_Dir postDirection);
|
||||
~ChangePoint() = default;
|
||||
|
||||
QPointF getLocation() const { return m_location; }
|
||||
QPointF getPreDirection() const { return m_preDirection; }
|
||||
QPointF getPostDirection() const { return m_postDirection; }
|
||||
void scale(double scaleFactor);
|
||||
|
||||
private:
|
||||
QPointF m_location;
|
||||
QPointF m_preDirection;
|
||||
QPointF m_postDirection;
|
||||
};
|
||||
|
||||
using ChangePointVector = std::vector<ChangePoint>;
|
||||
|
||||
class TechDrawExport DrawComplexSection: public DrawViewSection
|
||||
{
|
||||
PROPERTY_HEADER_WITH_OVERRIDE(Part::DrawComplexSection);
|
||||
|
||||
public:
|
||||
DrawComplexSection();
|
||||
~DrawComplexSection() = default;
|
||||
|
||||
App::PropertyLink CuttingToolWireObject;
|
||||
App::PropertyEnumeration ProjectionStrategy;//Offset or Aligned
|
||||
|
||||
TopoDS_Shape getShapeToCut() override;
|
||||
TopoDS_Shape makeCuttingTool(double dMax) override;
|
||||
gp_Ax2 getCSFromBase(const std::string sectionName) const override;
|
||||
bool isBaseValid() const override;
|
||||
TopoDS_Compound findSectionPlaneIntersections(const TopoDS_Shape &cutShape) override;
|
||||
TopoDS_Shape prepareShape(const TopoDS_Shape &cutShape, double shapeSize) override;
|
||||
TopoDS_Shape getShapeToPrepare() const override;
|
||||
void makeSectionCut(TopoDS_Shape &baseShape) override;
|
||||
TopoDS_Shape getShapeToIntersect() override;
|
||||
gp_Pln getSectionPlane() const override;
|
||||
TopoDS_Compound alignSectionFaces(TopoDS_Shape faceIntersections) override;
|
||||
std::pair<Base::Vector3d, Base::Vector3d> sectionLineEnds() override;
|
||||
|
||||
bool boxesIntersect(TopoDS_Face &face, TopoDS_Shape &shape);
|
||||
TopoDS_Shape shapeShapeIntersect(const TopoDS_Shape &shape0, const TopoDS_Shape &shape1);
|
||||
std::vector<TopoDS_Face> faceShapeIntersect(const TopoDS_Face &face, const TopoDS_Shape &shape);
|
||||
TopoDS_Shape extrudeWireToFace(TopoDS_Wire &wire, gp_Dir extrudeDir, double extrudeDist);
|
||||
TopoDS_Shape makeAlignedPieces(const TopoDS_Shape &rawShape, const TopoDS_Shape &toolFaceShape,
|
||||
double extrudeDistance);
|
||||
TopoDS_Shape distributeAlignedPieces(std::vector<TopoDS_Shape> pieces);
|
||||
TopoDS_Compound singleToolIntersections(const TopoDS_Shape &cutShape);
|
||||
TopoDS_Compound piecewiseToolIntersections(const TopoDS_Shape &cutShape);
|
||||
|
||||
BaseGeomPtrVector makeSectionLineGeometry();
|
||||
std::pair<Base::Vector3d, Base::Vector3d> sectionArrowDirs();
|
||||
TopoDS_Wire makeSectionLineWire();
|
||||
|
||||
TopoDS_Wire makeProfileWire(App::DocumentObject *toolObj);
|
||||
TopoDS_Wire makeNoseToTailWire(TopoDS_Wire inWire);
|
||||
gp_Dir projectProfileWire(TopoDS_Wire profileWire, gp_Ax3 paperCS);
|
||||
ChangePointVector getChangePointsFromSectionLine();
|
||||
|
||||
bool validateProfilePosition(TopoDS_Wire profileWire, gp_Ax2 sectionCS,
|
||||
gp_Dir &gClosestBasis) const;
|
||||
bool showSegment(gp_Dir segmentNormal) const;
|
||||
|
||||
static bool isProfileObject(App::DocumentObject *obj);
|
||||
static bool isMultiSegmentProfile(App::DocumentObject *obj);
|
||||
static bool isLinearProfile(App::DocumentObject *obj);
|
||||
|
||||
private:
|
||||
gp_Dir getFaceNormal(TopoDS_Face &face);
|
||||
|
||||
TopoDS_Shape m_toolFaceShape;
|
||||
TopoDS_Wire m_profileWire;
|
||||
|
||||
static const char *ProjectionStrategyEnums[];
|
||||
};
|
||||
|
||||
using DrawComplexSectionPython = App::FeaturePythonT<DrawComplexSection>;
|
||||
|
||||
}//namespace TechDraw
|
||||
|
||||
#endif
|
||||
@@ -512,6 +512,12 @@ std::vector<TopoDS_Edge> DrawProjectSplit::scrubEdges(const std::vector<TechDraw
|
||||
std::vector<TopoDS_Edge> DrawProjectSplit::scrubEdges(std::vector<TopoDS_Edge>& origEdges,
|
||||
std::vector<TopoDS_Edge> &closedEdges)
|
||||
{
|
||||
if (origEdges.empty()) {
|
||||
//how did this happen? if Scale is zero, all the edges will be zero length,
|
||||
//but Scale property has constraint, so this shouldn't happen!
|
||||
// Base::Console().Message("DPS::scrubEdges(2) - origEdges is empty\n"); //debug
|
||||
return std::vector<TopoDS_Edge>();
|
||||
}
|
||||
//HLR usually delivers overlapping edges. We need to refine edge overlaps
|
||||
//into non-overlapping pieces
|
||||
std::vector<TopoDS_Edge> noOverlaps;
|
||||
|
||||
@@ -23,36 +23,38 @@
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <cmath>
|
||||
# include <cstdlib>
|
||||
# include <cstring>
|
||||
# include <sstream>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
|
||||
# include <boost/regex.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
# include <QChar>
|
||||
# include <QPointF>
|
||||
# include <QString>
|
||||
#include <QChar>
|
||||
#include <QPointF>
|
||||
#include <QString>
|
||||
|
||||
# include <BRep_Builder.hxx>
|
||||
# include <BRep_Tool.hxx>
|
||||
# include <BRepAdaptor_Curve.hxx>
|
||||
# include <BRepAdaptor_Surface.hxx>
|
||||
# include <BRepExtrema_DistShapeShape.hxx>
|
||||
# include <BRepLProp_CLProps.hxx>
|
||||
# include <BRepLProp_CurveTool.hxx>
|
||||
# include <BRepLProp_SLProps.hxx>
|
||||
# include <BRepTools.hxx>
|
||||
# include <GCPnts_AbscissaPoint.hxx>
|
||||
# include <gp_Ax3.hxx>
|
||||
# include <gp_Dir.hxx>
|
||||
# include <gp_Elips.hxx>
|
||||
# include <gp_Pnt.hxx>
|
||||
# include <gp_Vec.hxx>
|
||||
# include <Precision.hxx>
|
||||
# include <TopExp.hxx>
|
||||
# include <TopExp_Explorer.hxx>
|
||||
# include <TopTools_IndexedMapOfShape.hxx>
|
||||
#include <BRepBndLib.hxx>
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <BRepAdaptor_Curve.hxx>
|
||||
#include <BRepAdaptor_Surface.hxx>
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRepExtrema_DistShapeShape.hxx>
|
||||
#include <BRepLProp_CLProps.hxx>
|
||||
#include <BRepLProp_CurveTool.hxx>
|
||||
#include <BRepLProp_SLProps.hxx>
|
||||
#include <BRepTools.hxx>
|
||||
#include <GCPnts_AbscissaPoint.hxx>
|
||||
#include <gp_Ax3.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
#include <gp_Elips.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <TopExp.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopTools_IndexedMapOfShape.hxx>
|
||||
#endif
|
||||
|
||||
#include <App/Application.h>
|
||||
@@ -60,6 +62,7 @@
|
||||
#include <Base/FileInfo.h>
|
||||
#include <Base/Parameter.h>
|
||||
#include <Base/Stream.h>
|
||||
#include <Base/UnitsApi.h>
|
||||
#include <Base/Vector3D.h>
|
||||
|
||||
#include "DrawUtil.h"
|
||||
@@ -348,19 +351,19 @@ Base::Vector3d DrawUtil::vertex2Vector(const TopoDS_Vertex& v)
|
||||
return Base::Vector3d(gp.X(), gp.Y(), gp.Z());
|
||||
}
|
||||
|
||||
//TODO: make formatVector using toVector3d
|
||||
std::string DrawUtil::formatVector(const Base::Vector3d& v)
|
||||
{
|
||||
std::stringstream builder;
|
||||
builder << std::fixed << std::setprecision(3) ;
|
||||
builder << std::fixed << std::setprecision(Base::UnitsApi::getDecimals()) ;
|
||||
builder << " (" << v.x << ", " << v.y << ", " << v.z << ") ";
|
||||
// builder << " (" << setw(6) << v.x << ", " << setw(6) << v.y << ", " << setw(6) << v.z << ") ";
|
||||
return builder.str();
|
||||
}
|
||||
|
||||
std::string DrawUtil::formatVector(const gp_Dir& v)
|
||||
{
|
||||
std::stringstream builder;
|
||||
builder << std::fixed << std::setprecision(3) ;
|
||||
builder << std::fixed << std::setprecision(Base::UnitsApi::getDecimals()) ;
|
||||
builder << " (" << v.X() << ", " << v.Y() << ", " << v.Z() << ") ";
|
||||
return builder.str();
|
||||
}
|
||||
@@ -368,14 +371,14 @@ std::string DrawUtil::formatVector(const gp_Dir& v)
|
||||
std::string DrawUtil::formatVector(const gp_Dir2d& v)
|
||||
{
|
||||
std::stringstream builder;
|
||||
builder << std::fixed << std::setprecision(3) ;
|
||||
builder << std::fixed << std::setprecision(Base::UnitsApi::getDecimals()) ;
|
||||
builder << " (" << v.X() << ", " << v.Y() << ") ";
|
||||
return builder.str();
|
||||
}
|
||||
std::string DrawUtil::formatVector(const gp_Vec& v)
|
||||
{
|
||||
std::stringstream builder;
|
||||
builder << std::fixed << std::setprecision(3) ;
|
||||
builder << std::fixed << std::setprecision(Base::UnitsApi::getDecimals()) ;
|
||||
builder << " (" << v.X() << ", " << v.Y() << ", " << v.Z() << ") ";
|
||||
return builder.str();
|
||||
}
|
||||
@@ -383,7 +386,7 @@ std::string DrawUtil::formatVector(const gp_Vec& v)
|
||||
std::string DrawUtil::formatVector(const gp_Pnt& v)
|
||||
{
|
||||
std::stringstream builder;
|
||||
builder << std::fixed << std::setprecision(3) ;
|
||||
builder << std::fixed << std::setprecision(Base::UnitsApi::getDecimals()) ;
|
||||
builder << " (" << v.X() << ", " << v.Y() << ", " << v.Z() << ") ";
|
||||
return builder.str();
|
||||
}
|
||||
@@ -391,7 +394,7 @@ std::string DrawUtil::formatVector(const gp_Pnt& v)
|
||||
std::string DrawUtil::formatVector(const gp_Pnt2d& v)
|
||||
{
|
||||
std::stringstream builder;
|
||||
builder << std::fixed << std::setprecision(3) ;
|
||||
builder << std::fixed << std::setprecision(Base::UnitsApi::getDecimals()) ;
|
||||
builder << " (" << v.X() << ", " << v.Y() << ") ";
|
||||
return builder.str();
|
||||
}
|
||||
@@ -399,7 +402,7 @@ std::string DrawUtil::formatVector(const gp_Pnt2d& v)
|
||||
std::string DrawUtil::formatVector(const QPointF& v)
|
||||
{
|
||||
std::stringstream builder;
|
||||
builder << std::fixed << std::setprecision(3) ;
|
||||
builder << std::fixed << std::setprecision(Base::UnitsApi::getDecimals()) ;
|
||||
builder << " (" << v.x() << ", " << v.y() << ") ";
|
||||
return builder.str();
|
||||
}
|
||||
@@ -511,6 +514,11 @@ Base::Vector3d DrawUtil::vecRotate(Base::Vector3d vec,
|
||||
return Base::Vector3d(xForm * (vec));
|
||||
}
|
||||
|
||||
gp_Vec DrawUtil::closestBasis(gp_Vec inVec)
|
||||
{
|
||||
return gp_Vec(togp_Dir(closestBasis(toVector3d(inVec))));
|
||||
}
|
||||
|
||||
Base::Vector3d DrawUtil::closestBasis(Base::Vector3d v)
|
||||
{
|
||||
Base::Vector3d result(0.0, -1, 0);
|
||||
@@ -522,11 +530,16 @@ Base::Vector3d DrawUtil::closestBasis(Base::Vector3d v)
|
||||
Base::Vector3d stdZr(0.0, 0.0, -1.0);
|
||||
|
||||
//first check if already a basis
|
||||
if (checkParallel(v, stdZ) ||
|
||||
checkParallel(v, stdY) ||
|
||||
checkParallel(v, stdX)) {
|
||||
if (v.Dot(stdX) == 1.0 ||
|
||||
v.Dot(stdY) == 1.0 ||
|
||||
v.Dot(stdZ) == 1.0) {
|
||||
return v;
|
||||
}
|
||||
if (v.Dot(stdX) == -1.0 ||
|
||||
v.Dot(stdY) == -1.0 ||
|
||||
v.Dot(stdZ) == -1.0) {
|
||||
return -v;
|
||||
}
|
||||
|
||||
//not a basis. find smallest angle with a basis.
|
||||
double angleX, angleY, angleZ, angleXr, angleYr, angleZr, angleMin;
|
||||
@@ -537,23 +550,139 @@ Base::Vector3d DrawUtil::closestBasis(Base::Vector3d v)
|
||||
angleYr = stdYr.GetAngle(v);
|
||||
angleZr = stdZr.GetAngle(v);
|
||||
|
||||
angleMin = angleX;
|
||||
if (angleY < angleMin) {
|
||||
return stdY;
|
||||
angleMin = std::min({angleX, angleY, angleZ, angleXr, angleYr, angleZr});
|
||||
if (angleX == angleMin) {
|
||||
return Base::Vector3d(1.0, 0.0, 0.0);
|
||||
}
|
||||
if (angleZ < angleMin) {
|
||||
return stdZ;
|
||||
|
||||
if (angleY == angleMin) {
|
||||
return Base::Vector3d(0.0, 1.0, 0.0);
|
||||
}
|
||||
if (angleXr < angleMin) {
|
||||
return stdXr;
|
||||
|
||||
if (angleZ == angleMin) {
|
||||
return Base::Vector3d(0.0, 0.0, 1.0);
|
||||
}
|
||||
if (angleYr < angleMin) {
|
||||
return stdYr;
|
||||
|
||||
if (angleXr == angleMin) {
|
||||
return Base::Vector3d(1.0, 0.0, 0.0);
|
||||
}
|
||||
if (angleZr < angleMin) {
|
||||
return stdZr;
|
||||
|
||||
if (angleYr == angleMin) {
|
||||
return Base::Vector3d(0.0, 1.0, 0.0);
|
||||
}
|
||||
return stdX;
|
||||
|
||||
if (angleZr == angleMin) {
|
||||
return Base::Vector3d(0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
//should not get to here
|
||||
return Base::Vector3d(1.0, 0.0, 0.0);
|
||||
|
||||
}
|
||||
|
||||
Base::Vector3d DrawUtil::closestBasis(Base::Vector3d vDir, gp_Ax2 coordSys)
|
||||
{
|
||||
gp_Dir gDir(vDir.x, vDir.y, vDir.z);
|
||||
return closestBasis(gDir, coordSys);
|
||||
}
|
||||
|
||||
Base::Vector3d DrawUtil::closestBasis(gp_Dir gDir, gp_Ax2 coordSys)
|
||||
{
|
||||
gp_Dir xCS = coordSys.XDirection();
|
||||
gp_Dir yCS = coordSys.YDirection();
|
||||
gp_Dir zCS = coordSys.Direction();
|
||||
|
||||
//first check if already a basis
|
||||
if (gDir.Dot(xCS) == 1.0 ||
|
||||
gDir.Dot(yCS) == 1.0 ||
|
||||
gDir.Dot(zCS) == 1.0 ) {
|
||||
//gDir is parallel with a basis
|
||||
return Base::Vector3d( gDir.X(), gDir.Y(), gDir.Z()) ;
|
||||
}
|
||||
|
||||
if (gDir.Dot(xCS.Reversed()) == 1.0 ||
|
||||
gDir.Dot(yCS.Reversed()) == 1.0 ||
|
||||
gDir.Dot(zCS.Reversed()) == 1.0 ) {
|
||||
//gDir is anti-parallel with a basis
|
||||
return Base::Vector3d( -gDir.X(), -gDir.Y(), -gDir.Z());
|
||||
}
|
||||
|
||||
//not a basis. find smallest angle with a basis.
|
||||
double angleX, angleY, angleZ, angleXr, angleYr, angleZr, angleMin;
|
||||
angleX = gDir.Angle(xCS);
|
||||
angleY = gDir.Angle(yCS);
|
||||
angleZ = gDir.Angle(zCS);
|
||||
angleXr = gDir.Angle(xCS.Reversed());
|
||||
angleYr = gDir.Angle(yCS.Reversed());
|
||||
angleZr = gDir.Angle(zCS.Reversed());
|
||||
|
||||
angleMin = std::min({angleX, angleY, angleZ, angleXr, angleYr, angleZr});
|
||||
if (angleX == angleMin) {
|
||||
return Base::Vector3d(xCS.X(), xCS.Y(), xCS.Z());
|
||||
}
|
||||
|
||||
if (angleY == angleMin) {
|
||||
return Base::Vector3d(yCS.X(), yCS.Y(), yCS.Z());
|
||||
}
|
||||
|
||||
if (angleZ == angleMin) {
|
||||
return Base::Vector3d(zCS.X(), zCS.Y(), zCS.Z()) ;
|
||||
}
|
||||
|
||||
if (angleXr == angleMin) {
|
||||
return Base::Vector3d(-xCS.X(), -xCS.Y(), -xCS.Z());
|
||||
}
|
||||
|
||||
if (angleYr == angleMin) {
|
||||
return Base::Vector3d(-yCS.X(), -yCS.Y(), -yCS.Z());
|
||||
}
|
||||
|
||||
if (angleZr == angleMin) {
|
||||
return Base::Vector3d(-zCS.X(), -zCS.Y(), -zCS.Z());
|
||||
}
|
||||
|
||||
//should not get to here
|
||||
return Base::Vector3d(xCS.X(), xCS.Y(), xCS.Z());
|
||||
}
|
||||
|
||||
double DrawUtil::getWidthInDirection(gp_Dir direction, TopoDS_Shape& shape)
|
||||
{
|
||||
Base::Vector3d stdX(1.0, 0.0, 0.0);
|
||||
Base::Vector3d stdY(0.0, 1.0, 0.0);
|
||||
Base::Vector3d stdZ(0.0, 0.0, 1.0);
|
||||
Base::Vector3d stdXr(-1.0, 0.0, 0.0);
|
||||
Base::Vector3d stdYr(0.0, -1.0, 0.0);
|
||||
Base::Vector3d stdZr(0.0, 0.0, -1.0);
|
||||
Base::Vector3d vClosestBasis = closestBasis(toVector3d(direction));
|
||||
|
||||
Bnd_Box shapeBox;
|
||||
shapeBox.SetGap(0.0);
|
||||
BRepBndLib::AddOptimal(shape, shapeBox);
|
||||
double xMin = 0, xMax = 0, yMin = 0, yMax = 0, zMin = 0, zMax = 0;
|
||||
if (shapeBox.IsVoid()) {
|
||||
//this really shouldn't happen here as null shapes should have been caught
|
||||
//long before this
|
||||
Base::Console().Error("DU::getWidthInDirection - shapeBox is void\n");
|
||||
return 0.0;
|
||||
}
|
||||
shapeBox.Get(xMin, yMin, zMin, xMax, yMax, zMax);
|
||||
|
||||
if (vClosestBasis.IsEqual(stdX, EWTOLERANCE) ||
|
||||
vClosestBasis.IsEqual(stdXr, EWTOLERANCE) ) {
|
||||
return xMax - xMin;
|
||||
}
|
||||
|
||||
if (vClosestBasis.IsEqual(stdY, EWTOLERANCE) ||
|
||||
vClosestBasis.IsEqual(stdYr, EWTOLERANCE) ) {
|
||||
return yMax - yMin;
|
||||
}
|
||||
|
||||
if (vClosestBasis.IsEqual(stdZ, EWTOLERANCE) ||
|
||||
vClosestBasis.IsEqual(stdZr, EWTOLERANCE) ) {
|
||||
return zMax - zMin;
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
//based on Function provided by Joe Dowsett, 2014
|
||||
@@ -873,6 +1002,102 @@ void DrawUtil::encodeXmlSpecialChars(std::string& inoutText)
|
||||
inoutText.swap(buffer);
|
||||
}
|
||||
|
||||
//Sort edges into nose to tail order. From Part/App/AppPartPy.cpp. gives back a sequence
|
||||
//of nose to tail edges and a shrunken input sequence of edges (the unconnected left overs)
|
||||
//struct EdgePoints {
|
||||
// gp_Pnt v1, v2;
|
||||
// std::list<TopoDS_Edge>::iterator it;
|
||||
// TopoDS_Edge edge;
|
||||
//};
|
||||
std::list<TopoDS_Edge> DrawUtil::sort_Edges(double tol3d, std::list<TopoDS_Edge>& edges)
|
||||
{
|
||||
tol3d = tol3d * tol3d;
|
||||
std::list<EdgePoints> edge_points;
|
||||
TopExp_Explorer xp;
|
||||
for (std::list<TopoDS_Edge>::iterator it = edges.begin(); it != edges.end(); ++it) {
|
||||
EdgePoints ep;
|
||||
xp.Init(*it,TopAbs_VERTEX);
|
||||
ep.v1 = BRep_Tool::Pnt(TopoDS::Vertex(xp.Current()));
|
||||
xp.Next();
|
||||
ep.v2 = BRep_Tool::Pnt(TopoDS::Vertex(xp.Current()));
|
||||
ep.it = it;
|
||||
ep.edge = *it;
|
||||
edge_points.push_back(ep);
|
||||
}
|
||||
|
||||
if (edge_points.empty())
|
||||
return std::list<TopoDS_Edge>();
|
||||
|
||||
std::list<TopoDS_Edge> sorted;
|
||||
gp_Pnt gpChainFirst, gpChainLast;
|
||||
gpChainFirst = edge_points.front().v1;
|
||||
gpChainLast = edge_points.front().v2;
|
||||
|
||||
sorted.push_back(edge_points.front().edge);
|
||||
edges.erase(edge_points.front().it);
|
||||
edge_points.erase(edge_points.begin());
|
||||
|
||||
while (!edge_points.empty()) {
|
||||
// search for adjacent edge
|
||||
std::list<EdgePoints>::iterator itEdgePoint;
|
||||
for (itEdgePoint = edge_points.begin(); itEdgePoint != edge_points.end(); ++itEdgePoint) {
|
||||
if (itEdgePoint->v1.SquareDistance(gpChainLast) <= tol3d) {
|
||||
//found a connection from end of chain to start of edge
|
||||
gpChainLast = itEdgePoint->v2;
|
||||
sorted.push_back(itEdgePoint->edge);
|
||||
edges.erase(itEdgePoint->it);
|
||||
edge_points.erase(itEdgePoint);
|
||||
itEdgePoint = edge_points.begin();
|
||||
break;
|
||||
}
|
||||
else if (itEdgePoint->v2.SquareDistance(gpChainFirst) <= tol3d) {
|
||||
//found a connection from start of chain to end of edge
|
||||
gpChainFirst = itEdgePoint->v1;
|
||||
sorted.push_front(itEdgePoint->edge);
|
||||
edges.erase(itEdgePoint->it);
|
||||
edge_points.erase(itEdgePoint);
|
||||
itEdgePoint = edge_points.begin();
|
||||
break;
|
||||
}
|
||||
else if (itEdgePoint->v2.SquareDistance(gpChainLast) <= tol3d) {
|
||||
//found a connection from end of chain to end of edge
|
||||
gpChainLast = itEdgePoint->v1;
|
||||
Standard_Real firstParam, lastParam;
|
||||
const Handle(Geom_Curve) & curve = BRep_Tool::Curve(itEdgePoint->edge, firstParam, lastParam);
|
||||
firstParam = curve->ReversedParameter(firstParam);
|
||||
lastParam = curve->ReversedParameter(lastParam);
|
||||
TopoDS_Edge edgeReversed = BRepBuilderAPI_MakeEdge(curve->Reversed(), firstParam, lastParam);
|
||||
sorted.push_back(edgeReversed);
|
||||
edges.erase(itEdgePoint->it);
|
||||
edge_points.erase(itEdgePoint);
|
||||
itEdgePoint = edge_points.begin();
|
||||
break;
|
||||
}
|
||||
else if (itEdgePoint->v1.SquareDistance(gpChainFirst) <= tol3d) {
|
||||
//found a connection from start of chain to start of edge
|
||||
gpChainFirst = itEdgePoint->v2;
|
||||
Standard_Real firstParam, lastParam;
|
||||
const Handle(Geom_Curve) & curve = BRep_Tool::Curve(itEdgePoint->edge, firstParam, lastParam);
|
||||
firstParam = curve->ReversedParameter(firstParam);
|
||||
lastParam = curve->ReversedParameter(lastParam);
|
||||
TopoDS_Edge edgeReversed = BRepBuilderAPI_MakeEdge(curve->Reversed(), firstParam, lastParam);
|
||||
sorted.push_front(edgeReversed);
|
||||
edges.erase(itEdgePoint->it);
|
||||
edge_points.erase(itEdgePoint);
|
||||
itEdgePoint = edge_points.begin();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((itEdgePoint == edge_points.end()) || (gpChainLast.SquareDistance(gpChainFirst) <= tol3d)) {
|
||||
// no adjacent edge found or polyline is closed
|
||||
return sorted;
|
||||
}
|
||||
}
|
||||
|
||||
return sorted;
|
||||
}
|
||||
|
||||
// Supplementary mathematical functions
|
||||
// ====================================
|
||||
|
||||
@@ -1367,7 +1592,7 @@ void DrawUtil::dumpCS3(const char* text,
|
||||
gp_Dir baseX = CS.XDirection();
|
||||
gp_Dir baseY = CS.YDirection();
|
||||
gp_Pnt baseOrg = CS.Location();
|
||||
Base::Console().Message("DU::dumpCSF - %s Loc: %s Axis: %s X: %s Y: %s\n", text,
|
||||
Base::Console().Message("DU::dumpCS3 - %s Loc: %s Axis: %s X: %s Y: %s\n", text,
|
||||
DrawUtil::formatVector(baseOrg).c_str(),
|
||||
DrawUtil::formatVector(baseAxis).c_str(),
|
||||
DrawUtil::formatVector(baseX).c_str(),
|
||||
|
||||
@@ -70,6 +70,13 @@
|
||||
namespace TechDraw
|
||||
{
|
||||
|
||||
//used by sort_Edges
|
||||
struct EdgePoints {
|
||||
gp_Pnt v1, v2;
|
||||
std::list<TopoDS_Edge>::iterator it;
|
||||
TopoDS_Edge edge;
|
||||
};
|
||||
|
||||
/// Convenient utility functions for TechDraw Module
|
||||
class TechDrawExport DrawUtil {
|
||||
public:
|
||||
@@ -122,10 +129,15 @@ class TechDrawExport DrawUtil {
|
||||
double angle,
|
||||
Base::Vector3d axis,
|
||||
Base::Vector3d org = Base::Vector3d(0.0, 0.0, 0.0));
|
||||
|
||||
static Base::Vector3d closestBasis(Base::Vector3d v);
|
||||
static gp_Vec closestBasis(gp_Vec inVec);
|
||||
static Base::Vector3d closestBasis(Base::Vector3d vDir, gp_Ax2 coordSys);
|
||||
static Base::Vector3d closestBasis(gp_Dir gDir, gp_Ax2 coordSys);
|
||||
|
||||
static double getWidthInDirection(gp_Dir direction, TopoDS_Shape& shape);
|
||||
|
||||
static double getDefaultLineWeight(std::string s);
|
||||
/* static Base::Vector3d vector23(const Base::Vector3d& v2) { return Base::Vector3d(v2.x, v2.y, 0.0); }*/
|
||||
/* static Base::Vector3d vector32(const Base::Vector3d& v3) { return Base::Vector3d(v3.x, v3.y); }*/
|
||||
//! is pt between end1 and end2?
|
||||
static bool isBetween(const Base::Vector3d pt, const Base::Vector3d end1, const Base::Vector3d end2);
|
||||
//! find intersection in 2d for 2 lines in point+direction form
|
||||
@@ -133,8 +145,10 @@ class TechDrawExport DrawUtil {
|
||||
Base::Vector3d p2, Base::Vector3d d2);
|
||||
static Base::Vector2d Intersect2d(Base::Vector2d p1, Base::Vector2d d1,
|
||||
Base::Vector2d p2, Base::Vector2d d2);
|
||||
static Base::Vector3d gpPnt2V3(const gp_Pnt gp) { return Base::Vector3d(gp.X(), gp.Y(), gp.Z()); }
|
||||
static gp_Pnt V32gpPnt(const Base::Vector3d v) { return gp_Pnt(v.x, v.y, v.z); }
|
||||
static Base::Vector3d toVector3d(const gp_Pnt gp) { return Base::Vector3d(gp.X(), gp.Y(), gp.Z()); }
|
||||
static Base::Vector3d toVector3d(const gp_Dir gp) { return Base::Vector3d(gp.X(), gp.Y(), gp.Z()); }
|
||||
static gp_Pnt togp_Pnt(const Base::Vector3d v) { return gp_Pnt(v.x, v.y, v.z); }
|
||||
static gp_Dir togp_Dir(const Base::Vector3d v) { return gp_Dir(v.x, v.y, v.z); }
|
||||
static std::string shapeToString(TopoDS_Shape s);
|
||||
static TopoDS_Shape shapeFromString(std::string s);
|
||||
static Base::Vector3d invertY(Base::Vector3d v);
|
||||
@@ -148,7 +162,7 @@ class TechDrawExport DrawUtil {
|
||||
static bool circulation(Base::Vector3d A, Base::Vector3d B, Base::Vector3d C);
|
||||
static int countSubShapes(TopoDS_Shape shape, TopAbs_ShapeEnum subShape);
|
||||
static void encodeXmlSpecialChars(std::string& inoutText);
|
||||
|
||||
static std::list<TopoDS_Edge> sort_Edges(double tol3d, std::list<TopoDS_Edge>& edges);
|
||||
|
||||
// Supplementary mathematical functions
|
||||
static int sgn(double x);
|
||||
|
||||
@@ -118,6 +118,15 @@ void DrawView::onChanged(const App::Property* prop)
|
||||
//Coding note: calling execute, recompute or recomputeFeature inside an onChanged
|
||||
//method can create infinite loops if the called method changes a property. In general
|
||||
//don't do this! There are situations where it is OK, but careful analysis is a must.
|
||||
|
||||
if (prop == &Scale &&
|
||||
Scale.getValue() < Precision::Confusion()) {
|
||||
//this is not supposed to happen since Scale has constraints, but it may
|
||||
//happen during changes made in PropertyEditor?
|
||||
Scale.setValue(1.0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isRestoring()) {
|
||||
App::DocumentObject::onChanged(prop);
|
||||
return;
|
||||
|
||||
@@ -25,29 +25,32 @@
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <sstream>
|
||||
# include <QtConcurrentRun>
|
||||
# include <Bnd_Box.hxx>
|
||||
# include <BRep_Tool.hxx>
|
||||
# include <BRepAlgo_NormalProjection.hxx>
|
||||
# include <BRepBndLib.hxx>
|
||||
# include <BRepBuilderAPI_Copy.hxx>
|
||||
# include <BRepBuilderAPI_MakeFace.hxx>
|
||||
# include <BRepBuilderAPI_MakeWire.hxx>
|
||||
# include <BRepTools.hxx>
|
||||
# include <gp_Ax2.hxx>
|
||||
# include <gp_Dir.hxx>
|
||||
# include <gp_Pln.hxx>
|
||||
# include <gp_Pnt.hxx>
|
||||
# include <HLRAlgo_Projector.hxx>
|
||||
# include <ShapeAnalysis.hxx>
|
||||
# include <TopExp.hxx>
|
||||
# include <TopoDS.hxx>
|
||||
# include <TopoDS_Edge.hxx>
|
||||
# include <TopoDS_Face.hxx>
|
||||
# include <TopoDS_Shape.hxx>
|
||||
# include <TopoDS_Vertex.hxx>
|
||||
# include <TopoDS_Wire.hxx>
|
||||
#include <sstream>
|
||||
#include <QtConcurrentRun>
|
||||
#include <Bnd_Box.hxx>
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <BRepAlgo_NormalProjection.hxx>
|
||||
#include <BRepBndLib.hxx>
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <BRepBuilderAPI_Copy.hxx>
|
||||
#include <BRepBuilderAPI_MakeFace.hxx>
|
||||
#include <BRepBuilderAPI_Transform.hxx>
|
||||
#include <BRepBuilderAPI_MakeWire.hxx>
|
||||
#include <BRepTools.hxx>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
#include <gp_Pln.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <HLRAlgo_Projector.hxx>
|
||||
#include <ShapeAnalysis.hxx>
|
||||
#include <TopExp.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
#include <TopoDS_Vertex.hxx>
|
||||
#include <TopoDS_Wire.hxx>
|
||||
#endif
|
||||
|
||||
#include <App/Application.h>
|
||||
@@ -237,7 +240,7 @@ App::DocumentObjectExecReturn *DrawViewPart::execute(void)
|
||||
|
||||
TopoDS_Shape shape = getSourceShape();
|
||||
if (shape.IsNull()) {
|
||||
Base::Console().Log("DVP::execute - %s - Source shape is Null.\n",
|
||||
Base::Console().Message("DVP::execute - %s - Source shape is Null.\n",
|
||||
getNameInDocument());
|
||||
return DrawView::execute();
|
||||
}
|
||||
@@ -345,7 +348,7 @@ GeometryObject* DrawViewPart::makeGeometryForShape(TopoDS_Shape& shape)
|
||||
}
|
||||
|
||||
//create a geometry object and trigger the HLR process in another thread
|
||||
TechDraw::GeometryObject* DrawViewPart::buildGeometryObject(TopoDS_Shape& shape, gp_Ax2& viewAxis)
|
||||
TechDraw::GeometryObject* DrawViewPart::buildGeometryObject(TopoDS_Shape& shape, const gp_Ax2 &viewAxis)
|
||||
{
|
||||
// Base::Console().Message("DVP::buildGeometryObject() - %s\n", getNameInDocument());
|
||||
showProgressMessage(getNameInDocument(), "is finding hidden lines");
|
||||
@@ -381,11 +384,17 @@ void DrawViewPart::onHlrFinished(void)
|
||||
// Base::Console().Message("DVP::onHlrFinished() - %s\n", getNameInDocument());
|
||||
|
||||
//now that the new GeometryObject is fully populated, we can replace the old one
|
||||
if (geometryObject) {
|
||||
delete geometryObject;
|
||||
if (geometryObject &&
|
||||
m_tempGeometryObject) {
|
||||
delete geometryObject; //remove the old
|
||||
}
|
||||
if (m_tempGeometryObject) {
|
||||
geometryObject = m_tempGeometryObject; //replace with new
|
||||
m_tempGeometryObject = nullptr; //superfluous?
|
||||
}
|
||||
if (!geometryObject) {
|
||||
throw Base::RuntimeError("DrawViewPart has lost its geometry");
|
||||
}
|
||||
geometryObject = m_tempGeometryObject;
|
||||
m_tempGeometryObject = nullptr; //superfluous
|
||||
|
||||
//the last hlr related task is to make a bbox of the results
|
||||
bbox = geometryObject->calcBoundingBox();
|
||||
@@ -468,7 +477,7 @@ void DrawViewPart::extractFaces()
|
||||
geometryObject->getVisibleFaceEdges(SmoothVisible.getValue(),SeamVisible.getValue());
|
||||
|
||||
if (goEdges.empty()) {
|
||||
Base::Console().Message("DVP::extractFaces - %s - no face edges available!\n", getNameInDocument());
|
||||
// Base::Console().Message("DVP::extractFaces - %s - no face edges available!\n", getNameInDocument()); //debug
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -476,6 +485,13 @@ void DrawViewPart::extractFaces()
|
||||
std::vector<TopoDS_Edge> closedEdges;
|
||||
std::vector<TopoDS_Edge> cleanEdges = DrawProjectSplit::scrubEdges(goEdges, closedEdges);
|
||||
|
||||
if (cleanEdges.empty() &&
|
||||
closedEdges.empty()) {
|
||||
//how does this happen? something wrong somewhere
|
||||
// Base::Console().Message("DVP::extractFaces - no clean or closed wires\n"); //debug
|
||||
return;
|
||||
}
|
||||
|
||||
//use EdgeWalker to make wires from edges
|
||||
EdgeWalker eWalker;
|
||||
std::vector<TopoDS_Wire> sortedWires;
|
||||
@@ -861,10 +877,55 @@ QRectF DrawViewPart::getRect() const
|
||||
return result;
|
||||
}
|
||||
|
||||
//returns a compound of all the visible projected edges
|
||||
TopoDS_Shape DrawViewPart::getShape() const
|
||||
{
|
||||
BRep_Builder builder;
|
||||
TopoDS_Compound result;
|
||||
builder.MakeCompound(result);
|
||||
if (geometryObject) {
|
||||
if (!geometryObject->getVisHard().IsNull()) {
|
||||
builder.Add(result, geometryObject->getVisHard());
|
||||
}
|
||||
if (!geometryObject->getVisOutline().IsNull()) {
|
||||
builder.Add(result, geometryObject->getVisOutline());
|
||||
}
|
||||
if (!geometryObject->getVisSeam().IsNull()) {
|
||||
builder.Add(result, geometryObject->getVisSeam());
|
||||
}
|
||||
if (!geometryObject->getVisSmooth().IsNull()) {
|
||||
builder.Add(result, geometryObject->getVisSmooth());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//returns the (unscaled) size of the visible lines along the alignment vector
|
||||
double DrawViewPart::getSizeAlongVector(Base::Vector3d alignmentVector)
|
||||
{
|
||||
gp_Ax3 projectedCS3(getProjectionCS());
|
||||
projectedCS3.SetXDirection(DrawUtil::togp_Dir(alignmentVector));
|
||||
gp_Ax3 stdCS; //OXYZ
|
||||
|
||||
gp_Trsf xPieceAlign;
|
||||
xPieceAlign.SetTransformation(stdCS, projectedCS3);
|
||||
BRepBuilderAPI_Transform mkTransAlign(getShape(), xPieceAlign);
|
||||
TopoDS_Shape shapeAligned = mkTransAlign.Shape();
|
||||
|
||||
Bnd_Box shapeBox;
|
||||
shapeBox.SetGap(0.0);
|
||||
BRepBndLib::AddOptimal(shapeAligned, shapeBox);
|
||||
double xMin = 0, xMax = 0, yMin = 0, yMax = 0, zMin = 0, zMax = 0;
|
||||
shapeBox.Get(xMin, yMin, zMin, xMax, yMax, zMax);
|
||||
double shapeWidth((xMax - xMin) / getScale());
|
||||
return shapeWidth;
|
||||
}
|
||||
|
||||
//used to project a pt (ex SectionOrigin) onto paper plane
|
||||
Base::Vector3d DrawViewPart::projectPoint(const Base::Vector3d& pt, bool invert) const
|
||||
{
|
||||
// Base::Console().Message("DVP::projectPoint()\n");
|
||||
// Base::Console().Message("DVP::projectPoint(%s, %d\n",
|
||||
// DrawUtil::formatVector(pt).c_str(), invert);
|
||||
Base::Vector3d stdOrg(0.0, 0.0, 0.0);
|
||||
gp_Ax2 viewAxis = getProjectionCS(stdOrg);
|
||||
gp_Pnt gPt(pt.x, pt.y, pt.z);
|
||||
@@ -892,8 +953,27 @@ BaseGeomPtr DrawViewPart::projectEdge(const TopoDS_Edge& e) const
|
||||
projector.Add(e);
|
||||
projector.Build();
|
||||
TopoDS_Shape s = projector.Projection();
|
||||
// Base::Console().Message("DVP::projectEdge - s.IsNull: %d\n", s.IsNull());
|
||||
BaseGeomPtr result;
|
||||
return BaseGeom::baseFactory(TopoDS::Edge(s));
|
||||
}
|
||||
|
||||
//simple projection of inWire with conversion of the result to TD geometry
|
||||
BaseGeomPtrVector DrawViewPart::projectWire(const TopoDS_Wire& inWire) const
|
||||
{
|
||||
// Base::Console().Message("DVP::projectWire() - inWire.IsNull: %d\n", inWire.IsNull());
|
||||
BaseGeomPtrVector result;
|
||||
Base::Vector3d stdOrg(0.0, 0.0, 0.0);
|
||||
|
||||
TopoDS_Face paper = BRepBuilderAPI_MakeFace(gp_Pln(getProjectionCS(stdOrg)));
|
||||
BRepAlgo_NormalProjection projector(paper);
|
||||
projector.Add(inWire);
|
||||
projector.Build();
|
||||
BRepTools::Write(projector.Projection(), "DVPprojectedWire.brep"); //debug
|
||||
|
||||
TopExp_Explorer expShape(projector.Projection(), TopAbs_EDGE);
|
||||
for (; expShape.More(); expShape.Next()) {
|
||||
BaseGeomPtr edge = BaseGeom::baseFactory(TopoDS::Edge(expShape.Current()));
|
||||
result.push_back(edge);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -926,6 +1006,27 @@ bool DrawViewPart::hasGeometry(void) const
|
||||
return false;
|
||||
}
|
||||
|
||||
//convert a vector in local XY coords into a coordinate sytem in global
|
||||
//coordinates aligned to the vector.
|
||||
//Note that this CS may not have the ideal XDirection for the derived view
|
||||
//(likely a DrawViewSection) and the user may need to adjust the XDirection
|
||||
//in the derived view.
|
||||
gp_Ax2 DrawViewPart::localVectorToCS(const Base::Vector3d localUnit) const
|
||||
{
|
||||
gp_Pnt stdOrigin(0.0, 0.0, 0.0);
|
||||
gp_Ax2 dvpCS = getProjectionCS(DrawUtil::toVector3d(stdOrigin));
|
||||
gp_Vec gLocalUnit = DrawUtil::togp_Dir(localUnit);
|
||||
gp_Vec gLocalX(-gLocalUnit.Y(), gLocalUnit.X(), 0.0); //clockwise perp for 2d
|
||||
|
||||
gp_Ax3 OXYZ;
|
||||
gp_Trsf xLocalOXYZ;
|
||||
xLocalOXYZ.SetTransformation(OXYZ, gp_Ax3(dvpCS));
|
||||
gp_Vec gLocalUnitOXYZ = gLocalUnit.Transformed(xLocalOXYZ);
|
||||
gp_Vec gLocalXOXYZ = gLocalX.Transformed(xLocalOXYZ);
|
||||
|
||||
return { stdOrigin, gp_Dir(gLocalUnitOXYZ), gp_Dir(gLocalXOXYZ) };
|
||||
}
|
||||
|
||||
gp_Ax2 DrawViewPart::getProjectionCS(const Base::Vector3d pt) const
|
||||
{
|
||||
// Base::Console().Message("DVP::getProjectionCS() - %s - %s\n", getNameInDocument(), Label.getValue());
|
||||
|
||||
@@ -142,17 +142,19 @@ public:
|
||||
virtual Base::Vector3d projectPoint(const Base::Vector3d& pt,
|
||||
bool invert = true) const;
|
||||
virtual BaseGeomPtr projectEdge(const TopoDS_Edge& e) const;
|
||||
virtual BaseGeomPtrVector projectWire(const TopoDS_Wire& inWire) const;
|
||||
|
||||
virtual gp_Ax2 getViewAxis(const Base::Vector3d& pt,
|
||||
const Base::Vector3d& direction,
|
||||
const bool flip=true) const;
|
||||
virtual gp_Ax2 getProjectionCS(Base::Vector3d pt) const;
|
||||
virtual gp_Ax2 getProjectionCS(Base::Vector3d pt = Base::Vector3d(0.0, 0.0, 0.0)) const;
|
||||
virtual Base::Vector3d getXDirection() const; //don't use XDirection.getValue()
|
||||
virtual Base::Vector3d getOriginalCentroid() const;
|
||||
virtual Base::Vector3d getCurrentCentroid() const;
|
||||
virtual Base::Vector3d getLegacyX(const Base::Vector3d& pt,
|
||||
const Base::Vector3d& axis,
|
||||
const bool flip = true) const;
|
||||
gp_Ax2 localVectorToCS(const Base::Vector3d localUnit) const;
|
||||
|
||||
|
||||
bool handleFaces();
|
||||
@@ -166,6 +168,9 @@ public:
|
||||
virtual TopoDS_Shape getSourceShapeFused() const;
|
||||
virtual std::vector<TopoDS_Shape> getSourceShape2d() const;
|
||||
|
||||
TopoDS_Shape getShape() const;
|
||||
double getSizeAlongVector(Base::Vector3d alignmentVector);
|
||||
|
||||
virtual void postHlrTasks(void);
|
||||
|
||||
bool isIso() const;
|
||||
@@ -223,7 +228,7 @@ protected:
|
||||
void onChanged(const App::Property* prop) override;
|
||||
void unsetupObject() override;
|
||||
|
||||
virtual TechDraw::GeometryObject* buildGeometryObject(TopoDS_Shape& shape, gp_Ax2& viewAxis);
|
||||
virtual TechDraw::GeometryObject* buildGeometryObject(TopoDS_Shape& shape, const gp_Ax2& viewAxis);
|
||||
virtual TechDraw::GeometryObject* makeGeometryForShape(TopoDS_Shape& shape); //const??
|
||||
void partExec(TopoDS_Shape& shape);
|
||||
virtual void addShapes2d(void);
|
||||
|
||||
@@ -22,33 +22,55 @@
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
//DrawViewSection processing overview
|
||||
|
||||
//execute
|
||||
// sectionExec(getShapeToCut())
|
||||
|
||||
//sectionExec
|
||||
// makeSectionCut(baseShape)
|
||||
|
||||
//makeSectionCut (separate thread)
|
||||
// m_cuttingTool = makeCuttingTool (DVSTool.brep)
|
||||
// m_cutPieces = (baseShape - m_cuttingTool) (DVSCutPieces.brep)
|
||||
|
||||
//onSectionCutFinished
|
||||
// m_preparedShape = prepareShape(m_cutPieces) - centered, scaled, rotated
|
||||
// geometryObject = DVP::buildGeometryObject(m_preparedShape) (HLR)
|
||||
|
||||
//postHlrTasks
|
||||
// faceIntersections = findSectionPlaneIntersections
|
||||
// m_sectionTopoDSFaces = alignSectionFaces(faceIntersections)
|
||||
// m_tdSectionFaces = makeTDSectionFaces(m_sectionTopoDSFaces)
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <chrono>
|
||||
# include <sstream>
|
||||
# include <QtConcurrentRun>
|
||||
# include <Bnd_Box.hxx>
|
||||
# include <BRep_Builder.hxx>
|
||||
# include <BRepBndLib.hxx>
|
||||
# include <BRepAdaptor_Surface.hxx>
|
||||
# include <BRepAlgoAPI_Cut.hxx>
|
||||
# include <BRepBuilderAPI_Copy.hxx>
|
||||
# include <BRepBuilderAPI_MakeFace.hxx>
|
||||
# include <BRepBuilderAPI_Transform.hxx>
|
||||
# include <BRepPrimAPI_MakePrism.hxx>
|
||||
# include <BRepTools.hxx>
|
||||
# include <gp_Ax2.hxx>
|
||||
# include <gp_Ax3.hxx>
|
||||
# include <gp_Dir.hxx>
|
||||
# include <gp_Pln.hxx>
|
||||
# include <gp_Pnt.hxx>
|
||||
# include <TopoDS_Shape.hxx>
|
||||
# include <TopoDS.hxx>
|
||||
# include <TopoDS_Face.hxx>
|
||||
# include <TopoDS_Edge.hxx>
|
||||
# include <TopoDS_Compound.hxx>
|
||||
# include <TopExp_Explorer.hxx>
|
||||
#include <chrono>
|
||||
#include <sstream>
|
||||
#include <QtConcurrentRun>
|
||||
#include <Bnd_Box.hxx>
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <BRepBndLib.hxx>
|
||||
#include <BRepAdaptor_Surface.hxx>
|
||||
#include <BRepAlgoAPI_Cut.hxx>
|
||||
#include <BRepBuilderAPI_Copy.hxx>
|
||||
#include <BRepBuilderAPI_MakeFace.hxx>
|
||||
#include <BRepBuilderAPI_Transform.hxx>
|
||||
#include <BRepPrimAPI_MakePrism.hxx>
|
||||
#include <BRepTools.hxx>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Ax3.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
#include <gp_Pln.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include <TopoDS_Compound.hxx>
|
||||
#include <TopExp.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#endif
|
||||
|
||||
#include <App/Application.h>
|
||||
@@ -58,21 +80,26 @@
|
||||
#include <Base/FileInfo.h>
|
||||
#include <Base/Parameter.h>
|
||||
|
||||
#include "DrawViewSection.h"
|
||||
#include <Mod/Part/App/PartFeature.h>
|
||||
|
||||
#include "DrawGeomHatch.h"
|
||||
#include "DrawHatch.h"
|
||||
#include "DrawProjGroupItem.h"
|
||||
#include "DrawUtil.h"
|
||||
#include "Geometry.h"
|
||||
#include "EdgeWalker.h"
|
||||
#include "DrawProjGroupItem.h"
|
||||
#include "GeometryObject.h"
|
||||
|
||||
#include "DrawViewSection.h"
|
||||
|
||||
using namespace TechDraw;
|
||||
|
||||
using DU = DrawUtil;
|
||||
|
||||
const char* DrawViewSection::SectionDirEnums[]= {"Right",
|
||||
"Left",
|
||||
"Up",
|
||||
"Down",
|
||||
"Aligned",
|
||||
nullptr};
|
||||
|
||||
const char* DrawViewSection::CutSurfaceEnums[]= {"Hide",
|
||||
@@ -88,25 +115,34 @@ const char* DrawViewSection::CutSurfaceEnums[]= {"Hide",
|
||||
PROPERTY_SOURCE(TechDraw::DrawViewSection, TechDraw::DrawViewPart)
|
||||
|
||||
DrawViewSection::DrawViewSection() :
|
||||
m_waitingForCut(false)
|
||||
m_waitingForCut(false),
|
||||
m_shapeSize(0.0)
|
||||
{
|
||||
static const char *sgroup = "Section";
|
||||
static const char *fgroup = "Cut Surface Format";
|
||||
static const char *ggroup = "Cut Operation";
|
||||
|
||||
//general section properties
|
||||
ADD_PROPERTY_TYPE(SectionSymbol ,(""), sgroup, App::Prop_None, "The identifier for this section");
|
||||
ADD_PROPERTY_TYPE(BaseView ,(nullptr), sgroup, App::Prop_None, "2D View source for this Section");
|
||||
BaseView.setScope(App::LinkScope::Global);
|
||||
ADD_PROPERTY_TYPE(SectionNormal ,(0, 0,1.0) ,sgroup, App::Prop_None,
|
||||
"Section Plane normal direction"); //direction of extrusion of cutting prism
|
||||
ADD_PROPERTY_TYPE(SectionOrigin ,(0, 0,0) ,sgroup, App::Prop_None, "Section Plane Origin");
|
||||
SectionDirection.setEnums(SectionDirEnums);
|
||||
ADD_PROPERTY_TYPE(SectionDirection, ((long)0), sgroup, App::Prop_None, "Direction in Base View for this Section");
|
||||
ADD_PROPERTY_TYPE(FuseBeforeCut ,(false), sgroup, App::Prop_None, "Merge Source(s) into a single shape before cutting");
|
||||
|
||||
//TODO: SectionDirection is a legacy from when SectionViews were only available along
|
||||
//cardinal directions. It should be made obsolete and replaced with Aligned sections and
|
||||
//local unit vectors.
|
||||
SectionDirection.setEnums(SectionDirEnums);
|
||||
ADD_PROPERTY_TYPE(SectionDirection, ((long)0), sgroup, App::Prop_None, "Orientation of this Section in the Base View");
|
||||
|
||||
//properties related to the cut operation
|
||||
ADD_PROPERTY_TYPE(FuseBeforeCut ,(false), ggroup, App::Prop_None, "Merge Source(s) into a single shape before cutting");
|
||||
ADD_PROPERTY_TYPE(TrimAfterCut ,(false), ggroup, App::Prop_None, "Trim the resulting shape after the section cut");
|
||||
|
||||
//properties related to the display of the cut surface
|
||||
CutSurfaceDisplay.setEnums(CutSurfaceEnums);
|
||||
ADD_PROPERTY_TYPE(CutSurfaceDisplay, (prefCutSurface()), fgroup, App::Prop_None, "Appearance of Cut Surface");
|
||||
|
||||
//initialize these to defaults
|
||||
ADD_PROPERTY_TYPE(FileHatchPattern ,(DrawHatch::prefSvgHatch()), fgroup, App::Prop_None, "The hatch pattern file for the cut surface");
|
||||
ADD_PROPERTY_TYPE(FileGeomPattern ,(DrawGeomHatch::prefGeomHatchFile()), fgroup, App::Prop_None, "The PAT pattern file for geometric hatching");
|
||||
|
||||
@@ -126,6 +162,8 @@ DrawViewSection::DrawViewSection() :
|
||||
|
||||
SvgIncluded.setStatus(App::Property::ReadOnly, true);
|
||||
PatIncluded.setStatus(App::Property::ReadOnly, true);
|
||||
//SectionNormal is used instead to Direction
|
||||
Direction.setStatus(App::Property::ReadOnly, true);
|
||||
}
|
||||
|
||||
DrawViewSection::~DrawViewSection()
|
||||
@@ -168,7 +206,9 @@ void DrawViewSection::onChanged(const App::Property* prop)
|
||||
return;
|
||||
}
|
||||
|
||||
if (prop == &SectionSymbol) {
|
||||
if (prop == &SectionNormal) {
|
||||
Direction.setValue(SectionNormal.getValue());
|
||||
} else if (prop == &SectionSymbol) {
|
||||
std::string lblText = "Section " +
|
||||
std::string(SectionSymbol.getValue()) +
|
||||
" - " +
|
||||
@@ -200,29 +240,37 @@ void DrawViewSection::onChanged(const App::Property* prop)
|
||||
DrawView::onChanged(prop);
|
||||
}
|
||||
|
||||
TopoDS_Shape DrawViewSection::getShapeToCut()
|
||||
{
|
||||
// Base::Console().Message("DVS::getShapeToCut()\n");
|
||||
App::DocumentObject* base = BaseView.getValue();
|
||||
TechDraw::DrawViewPart* dvp = nullptr;
|
||||
if (!base ||
|
||||
!base->getTypeId().isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) {
|
||||
//this can probably only happen with scripting
|
||||
return TopoDS_Shape();
|
||||
} else {
|
||||
dvp = static_cast<TechDraw::DrawViewPart*>(base);
|
||||
}
|
||||
TopoDS_Shape shapeToCut = dvp->getSourceShape();
|
||||
if (FuseBeforeCut.getValue()) {
|
||||
shapeToCut = dvp->getSourceShapeFused();
|
||||
}
|
||||
return shapeToCut;
|
||||
}
|
||||
|
||||
App::DocumentObjectExecReturn *DrawViewSection::execute()
|
||||
{
|
||||
// Base::Console().Message("DVS::execute() - %s\n", getNameInDocument());
|
||||
if (!keepUpdated()) {
|
||||
return App::DocumentObject::StdReturn;
|
||||
}
|
||||
|
||||
App::DocumentObject* base = BaseView.getValue();
|
||||
if (!base) {
|
||||
if (!isBaseValid()) {
|
||||
return new App::DocumentObjectExecReturn("BaseView object not found");
|
||||
}
|
||||
|
||||
TechDraw::DrawViewPart* dvp = nullptr;
|
||||
if (!base->getTypeId().isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) {
|
||||
//this can probably only happen with scripting
|
||||
return new App::DocumentObjectExecReturn("BaseView object is not a DrawViewPart object");
|
||||
} else {
|
||||
dvp = static_cast<TechDraw::DrawViewPart*>(base);
|
||||
}
|
||||
|
||||
TopoDS_Shape baseShape = dvp->getSourceShape();
|
||||
if (FuseBeforeCut.getValue()) {
|
||||
baseShape = dvp->getSourceShapeFused();
|
||||
}
|
||||
TopoDS_Shape baseShape = getShapeToCut();
|
||||
|
||||
if (baseShape.IsNull()) {
|
||||
return DrawView::execute();
|
||||
@@ -230,7 +278,6 @@ App::DocumentObjectExecReturn *DrawViewSection::execute()
|
||||
|
||||
m_saveShape = baseShape; //save shape for 2nd pass
|
||||
|
||||
// checkXDirection();
|
||||
bool haveX = checkXDirection();
|
||||
if (!haveX) {
|
||||
//block touch/onChanged stuff
|
||||
@@ -246,6 +293,16 @@ App::DocumentObjectExecReturn *DrawViewSection::execute()
|
||||
return DrawView::execute();
|
||||
}
|
||||
|
||||
bool DrawViewSection::isBaseValid() const
|
||||
{
|
||||
App::DocumentObject* base = BaseView.getValue();
|
||||
if (base &&
|
||||
base->getTypeId().isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DrawViewSection::sectionExec(TopoDS_Shape& baseShape)
|
||||
{
|
||||
// Base::Console().Message("DVS::sectionExec() - %s baseShape.IsNull: %d\n",
|
||||
@@ -289,112 +346,134 @@ void DrawViewSection::makeSectionCut(TopoDS_Shape &baseShape)
|
||||
Bnd_Box centerBox;
|
||||
BRepBndLib::AddOptimal(baseShape, centerBox);
|
||||
centerBox.SetGap(0.0);
|
||||
gp_Pln pln = getSectionPlane();
|
||||
gp_Dir gpNormal = pln.Axis().Direction();
|
||||
Base::Vector3d orgPnt = SectionOrigin.getValue();
|
||||
|
||||
if(!isReallyInBox(gp_Pnt(orgPnt.x, orgPnt.y, orgPnt.z), centerBox)) {
|
||||
Base::Console().Warning("DVS: SectionOrigin doesn't intersect part in %s\n", getNameInDocument());
|
||||
}
|
||||
|
||||
// make cutting tool
|
||||
// Make the extrusion face
|
||||
double dMax = sqrt(centerBox.SquareExtent());
|
||||
BRepBuilderAPI_MakeFace mkFace(pln, -dMax, dMax, -dMax, dMax);
|
||||
TopoDS_Face aProjFace = mkFace.Face();
|
||||
if(aProjFace.IsNull()) {
|
||||
Base::Console().Warning("DVS: Section face is NULL in %s\n", getNameInDocument());
|
||||
return;
|
||||
}
|
||||
gp_Vec extrudeDir = dMax * gp_Vec(gpNormal);
|
||||
TopoDS_Shape prism = BRepPrimAPI_MakePrism(aProjFace, extrudeDir, false, true).Shape();
|
||||
m_shapeSize = sqrt(centerBox.SquareExtent());
|
||||
|
||||
// We need to copy the shape to not modify the BRepstructure
|
||||
BRepBuilderAPI_Copy BuilderCopy(baseShape);
|
||||
TopoDS_Shape myShape = BuilderCopy.Shape();
|
||||
m_saveShape = myShape; //save shape for 2nd pass
|
||||
|
||||
if (debugSection()) {
|
||||
BRepTools::Write(myShape, "DVSCopy.brep"); //debug
|
||||
}
|
||||
|
||||
m_cuttingTool = makeCuttingTool(m_shapeSize);
|
||||
|
||||
if (debugSection()) {
|
||||
BRepTools::Write(m_cuttingTool, "DVSTool.brep"); //debug
|
||||
}
|
||||
|
||||
// perform cut
|
||||
BRep_Builder builder;
|
||||
TopoDS_Compound pieces;
|
||||
builder.MakeCompound(pieces);
|
||||
TopoDS_Compound cutPieces;
|
||||
builder.MakeCompound(cutPieces);
|
||||
TopExp_Explorer expl(myShape, TopAbs_SOLID);
|
||||
int indb = 0;
|
||||
int outdb = 0;
|
||||
for (; expl.More(); expl.Next()) {
|
||||
indb++;
|
||||
const TopoDS_Solid& s = TopoDS::Solid(expl.Current());
|
||||
BRepAlgoAPI_Cut mkCut(s, prism);
|
||||
BRepAlgoAPI_Cut mkCut(s, m_cuttingTool);
|
||||
if (!mkCut.IsDone()) {
|
||||
Base::Console().Warning("DVS: Section cut has failed in %s\n", getNameInDocument());
|
||||
continue;
|
||||
}
|
||||
TopoDS_Shape cut = mkCut.Shape();
|
||||
builder.Add(pieces, cut);
|
||||
outdb++;
|
||||
builder.Add(cutPieces, mkCut.Shape());
|
||||
}
|
||||
|
||||
// pieces contains result of cutting each subshape in baseShape with tool
|
||||
TopoDS_Shape rawShape = pieces;
|
||||
|
||||
// cutPieces contains result of cutting each subshape in baseShape with tool
|
||||
m_cutPieces = cutPieces;
|
||||
if (debugSection()) {
|
||||
BRepTools::Write(myShape, "DVSCopy.brep"); //debug
|
||||
BRepTools::Write(aProjFace, "DVSFace.brep"); //debug
|
||||
BRepTools::Write(prism, "DVSTool.brep"); //debug
|
||||
BRepTools::Write(pieces, "DVSPieces.brep"); //debug
|
||||
BRepTools::Write(cutPieces, "DVSCutPieces1.brep"); //debug
|
||||
}
|
||||
|
||||
//second cut if requested. Sometimes the first cut includes extra uncut pieces.
|
||||
if (trimAfterCut()) {
|
||||
BRepAlgoAPI_Cut mkCut2(cutPieces, m_cuttingTool);
|
||||
if (mkCut2.IsDone()) {
|
||||
m_cutPieces = mkCut2.Shape();
|
||||
if (debugSection()) {
|
||||
BRepTools::Write(m_cutPieces, "DVSCutPieces2.brep"); //debug
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check for error in cut
|
||||
Bnd_Box testBox;
|
||||
BRepBndLib::AddOptimal(rawShape, testBox);
|
||||
BRepBndLib::AddOptimal(m_cutPieces, testBox);
|
||||
testBox.SetGap(0.0);
|
||||
if (testBox.IsVoid()) { //prism & input don't intersect. rawShape is garbage, don't bother.
|
||||
Base::Console().Warning("DVS::makeSectionCut - prism & input don't intersect - %s\n", Label.getValue());
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// build display geometry as in DVP, with minor mods
|
||||
TopoDS_Shape centeredShape;
|
||||
waitingForCut(false);
|
||||
}
|
||||
|
||||
//position, scale and rotate shape for buildGeometryObject
|
||||
TopoDS_Shape DrawViewSection::prepareShape(const TopoDS_Shape& rawShape,
|
||||
double shapeSize)
|
||||
{
|
||||
// Base::Console().Message("DVS::prepareShape - %s - rawShape.IsNull: %d shapeSize: %.3f\n",
|
||||
// getNameInDocument(), rawShape.IsNull(), shapeSize);
|
||||
(void) shapeSize; //shapeSize is not used in this base class, but is interesting for
|
||||
//derived classes
|
||||
// build display geometry as in DVP, with minor mods
|
||||
TopoDS_Shape preparedShape;
|
||||
try {
|
||||
Base::Vector3d origin(0.0, 0.0, 0.0);
|
||||
m_viewAxis = getProjectionCS(origin);
|
||||
m_projectionCS = getProjectionCS(origin);
|
||||
gp_Pnt inputCenter;
|
||||
inputCenter = TechDraw::findCentroid(rawShape,
|
||||
m_viewAxis);
|
||||
m_projectionCS);
|
||||
Base::Vector3d centroid(inputCenter.X(),
|
||||
inputCenter.Y(),
|
||||
inputCenter.Z());
|
||||
|
||||
centeredShape = TechDraw::moveShape(rawShape,
|
||||
preparedShape = TechDraw::moveShape(rawShape,
|
||||
centroid * -1.0);
|
||||
m_cutShape = centeredShape;
|
||||
m_cutShape = preparedShape;
|
||||
m_saveCentroid = centroid;
|
||||
|
||||
m_scaledShape = TechDraw::scaleShape(centeredShape,
|
||||
getScale());
|
||||
preparedShape = TechDraw::scaleShape(preparedShape,
|
||||
getScale());
|
||||
|
||||
if (!DrawUtil::fpCompare(Rotation.getValue(), 0.0)) {
|
||||
m_scaledShape = TechDraw::rotateShape(m_scaledShape,
|
||||
m_viewAxis,
|
||||
preparedShape = TechDraw::rotateShape(preparedShape,
|
||||
m_projectionCS,
|
||||
Rotation.getValue());
|
||||
}
|
||||
if (debugSection()) {
|
||||
BRepTools::Write(m_cutShape, "DVSmCutShape.brep"); //debug
|
||||
BRepTools::Write(m_scaledShape, "DVSScaled.brep"); //debug
|
||||
BRepTools::Write(m_cutShape, "DVSCutShape.brep"); //debug
|
||||
// DrawUtil::dumpCS("DVS::makeSectionCut - CS to GO", viewAxis);
|
||||
}
|
||||
|
||||
m_rawShape = rawShape; //save for section face finding
|
||||
|
||||
}
|
||||
catch (Standard_Failure& e1) {
|
||||
Base::Console().Warning("DVS::makeSectionCut - failed to build base shape %s - %s **\n",
|
||||
Base::Console().Warning("DVS::prepareShape - failed to build shape %s - %s **\n",
|
||||
getNameInDocument(), e1.GetMessageString());
|
||||
return;
|
||||
}
|
||||
return preparedShape;
|
||||
}
|
||||
|
||||
waitingForCut(false);
|
||||
TopoDS_Shape DrawViewSection::makeCuttingTool(double shapeSize)
|
||||
{
|
||||
// Base::Console().Message("DVS::makeCuttingTool(%.3f) - %s\n", shapeSize, getNameInDocument());
|
||||
// Make the extrusion face
|
||||
gp_Pln pln = getSectionPlane();
|
||||
gp_Dir gpNormal = pln.Axis().Direction();
|
||||
BRepBuilderAPI_MakeFace mkFace(pln, -shapeSize, shapeSize, -shapeSize, shapeSize);
|
||||
TopoDS_Face aProjFace = mkFace.Face();
|
||||
if(aProjFace.IsNull()) {
|
||||
return TopoDS_Shape();
|
||||
}
|
||||
if (debugSection()){
|
||||
BRepTools::Write(aProjFace, "DVSSectionFace.brep"); //debug
|
||||
}
|
||||
gp_Vec extrudeDir = shapeSize * gp_Vec(gpNormal);
|
||||
return BRepPrimAPI_MakePrism(aProjFace, extrudeDir, false, true).Shape();
|
||||
}
|
||||
|
||||
void DrawViewSection::onSectionCutFinished()
|
||||
@@ -404,10 +483,15 @@ void DrawViewSection::onSectionCutFinished()
|
||||
|
||||
showProgressMessage(getNameInDocument(), "has finished making section cut");
|
||||
|
||||
m_preparedShape = prepareShape(getShapeToPrepare(), m_shapeSize);
|
||||
if (debugSection()) {
|
||||
BRepTools::Write(m_preparedShape, "DVSPreparedShape.brep"); //debug
|
||||
}
|
||||
|
||||
postSectionCutTasks();
|
||||
|
||||
//display geometry for cut shape is in geometryObject as in DVP
|
||||
m_tempGeometryObject = buildGeometryObject(m_scaledShape, m_viewAxis);
|
||||
m_tempGeometryObject = buildGeometryObject(m_preparedShape, getSectionCS());
|
||||
}
|
||||
|
||||
//activities that depend on updated geometry object
|
||||
@@ -430,78 +514,41 @@ void DrawViewSection::postHlrTasks(void)
|
||||
|
||||
|
||||
// build section face geometry
|
||||
TopoDS_Compound faceIntersections = findSectionPlaneIntersections(m_rawShape);
|
||||
TopoDS_Compound faceIntersections = findSectionPlaneIntersections(getShapeToIntersect());
|
||||
if (faceIntersections.IsNull()) {
|
||||
requestPaint();
|
||||
return;
|
||||
}
|
||||
|
||||
TopoDS_Shape centeredShapeF = TechDraw::moveShape(faceIntersections,
|
||||
TopoDS_Shape centeredFaces = TechDraw::moveShape(faceIntersections,
|
||||
m_saveCentroid * -1.0);
|
||||
|
||||
TopoDS_Shape scaledSection = TechDraw::scaleShape(centeredShapeF,
|
||||
TopoDS_Shape scaledSection = TechDraw::scaleShape(centeredFaces,
|
||||
getScale());
|
||||
if (!DrawUtil::fpCompare(Rotation.getValue(), 0.0)) {
|
||||
scaledSection = TechDraw::rotateShape(scaledSection,
|
||||
m_viewAxis,
|
||||
getProjectionCS(),
|
||||
Rotation.getValue());
|
||||
}
|
||||
|
||||
m_sectionTopoDSFaces = alignSectionFaces(faceIntersections);
|
||||
if (debugSection()) {
|
||||
BRepTools::Write(scaledSection, "DVSScaledFaces.brep"); //debug
|
||||
BRepTools::Write(m_sectionTopoDSFaces, "DVSTopoSectionFaces.brep"); //debug
|
||||
}
|
||||
m_tdSectionFaces = makeTDSectionFaces(m_sectionTopoDSFaces);
|
||||
|
||||
// scaledSection is compound of TopoDS_Face intersections, but aligned to pln(origin, sectionNormal)
|
||||
// needs to be aligned to pln (origin, stdZ);
|
||||
gp_Ax3 R3;
|
||||
gp_Ax2 projCS = getSectionCS();
|
||||
gp_Ax3 proj3 = gp_Ax3(gp_Pnt(0.0, 0.0, 0.0),
|
||||
projCS.Direction(),
|
||||
projCS.XDirection());
|
||||
gp_Trsf fromR3;
|
||||
fromR3.SetTransformation(R3, proj3);
|
||||
BRepBuilderAPI_Transform xformer(fromR3);
|
||||
xformer.Perform(scaledSection, true);
|
||||
if (xformer.IsDone()) {
|
||||
sectionTopoDSFaces = TopoDS::Compound(xformer.Shape());
|
||||
} else {
|
||||
Base::Console().Message("DVS::sectionExec - face xform failed\n");
|
||||
}
|
||||
|
||||
sectionTopoDSFaces = TopoDS::Compound(GeometryObject::invertGeometry(sectionTopoDSFaces)); //handle Qt -y
|
||||
|
||||
//turn section faces into TD geometry
|
||||
tdSectionFaces.clear();
|
||||
TopExp_Explorer sectionExpl(sectionTopoDSFaces, TopAbs_FACE);
|
||||
for (; sectionExpl.More(); sectionExpl.Next()) {
|
||||
const TopoDS_Face& face = TopoDS::Face(sectionExpl.Current());
|
||||
TechDraw::FacePtr sectionFace(std::make_shared<TechDraw::Face>());
|
||||
TopExp_Explorer expFace(face, TopAbs_WIRE);
|
||||
for ( ; expFace.More(); expFace.Next()) {
|
||||
TechDraw::Wire* w = new TechDraw::Wire();
|
||||
const TopoDS_Wire& wire = TopoDS::Wire(expFace.Current());
|
||||
TopExp_Explorer expWire(wire, TopAbs_EDGE);
|
||||
for ( ; expWire.More(); expWire.Next()) {
|
||||
const TopoDS_Edge& edge = TopoDS::Edge(expWire.Current());
|
||||
TechDraw::BaseGeomPtr e = BaseGeom::baseFactory(edge);
|
||||
if (e) {
|
||||
w->geoms.push_back(e);
|
||||
}
|
||||
}
|
||||
sectionFace->wires.push_back(w);
|
||||
}
|
||||
tdSectionFaces.push_back(sectionFace);
|
||||
}
|
||||
|
||||
TechDraw::DrawViewPart* dvp = dynamic_cast<TechDraw::DrawViewPart*>(BaseView.getValue());
|
||||
if (dvp) {
|
||||
dvp->requestPaint(); //to refresh section line
|
||||
}
|
||||
requestPaint();
|
||||
requestPaint(); //this will be a duplicate paint if we are making a standalone ComplexSection
|
||||
}
|
||||
|
||||
//activities that depend on a valid section cut
|
||||
void DrawViewSection::postSectionCutTasks()
|
||||
{
|
||||
// Base::Console().Message("DVS::postSectionCutTasks()\n");
|
||||
std::vector<App::DocumentObject*> children = getInList();
|
||||
for (auto& c: children) {
|
||||
if (c->getTypeId().isDerivedFrom(DrawViewPart::getClassTypeId())) {
|
||||
@@ -529,16 +576,24 @@ gp_Pln DrawViewSection::getSectionPlane() const
|
||||
}
|
||||
|
||||
//! tries to find the intersection of the section plane with the shape giving a collection of planar faces
|
||||
//! the original algo finds the intersections first then transforms them to match the centered, rotated
|
||||
//! and scaled cut shape. Aligned complex sections need to intersect the final cut shape (which in this
|
||||
//! case is a compound of individual cuts) with the "effective" (flattened) section plane.
|
||||
TopoDS_Compound DrawViewSection::findSectionPlaneIntersections(const TopoDS_Shape& shape)
|
||||
{
|
||||
// Base::Console().Message("DVS::findSectionPlaneIntersections() - %s\n", getNameInDocument());
|
||||
if(shape.IsNull()){
|
||||
// this shouldn't happen
|
||||
Base::Console().Warning("DrawViewSection::findSectionPlaneInter - %s - input shape is Null\n", getNameInDocument());
|
||||
// Base::Console().Warning("DrawViewSection::findSectionPlaneInter - %s - input shape is Null\n", getNameInDocument());
|
||||
return TopoDS_Compound();
|
||||
}
|
||||
|
||||
gp_Pln plnSection = getSectionPlane();
|
||||
if (debugSection()) {
|
||||
BRepBuilderAPI_MakeFace mkFace(plnSection, -m_shapeSize, m_shapeSize, -m_shapeSize, m_shapeSize);
|
||||
BRepTools::Write(mkFace.Face(), "DVSSectionPlane.brep"); //debug
|
||||
BRepTools::Write(shape, "DVSShapeToIntersect.brep)");
|
||||
}
|
||||
BRep_Builder builder;
|
||||
TopoDS_Compound result;
|
||||
builder.MakeCompound(result);
|
||||
@@ -558,6 +613,102 @@ TopoDS_Compound DrawViewSection::findSectionPlaneIntersections(const TopoDS_Shap
|
||||
return result;
|
||||
}
|
||||
|
||||
//move section faces to line up with cut shape
|
||||
TopoDS_Compound DrawViewSection::alignSectionFaces(TopoDS_Shape faceIntersections)
|
||||
{
|
||||
// Base::Console().Message("DVS::alignSectionFaces()\n");
|
||||
TopoDS_Compound sectionFaces;
|
||||
TopoDS_Shape centeredShape = TechDraw::moveShape(faceIntersections,
|
||||
getOriginalCentroid() * -1.0);
|
||||
|
||||
TopoDS_Shape scaledSection = TechDraw::scaleShape(centeredShape,
|
||||
getScale());
|
||||
if (!DrawUtil::fpCompare(Rotation.getValue(), 0.0)) {
|
||||
scaledSection = TechDraw::rotateShape(scaledSection,
|
||||
getSectionCS(),
|
||||
Rotation.getValue());
|
||||
}
|
||||
|
||||
return mapToPage(scaledSection);
|
||||
}
|
||||
|
||||
TopoDS_Compound DrawViewSection::mapToPage(TopoDS_Shape& shapeToAlign)
|
||||
{
|
||||
// shapeToAlign is compound of TopoDS_Face intersections, but aligned to pln(origin, sectionNormal)
|
||||
// needs to be aligned to paper plane (origin, stdZ);
|
||||
//project the faces in the shapeToAlign, build new faces from the resulting wires and
|
||||
//combine everything into a compound of faces
|
||||
|
||||
BRep_Builder builder;
|
||||
TopoDS_Compound result;
|
||||
builder.MakeCompound(result);
|
||||
|
||||
TopExp_Explorer expFace(shapeToAlign, TopAbs_FACE);
|
||||
for (int iFace = 1; expFace.More(); expFace.Next(), iFace++) {
|
||||
const TopoDS_Face& face = TopoDS::Face(expFace.Current());
|
||||
std::vector<TopoDS_Wire> faceWires;
|
||||
TopExp_Explorer expWires(face, TopAbs_WIRE);
|
||||
for ( ; expWires.More(); expWires.Next()) {
|
||||
const TopoDS_Wire& wire = TopoDS::Wire(expWires.Current());
|
||||
TopoDS_Shape projectedShape = GeometryObject::projectSimpleShape(wire, getSectionCS());
|
||||
std::vector<TopoDS_Edge> wireEdges;
|
||||
//projectedShape is just a bunch of edges. we have to rebuild the wire.
|
||||
TopExp_Explorer expEdges(projectedShape, TopAbs_EDGE);
|
||||
for ( ; expEdges.More(); expEdges.Next()) {
|
||||
const TopoDS_Edge& edge = TopoDS::Edge(expEdges.Current());
|
||||
wireEdges.push_back(edge);
|
||||
}
|
||||
TopoDS_Wire cleanWire = EdgeWalker::makeCleanWire(wireEdges, 2.0 * EWTOLERANCE);
|
||||
faceWires.push_back(cleanWire);
|
||||
}
|
||||
|
||||
//first wire should be the outer boundary of the face
|
||||
BRepBuilderAPI_MakeFace mkFace(faceWires.front());
|
||||
int wireCount = faceWires.size();
|
||||
for (int iWire = 1; iWire < wireCount; iWire++) {
|
||||
//make holes in the face with the rest of the wires
|
||||
mkFace.Add(faceWires.at(iWire));
|
||||
}
|
||||
builder.Add(result, mkFace.Face());
|
||||
if (debugSection()) {
|
||||
std::stringstream ss;
|
||||
ss << "DVSFaceFromWires" << iFace << ".brep";
|
||||
BRepTools::Write(mkFace.Face(), ss.str().c_str()); //debug
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//turn OCC section faces into TD geometry
|
||||
std::vector<TechDraw::FacePtr> DrawViewSection::makeTDSectionFaces(TopoDS_Compound topoDSFaces)
|
||||
{
|
||||
// Base::Console().Message("DVS::makeTDSectionFaces()\n");
|
||||
std::vector<TechDraw::FacePtr> tdSectionFaces;
|
||||
TopExp_Explorer sectionExpl(topoDSFaces, TopAbs_FACE);
|
||||
for (; sectionExpl.More(); sectionExpl.Next()) {
|
||||
const TopoDS_Face& face = TopoDS::Face(sectionExpl.Current());
|
||||
TechDraw::FacePtr sectionFace(std::make_shared<TechDraw::Face>());
|
||||
TopExp_Explorer expFace(face, TopAbs_WIRE);
|
||||
for ( ; expFace.More(); expFace.Next()) {
|
||||
TechDraw::Wire* w = new TechDraw::Wire();
|
||||
const TopoDS_Wire& wire = TopoDS::Wire(expFace.Current());
|
||||
TopExp_Explorer expWire(wire, TopAbs_EDGE);
|
||||
for ( ; expWire.More(); expWire.Next()) {
|
||||
const TopoDS_Edge& edge = TopoDS::Edge(expWire.Current());
|
||||
TechDraw::BaseGeomPtr e = BaseGeom::baseFactory(edge);
|
||||
if (e) {
|
||||
w->geoms.push_back(e);
|
||||
}
|
||||
}
|
||||
sectionFace->wires.push_back(w);
|
||||
}
|
||||
tdSectionFaces.push_back(sectionFace);
|
||||
}
|
||||
|
||||
return tdSectionFaces;
|
||||
}
|
||||
|
||||
//calculate the ends of the section line in BaseView's coords
|
||||
std::pair<Base::Vector3d, Base::Vector3d> DrawViewSection::sectionLineEnds()
|
||||
{
|
||||
@@ -577,20 +728,9 @@ std::pair<Base::Vector3d, Base::Vector3d> DrawViewSection::sectionLineEnds()
|
||||
|
||||
Base::Vector3d sectionOrg = SectionOrigin.getValue() - getBaseDVP()->getOriginalCentroid();
|
||||
sectionOrg = getBaseDVP()->projectPoint(sectionOrg); //convert to base view CS
|
||||
|
||||
//get the unscaled X and Y ranges of the base view geometry
|
||||
auto bbx = getBaseDVP()->getBoundingBox();
|
||||
double xRange = bbx.MaxX - bbx.MinX;
|
||||
xRange /= getBaseDVP()->getScale();
|
||||
double yRange = bbx.MaxY - bbx.MinY;
|
||||
yRange /= getBaseDVP()->getScale();
|
||||
|
||||
sectionOrg = rotator.multVec(sectionOrg);
|
||||
sectionLineDir = rotator.multVec(sectionLineDir);
|
||||
|
||||
result = DrawUtil::boxIntersect2d(sectionOrg, sectionLineDir, xRange, yRange); //unscaled
|
||||
result.first = unrotator.multVec(result.first);
|
||||
result.second = unrotator.multVec(result.second);
|
||||
double halfSize = getBaseDVP()->getSizeAlongVector(sectionLineDir) / 2.0;
|
||||
result.first = sectionOrg + sectionLineDir * halfSize;
|
||||
result.second = sectionOrg - sectionLineDir * halfSize;
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -659,11 +799,40 @@ void DrawViewSection::setCSFromBase(const std::string sectionName)
|
||||
XDirection.setValue(vXDir);
|
||||
}
|
||||
|
||||
//set the section CS based on an XY vector in BaseViews CS
|
||||
void DrawViewSection::setCSFromBase(const Base::Vector3d localUnit)
|
||||
{
|
||||
// Base::Console().Message("DVS::setCSFromBase(%s)\n", DrawUtil::formatVector(localUnit).c_str());
|
||||
gp_Ax2 newSectionCS = getBaseDVP()->localVectorToCS(localUnit);
|
||||
|
||||
Base::Vector3d vDir(newSectionCS.Direction().X(),
|
||||
newSectionCS.Direction().Y(),
|
||||
newSectionCS.Direction().Z());
|
||||
Direction.setValue(vDir);
|
||||
SectionNormal.setValue(vDir);
|
||||
Base::Vector3d vXDir(newSectionCS.XDirection().X(),
|
||||
newSectionCS.XDirection().Y(),
|
||||
newSectionCS.XDirection().Z());
|
||||
XDirection.setValue(vXDir);
|
||||
}
|
||||
|
||||
//reset the section CS based on an XY vector in current section CS
|
||||
void DrawViewSection::setCSFromLocalUnit(const Base::Vector3d localUnit)
|
||||
{
|
||||
// Base::Console().Message("DVS::setCSFromLocalUnit(%s)\n", DrawUtil::formatVector(localUnit).c_str());
|
||||
gp_Dir verticalDir = getSectionCS().YDirection();
|
||||
gp_Ax1 verticalAxis(DrawUtil::togp_Pnt(SectionOrigin.getValue()), verticalDir);
|
||||
gp_Dir oldNormal = getSectionCS().Direction();
|
||||
gp_Dir newNormal = DrawUtil::togp_Dir(projectPoint(localUnit));
|
||||
double angle = oldNormal.AngleWithRef(newNormal, verticalDir);
|
||||
gp_Ax2 newCS = getSectionCS().Rotated(verticalAxis, angle);
|
||||
SectionNormal.setValue(DrawUtil::toVector3d(newCS.Direction()));
|
||||
XDirection.setValue(DrawUtil::toVector3d(newCS.XDirection()));
|
||||
}
|
||||
|
||||
gp_Ax2 DrawViewSection::getCSFromBase(const std::string sectionName) const
|
||||
{
|
||||
// Base::Console().Message("DVS::getCSFromBase(%s)\n", sectionName.c_str());
|
||||
Base::Vector3d sectionNormal;
|
||||
Base::Vector3d sectionXDir;
|
||||
Base::Vector3d origin(0.0, 0.0, 0.0);
|
||||
Base::Vector3d sectOrigin = SectionOrigin.getValue();
|
||||
|
||||
@@ -693,6 +862,12 @@ gp_Ax2 DrawViewSection::getCSFromBase(const std::string sectionName) const
|
||||
} else if (sectionName == "Right") {
|
||||
dvsDir = dvpRight.Reversed();
|
||||
dvsXDir = dvpDir;
|
||||
} else if (sectionName == "Aligned") {
|
||||
//if aligned, we don't get our direction from the base view
|
||||
Base::Vector3d sectionNormal = SectionNormal.getValue();
|
||||
dvsDir = gp_Dir(sectionNormal.x, sectionNormal.y, sectionNormal.z);
|
||||
Base::Vector3d sectionXDir = XDirection.getValue();
|
||||
dvsXDir = gp_Dir(sectionXDir.x, sectionXDir.y, sectionXDir.z);
|
||||
} else {
|
||||
Base::Console().Log("Error - DVS::getCSFromBase - bad sectionName: %s\n", sectionName.c_str());
|
||||
dvsDir = dvpRight;
|
||||
@@ -739,6 +914,26 @@ gp_Ax2 DrawViewSection::getSectionCS() const
|
||||
return sectionCS;
|
||||
}
|
||||
|
||||
gp_Ax2 DrawViewSection::getProjectionCS(const Base::Vector3d pt) const
|
||||
{
|
||||
Base::Vector3d vNormal = SectionNormal.getValue();
|
||||
gp_Dir gNormal(vNormal.x,
|
||||
vNormal.y,
|
||||
vNormal.z);
|
||||
Base::Vector3d vXDir = getXDirection();
|
||||
gp_Dir gXDir(vXDir.x,
|
||||
vXDir.y,
|
||||
vXDir.z);
|
||||
if (DrawUtil::fpCompare(fabs(gNormal.Dot(gXDir)), 1.0)) {
|
||||
//can not build a gp_Ax2 from these values
|
||||
throw Base::RuntimeError("DVS::getProjectionCS - SectionNormal and XDirection are parallel");
|
||||
}
|
||||
gp_Pnt gOrigin(pt.x,
|
||||
pt.y,
|
||||
pt.z);
|
||||
return { gOrigin, gNormal, gXDir };
|
||||
}
|
||||
|
||||
std::vector<LineSet> DrawViewSection::getDrawableLines(int i)
|
||||
{
|
||||
// Base::Console().Message("DVS::getDrawableLines(%d) - lineSets: %d\n", i, m_lineSets.size());
|
||||
@@ -752,7 +947,7 @@ std::vector<LineSet> DrawViewSection::getDrawableLines(int i)
|
||||
TopoDS_Face DrawViewSection::getSectionTopoDSFace(int i)
|
||||
{
|
||||
TopoDS_Face result;
|
||||
TopExp_Explorer expl(sectionTopoDSFaces, TopAbs_FACE);
|
||||
TopExp_Explorer expl(m_sectionTopoDSFaces, TopAbs_FACE);
|
||||
int count = 1;
|
||||
for (; expl.More(); expl.Next(), count++) {
|
||||
if (count == i+1) {
|
||||
@@ -967,6 +1162,10 @@ bool DrawViewSection::showSectionEdges(void)
|
||||
return (hGrp->GetBool("ShowSectionEdges", true));
|
||||
}
|
||||
|
||||
bool DrawViewSection::trimAfterCut() const
|
||||
{
|
||||
return TrimAfterCut.getValue();
|
||||
}
|
||||
// Python Drawing feature ---------------------------------------------------------
|
||||
|
||||
namespace App {
|
||||
|
||||
@@ -69,8 +69,10 @@ public:
|
||||
App::PropertyLink BaseView;
|
||||
App::PropertyVector SectionNormal;
|
||||
App::PropertyVector SectionOrigin;
|
||||
App::PropertyEnumeration SectionDirection;
|
||||
App::PropertyString SectionSymbol;
|
||||
|
||||
|
||||
App::PropertyEnumeration SectionDirection; //to be made obsolete eventually
|
||||
App::PropertyEnumeration CutSurfaceDisplay; //new v019
|
||||
App::PropertyFile FileHatchPattern;
|
||||
App::PropertyFile FileGeomPattern; //new v019
|
||||
@@ -79,8 +81,8 @@ public:
|
||||
App::PropertyString NameGeomPattern;
|
||||
App::PropertyFloat HatchScale;
|
||||
|
||||
App::PropertyString SectionSymbol;
|
||||
App::PropertyBool FuseBeforeCut;
|
||||
App::PropertyBool TrimAfterCut; //new v021
|
||||
|
||||
bool isReallyInBox (const Base::Vector3d v, const Base::BoundBox3d bb) const;
|
||||
bool isReallyInBox (const gp_Pnt p, const Bnd_Box& bb) const;
|
||||
@@ -94,26 +96,41 @@ public:
|
||||
short mustExecute() const override;
|
||||
|
||||
void sectionExec(TopoDS_Shape& s);
|
||||
void makeSectionCut(TopoDS_Shape &baseShape);
|
||||
virtual void makeSectionCut(TopoDS_Shape &baseShape);
|
||||
void postHlrTasks(void) override;
|
||||
virtual void postSectionCutTasks();
|
||||
void waitingForCut(bool s) { m_waitingForCut = s; }
|
||||
bool waitingForCut(void) const { return m_waitingForCut; }
|
||||
bool waitingForResult() const override;
|
||||
|
||||
std::vector<TechDraw::FacePtr> getTDFaceGeometry() {return tdSectionFaces;}
|
||||
virtual TopoDS_Shape makeCuttingTool(double shapeSize);
|
||||
virtual TopoDS_Shape getShapeToCut();
|
||||
virtual bool isBaseValid() const;
|
||||
virtual TopoDS_Shape prepareShape(const TopoDS_Shape& rawShape,
|
||||
double shapeSize);
|
||||
virtual TopoDS_Shape getShapeToPrepare() const { return m_cutPieces; }
|
||||
|
||||
//CS related methods
|
||||
gp_Ax2 getProjectionCS(Base::Vector3d pt = Base::Vector3d(0.0, 0.0, 0.0)) const override;
|
||||
void setCSFromBase(const std::string sectionName);
|
||||
gp_Ax2 getCSFromBase(const std::string sectionName) const;
|
||||
|
||||
void setCSFromBase(Base::Vector3d localUnit);
|
||||
void setCSFromLocalUnit(const Base::Vector3d localUnit);
|
||||
virtual gp_Ax2 getCSFromBase(const std::string sectionName) const;
|
||||
gp_Ax2 getSectionCS() const;
|
||||
Base::Vector3d getXDirection() const override; //don't use XDirection.getValue()
|
||||
|
||||
TechDraw::DrawViewPart* getBaseDVP() const;
|
||||
TechDraw::DrawProjGroupItem* getBaseDPGI() const;
|
||||
|
||||
TopoDS_Compound getSectionTFaces() { return sectionTopoDSFaces;}
|
||||
//section face related methods
|
||||
TopoDS_Compound getSectionTFaces() { return m_sectionTopoDSFaces;}
|
||||
std::vector<TechDraw::FacePtr> getTDFaceGeometry() {return m_tdSectionFaces;}
|
||||
TopoDS_Face getSectionTopoDSFace(int i);
|
||||
virtual TopoDS_Compound alignSectionFaces(TopoDS_Shape faceIntersections);
|
||||
TopoDS_Compound mapToPage(TopoDS_Shape& shapeToAlign);
|
||||
virtual std::vector<TechDraw::FacePtr> makeTDSectionFaces(TopoDS_Compound topoDSFaces);
|
||||
virtual TopoDS_Shape getShapeToIntersect() { return m_cutPieces; }
|
||||
|
||||
void makeLineSets(void) ;
|
||||
std::vector<LineSet> getDrawableLines(int i = 0);
|
||||
std::vector<PATLineSpec> getDecodedSpecsFromFile(std::string fileSpec, std::string myPattern);
|
||||
@@ -123,7 +140,7 @@ public:
|
||||
static const char* SectionDirEnums[];
|
||||
static const char* CutSurfaceEnums[];
|
||||
|
||||
std::pair<Base::Vector3d, Base::Vector3d> sectionLineEnds();
|
||||
virtual std::pair<Base::Vector3d, Base::Vector3d> sectionLineEnds();
|
||||
|
||||
bool showSectionEdges(void);
|
||||
|
||||
@@ -131,16 +148,17 @@ public Q_SLOTS:
|
||||
void onSectionCutFinished(void);
|
||||
|
||||
protected:
|
||||
TopoDS_Compound sectionTopoDSFaces; //needed for hatching
|
||||
TopoDS_Compound m_sectionTopoDSFaces; //needed for hatching
|
||||
std::vector<LineSet> m_lineSets;
|
||||
std::vector<TechDraw::FacePtr> tdSectionFaces;
|
||||
std::vector<TechDraw::FacePtr> m_tdSectionFaces;
|
||||
|
||||
|
||||
gp_Pln getSectionPlane() const;
|
||||
TopoDS_Compound findSectionPlaneIntersections(const TopoDS_Shape& shape);
|
||||
virtual gp_Pln getSectionPlane() const;
|
||||
virtual TopoDS_Compound findSectionPlaneIntersections(const TopoDS_Shape& shape);
|
||||
void getParameters();
|
||||
bool debugSection() const;
|
||||
int prefCutSurface() const;
|
||||
bool trimAfterCut() const;
|
||||
|
||||
TopoDS_Shape m_cutShape;
|
||||
|
||||
@@ -151,15 +169,16 @@ protected:
|
||||
void replaceSvgIncluded(std::string newSvgFile);
|
||||
void replacePatIncluded(std::string newPatFile);
|
||||
|
||||
TopoDS_Shape m_rawShape;
|
||||
gp_Ax2 m_viewAxis;
|
||||
TopoDS_Shape m_scaledShape;
|
||||
TopoDS_Shape m_cutPieces; //the shape after cutting, but before centering & scaling
|
||||
gp_Ax2 m_projectionCS;
|
||||
TopoDS_Shape m_preparedShape; //the shape after cutting, centering, scaling etc
|
||||
|
||||
QMetaObject::Connection connectCutWatcher;
|
||||
QFutureWatcher<void> m_cutWatcher;
|
||||
QFuture<void> m_cutFuture;
|
||||
bool m_waitingForCut;
|
||||
|
||||
TopoDS_Shape m_cuttingTool;
|
||||
double m_shapeSize;
|
||||
};
|
||||
|
||||
using DrawViewSectionPython = App::FeaturePythonT<DrawViewSection>;
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <iomanip>
|
||||
# include <sstream>
|
||||
# include <boost/regex.hpp>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <boost/regex.hpp>
|
||||
#endif
|
||||
|
||||
#include <App/Property.h>
|
||||
@@ -34,10 +34,10 @@
|
||||
#include <Mod/Spreadsheet/App/Cell.h>
|
||||
#include <Mod/Spreadsheet/App/Sheet.h>
|
||||
|
||||
#include "DrawViewSpreadsheet.h"
|
||||
#include "DrawUtil.h"
|
||||
#include "Preferences.h"
|
||||
|
||||
#include "DrawViewSpreadsheet.h"
|
||||
|
||||
using namespace TechDraw;
|
||||
|
||||
|
||||
@@ -1246,8 +1246,8 @@ bool BSpline::isLine()
|
||||
return false;
|
||||
}
|
||||
|
||||
Base::Vector3d vs = DrawUtil::gpPnt2V3(s);
|
||||
Base::Vector3d ve = DrawUtil::gpPnt2V3(e);
|
||||
Base::Vector3d vs = DrawUtil::toVector3d(s);
|
||||
Base::Vector3d ve = DrawUtil::toVector3d(e);
|
||||
double endLength = (vs - ve).Length();
|
||||
int low = 0;
|
||||
int high = spline->NbPoles() - 1;
|
||||
@@ -1256,9 +1256,9 @@ bool BSpline::isLine()
|
||||
double lenTotal = 0.0;
|
||||
for (int i = 0; i < high; i++) {
|
||||
gp_Pnt p1 = poles(i);
|
||||
Base::Vector3d v1 = DrawUtil::gpPnt2V3(p1);
|
||||
Base::Vector3d v1 = DrawUtil::toVector3d(p1);
|
||||
gp_Pnt p2 = poles(i+1);
|
||||
Base::Vector3d v2 = DrawUtil::gpPnt2V3(p2);
|
||||
Base::Vector3d v2 = DrawUtil::toVector3d(p2);
|
||||
lenTotal += (v2-v1).Length();
|
||||
}
|
||||
|
||||
@@ -1415,7 +1415,7 @@ TopoDS_Edge BSpline::asCircle(bool& arc)
|
||||
gp_Circ circle1 = gce_circ1.Value();
|
||||
double radius1 = circle1.Radius();
|
||||
gp_Pnt center1 = circle1.Location();
|
||||
Base::Vector3d vc1 = DrawUtil::gpPnt2V3(center1);
|
||||
Base::Vector3d vc1 = DrawUtil::toVector3d(center1);
|
||||
|
||||
gce_MakeCirc gce_circ2 = gce_MakeCirc(pcm, pc2, e);
|
||||
if (gce_circ2.Status() != gce_Done) {
|
||||
@@ -1424,7 +1424,7 @@ TopoDS_Edge BSpline::asCircle(bool& arc)
|
||||
gp_Circ circle2 = gce_circ2.Value();
|
||||
double radius2 = circle2.Radius();
|
||||
gp_Pnt center2 = circle2.Location();
|
||||
Base::Vector3d vc2 = DrawUtil::gpPnt2V3(center2);
|
||||
Base::Vector3d vc2 = DrawUtil::toVector3d(center2);
|
||||
|
||||
// compare radii & centers
|
||||
double allowError = 0.001; //mm^-3 good enough for printing
|
||||
|
||||
@@ -24,32 +24,39 @@
|
||||
|
||||
#ifndef _PreComp_
|
||||
#include <Bnd_Box.hxx>
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <BRepAlgo_NormalProjection.hxx>
|
||||
#include <BRepBndLib.hxx>
|
||||
#include <BRepBuilderAPI_Copy.hxx>
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRepBuilderAPI_MakeFace.hxx>
|
||||
#include <BRepBuilderAPI_Transform.hxx>
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <BRepLib.hxx>
|
||||
#include <BRepLib.hxx>
|
||||
#include <BRepLProp_CLProps.hxx>
|
||||
#include <BRepLProp_CurveTool.hxx>
|
||||
#include <BRepMesh_IncrementalMesh.hxx>
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <BRepTools.hxx>
|
||||
#include <gp_Ax1.hxx>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Ax3.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Pln.hxx>
|
||||
#include <gp_Trsf.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#include <HLRBRep.hxx>
|
||||
#include <HLRAlgo_Projector.hxx>
|
||||
#include <HLRBRep_Algo.hxx>
|
||||
#include <HLRBRep_HLRToShape.hxx>
|
||||
#include <HLRBRep.hxx>
|
||||
#include <HLRBRep_PolyAlgo.hxx>
|
||||
#include <HLRAlgo_Projector.hxx>
|
||||
#include <HLRBRep_PolyHLRToShape.hxx>
|
||||
#include <TopExp.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopExp.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
#include <TopoDS_Vertex.hxx>
|
||||
#endif // #ifndef _PreComp_
|
||||
@@ -70,6 +77,8 @@
|
||||
using namespace TechDraw;
|
||||
using namespace std;
|
||||
|
||||
using DU = DrawUtil;
|
||||
|
||||
struct EdgePoints {
|
||||
gp_Pnt v1, v2;
|
||||
TopoDS_Edge edge;
|
||||
@@ -180,6 +189,7 @@ void GeometryObject::projectShape(const TopoDS_Shape& inShape,
|
||||
visHard = hlrToShape.VCompound();
|
||||
BRepLib::BuildCurves3d(visHard);
|
||||
visHard = invertGeometry(visHard);
|
||||
// BRepTools::Write(visHard, "GOvisHard.brep"); //debug
|
||||
}
|
||||
|
||||
if (!hlrToShape.Rg1LineVCompound().IsNull()) {
|
||||
@@ -417,6 +427,46 @@ void GeometryObject::projectShapeWithPolygonAlgo(const TopoDS_Shape& input,
|
||||
makeTDGeometry();
|
||||
}
|
||||
|
||||
//project the edges in shape onto XY.mirrored plane of CS. mimics the projection
|
||||
//of the main hlr routine. Only the visible hard edges are returned, so this method
|
||||
//is only suitable for simple shapes that have no hidden edges, like faces or wires.
|
||||
//TODO: allow use of perspective projector
|
||||
TopoDS_Shape GeometryObject::projectSimpleShape(const TopoDS_Shape &shape,
|
||||
const gp_Ax2 &CS)
|
||||
{
|
||||
// Base::Console().Message("GO::()\n");
|
||||
if(shape.IsNull()) {
|
||||
throw Base::ValueError("GO::projectSimpleShape - input shape is NULL");
|
||||
}
|
||||
|
||||
HLRBRep_Algo *brep_hlr = new HLRBRep_Algo();
|
||||
brep_hlr->Add(shape);
|
||||
HLRAlgo_Projector projector( CS );
|
||||
brep_hlr->Projector(projector);
|
||||
brep_hlr->Update();
|
||||
brep_hlr->Hide();
|
||||
|
||||
HLRBRep_HLRToShape hlrToShape(brep_hlr);
|
||||
TopoDS_Shape hardEdges = hlrToShape.VCompound();
|
||||
BRepLib::BuildCurves3d(hardEdges);
|
||||
hardEdges = invertGeometry(hardEdges);
|
||||
|
||||
return hardEdges;
|
||||
}
|
||||
|
||||
//project the edges of a shape onto the XY plane of projCS. This does not give
|
||||
//the same result as the hlr projections
|
||||
TopoDS_Shape GeometryObject::simpleProjection(const TopoDS_Shape& shape,
|
||||
const gp_Ax2& projCS)
|
||||
{
|
||||
gp_Pln plane(projCS);
|
||||
TopoDS_Face paper = BRepBuilderAPI_MakeFace(plane);
|
||||
BRepAlgo_NormalProjection projector(paper);
|
||||
projector.Add(shape);
|
||||
projector.Build();
|
||||
return projector.Projection();
|
||||
}
|
||||
|
||||
TopoDS_Shape GeometryObject::projectFace(const TopoDS_Shape &face,
|
||||
const gp_Ax2 &CS)
|
||||
{
|
||||
@@ -510,11 +560,11 @@ void GeometryObject::addGeomFromCompound(TopoDS_Shape edgeCompound, edgeClass ca
|
||||
Base::Console().Log("GO::addGeomFromCompound - edge: %d is NULL\n", i);
|
||||
continue;
|
||||
}
|
||||
if (DrawUtil::isZeroEdge(edge)) {
|
||||
if (DU::isZeroEdge(edge)) {
|
||||
Base::Console().Log("GO::addGeomFromCompound - edge: %d is zeroEdge\n", i);
|
||||
continue;
|
||||
}
|
||||
if (DrawUtil::isCrazy(edge)) {
|
||||
if (DU::isCrazy(edge)) {
|
||||
Base::Console().Log("GO::addGeomFromCompound - edge: %d is crazy\n", i);
|
||||
continue;
|
||||
}
|
||||
@@ -860,7 +910,7 @@ gp_Ax2 TechDraw::getViewAxis(const Base::Vector3d origin,
|
||||
Base::Vector3d stdZ(0.0, 0.0, 1.0);
|
||||
Base::Vector3d stdOrg(0.0, 0.0, 0.0);
|
||||
Base::Vector3d cross = direction;
|
||||
if (TechDraw::DrawUtil::checkParallel(direction, stdZ)) {
|
||||
if (DU::checkParallel(direction, stdZ)) {
|
||||
cross = Base::Vector3d(1.0, 0.0, 0.0);
|
||||
} else {
|
||||
cross.Normalize();
|
||||
@@ -913,7 +963,7 @@ gp_Ax2 TechDraw::legacyViewAxis1(const Base::Vector3d origin,
|
||||
}
|
||||
Base::Vector3d cross = flipDirection;
|
||||
// //special case
|
||||
if (TechDraw::DrawUtil::checkParallel(flipDirection, stdZ)) {
|
||||
if (DU::checkParallel(flipDirection, stdZ)) {
|
||||
cross = Base::Vector3d(1.0, 0.0, 0.0);
|
||||
} else {
|
||||
cross.Normalize();
|
||||
@@ -940,6 +990,23 @@ gp_Ax2 TechDraw::legacyViewAxis1(const Base::Vector3d origin,
|
||||
return viewAxis;
|
||||
}
|
||||
|
||||
//! Returns the centroid of shape based on R3
|
||||
gp_Pnt TechDraw::findCentroid(const TopoDS_Shape& shape)
|
||||
{
|
||||
Bnd_Box tBounds;
|
||||
tBounds.SetGap(0.0);
|
||||
BRepBndLib::AddOptimal(shape, tBounds, true, false);
|
||||
|
||||
Standard_Real xMin, yMin, zMin, xMax, yMax, zMax;
|
||||
tBounds.Get(xMin, yMin, zMin, xMax, yMax, zMax);
|
||||
|
||||
Standard_Real x = (xMin + xMax) / 2.0,
|
||||
y = (yMin + yMax) / 2.0,
|
||||
z = (zMin + zMax) / 2.0;
|
||||
|
||||
return gp_Pnt(x, y, z);
|
||||
}
|
||||
|
||||
//! Returns the centroid of shape, as viewed according to direction
|
||||
gp_Pnt TechDraw::findCentroid(const TopoDS_Shape &shape,
|
||||
const Base::Vector3d &direction)
|
||||
@@ -955,8 +1022,6 @@ gp_Pnt TechDraw::findCentroid(const TopoDS_Shape &shape,
|
||||
const gp_Ax2 &viewAxis)
|
||||
{
|
||||
// Base::Console().Message("GO::findCentroid() - 2\n");
|
||||
// Base::Vector3d origin(0.0, 0.0, 0.0);
|
||||
// gp_Ax2 viewAxis = getViewAxis(origin, direction);
|
||||
|
||||
gp_Trsf tempTransform;
|
||||
tempTransform.SetTransformation(viewAxis);
|
||||
@@ -1020,7 +1085,7 @@ TopoDS_Shape TechDraw::mirrorShape(const TopoDS_Shape &input,
|
||||
// mirror about the Y axis
|
||||
gp_Trsf tempTransform;
|
||||
//BRepBuilderAPI_Transform will loop forever if asked to use 0.0 as scale
|
||||
if (!(scale > 0.0)) {
|
||||
if (scale <= 0.0) {
|
||||
tempTransform.SetScale(inputCenter, 1.0);
|
||||
} else {
|
||||
tempTransform.SetScale(inputCenter, scale);
|
||||
@@ -1042,8 +1107,8 @@ TopoDS_Shape TechDraw::mirrorShape(const TopoDS_Shape &input,
|
||||
|
||||
//!rotates a shape about a viewAxis
|
||||
TopoDS_Shape TechDraw::rotateShape(const TopoDS_Shape &input,
|
||||
gp_Ax2& viewAxis,
|
||||
double rotAngle)
|
||||
const gp_Ax2 &viewAxis,
|
||||
double rotAngle)
|
||||
{
|
||||
TopoDS_Shape transShape;
|
||||
if (input.IsNull()) {
|
||||
@@ -1103,3 +1168,62 @@ TopoDS_Shape TechDraw::moveShape(const TopoDS_Shape &input,
|
||||
}
|
||||
return transShape;
|
||||
}
|
||||
|
||||
|
||||
//!moves a shape with restricts on directions
|
||||
TopoDS_Shape TechDraw::moveShapeRestricted(const TopoDS_Shape &input,
|
||||
const Base::Vector3d& motion,
|
||||
bool allowX,
|
||||
bool allowY,
|
||||
bool allowZ)
|
||||
{
|
||||
gp_Vec gMotion(allowX ? motion.x : 0.0,
|
||||
allowY ? motion.y : 0.0,
|
||||
allowZ ? motion.z : 0.0);
|
||||
TopoDS_Shape transShape;
|
||||
try {
|
||||
gp_Trsf xlate;
|
||||
xlate.SetTranslation(gMotion);
|
||||
|
||||
BRepBuilderAPI_Transform mkTrf(input, xlate);
|
||||
transShape = mkTrf.Shape();
|
||||
}
|
||||
catch (...) {
|
||||
Base::Console().Log("GeometryObject::moveShapeRestricted - move failed.\n");
|
||||
return transShape;
|
||||
}
|
||||
return transShape;
|
||||
}
|
||||
|
||||
//!moves a shape with restricts on directions
|
||||
TopoDS_Shape TechDraw::moveShapeRestricted(const TopoDS_Shape &input,
|
||||
const Base::Vector3d& motion,
|
||||
const Base::Vector3d& mask)
|
||||
{
|
||||
gp_Vec gMotion(mask.x ? motion.x : 0.0,
|
||||
mask.y ? motion.y : 0.0,
|
||||
mask.z ? motion.z : 0.0);
|
||||
|
||||
TopoDS_Shape transShape;
|
||||
try {
|
||||
gp_Trsf xlate;
|
||||
xlate.SetTranslation(gMotion);
|
||||
|
||||
BRepBuilderAPI_Transform mkTrf(input, xlate);
|
||||
transShape = mkTrf.Shape();
|
||||
}
|
||||
catch (...) {
|
||||
Base::Console().Log("GeometryObject::moveShapeRestricted - move failed.\n");
|
||||
return transShape;
|
||||
}
|
||||
return transShape;
|
||||
}
|
||||
|
||||
TopoDS_Shape TechDraw::moveShapeRestricted(const TopoDS_Shape &input,
|
||||
const gp_Vec& motion,
|
||||
const gp_Vec& mask)
|
||||
{
|
||||
return moveShapeRestricted(input,
|
||||
DU::toVector3d(motion),
|
||||
DU::toVector3d(mask));
|
||||
}
|
||||
|
||||
@@ -67,13 +67,24 @@ TopoDS_Shape TechDrawExport mirrorShape(const TopoDS_Shape &input,
|
||||
TopoDS_Shape TechDrawExport scaleShape(const TopoDS_Shape &input,
|
||||
double scale);
|
||||
TopoDS_Shape TechDrawExport rotateShape(const TopoDS_Shape &input,
|
||||
gp_Ax2& viewAxis,
|
||||
double rotAngle);
|
||||
const gp_Ax2& viewAxis,
|
||||
double rotAngle);
|
||||
TopoDS_Shape TechDrawExport moveShape(const TopoDS_Shape &input,
|
||||
const Base::Vector3d& motion);
|
||||
|
||||
TopoDS_Shape TechDrawExport moveShapeRestricted(const TopoDS_Shape &input,
|
||||
const Base::Vector3d& motion,
|
||||
bool allowX = true,
|
||||
bool allowY = true,
|
||||
bool allowZ = true);
|
||||
TopoDS_Shape TechDrawExport moveShapeRestricted(const TopoDS_Shape &input,
|
||||
const Base::Vector3d& motion,
|
||||
const Base::Vector3d& mask);
|
||||
TopoDS_Shape TechDrawExport moveShapeRestricted(const TopoDS_Shape &input,
|
||||
const gp_Vec& motion,
|
||||
const gp_Vec& mask);
|
||||
|
||||
//! Returns the centroid of shape, as viewed according to direction
|
||||
gp_Pnt TechDrawExport findCentroid(const TopoDS_Shape& shape);
|
||||
gp_Pnt TechDrawExport findCentroid(const TopoDS_Shape &shape,
|
||||
const Base::Vector3d &direction);
|
||||
gp_Pnt TechDrawExport findCentroid(const TopoDS_Shape &shape,
|
||||
@@ -118,9 +129,12 @@ public:
|
||||
const gp_Ax2 &viewAxis);
|
||||
void projectShapeWithPolygonAlgo(const TopoDS_Shape &input,
|
||||
const gp_Ax2 &viewAxis);
|
||||
TopoDS_Shape projectFace(const TopoDS_Shape &face,
|
||||
const gp_Ax2 &CS);
|
||||
|
||||
static TopoDS_Shape projectSimpleShape(const TopoDS_Shape &shape,
|
||||
const gp_Ax2 &CS);
|
||||
static TopoDS_Shape simpleProjection(const TopoDS_Shape& shape,
|
||||
const gp_Ax2& projCS);
|
||||
static TopoDS_Shape projectFace(const TopoDS_Shape &face,
|
||||
const gp_Ax2 &CS);
|
||||
void makeTDGeometry();
|
||||
void extractGeometry(edgeClass category, bool visible);
|
||||
void addFaceGeom(FacePtr f);
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <chrono>
|
||||
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
@@ -132,7 +132,28 @@ double Preferences::vertexScale()
|
||||
return result;
|
||||
}
|
||||
|
||||
int Preferences::scaleType()
|
||||
{
|
||||
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
|
||||
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/General");
|
||||
int result = hGrp->GetInt("DefaultScaleType", 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
double Preferences::scale()
|
||||
{
|
||||
int prefScaleType = scaleType();
|
||||
if (prefScaleType == 0) { //page scale
|
||||
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
|
||||
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/General");
|
||||
return hGrp->GetFloat("DefaultPageScale", 1.0);
|
||||
} else if (prefScaleType == 1) { //custom scale
|
||||
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
|
||||
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/General");
|
||||
return hGrp->GetFloat("DefaultViewScale", 1.0);
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
//lightgray #D3D3D3
|
||||
|
||||
|
||||
@@ -52,7 +52,8 @@ static App::Color selectColor();
|
||||
static App::Color preselectColor();
|
||||
static App::Color vertexColor();
|
||||
static double vertexScale();
|
||||
|
||||
static int scaleType();
|
||||
static double scale();
|
||||
static bool useGlobalDecimals();
|
||||
static bool keepPagesUpToDate();
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@ set(TechDrawGui_UIC_SRCS
|
||||
SymbolChooser.ui
|
||||
TaskMoveView.ui
|
||||
TaskProjection.ui
|
||||
TaskComplexSection.ui
|
||||
)
|
||||
|
||||
if(BUILD_QT5)
|
||||
@@ -222,6 +223,15 @@ SET(TechDrawGui_SRCS
|
||||
TaskProjection.cpp
|
||||
TaskProjection.h
|
||||
TaskProjection.ui
|
||||
TaskComplexSection.cpp
|
||||
TaskComplexSection.h
|
||||
TaskComplexSection.ui
|
||||
Widgets/CompassDialWidget.cpp
|
||||
Widgets/CompassDialWidget.h
|
||||
Widgets/CompassWidget.cpp
|
||||
Widgets/CompassWidget.h
|
||||
Widgets/VectorEditWidget.cpp
|
||||
Widgets/VectorEditWidget.h
|
||||
)
|
||||
|
||||
SET(TechDrawGuiView_SRCS
|
||||
@@ -419,6 +429,7 @@ SET(TechDrawGuiTaskDlgs_SRCS
|
||||
TaskCustomizeFormat.ui
|
||||
TaskMoveView.ui
|
||||
TaskProjection.ui
|
||||
TaskComplexSection.ui
|
||||
)
|
||||
|
||||
SOURCE_GROUP("MRTE" FILES ${MRTE_SRCS})
|
||||
|
||||
@@ -21,19 +21,23 @@
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <QFileInfo>
|
||||
# include <QMessageBox>
|
||||
# include <sstream>
|
||||
# include <vector>
|
||||
#include <QApplication>
|
||||
#include <QFileInfo>
|
||||
#include <QMessageBox>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#endif
|
||||
|
||||
#include <App/Document.h>
|
||||
#include <App/DocumentObject.h>
|
||||
#include <App/Link.h>
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Tools.h>
|
||||
|
||||
#include <Gui/Action.h>
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/BitmapFactory.h>
|
||||
#include <Gui/Command.h>
|
||||
#include <Gui/Control.h>
|
||||
#include <Gui/Document.h>
|
||||
@@ -43,14 +47,18 @@
|
||||
#include <Gui/SelectionObject.h>
|
||||
#include <Gui/ViewProvider.h>
|
||||
#include <Gui/WaitCursor.h>
|
||||
|
||||
#include <Mod/Spreadsheet/App/Sheet.h>
|
||||
|
||||
#include <Mod/TechDraw/App/DrawComplexSection.h>
|
||||
#include <Mod/TechDraw/App/DrawPage.h>
|
||||
#include <Mod/TechDraw/App/DrawProjGroup.h>
|
||||
#include <Mod/TechDraw/App/DrawUtil.h>
|
||||
#include <Mod/TechDraw/App/DrawUtil.h>
|
||||
#include <Mod/TechDraw/App/DrawViewArch.h>
|
||||
#include <Mod/TechDraw/App/DrawViewClip.h>
|
||||
#include <Mod/TechDraw/App/DrawViewDetail.h>
|
||||
#include <Mod/TechDraw/App/DrawViewDraft.h>
|
||||
#include <Mod/TechDraw/App/DrawViewMulti.h>
|
||||
#include <Mod/TechDraw/App/DrawViewPart.h>
|
||||
#include <Mod/TechDraw/App/DrawViewSymbol.h>
|
||||
#include <Mod/TechDraw/App/Preferences.h>
|
||||
@@ -62,6 +70,7 @@
|
||||
#include "QGVPage.h"
|
||||
#include "Rez.h"
|
||||
#include "TaskActiveView.h"
|
||||
#include "TaskComplexSection.h"
|
||||
#include "TaskDetail.h"
|
||||
#include "TaskProjGroup.h"
|
||||
#include "TaskProjection.h"
|
||||
@@ -69,6 +78,8 @@
|
||||
#include "ViewProviderViewPart.h"
|
||||
#include "TaskSectionView.h"
|
||||
|
||||
void execSimpleSection(Gui::Command* cmd);
|
||||
void execComplexSection(Gui::Command* cmd);
|
||||
|
||||
class Vertex;
|
||||
using namespace TechDrawGui;
|
||||
@@ -462,6 +473,98 @@ bool CmdTechDrawActiveView::isActive()
|
||||
return DrawGuiUtil::needPage(this, true);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// TechDraw_SectionGroup
|
||||
//===========================================================================
|
||||
|
||||
DEF_STD_CMD_ACL(CmdTechDrawSectionGroup)
|
||||
|
||||
CmdTechDrawSectionGroup::CmdTechDrawSectionGroup()
|
||||
: Command("TechDraw_SectionGroup")
|
||||
{
|
||||
sAppModule = "TechDraw";
|
||||
sGroup = QT_TR_NOOP("TechDraw");
|
||||
sMenuText = QT_TR_NOOP("Insert a simple or complex Section View");
|
||||
sToolTipText = sMenuText;
|
||||
sWhatsThis = "TechDraw_SectionGroup";
|
||||
sStatusTip = sToolTipText;
|
||||
}
|
||||
|
||||
void CmdTechDrawSectionGroup::activated(int iMsg)
|
||||
{
|
||||
// Base::Console().Message("CMD::SectionGrp - activated(%d)\n", iMsg);
|
||||
Gui::TaskView::TaskDialog *dlg = Gui::Control().activeDialog();
|
||||
if (dlg) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Task In Progress"),
|
||||
QObject::tr("Close active task dialog and try again."));
|
||||
return;
|
||||
}
|
||||
|
||||
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
|
||||
pcAction->setIcon(pcAction->actions().at(iMsg)->icon());
|
||||
switch(iMsg) {
|
||||
case 0:
|
||||
execSimpleSection(this);
|
||||
break;
|
||||
case 1:
|
||||
execComplexSection(this);
|
||||
break;
|
||||
default:
|
||||
Base::Console().Message("CMD::SectionGrp - invalid iMsg: %d\n", iMsg);
|
||||
};
|
||||
}
|
||||
|
||||
Gui::Action * CmdTechDrawSectionGroup::createAction()
|
||||
{
|
||||
Gui::ActionGroup* pcAction = new Gui::ActionGroup(this, Gui::getMainWindow());
|
||||
pcAction->setDropDownMenu(true);
|
||||
applyCommandData(this->className(), pcAction);
|
||||
|
||||
QAction* p1 = pcAction->addAction(QString());
|
||||
p1->setIcon(Gui::BitmapFactory().iconFromTheme("actions/TechDraw_SectionView"));
|
||||
p1->setObjectName(QString::fromLatin1("TechDraw_SectionView"));
|
||||
p1->setWhatsThis(QString::fromLatin1("TechDraw_SectionView"));
|
||||
QAction* p2 = pcAction->addAction(QString());
|
||||
p2->setIcon(Gui::BitmapFactory().iconFromTheme("actions/TechDraw_ComplexSection"));
|
||||
p2->setObjectName(QString::fromLatin1("TechDraw_ComplexSection"));
|
||||
p2->setWhatsThis(QString::fromLatin1("TechDraw_ComplexSection"));
|
||||
|
||||
_pcAction = pcAction;
|
||||
languageChange();
|
||||
|
||||
pcAction->setIcon(p1->icon());
|
||||
int defaultId = 0;
|
||||
pcAction->setProperty("defaultAction", QVariant(defaultId));
|
||||
|
||||
return pcAction;
|
||||
}
|
||||
|
||||
void CmdTechDrawSectionGroup::languageChange()
|
||||
{
|
||||
Command::languageChange();
|
||||
|
||||
if (!_pcAction)
|
||||
return;
|
||||
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
|
||||
QList<QAction*> a = pcAction->actions();
|
||||
|
||||
QAction* arc1 = a[0];
|
||||
arc1->setText(QApplication::translate("CmdTechDrawSectionGroup", "Section View"));
|
||||
arc1->setToolTip(QApplication::translate("TechDraw_SectionView", "Insert simple Section View"));
|
||||
arc1->setStatusTip(arc1->toolTip());
|
||||
QAction* arc2 = a[1];
|
||||
arc2->setText(QApplication::translate("CmdTechDrawSectionGroup", "Complex Section"));
|
||||
arc2->setToolTip(QApplication::translate("TechDraw_ComplexSection", "Insert complex Section View"));
|
||||
arc2->setStatusTip(arc2->toolTip());
|
||||
}
|
||||
|
||||
bool CmdTechDrawSectionGroup::isActive()
|
||||
{
|
||||
bool havePage = DrawGuiUtil::needPage(this);
|
||||
bool haveView = DrawGuiUtil::needView(this, false);
|
||||
return (havePage && haveView);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// TechDraw_SectionView
|
||||
//===========================================================================
|
||||
@@ -483,22 +586,14 @@ CmdTechDrawSectionView::CmdTechDrawSectionView()
|
||||
void CmdTechDrawSectionView::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
TechDraw::DrawPage* page = DrawGuiUtil::findPage(this);
|
||||
if (!page) {
|
||||
Gui::TaskView::TaskDialog *dlg = Gui::Control().activeDialog();
|
||||
if (dlg) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Task In Progress"),
|
||||
QObject::tr("Close active task dialog and try again."));
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<App::DocumentObject*> baseObj = getSelection().getObjectsOfType(TechDraw::DrawViewPart::getClassTypeId());
|
||||
if (baseObj.empty()) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Select at least 1 DrawViewPart object as Base."));
|
||||
return;
|
||||
}
|
||||
TechDraw::DrawViewPart* dvp = static_cast<TechDraw::DrawViewPart*>(*baseObj.begin());
|
||||
Gui::Control().showDialog(new TaskDlgSectionView(dvp));
|
||||
|
||||
updateActive(); //ok here since dialog doesn't call doc.recompute()
|
||||
commitCommand();
|
||||
execSimpleSection(this);
|
||||
}
|
||||
|
||||
bool CmdTechDrawSectionView::isActive()
|
||||
@@ -512,6 +607,154 @@ bool CmdTechDrawSectionView::isActive()
|
||||
return (havePage && haveView && !taskInProgress);
|
||||
}
|
||||
|
||||
void execSimpleSection(Gui::Command* cmd)
|
||||
{
|
||||
TechDraw::DrawPage* page = DrawGuiUtil::findPage(cmd);
|
||||
if (!page) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<App::DocumentObject*> baseObj = cmd->getSelection().getObjectsOfType(TechDraw::DrawViewPart::getClassTypeId());
|
||||
if (baseObj.empty()) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Select at least 1 DrawViewPart object as Base."));
|
||||
return;
|
||||
}
|
||||
TechDraw::DrawViewPart* dvp = static_cast<TechDraw::DrawViewPart*>(*baseObj.begin());
|
||||
Gui::Control().showDialog(new TaskDlgSectionView(dvp));
|
||||
|
||||
cmd->updateActive(); //ok here since dialog doesn't call doc.recompute()
|
||||
cmd->commitCommand();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// TechDraw_ComplexSection
|
||||
//===========================================================================
|
||||
|
||||
DEF_STD_CMD_A(CmdTechDrawComplexSection)
|
||||
|
||||
CmdTechDrawComplexSection::CmdTechDrawComplexSection()
|
||||
: Command("TechDraw_ComplexSection")
|
||||
{
|
||||
sAppModule = "TechDraw";
|
||||
sGroup = QT_TR_NOOP("TechDraw");
|
||||
sMenuText = QT_TR_NOOP("Insert Complex Section");
|
||||
sToolTipText = QT_TR_NOOP("Insert a Complex Section");
|
||||
sWhatsThis = "TechDraw_ComplexSection";
|
||||
sStatusTip = sToolTipText;
|
||||
sPixmap = "actions/TechDraw_ComplexSection";
|
||||
}
|
||||
|
||||
void CmdTechDrawComplexSection::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
Gui::TaskView::TaskDialog *dlg = Gui::Control().activeDialog();
|
||||
if (dlg) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Task In Progress"),
|
||||
QObject::tr("Close active task dialog and try again."));
|
||||
return;
|
||||
}
|
||||
|
||||
execComplexSection(this);
|
||||
}
|
||||
|
||||
bool CmdTechDrawComplexSection::isActive()
|
||||
{
|
||||
return DrawGuiUtil::needPage(this);
|
||||
}
|
||||
|
||||
//Complex Sections can be created without a baseView, so the gathering of input
|
||||
//for the dialog is more involved that simple section
|
||||
void execComplexSection(Gui::Command* cmd)
|
||||
{
|
||||
TechDraw::DrawPage* page = DrawGuiUtil::findPage(cmd);
|
||||
if (!page) {
|
||||
return;
|
||||
}
|
||||
std::string PageName = page->getNameInDocument();
|
||||
|
||||
TechDraw::DrawViewPart* baseView(nullptr);
|
||||
std::vector<App::DocumentObject*> shapes;
|
||||
std::vector<App::DocumentObject*> xShapes;
|
||||
App::DocumentObject* profileObject(nullptr);
|
||||
std::vector<std::string> profileSubs;
|
||||
Gui::ResolveMode resolve = Gui::ResolveMode::OldStyleElement; //mystery
|
||||
bool single = false; //mystery
|
||||
auto selection = 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(TechDraw::DrawViewPart::getClassTypeId())) {
|
||||
//use the dvp's Sources as sources for this ComplexSection &
|
||||
//check the subelement(s) to see if they can be used as a profile
|
||||
baseView = static_cast<TechDraw::DrawViewPart*>(obj);
|
||||
if (!sel.getSubNames().empty()) {
|
||||
//need to add profile subs as parameter
|
||||
profileObject = baseView;
|
||||
profileSubs = sel.getSubNames();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (obj->isDerivedFrom(App::LinkElement::getClassTypeId()) ||
|
||||
obj->isDerivedFrom(App::LinkGroup::getClassTypeId()) ||
|
||||
obj->isDerivedFrom(App::Link::getClassTypeId()) ) {
|
||||
is_linked = true;
|
||||
}
|
||||
// If parent of the obj is a link to another document, we possibly need to treat non-link obj as linked, too
|
||||
// 1st, is obj in another document?
|
||||
if (obj->getDocument() != 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's an XLink target
|
||||
is_linked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_linked) {
|
||||
xShapes.push_back(obj);
|
||||
continue;
|
||||
}
|
||||
//not a Link and not null. assume to be drawable. Undrawables will be
|
||||
// skipped later.
|
||||
if (TechDraw::DrawComplexSection::isProfileObject(obj)) {
|
||||
profileObject = obj;
|
||||
} else {
|
||||
shapes.push_back(obj);
|
||||
}
|
||||
}
|
||||
|
||||
if (shapes.empty() &&
|
||||
xShapes.empty() &&
|
||||
!baseView) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("No Base View, Shapes, Groups or Links in this selection"));
|
||||
return;
|
||||
}
|
||||
if (!profileObject) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("No profile object found in selection"));
|
||||
return;
|
||||
}
|
||||
|
||||
Gui::Control().showDialog(new TaskDlgComplexSection(page, baseView,
|
||||
shapes, xShapes,
|
||||
profileObject, profileSubs));
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// TechDraw_DetailView
|
||||
//===========================================================================
|
||||
@@ -714,63 +957,6 @@ bool CmdTechDrawProjectionGroup::isActive()
|
||||
return (havePage && !taskInProgress);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// TechDraw_NewMulti **deprecated**
|
||||
//===========================================================================
|
||||
|
||||
//DEF_STD_CMD_A(CmdTechDrawNewMulti);
|
||||
|
||||
//CmdTechDrawNewMulti::CmdTechDrawNewMulti()
|
||||
// : Command("TechDraw_NewMulti")
|
||||
//{
|
||||
// sAppModule = "TechDraw";
|
||||
// sGroup = QT_TR_NOOP("TechDraw");
|
||||
// sMenuText = QT_TR_NOOP("Insert multi-part view in drawing");
|
||||
// sToolTipText = QT_TR_NOOP("Insert a new View of a multiple Parts in the active drawing");
|
||||
// sWhatsThis = "TechDraw_NewMulti";
|
||||
// sStatusTip = sToolTipText;
|
||||
// sPixmap = "actions/TechDraw_Multiview";
|
||||
//}
|
||||
|
||||
//void CmdTechDrawNewMulti::activated(int iMsg)
|
||||
//{
|
||||
// Q_UNUSED(iMsg);
|
||||
// TechDraw::DrawPage* page = DrawGuiUtil::findPage(this);
|
||||
// if (!page) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// std::vector<App::DocumentObject*> shapes = getSelection().getObjectsOfType(App::DocumentObject::getClassTypeId());
|
||||
// if (shapes.empty()) {
|
||||
// QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
// QObject::tr("Can not MultiView from this selection."));
|
||||
// return;
|
||||
// }
|
||||
|
||||
// std::string PageName = page->getNameInDocument();
|
||||
|
||||
// Gui::WaitCursor wc;
|
||||
|
||||
// openCommand(QT_TRANSLATE_NOOP("Command", "Create view"));
|
||||
// std::string FeatName = getUniqueObjectName("MultiView");
|
||||
// doCommand(Doc, "App.activeDocument().addObject('TechDraw::DrawViewMulti', '%s')", FeatName.c_str());
|
||||
// App::DocumentObject *docObj = getDocument()->getObject(FeatName.c_str());
|
||||
// auto multiView( static_cast<TechDraw::DrawViewMulti *>(docObj) );
|
||||
// multiView->Sources.setValues(shapes);
|
||||
// doCommand(Doc, "App.activeDocument().%s.addView(App.activeDocument().%s)", PageName.c_str(), FeatName.c_str());
|
||||
// updateActive();
|
||||
// commitCommand();
|
||||
//}
|
||||
|
||||
//bool CmdTechDrawNewMulti::isActive(void)
|
||||
//{
|
||||
// return DrawGuiUtil::needPage(this);
|
||||
//}
|
||||
|
||||
//===========================================================================
|
||||
// TechDraw_Balloon
|
||||
//===========================================================================
|
||||
|
||||
//! common checks of Selection for Dimension commands
|
||||
//non-empty selection, no more than maxObjs selected and at least 1 DrawingPage exists
|
||||
bool _checkSelectionBalloon(Gui::Command* cmd, unsigned maxObjs) {
|
||||
@@ -1496,7 +1682,9 @@ void CreateTechDrawCommands()
|
||||
rcCmdMgr.addCommand(new CmdTechDrawPrintAll());
|
||||
rcCmdMgr.addCommand(new CmdTechDrawView());
|
||||
rcCmdMgr.addCommand(new CmdTechDrawActiveView());
|
||||
rcCmdMgr.addCommand(new CmdTechDrawSectionGroup());
|
||||
rcCmdMgr.addCommand(new CmdTechDrawSectionView());
|
||||
rcCmdMgr.addCommand(new CmdTechDrawComplexSection());
|
||||
rcCmdMgr.addCommand(new CmdTechDrawDetailView());
|
||||
rcCmdMgr.addCommand(new CmdTechDrawProjectionGroup());
|
||||
rcCmdMgr.addCommand(new CmdTechDrawClipGroup());
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>440</width>
|
||||
<height>447</height>
|
||||
<width>450</width>
|
||||
<height>541</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@@ -33,21 +33,34 @@
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout_2" columnstretch="1,0,1">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<layout class="QGridLayout" name="gridLayout_2" columnstretch="1,0,0">
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
<italic>false</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Section Line Standard</string>
|
||||
<string>Detail View Outline Shape</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="Gui::PrefComboBox" name="cbSectionLineStd">
|
||||
<item row="7" column="1">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="13" column="0">
|
||||
<widget class="Gui::PrefCheckBox" name="cbShowCenterMarks">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
@@ -56,43 +69,137 @@
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>184</width>
|
||||
<height>22</height>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show arc center marks in views</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show Center Marks</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>ShowCenterMarks</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/TechDraw/Decorations</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="2">
|
||||
<widget class="Gui::PrefCheckBox" name="cbPrintCenterMarks">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Standard to be used to draw section lines</string>
|
||||
<string>Show arc centers in printed output</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
<property name="text">
|
||||
<string>Print Center Marks</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>SectionLineStandard</cstring>
|
||||
<cstring>PrintCenterMarks</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/TechDraw/Standards</cstring>
|
||||
<cstring>Mod/TechDraw/Decorations</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="2">
|
||||
<widget class="Gui::PrefComboBox" name="pcbBalloonArrow">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Style for balloon leader line ends</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>BalloonArrow</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/TechDraw/Decorations</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="Gui::PrefComboBox" name="pcbMatting">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Outline shape for detail views</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>MattingStyle</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>/Mod/TechDraw/Decorations</cstring>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>ANSI</string>
|
||||
<string>Circle</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="Resources/TechDraw.qrc">
|
||||
<normaloff>:/icons/circular.svg</normaloff>:/icons/circular.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>ISO</string>
|
||||
<string>Square</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="Resources/TechDraw.qrc">
|
||||
<normaloff>:/icons/square.svg</normaloff>:/icons/square.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Section Line Style</string>
|
||||
<string>Balloon Shape</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -178,76 +285,87 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_19">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Section Cut Surface</string>
|
||||
<string>Section Line Standard</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="Gui::PrefComboBox" name="cbCutSurface">
|
||||
<item row="0" column="2">
|
||||
<widget class="Gui::PrefComboBox" name="cbSectionLineStd">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<width>184</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Default appearance of cut surface in section view</string>
|
||||
<string>Standard to be used to draw section lines</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>CutSurfaceDisplay</cstring>
|
||||
<cstring>SectionLineStandard</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>/Mod/TechDraw/Decorations</cstring>
|
||||
<cstring>Mod/TechDraw/Standards</cstring>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Hide</string>
|
||||
<string>ANSI</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Solid Color</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>SVG Hatch</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>PAT Hatch</string>
|
||||
<string>ISO</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_20">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Line group used to set line widths</string>
|
||||
<string>Line style of detail highlight on base view</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Line Width Group</string>
|
||||
<string>Detail Highlight Style</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Length of horizontal portion of Balloon leader</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Ballon Leader Kink Length</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="Gui::PrefComboBox" name="pcbLineGroup">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
@@ -272,77 +390,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>false</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Detail View Outline Shape</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="Gui::PrefComboBox" name="pcbMatting">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Outline shape for detail views</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>MattingStyle</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>/Mod/TechDraw/Decorations</cstring>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Circle</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="Resources/TechDraw.qrc">
|
||||
<normaloff>:/icons/circular.svg</normaloff>:/icons/circular.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Square</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="Resources/TechDraw.qrc">
|
||||
<normaloff>:/icons/square.svg</normaloff>:/icons/square.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_20">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Line style of detail highlight on base view</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Detail Highlight Style</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<item row="6" column="2">
|
||||
<widget class="Gui::PrefComboBox" name="pcbHighlightStyle">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
@@ -415,33 +463,8 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Center Line Style</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<widget class="Gui::PrefComboBox" name="pcbCenterStyle">
|
||||
<item row="10" column="2">
|
||||
<widget class="Gui::PrefUnitSpinBox" name="pdsbBalloonKink">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
@@ -455,86 +478,66 @@
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Type for centerlines</string>
|
||||
<string>Length of balloon leader line kink</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>5.000000000000000</double>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>CenterLine</cstring>
|
||||
<cstring>BalloonKink</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>/Mod/TechDraw/Decorations</cstring>
|
||||
<cstring>Mod/TechDraw/Dimensions</cstring>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>NeverShow</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="Resources/TechDraw.qrc">
|
||||
<normaloff>:/icons/arrownone.svg</normaloff>:/icons/arrownone.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Continuous</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="Resources/TechDraw.qrc">
|
||||
<normaloff>:/icons/continuous-line.svg</normaloff>:/icons/continuous-line.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Dash</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="Resources/TechDraw.qrc">
|
||||
<normaloff>:/icons/dash-line.svg</normaloff>:/icons/dash-line.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Dot</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="Resources/TechDraw.qrc">
|
||||
<normaloff>:/icons/dot-line.svg</normaloff>:/icons/dot-line.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>DashDot</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="Resources/TechDraw.qrc">
|
||||
<normaloff>:/icons/dashDot-line.svg</normaloff>:/icons/dashDot-line.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>DashDotDot</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="Resources/TechDraw.qrc">
|
||||
<normaloff>:/icons/dashDotDot-line.svg</normaloff>:/icons/dashDotDot-line.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Balloon Shape</string>
|
||||
<string>Balloon Leader End</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="2">
|
||||
<item row="11" column="0">
|
||||
<widget class="Gui::PrefCheckBox" name="cbPyramidOrtho">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Restrict Filled Triangle line end to vertical or horizontal directions</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Balloon Orthogonal Triangle</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>PyramidOrtho</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/TechDraw/Decorations</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="2">
|
||||
<widget class="Gui::PrefComboBox" name="pcbBalloonShape">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
@@ -631,121 +634,101 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<item row="7" column="2">
|
||||
<widget class="Gui::PrefComboBox" name="pcbCenterStyle">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Type for centerlines</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>CenterLine</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>/Mod/TechDraw/Decorations</cstring>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>NeverShow</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="Resources/TechDraw.qrc">
|
||||
<normaloff>:/icons/arrownone.svg</normaloff>:/icons/arrownone.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Continuous</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="Resources/TechDraw.qrc">
|
||||
<normaloff>:/icons/continuous-line.svg</normaloff>:/icons/continuous-line.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Dash</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="Resources/TechDraw.qrc">
|
||||
<normaloff>:/icons/dash-line.svg</normaloff>:/icons/dash-line.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Dot</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="Resources/TechDraw.qrc">
|
||||
<normaloff>:/icons/dot-line.svg</normaloff>:/icons/dot-line.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>DashDot</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="Resources/TechDraw.qrc">
|
||||
<normaloff>:/icons/dashDot-line.svg</normaloff>:/icons/dashDot-line.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>DashDotDot</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="Resources/TechDraw.qrc">
|
||||
<normaloff>:/icons/dashDotDot-line.svg</normaloff>:/icons/dashDotDot-line.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Balloon Leader End</string>
|
||||
<string>Section Cut Surface</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="2">
|
||||
<widget class="Gui::PrefComboBox" name="pcbBalloonArrow">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Style for balloon leader line ends</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>BalloonArrow</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/TechDraw/Decorations</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Length of horizontal portion of Balloon leader</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Ballon Leader Kink Length</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="2">
|
||||
<widget class="Gui::PrefUnitSpinBox" name="pdsbBalloonKink">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Length of balloon leader line kink</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>5.000000000000000</double>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>BalloonKink</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/TechDraw/Dimensions</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="Gui::PrefCheckBox" name="cbPyramidOrtho">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Restrict Filled Triangle line end to vertical or horizontal directions</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Balloon Orthogonal Triangle</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>PyramidOrtho</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/TechDraw/Decorations</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="2">
|
||||
<item row="11" column="2">
|
||||
<widget class="Gui::PrefCheckBox" name="cbAutoHoriz">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
@@ -776,71 +759,112 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="Gui::PrefCheckBox" name="cbShowCenterMarks">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Section Line Style</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Center Line Style</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="Gui::PrefComboBox" name="cbCutSurface">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Default appearance of cut surface in section view</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>CutSurfaceDisplay</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>/Mod/TechDraw/Decorations</cstring>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Hide</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Solid Color</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>SVG Hatch</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>PAT Hatch</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show arc center marks in views</string>
|
||||
<string>Line group used to set line widths</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show Center Marks</string>
|
||||
<string>Line Width Group</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="Gui::PrefCheckBox" name="cbComplexMarks">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show or hide marks at direction changes on ComplexSection lines.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Complex Section Line Marks</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>ShowCenterMarks</cstring>
|
||||
<cstring>SectionLineMarks</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/TechDraw/Decorations</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="2">
|
||||
<widget class="Gui::PrefCheckBox" name="cbPrintCenterMarks">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show arc centers in printed output</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Print Center Marks</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>PrintCenterMarks</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/TechDraw/Decorations</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@@ -854,7 +878,7 @@
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><span style=" font-weight:600;">Note:</span> Items in <span style=" font-style:italic;">italics</span> are default values for new objects. They have no effect on existing objects.</p></body></html></string>
|
||||
<string><html><head/><body><p><span style=" font-weight:600;">Note:</span> Items in <span style=" font-style:italic;">italics</span> are default values for new objects. They have no effect on existing objects.</p></body></html></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
|
||||
@@ -62,6 +62,7 @@ void DlgPrefsTechDrawAnnotationImp::saveSettings()
|
||||
ui->cbPrintCenterMarks->onSave();
|
||||
ui->cbPyramidOrtho->onSave();
|
||||
ui->cbSectionLineStd->onSave();
|
||||
ui->cbComplexMarks->onSave();
|
||||
ui->cbShowCenterMarks->onSave();
|
||||
ui->pcbLineGroup->onSave();
|
||||
ui->pcbBalloonArrow->onSave();
|
||||
@@ -100,6 +101,7 @@ void DlgPrefsTechDrawAnnotationImp::loadSettings()
|
||||
ui->cbPrintCenterMarks->onRestore();
|
||||
ui->cbPyramidOrtho->onRestore();
|
||||
ui->cbSectionLineStd->onRestore();
|
||||
ui->cbComplexMarks->onRestore();
|
||||
ui->cbShowCenterMarks->onRestore();
|
||||
ui->pcbLineGroup->onRestore();
|
||||
ui->pcbBalloonArrow->onRestore();
|
||||
|
||||
@@ -181,6 +181,13 @@ Qt::PenStyle PreferencesGui::sectionLineStyle()
|
||||
return sectStyle;
|
||||
}
|
||||
|
||||
bool PreferencesGui::sectionLineMarks()
|
||||
{
|
||||
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter().
|
||||
GetGroup("BaseApp")->GetGroup("Preferences")->
|
||||
GetGroup("Mod/TechDraw/Decorations");
|
||||
return hGrp->GetBool("SectionLineMarks", true);
|
||||
}
|
||||
|
||||
QString PreferencesGui::weldingDirectory()
|
||||
{
|
||||
|
||||
@@ -62,6 +62,7 @@ static double dimArrowSize();
|
||||
static double edgeFuzz();
|
||||
|
||||
static Qt::PenStyle sectionLineStyle();
|
||||
static bool sectionLineMarks();
|
||||
|
||||
static QString weldingDirectory();
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ public:
|
||||
virtual void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = nullptr );
|
||||
virtual void draw();
|
||||
void setWidth(double w);
|
||||
double getWidth() { return m_width; }
|
||||
void setStyle(Qt::PenStyle s);
|
||||
void setColor(QColor c);
|
||||
QColor getColor(void) { return m_colNormal; }
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <qmath.h>
|
||||
#include <QGraphicsScene>
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QPainterPathStroker>
|
||||
@@ -43,23 +44,30 @@
|
||||
#include "QGIView.h"
|
||||
#include "PreferencesGui.h"
|
||||
#include "Rez.h"
|
||||
#include "ZVALUE.h"
|
||||
|
||||
#define ANSISTANDARD 0
|
||||
#define ISOSTANDARD 1
|
||||
#define SINGLEDIRECTIONMODE 0 //both arrows point along the section normal
|
||||
#define MULTIDIRECTIONMODE 1 //the arrows point along the normal of their section line segment
|
||||
|
||||
using namespace TechDrawGui;
|
||||
using namespace TechDraw;
|
||||
|
||||
QGISectionLine::QGISectionLine()
|
||||
QGISectionLine::QGISectionLine() :
|
||||
m_pathMode(false),
|
||||
m_arrowMode()
|
||||
{
|
||||
m_symbol = "";
|
||||
m_symSize = 0.0;
|
||||
|
||||
m_extLen = 1.5 * Rez::guiX(QGIArrow::getPrefArrowSize());
|
||||
m_extLen = 1.5 * Rez::guiX(QGIArrow::getPrefArrowSize()); //is there a standard for this??
|
||||
m_arrowSize = QGIArrow::getPrefArrowSize();
|
||||
|
||||
m_line = new QGraphicsPathItem();
|
||||
addToGroup(m_line);
|
||||
m_extend = new QGraphicsPathItem();
|
||||
addToGroup(m_extend);
|
||||
m_arrow1 = new QGIArrow();
|
||||
addToGroup(m_arrow1);
|
||||
m_arrow2 = new QGIArrow();
|
||||
@@ -69,7 +77,7 @@ QGISectionLine::QGISectionLine()
|
||||
m_symbol2 = new QGCustomText();
|
||||
addToGroup(m_symbol2);
|
||||
|
||||
setWidth(Rez::guiX(0.75));
|
||||
setWidth(Rez::guiX(0.75)); //a default?
|
||||
setStyle(getSectionStyle());
|
||||
setColor(getSectionColor());
|
||||
|
||||
@@ -85,14 +93,25 @@ void QGISectionLine::draw()
|
||||
extensionEndsISO();
|
||||
}
|
||||
|
||||
makeLine();
|
||||
if (!pathMode()) {
|
||||
makeSectionLine();
|
||||
}
|
||||
makeExtensionLine();
|
||||
makeArrows();
|
||||
makeSymbols();
|
||||
makeChangePointMarks();
|
||||
update();
|
||||
}
|
||||
|
||||
void QGISectionLine::makeLine()
|
||||
void QGISectionLine::makeExtensionLine()
|
||||
{
|
||||
QPen extendPen;
|
||||
extendPen.setWidthF(getWidth());
|
||||
extendPen.setColor(getSectionColor());
|
||||
extendPen.setStyle(Qt::SolidLine);
|
||||
extendPen.setCapStyle(Qt::FlatCap);
|
||||
m_extend->setPen(extendPen);
|
||||
|
||||
QPainterPath pp;
|
||||
|
||||
pp.moveTo(m_beginExt1);
|
||||
@@ -100,7 +119,13 @@ void QGISectionLine::makeLine()
|
||||
|
||||
pp.moveTo(m_beginExt2);
|
||||
pp.lineTo(m_endExt2);
|
||||
m_extend->setPath(pp);
|
||||
}
|
||||
|
||||
//make the traditional straight section line
|
||||
void QGISectionLine::makeSectionLine()
|
||||
{
|
||||
QPainterPath pp;
|
||||
pp.moveTo(m_start);
|
||||
pp.lineTo(m_end);
|
||||
m_line->setPath(pp);
|
||||
@@ -119,62 +144,56 @@ void QGISectionLine::makeArrows()
|
||||
//make Euro (ISO) Arrows
|
||||
void QGISectionLine::makeArrowsISO()
|
||||
{
|
||||
double arrowRotation = 0.0;
|
||||
m_arrowDir.Normalize();
|
||||
double angle = atan2f(m_arrowDir.y, m_arrowDir.x);
|
||||
if (angle < 0.0) {
|
||||
angle = 2 * M_PI + angle;
|
||||
}
|
||||
arrowRotation = 360.0 - angle * (180.0/M_PI); //convert to Qt rotation (clockwise degrees)
|
||||
|
||||
m_arrow1->setStyle(0);
|
||||
m_arrow1->setSize(QGIArrow::getPrefArrowSize());
|
||||
m_arrow1->setPos(m_start);
|
||||
m_arrow1->draw();
|
||||
m_arrow1->setRotation(arrowRotation); //rotation = 0 ==> -> horizontal, pointing right
|
||||
|
||||
m_arrow2->setStyle(0);
|
||||
m_arrow2->setSize(QGIArrow::getPrefArrowSize());
|
||||
m_arrow2->setPos(m_end);
|
||||
|
||||
if (m_arrowMode == SINGLEDIRECTIONMODE) {
|
||||
double arrowRotation = getArrowRotation(m_arrowDir);
|
||||
m_arrow1->setRotation(arrowRotation); //rotation = 0 ==> -> horizontal, pointing right
|
||||
m_arrow2->setRotation(arrowRotation);
|
||||
} else {
|
||||
double arrowRotation1 = getArrowRotation(m_arrowDir1);
|
||||
m_arrow1->setRotation(arrowRotation1);
|
||||
double arrowRotation2 = getArrowRotation(m_arrowDir2);
|
||||
m_arrow2->setRotation(arrowRotation2);
|
||||
}
|
||||
m_arrow1->draw();
|
||||
m_arrow2->draw();
|
||||
m_arrow2->setRotation(arrowRotation);
|
||||
}
|
||||
|
||||
//make traditional (ASME) section arrows
|
||||
void QGISectionLine::makeArrowsTrad()
|
||||
{
|
||||
double arrowRotation = 0.0;
|
||||
m_arrowDir.Normalize();
|
||||
double angle = atan2f(m_arrowDir.y, m_arrowDir.x);
|
||||
if (angle < 0.0) {
|
||||
angle = 2 * M_PI + angle;
|
||||
}
|
||||
arrowRotation = 360.0 - angle * (180.0/M_PI); //convert to Qt rotation (clockwise degrees)
|
||||
|
||||
QPointF posArrow1, posArrow2;
|
||||
QPointF offsetDir(m_arrowDir.x, -m_arrowDir.y); //remember Y dir is flipped
|
||||
|
||||
double oblique = 1.0;
|
||||
if ( !DrawUtil::fpCompare((m_arrowDir.x + m_arrowDir.y), 1.0) ) {
|
||||
oblique = 1.25;
|
||||
}
|
||||
double offsetLength = (m_extLen * oblique) + Rez::guiX(QGIArrow::getPrefArrowSize());
|
||||
QPointF offsetVec = offsetLength * offsetDir;
|
||||
|
||||
posArrow1 = m_start + offsetVec;
|
||||
posArrow2 = m_end + offsetVec;
|
||||
|
||||
m_arrow1->setStyle(0);
|
||||
m_arrow1->setSize(QGIArrow::getPrefArrowSize());
|
||||
m_arrow1->setPos(posArrow1);
|
||||
m_arrow1->draw();
|
||||
m_arrow1->setRotation(arrowRotation); //rotation = 0 ==> -> horizontal, pointing right
|
||||
|
||||
m_arrow2->setStyle(0);
|
||||
m_arrow2->setSize(QGIArrow::getPrefArrowSize());
|
||||
m_arrow2->setPos(posArrow2);
|
||||
|
||||
if (m_arrowMode == SINGLEDIRECTIONMODE) {
|
||||
double arrowRotation = getArrowRotation(m_arrowDir);
|
||||
m_arrow1->setRotation(arrowRotation); //rotation = 0 ==> -> horizontal, pointing right
|
||||
m_arrow2->setRotation(arrowRotation);
|
||||
m_arrowPos1 = getArrowPosition(m_arrowDir, m_start);
|
||||
m_arrow1->setPos(m_arrowPos1);
|
||||
m_arrowPos2 = getArrowPosition(m_arrowDir, m_end);
|
||||
m_arrow2->setPos(m_arrowPos2);
|
||||
} else {
|
||||
double arrowRotation1 = getArrowRotation(m_arrowDir1);
|
||||
m_arrow1->setRotation(arrowRotation1);
|
||||
m_arrowPos1 = getArrowPosition(m_arrowDir1, m_start);
|
||||
m_arrow1->setPos(m_arrowPos1);
|
||||
double arrowRotation2 = getArrowRotation(m_arrowDir2);
|
||||
m_arrow2->setRotation(arrowRotation2);
|
||||
m_arrowPos2 = getArrowPosition(m_arrowDir2, m_end);
|
||||
m_arrow2->setPos(m_arrowPos2);
|
||||
}
|
||||
|
||||
m_arrow1->draw();
|
||||
m_arrow2->draw();
|
||||
m_arrow2->setRotation(arrowRotation);
|
||||
}
|
||||
|
||||
void QGISectionLine::makeSymbols()
|
||||
@@ -187,10 +206,10 @@ void QGISectionLine::makeSymbols()
|
||||
}
|
||||
}
|
||||
|
||||
//arrows go at arrowhead position.
|
||||
void QGISectionLine::makeSymbolsTrad()
|
||||
{
|
||||
prepareGeometryChange();
|
||||
// m_symFont.setPixelSize(QGIView::calculateFontPixelSize(m_symSize));
|
||||
int fontSize = QGIView::exactFontSize(Base::Tools::toStdString(m_symFont.family()), m_symSize);
|
||||
m_symFont.setPixelSize(fontSize);
|
||||
m_symbol1->setFont(m_symFont);
|
||||
@@ -199,33 +218,28 @@ void QGISectionLine::makeSymbolsTrad()
|
||||
m_symbol2->setPlainText(QString::fromUtf8(m_symbol));
|
||||
|
||||
QRectF symRect = m_symbol1->boundingRect();
|
||||
double symWidth = symRect.width();
|
||||
double symHeight = symRect.height();
|
||||
double symbolFudge = 0.75;
|
||||
double angle = atan2f(m_arrowDir.y, m_arrowDir.x);
|
||||
if (angle < 0.0) {
|
||||
angle = 2 * M_PI + angle;
|
||||
}
|
||||
Base::Vector3d adjustVector(cos(angle) * symWidth, sin(angle) * symHeight, 0.0);
|
||||
adjustVector = DrawUtil::invertY(adjustVector) * symbolFudge;
|
||||
QPointF qAdjust(adjustVector.x, adjustVector.y);
|
||||
double gap = 0.5 * symHeight; //symHeight as surrogate for char box
|
||||
|
||||
QPointF posSymbol1 = m_arrow1->pos() + qAdjust;
|
||||
m_symbol1->centerAt(posSymbol1);
|
||||
QPointF motion1(m_arrowDir1.x, -m_arrowDir1.y); //move in same direction as arrow
|
||||
QPointF motion2(m_arrowDir2.x, -m_arrowDir2.y); //Qt y coords!
|
||||
|
||||
QPointF posSymbol2 = m_arrow2->pos() + qAdjust;
|
||||
m_symbol2->centerAt(posSymbol2);
|
||||
QPointF symPos1 = m_arrowPos1 + motion1 * gap;
|
||||
QPointF symPos2 = m_arrowPos2 + motion2 * gap;
|
||||
|
||||
m_symbol1->setTransformOriginPoint(m_symbol1->mapFromParent(posSymbol1));
|
||||
m_symbol1->setRotation(360.0 - rotation());
|
||||
m_symbol2->setTransformOriginPoint(m_symbol2->mapFromParent(posSymbol2));
|
||||
m_symbol1->centerAt(symPos1);
|
||||
m_symbol2->centerAt(symPos2);
|
||||
|
||||
m_symbol1->setTransformOriginPoint(m_symbol1->mapFromParent(symPos1));
|
||||
m_symbol1->setRotation(360.0 - rotation()); //to Qt angle
|
||||
m_symbol2->setTransformOriginPoint(m_symbol2->mapFromParent(symPos2));
|
||||
m_symbol2->setRotation(360.0 - rotation());
|
||||
}
|
||||
|
||||
//symbols go at ends of extensions
|
||||
void QGISectionLine::makeSymbolsISO()
|
||||
{
|
||||
prepareGeometryChange();
|
||||
// m_symFont.setPixelSize(QGIView::calculateFontPixelSize(m_symSize));
|
||||
int fontSize = QGIView::exactFontSize(Base::Tools::toStdString(m_symFont.family()), m_symSize);
|
||||
m_symFont.setPixelSize(fontSize);
|
||||
m_symbol1->setFont(m_symFont);
|
||||
@@ -233,79 +247,111 @@ void QGISectionLine::makeSymbolsISO()
|
||||
m_symbol2->setFont(m_symFont);
|
||||
m_symbol2->setPlainText(QString::fromUtf8(m_symbol));
|
||||
|
||||
QPointF symPosStart, symPosEnd;
|
||||
//no normalize() for QPointF
|
||||
QPointF dist = (m_start - m_end);
|
||||
double lenDist = sqrt(dist.x()*dist.x() + dist.y()*dist.y());
|
||||
QPointF offsetDir = dist / lenDist;
|
||||
|
||||
QRectF symRect = m_symbol1->boundingRect();
|
||||
double symWidth = symRect.width();
|
||||
double symHeight = symRect.height();
|
||||
double gap = 0.5 * symHeight; //symHeight as surrogate for char box
|
||||
|
||||
double symbolFudge = 0.75;
|
||||
double angle = atan2f(offsetDir.y(), offsetDir.x());
|
||||
if (angle < 0.0) {
|
||||
angle = 2.0 * M_PI + angle;
|
||||
}
|
||||
Base::Vector3d adjustVector(cos(angle) * symWidth, sin(angle) * symHeight, 0.0);
|
||||
adjustVector = adjustVector * symbolFudge;
|
||||
QPointF qAdjust(adjustVector.x, adjustVector.y);
|
||||
QPointF motion1(-m_arrowDir1.x, m_arrowDir1.y); //move away from extension end
|
||||
QPointF motion2(-m_arrowDir2.x, m_arrowDir2.y); //Qt y coords!
|
||||
|
||||
symPosStart = m_start + qAdjust;
|
||||
symPosEnd = m_end - qAdjust;
|
||||
QPointF symPos1 = m_endExt1 + motion1 * gap;
|
||||
QPointF symPos2 = m_endExt2 + motion2 * gap;
|
||||
|
||||
m_symbol1->centerAt(symPosStart);
|
||||
m_symbol2->centerAt(symPosEnd);
|
||||
m_symbol1->centerAt(symPos1);
|
||||
m_symbol2->centerAt(symPos2);
|
||||
|
||||
m_symbol1->setTransformOriginPoint(m_symbol1->mapFromParent(symPosStart));
|
||||
m_symbol1->setTransformOriginPoint(m_symbol1->mapFromParent(symPos1));
|
||||
m_symbol1->setRotation(360.0 - rotation());
|
||||
m_symbol2->setTransformOriginPoint(m_symbol2->mapFromParent(symPosEnd));
|
||||
m_symbol2->setTransformOriginPoint(m_symbol2->mapFromParent(symPos2));
|
||||
m_symbol2->setRotation(360.0 - rotation());
|
||||
|
||||
}
|
||||
|
||||
//extension lines are on the stock side of the section line
|
||||
void QGISectionLine::extensionEndsTrad()
|
||||
{
|
||||
QPointF offsetDir(m_arrowDir.x, -m_arrowDir.y);
|
||||
if (m_arrowMode == SINGLEDIRECTIONMODE) {
|
||||
QPointF offsetDir(m_arrowDir.x, -m_arrowDir.y); //inverted Y
|
||||
offsetDir = normalizeQPointF(offsetDir);
|
||||
|
||||
//extensions for oblique section line needs to be a bit longer
|
||||
double oblique = 1.0;
|
||||
if ( !DrawUtil::fpCompare((m_arrowDir.x + m_arrowDir.y), 1.0) ) {
|
||||
oblique = 1.25;
|
||||
//draw from section line endpoint
|
||||
QPointF offsetEnd = m_extLen * offsetDir;
|
||||
m_beginExt1 = m_start;
|
||||
m_endExt1 = m_start + offsetEnd;
|
||||
m_beginExt2 = m_end;
|
||||
m_endExt2 = m_end + offsetEnd;
|
||||
} else {
|
||||
//extension lines run from point on section line to arrowhead
|
||||
m_beginExt1 = m_start;
|
||||
m_endExt1 = getArrowPosition(m_arrowDir1, m_start);
|
||||
m_beginExt2 = m_end;
|
||||
m_endExt2 = getArrowPosition(m_arrowDir2, m_end);
|
||||
}
|
||||
|
||||
//draw from section line endpoint
|
||||
QPointF offsetEnd = oblique * m_extLen * offsetDir;
|
||||
m_beginExt1 = m_start;
|
||||
m_endExt1 = m_start + offsetEnd;
|
||||
m_beginExt2 = m_end;
|
||||
m_endExt2 = m_end + offsetEnd;
|
||||
}
|
||||
|
||||
//the extension lines are on the waste side of the section line!
|
||||
void QGISectionLine::extensionEndsISO()
|
||||
{
|
||||
//lines are offset to other side of section line!
|
||||
QPointF offsetDir(m_arrowDir.x, -m_arrowDir.y);
|
||||
offsetDir = offsetDir * -1.0;
|
||||
if (m_arrowMode == SINGLEDIRECTIONMODE) {
|
||||
QPointF offsetDir(-m_arrowDir.x, m_arrowDir.y); //reversed and inverted y
|
||||
offsetDir = normalizeQPointF(offsetDir);
|
||||
|
||||
//extensions for oblique section line needs to be a bit longer?
|
||||
//this is just esthetics
|
||||
double oblique = 1.0;
|
||||
if ( !DrawUtil::fpCompare((m_arrowDir.x + m_arrowDir.y), 1.0) ) {
|
||||
oblique = 1.10;
|
||||
//draw from section line endpoint less arrow length
|
||||
QPointF offsetStart = offsetDir * Rez::guiX(QGIArrow::getPrefArrowSize());
|
||||
QPointF offsetEnd = m_extLen * offsetDir;
|
||||
|
||||
m_beginExt1 = m_start + offsetStart;
|
||||
m_endExt1 = m_start + offsetStart + offsetEnd;
|
||||
m_beginExt2 = m_end + offsetStart;
|
||||
m_endExt2 = m_end + offsetStart + offsetEnd;
|
||||
} else {
|
||||
//extension lines run in reverse of arrow direction from base of arrowhead for distance m_extLen
|
||||
QPointF offsetDir1(-m_arrowDir1.x, m_arrowDir1.y); //reversed and inverted y
|
||||
offsetDir1 = normalizeQPointF(offsetDir1);
|
||||
QPointF offsetStart1 = offsetDir1 * Rez::guiX(QGIArrow::getPrefArrowSize());
|
||||
QPointF offsetEnd1 = m_extLen * offsetDir1;
|
||||
m_beginExt1 = m_start + offsetStart1;
|
||||
m_endExt1 = m_start + offsetStart1 + offsetEnd1;
|
||||
|
||||
QPointF offsetDir2(-m_arrowDir2.x, m_arrowDir2.y); //reversed and inverted y
|
||||
offsetDir2 = normalizeQPointF(offsetDir2);
|
||||
QPointF offsetStart2 = offsetDir2 * Rez::guiX(QGIArrow::getPrefArrowSize());
|
||||
QPointF offsetEnd2 = m_extLen * offsetDir2;
|
||||
m_beginExt2 = m_end + offsetStart2;
|
||||
m_endExt2 = m_end + offsetStart2 + offsetEnd2;
|
||||
}
|
||||
|
||||
//draw from section line endpoint less arrow length
|
||||
QPointF offsetStart = offsetDir * Rez::guiX(QGIArrow::getPrefArrowSize());
|
||||
QPointF offsetEnd = oblique * m_extLen * offsetDir;
|
||||
|
||||
m_beginExt1 = m_start + offsetStart;
|
||||
m_endExt1 = m_start + offsetStart + offsetEnd;
|
||||
m_beginExt2 = m_end + offsetStart;
|
||||
m_endExt2 = m_end + offsetStart + offsetEnd;
|
||||
}
|
||||
|
||||
void QGISectionLine::makeChangePointMarks()
|
||||
{
|
||||
// Base::Console().Message("QGISL::makeChangePointMarks()\n");
|
||||
double segmentLength = 0.50 * QGIArrow::getPrefArrowSize();
|
||||
QPen cPointPen;
|
||||
//TODO: this should really be 2.0 * thickLineWidth, but we only have one
|
||||
//width available (which should be 'thin', for the section line)
|
||||
cPointPen.setWidthF(2.0 * getWidth());
|
||||
cPointPen.setColor(getSectionColor());
|
||||
cPointPen.setStyle(Qt::SolidLine);
|
||||
for (auto& cPoint : m_changePointData) {
|
||||
QGraphicsPathItem* cPointItem = new QGraphicsPathItem();
|
||||
addToGroup(cPointItem);
|
||||
|
||||
QPainterPath pPath;
|
||||
QPointF location = cPoint.getLocation();
|
||||
QPointF start = location + cPoint.getPreDirection() * segmentLength;
|
||||
QPointF end = location + cPoint.getPostDirection() * segmentLength;
|
||||
pPath.moveTo(Rez::guiPt(start));
|
||||
pPath.lineTo(Rez::guiPt(location));
|
||||
pPath.lineTo(Rez::guiPt(end));
|
||||
|
||||
cPointItem->setPath(pPath);
|
||||
cPointItem->setPen(cPointPen);
|
||||
cPointItem->setZValue(ZVALUE::SECTIONLINE + 1);
|
||||
cPointItem->setPos(0.0, 0.0);
|
||||
m_changePointMarks.push_back(cPointItem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void QGISectionLine::setEnds(Base::Vector3d l1, Base::Vector3d l2)
|
||||
{
|
||||
m_l1 = l1;
|
||||
@@ -333,8 +379,46 @@ void QGISectionLine::setDirection(double xDir, double yDir)
|
||||
|
||||
void QGISectionLine::setDirection(Base::Vector3d dir)
|
||||
{
|
||||
m_arrowMode = SINGLEDIRECTIONMODE;
|
||||
m_arrowDir = dir;
|
||||
m_arrowDir.Normalize();
|
||||
m_arrowDir1 = dir;
|
||||
m_arrowDir1.Normalize();
|
||||
m_arrowDir2 = dir;
|
||||
m_arrowDir2.Normalize();
|
||||
}
|
||||
|
||||
void QGISectionLine::setArrowDirections(Base::Vector3d dir1, Base::Vector3d dir2)
|
||||
{
|
||||
m_arrowMode = MULTIDIRECTIONMODE;
|
||||
m_arrowDir1 = dir1;
|
||||
m_arrowDir1.Normalize();
|
||||
m_arrowDir2 = dir2;
|
||||
m_arrowDir2.Normalize();
|
||||
}
|
||||
|
||||
//convert an arrow direction vector into a Qt rotation angle degrees
|
||||
double QGISectionLine::getArrowRotation(Base::Vector3d arrowDir)
|
||||
{
|
||||
arrowDir.Normalize();
|
||||
double angle = atan2f(arrowDir.y, arrowDir.x);
|
||||
if (angle < 0.0) {
|
||||
angle = 2 * M_PI + angle;
|
||||
}
|
||||
double arrowRotation = 360.0 - angle * (180.0/M_PI); //convert to Qt rotation (clockwise degrees)
|
||||
return arrowRotation;
|
||||
}
|
||||
|
||||
QPointF QGISectionLine::getArrowPosition(Base::Vector3d arrowDir, QPointF refPoint)
|
||||
{
|
||||
QPointF qArrowDir(arrowDir.x, -arrowDir.y); //remember Y dir is flipped
|
||||
qArrowDir = normalizeQPointF(qArrowDir);
|
||||
|
||||
double offsetLength = m_extLen + Rez::guiX(QGIArrow::getPrefArrowSize());
|
||||
QPointF offsetVec = offsetLength * qArrowDir;
|
||||
|
||||
QPointF arrowPos = refPoint + offsetVec;
|
||||
return arrowPos;
|
||||
}
|
||||
|
||||
void QGISectionLine::setFont(QFont f, double fsize)
|
||||
@@ -343,6 +427,44 @@ void QGISectionLine::setFont(QFont f, double fsize)
|
||||
m_symSize = fsize;
|
||||
}
|
||||
|
||||
void QGISectionLine::setPath(QPainterPath& path)
|
||||
{
|
||||
m_line->setPath(path);
|
||||
}
|
||||
|
||||
void QGISectionLine::setChangePoints(TechDraw::ChangePointVector changePointData)
|
||||
{
|
||||
m_changePointData = changePointData;
|
||||
clearChangePointMarks();
|
||||
}
|
||||
|
||||
void QGISectionLine::clearChangePoints()
|
||||
{
|
||||
clearChangePointMarks();
|
||||
m_changePointData.clear();
|
||||
}
|
||||
|
||||
void QGISectionLine::clearChangePointMarks()
|
||||
{
|
||||
if (!m_changePointMarks.empty()) {
|
||||
for (auto& cPoint : m_changePointMarks) {
|
||||
cPoint->hide();
|
||||
scene()->removeItem(cPoint);
|
||||
delete cPoint;
|
||||
}
|
||||
m_changePointMarks.clear();
|
||||
}
|
||||
}
|
||||
|
||||
//QPointF does not have length or normalize methods
|
||||
QPointF QGISectionLine::normalizeQPointF(QPointF inPoint)
|
||||
{
|
||||
double x2 = inPoint.x() * inPoint.x();
|
||||
double y2 = inPoint.y() * inPoint.y();
|
||||
double root = sqrt(x2 + y2);
|
||||
return inPoint / root;
|
||||
}
|
||||
|
||||
void QGISectionLine::setSectionColor(QColor c)
|
||||
{
|
||||
setColor(c);
|
||||
@@ -416,11 +538,6 @@ void QGISectionLine::setTools()
|
||||
|
||||
m_line->setPen(m_pen);
|
||||
|
||||
// m_arrow1->setPen(m_pen);
|
||||
// m_arrow2->setPen(m_pen);
|
||||
// m_arrow1->setBrush(m_brush);
|
||||
// m_arrow2->setBrush(m_brush);
|
||||
|
||||
m_arrow1->setNormalColor(m_colCurrent);
|
||||
m_arrow1->setFillColor(m_colCurrent);
|
||||
m_arrow1->setPrettyNormal();
|
||||
|
||||
@@ -28,9 +28,12 @@
|
||||
#include <QColor>
|
||||
#include <QFont>
|
||||
#include <QPointF>
|
||||
#include <QPainterPath>
|
||||
|
||||
#include <Base/Vector3D.h>
|
||||
|
||||
#include <Mod/TechDraw/App/DrawComplexSection.h>
|
||||
|
||||
#include "QGCustomText.h"
|
||||
#include "QGIDecoration.h"
|
||||
|
||||
@@ -53,34 +56,46 @@ public:
|
||||
|
||||
void setEnds(Base::Vector3d l1, Base::Vector3d l2);
|
||||
void setBounds(double x1, double y1, double x2, double y2);
|
||||
void setPath(QPainterPath& path);
|
||||
void setSymbol(char* sym);
|
||||
void setDirection(double xDir, double yDir);
|
||||
void setDirection(Base::Vector3d dir);
|
||||
void setArrowDirections(Base::Vector3d dir1, Base::Vector3d dir2);
|
||||
void setFont(QFont f, double fsize);
|
||||
void setSectionStyle(int style);
|
||||
void setSectionColor(QColor c);
|
||||
|
||||
void setPathMode(bool mode) { m_pathMode = mode; }
|
||||
bool pathMode() { return m_pathMode; }
|
||||
void setChangePoints(TechDraw::ChangePointVector changePoints);
|
||||
void clearChangePoints();
|
||||
virtual void draw();
|
||||
|
||||
protected:
|
||||
QColor getSectionColor();
|
||||
Qt::PenStyle getSectionStyle();
|
||||
void makeLine();
|
||||
void makeSectionLine();
|
||||
void makeExtensionLine();
|
||||
void makeArrows();
|
||||
void makeArrowsTrad();
|
||||
void makeArrowsISO();
|
||||
void makeSymbols();
|
||||
void makeSymbolsTrad();
|
||||
void makeSymbolsISO();
|
||||
void makeChangePointMarks();
|
||||
void setTools();
|
||||
int getPrefSectionStandard();
|
||||
void extensionEndsISO();
|
||||
void extensionEndsTrad();
|
||||
double getArrowRotation(Base::Vector3d arrowDir);
|
||||
QPointF getArrowPosition(Base::Vector3d arrowDir, QPointF refPoint);
|
||||
void clearChangePointMarks();
|
||||
|
||||
static QPointF normalizeQPointF(QPointF inPoint);
|
||||
|
||||
private:
|
||||
char* m_symbol;
|
||||
QGraphicsPathItem* m_line; //primpath?
|
||||
QGraphicsPathItem* m_line;
|
||||
QGraphicsPathItem* m_extend;
|
||||
QGIArrow* m_arrow1;
|
||||
QGIArrow* m_arrow2;
|
||||
QGCustomText* m_symbol1;
|
||||
@@ -92,15 +107,21 @@ private:
|
||||
QFont m_symFont;
|
||||
double m_symSize;
|
||||
double m_arrowSize;
|
||||
//QColor m_color;
|
||||
double m_extLen;
|
||||
// int m_sectionFormat; //0 = ASME, 1 = ISO
|
||||
Base::Vector3d m_l1; //end of main section line
|
||||
Base::Vector3d m_l2; //end of main section line
|
||||
QPointF m_beginExt1; //start of extension line 1
|
||||
QPointF m_endExt1; //end of extension line 1
|
||||
QPointF m_beginExt2; //start of extension line 2
|
||||
QPointF m_endExt2; //end of extension line 1
|
||||
bool m_pathMode; //use external path for line
|
||||
int m_arrowMode; //0 = 1 direction for both arrows, 1 = direction for each arrow
|
||||
Base::Vector3d m_arrowDir1;
|
||||
Base::Vector3d m_arrowDir2;
|
||||
QPointF m_arrowPos1;
|
||||
QPointF m_arrowPos2;
|
||||
std::vector<QGraphicsPathItem*> m_changePointMarks;
|
||||
TechDraw::ChangePointVector m_changePointData;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
#include <Mod/TechDraw/App/DrawUtil.h>
|
||||
#include <Mod/TechDraw/App/DrawViewPart.h>
|
||||
#include <Mod/TechDraw/App/DrawViewSection.h>
|
||||
#include <Mod/TechDraw/App/DrawComplexSection.h>
|
||||
#include <Mod/TechDraw/App/DrawHatch.h>
|
||||
#include <Mod/TechDraw/App/DrawGeomHatch.h>
|
||||
#include <Mod/TechDraw/App/DrawViewDetail.h>
|
||||
@@ -446,10 +447,10 @@ void QGIViewPart::drawViewPart()
|
||||
if (!vp)
|
||||
return;
|
||||
|
||||
float lineWidth = vp->LineWidth.getValue() * lineScaleFactor;
|
||||
float lineWidthHid = vp->HiddenWidth.getValue() * lineScaleFactor;
|
||||
float lineWidthIso = vp->IsoWidth.getValue() * lineScaleFactor;
|
||||
// float lineWidthExtra = viewPart->ExtraWidth.getValue() * lineScaleFactor;
|
||||
float lineWidth = vp->LineWidth.getValue() * lineScaleFactor; //thick
|
||||
float lineWidthHid = vp->HiddenWidth.getValue() * lineScaleFactor; //thin
|
||||
float lineWidthIso = vp->IsoWidth.getValue() * lineScaleFactor; //graphic
|
||||
// float lineWidthExtra = viewPart->ExtraWidth.getValue() * lineScaleFactor; //extra
|
||||
bool showAll = vp->ShowAllEdges.getValue();
|
||||
|
||||
prepareGeometryChange();
|
||||
@@ -803,7 +804,11 @@ void QGIViewPart::drawAllSectionLines()
|
||||
if (vp->ShowSectionLine.getValue()) {
|
||||
auto refs = viewPart->getSectionRefs();
|
||||
for (auto& r:refs) {
|
||||
drawSectionLine(r, true);
|
||||
if (r->isDerivedFrom(DrawComplexSection::getClassTypeId())) {
|
||||
drawComplexSectionLine(r, true);
|
||||
} else {
|
||||
drawSectionLine(r, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -820,8 +825,10 @@ void QGIViewPart::drawSectionLine(TechDraw::DrawViewSection* viewSection, bool b
|
||||
return;
|
||||
|
||||
auto vp = static_cast<ViewProviderViewPart*>(getViewProvider(getViewObject()));
|
||||
if (!vp)
|
||||
if (!vp) {
|
||||
return;
|
||||
}
|
||||
float lineWidthThin = vp->HiddenWidth.getValue() * lineScaleFactor; //thin
|
||||
|
||||
if (b) {
|
||||
QGISectionLine* sectionLine = new QGISectionLine();
|
||||
@@ -829,7 +836,7 @@ void QGIViewPart::drawSectionLine(TechDraw::DrawViewSection* viewSection, bool b
|
||||
sectionLine->setSymbol(const_cast<char*>(viewSection->SectionSymbol.getValue()));
|
||||
sectionLine->setSectionStyle(vp->SectionLineStyle.getValue());
|
||||
sectionLine->setSectionColor(vp->SectionLineColor.getValue().asValue<QColor>());
|
||||
|
||||
sectionLine->setPathMode(false);
|
||||
//find the ends of the section line
|
||||
double scale = viewPart->getScale();
|
||||
std::pair<Base::Vector3d, Base::Vector3d> sLineEnds = viewSection->sectionLineEnds();
|
||||
@@ -839,11 +846,8 @@ void QGIViewPart::drawSectionLine(TechDraw::DrawViewSection* viewSection, bool b
|
||||
//which way to the arrows point?
|
||||
Base::Vector3d lineDir = l2 - l1;
|
||||
lineDir.Normalize();
|
||||
Base::Vector3d normalDir = viewSection->SectionNormal.getValue();
|
||||
Base::Vector3d projNormal = viewPart->projectPoint(normalDir);
|
||||
projNormal.Normalize();
|
||||
Base::Vector3d arrowDir = viewSection->SectionNormal.getValue();
|
||||
arrowDir = - viewPart->projectPoint(arrowDir); //arrows point reverse of sectionNormal(extrusion dir)
|
||||
arrowDir = - viewPart->projectPoint(arrowDir); //arrows point reverse of sectionNormal
|
||||
sectionLine->setDirection(arrowDir.x, -arrowDir.y); //invert Y
|
||||
|
||||
//make the section line a little longer
|
||||
@@ -853,7 +857,7 @@ void QGIViewPart::drawSectionLine(TechDraw::DrawViewSection* viewSection, bool b
|
||||
|
||||
//set the general parameters
|
||||
sectionLine->setPos(0.0, 0.0);
|
||||
sectionLine->setWidth(Rez::guiX(vp->LineWidth.getValue()));
|
||||
sectionLine->setWidth(lineWidthThin);
|
||||
double fontSize = Preferences::dimFontSizeMM();
|
||||
sectionLine->setFont(getFont(), fontSize);
|
||||
sectionLine->setZValue(ZVALUE::SECTIONLINE);
|
||||
@@ -862,6 +866,73 @@ void QGIViewPart::drawSectionLine(TechDraw::DrawViewSection* viewSection, bool b
|
||||
}
|
||||
}
|
||||
|
||||
void QGIViewPart::drawComplexSectionLine(TechDraw::DrawViewSection* viewSection, bool b)
|
||||
{
|
||||
Q_UNUSED(b);
|
||||
TechDraw::DrawViewPart *viewPart = static_cast<TechDraw::DrawViewPart *>(getViewObject());
|
||||
if (!viewPart)
|
||||
return;
|
||||
if (!viewSection)
|
||||
return;
|
||||
auto vp = static_cast<ViewProviderViewPart*>(getViewProvider(getViewObject()));
|
||||
if (!vp) {
|
||||
return;
|
||||
}
|
||||
float lineWidthThin = vp->HiddenWidth.getValue() * lineScaleFactor; //thin
|
||||
|
||||
auto dcs = static_cast<DrawComplexSection*>(viewSection);
|
||||
BaseGeomPtrVector edges = dcs->makeSectionLineGeometry();
|
||||
QPainterPath wirePath;
|
||||
QPainterPath firstSeg = drawPainterPath(edges.front());
|
||||
wirePath.connectPath(firstSeg);
|
||||
int edgeCount = edges.size();
|
||||
//NOTE: if the edges are not in nose to tail order, Qt will insert extra segments
|
||||
//that will overlap the segments we add. for interupted line styles, this
|
||||
//will make the line look continuous. This is prevented in
|
||||
//DrawComplexSection::makeSectionLineGeometry by calling makeNoseToTailWire
|
||||
for (int i = 1; i < edgeCount; i++) {
|
||||
QPainterPath edgePath = drawPainterPath(edges.at(i));
|
||||
wirePath.connectPath(edgePath);
|
||||
}
|
||||
|
||||
std::pair<Base::Vector3d, Base::Vector3d> ends = dcs->sectionLineEnds();
|
||||
Base::Vector3d vStart = Rez::guiX(ends.first); //already scaled by dcs
|
||||
Base::Vector3d vEnd = Rez::guiX(ends.second);
|
||||
|
||||
QGISectionLine* sectionLine = new QGISectionLine();
|
||||
addToGroup(sectionLine);
|
||||
sectionLine->setSymbol(const_cast<char*>(viewSection->SectionSymbol.getValue()));
|
||||
sectionLine->setSectionStyle(vp->SectionLineStyle.getValue());
|
||||
sectionLine->setSectionColor(vp->SectionLineColor.getValue().asValue<QColor>());
|
||||
sectionLine->setPathMode(true);
|
||||
sectionLine->setPath(wirePath);
|
||||
sectionLine->setEnds(vStart, vEnd);
|
||||
if (vp->SectionLineMarks.getValue()) {
|
||||
sectionLine->setChangePoints(dcs->getChangePointsFromSectionLine());
|
||||
} else {
|
||||
sectionLine->clearChangePoints();
|
||||
}
|
||||
if (dcs->ProjectionStrategy.isValue("Offset")) {
|
||||
Base::Vector3d arrowDirOffset = viewSection->SectionNormal.getValue();
|
||||
arrowDirOffset = - viewPart->projectPoint(arrowDirOffset); //arrows are opposite section normal
|
||||
sectionLine->setDirection(arrowDirOffset.x, -arrowDirOffset.y); //invert y for Qt
|
||||
} else {
|
||||
std::pair<Base::Vector3d, Base::Vector3d> dirsAligned = dcs->sectionArrowDirs();
|
||||
dirsAligned.first = DrawUtil::invertY(dirsAligned.first);
|
||||
dirsAligned.second = DrawUtil::invertY(dirsAligned.second);
|
||||
sectionLine->setArrowDirections(dirsAligned.first, dirsAligned.second);
|
||||
}
|
||||
|
||||
//set the general parameters
|
||||
sectionLine->setPos(0.0, 0.0);
|
||||
sectionLine->setWidth(lineWidthThin);
|
||||
double fontSize = Preferences::dimFontSizeMM();
|
||||
sectionLine->setFont(getFont(), fontSize);
|
||||
sectionLine->setZValue(ZVALUE::SECTIONLINE);
|
||||
sectionLine->setRotation(- viewPart->Rotation.getValue());
|
||||
sectionLine->draw();
|
||||
}
|
||||
|
||||
//TODO: use Cosmetic::CenterLine object for this to make it usable for dims.
|
||||
void QGIViewPart::drawCenterLines(bool b)
|
||||
{
|
||||
@@ -885,35 +956,28 @@ void QGIViewPart::drawCenterLines(bool b)
|
||||
centerLine = new QGICenterLine();
|
||||
addToGroup(centerLine);
|
||||
centerLine->setPos(0.0, 0.0);
|
||||
//this should work from the viewPart's bbox, not the border
|
||||
// double scale = viewPart->getScale();
|
||||
double width = Rez::guiX(viewPart->getBoxX());
|
||||
sectionSpan = width + sectionFudge;
|
||||
// sectionSpan = m_border->rect().width() + sectionFudge;
|
||||
xVal = sectionSpan / 2.0;
|
||||
yVal = 0.0;
|
||||
centerLine->setIntersection(horiz && vert);
|
||||
centerLine->setBounds(-xVal, -yVal, xVal, yVal);
|
||||
centerLine->setWidth(Rez::guiX(vp->HiddenWidth.getValue()));
|
||||
centerLine->setZValue(ZVALUE::SECTIONLINE);
|
||||
// centerLine->setRotation(viewPart->Rotation.getValue());
|
||||
centerLine->draw();
|
||||
}
|
||||
if (vert) {
|
||||
centerLine = new QGICenterLine();
|
||||
addToGroup(centerLine);
|
||||
centerLine->setPos(0.0, 0.0);
|
||||
// double scale = viewPart->getScale();
|
||||
double height = Rez::guiX(viewPart->getBoxY());
|
||||
sectionSpan = height + sectionFudge;
|
||||
// sectionSpan = (m_border->rect().height() - m_label->boundingRect().height()) + sectionFudge;
|
||||
xVal = 0.0;
|
||||
yVal = sectionSpan / 2.0;
|
||||
centerLine->setIntersection(horiz && vert);
|
||||
centerLine->setBounds(-xVal, -yVal, xVal, yVal);
|
||||
centerLine->setWidth(Rez::guiX(vp->HiddenWidth.getValue()));
|
||||
centerLine->setZValue(ZVALUE::SECTIONLINE);
|
||||
// centerLine->setRotation(viewPart->Rotation.getValue());
|
||||
centerLine->draw();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ public:
|
||||
QRectF boundingRect() const override;
|
||||
virtual void drawAllSectionLines();
|
||||
virtual void drawSectionLine(TechDraw::DrawViewSection* s, bool b);
|
||||
virtual void drawComplexSectionLine(TechDraw::DrawViewSection* viewSection, bool b);
|
||||
virtual void drawCenterLines(bool b);
|
||||
virtual void drawHighlight(TechDraw::DrawViewDetail* viewDetail, bool b);
|
||||
virtual void drawMatting();
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
<file>icons/actions/TechDraw_View.svg</file>
|
||||
<file>icons/actions/TechDraw_WeldSymbol.svg</file>
|
||||
<file>icons/actions/TechDraw_SurfaceFinishSymbols.svg</file>
|
||||
<file>icons/actions/TechDraw_ComplexSection.svg</file>
|
||||
<file>icons/arrow-ccw.svg</file>
|
||||
<file>icons/arrow-cw.svg</file>
|
||||
<file>icons/arrow-down.svg</file>
|
||||
@@ -180,6 +181,8 @@
|
||||
<!-- main wb icon and preferences icons -->
|
||||
<file>icons/preferences-techdraw.svg</file>
|
||||
|
||||
<!-- bitmap images -->
|
||||
|
||||
<!-- translations -->
|
||||
<file>translations/TechDraw_af.qm</file>
|
||||
<file>translations/TechDraw_ar.qm</file>
|
||||
|
||||
@@ -0,0 +1,873 @@
|
||||
<?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"
|
||||
version="1.1"
|
||||
width="64"
|
||||
height="64"
|
||||
id="svg249">
|
||||
<defs
|
||||
id="defs3">
|
||||
<marker
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow2Mend"
|
||||
style="overflow:visible;">
|
||||
<path
|
||||
id="path5645"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
transform="scale(0.6) rotate(180) translate(0,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="marker7794"
|
||||
style="overflow:visible;">
|
||||
<path
|
||||
id="path7792"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
transform="scale(0.4) rotate(180) translate(10,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="marker7676"
|
||||
style="overflow:visible;">
|
||||
<path
|
||||
id="path7674"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
transform="scale(0.4) rotate(180) translate(10,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="marker7510"
|
||||
style="overflow:visible;">
|
||||
<path
|
||||
id="path7508"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
transform="scale(0.4) rotate(180) translate(10,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="marker7386"
|
||||
style="overflow:visible;">
|
||||
<path
|
||||
id="path7384"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
transform="scale(0.4) rotate(180) translate(10,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow1Mend"
|
||||
style="overflow:visible;">
|
||||
<path
|
||||
id="path5627"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
transform="scale(0.4) rotate(180) translate(10,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="marker7236"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path7234"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
transform="scale(0.6) translate(0,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="marker7190"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path7188"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
transform="scale(0.6) translate(0,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow1Sstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path5630"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
transform="scale(0.2) translate(6,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow2Lstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path5636"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
transform="scale(1.1) translate(1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow2Mstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path5642"
|
||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
transform="scale(0.6) translate(0,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow1Lstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path5618"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
transform="scale(0.8) translate(12.5,0)" />
|
||||
</marker>
|
||||
<linearGradient
|
||||
id="linearGradient3999">
|
||||
<stop
|
||||
style="stop-color:#34e0e2;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop4001" />
|
||||
<stop
|
||||
style="stop-color:#06989a;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop4003" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
cx="605.71429"
|
||||
cy="486.64789"
|
||||
r="117.14286"
|
||||
fx="605.71429"
|
||||
fy="486.64789"
|
||||
id="radialGradient5031"
|
||||
xlink:href="#linearGradient5060"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)" />
|
||||
<linearGradient
|
||||
id="linearGradient5060">
|
||||
<stop
|
||||
id="stop5062"
|
||||
style="stop-color:#000000;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop5064"
|
||||
style="stop-color:#000000;stop-opacity:0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
cx="605.71429"
|
||||
cy="486.64789"
|
||||
r="117.14286"
|
||||
fx="605.71429"
|
||||
fy="486.64789"
|
||||
id="radialGradient5029"
|
||||
xlink:href="#linearGradient5060"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)" />
|
||||
<linearGradient
|
||||
id="linearGradient5048">
|
||||
<stop
|
||||
id="stop5050"
|
||||
style="stop-color:#000000;stop-opacity:0"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop5056"
|
||||
style="stop-color:#000000;stop-opacity:1"
|
||||
offset="0.5" />
|
||||
<stop
|
||||
id="stop5052"
|
||||
style="stop-color:#000000;stop-opacity:0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="302.85715"
|
||||
y1="366.64789"
|
||||
x2="302.85715"
|
||||
y2="609.50507"
|
||||
id="linearGradient5027"
|
||||
xlink:href="#linearGradient5048"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)" />
|
||||
<linearGradient
|
||||
id="linearGradient4542">
|
||||
<stop
|
||||
id="stop4544"
|
||||
style="stop-color:#000000;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop4546"
|
||||
style="stop-color:#000000;stop-opacity:0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
cx="24.306795"
|
||||
cy="42.07798"
|
||||
r="15.821514"
|
||||
fx="24.306795"
|
||||
fy="42.07798"
|
||||
id="radialGradient4548"
|
||||
xlink:href="#linearGradient4542"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1,0,0,0.284916,0,30.08928)" />
|
||||
<linearGradient
|
||||
id="linearGradient15662">
|
||||
<stop
|
||||
id="stop15664"
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop15666"
|
||||
style="stop-color:#f8f8f8;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
cx="20.892099"
|
||||
cy="64.567902"
|
||||
r="5.257"
|
||||
fx="20.892099"
|
||||
fy="64.567902"
|
||||
id="aigrd3"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
id="stop15573"
|
||||
style="stop-color:#f0f0f0;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop15575"
|
||||
style="stop-color:#9a9a9a;stop-opacity:1"
|
||||
offset="1" />
|
||||
</radialGradient>
|
||||
<radialGradient
|
||||
cx="20.892099"
|
||||
cy="114.5684"
|
||||
r="5.256"
|
||||
fx="20.892099"
|
||||
fy="114.5684"
|
||||
id="aigrd2"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
id="stop15566"
|
||||
style="stop-color:#f0f0f0;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop15568"
|
||||
style="stop-color:#9a9a9a;stop-opacity:1"
|
||||
offset="1" />
|
||||
</radialGradient>
|
||||
<linearGradient
|
||||
id="linearGradient269">
|
||||
<stop
|
||||
id="stop270"
|
||||
style="stop-color:#a3a3a3;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop271"
|
||||
style="stop-color:#4c4c4c;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient259">
|
||||
<stop
|
||||
id="stop260"
|
||||
style="stop-color:#fafafa;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop261"
|
||||
style="stop-color:#bbbbbb;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient12512">
|
||||
<stop
|
||||
id="stop12513"
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop12517"
|
||||
style="stop-color:#fff520;stop-opacity:0.89108908"
|
||||
offset="0.5" />
|
||||
<stop
|
||||
id="stop12514"
|
||||
style="stop-color:#fff300;stop-opacity:0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
cx="8.824419"
|
||||
cy="3.7561285"
|
||||
r="37.751713"
|
||||
fx="8.824419"
|
||||
fy="3.7561285"
|
||||
id="radialGradient15656"
|
||||
xlink:href="#linearGradient269"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.968273,0,0,1.032767,3.4281936,-47.492271)" />
|
||||
<radialGradient
|
||||
cx="33.966679"
|
||||
cy="35.736916"
|
||||
r="86.70845"
|
||||
fx="33.966679"
|
||||
fy="35.736916"
|
||||
id="radialGradient15658"
|
||||
xlink:href="#linearGradient259"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.960493,0,0,1.041132,0.07464063,-48.138718)" />
|
||||
<radialGradient
|
||||
cx="8.1435566"
|
||||
cy="7.2678967"
|
||||
r="38.158695"
|
||||
fx="8.1435566"
|
||||
fy="7.2678967"
|
||||
id="radialGradient15668"
|
||||
xlink:href="#linearGradient15662"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.968273,0,0,1.032767,3.4281936,-47.492271)" />
|
||||
<radialGradient
|
||||
cx="20.892099"
|
||||
cy="114.5684"
|
||||
r="5.256"
|
||||
fx="20.892099"
|
||||
fy="114.5684"
|
||||
id="radialGradient2283"
|
||||
xlink:href="#aigrd2"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.229703,0,0,0.229703,4.613529,3.979808)" />
|
||||
<radialGradient
|
||||
cx="20.892099"
|
||||
cy="64.567902"
|
||||
r="5.257"
|
||||
fx="20.892099"
|
||||
fy="64.567902"
|
||||
id="radialGradient2285"
|
||||
xlink:href="#aigrd3"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.229703,0,0,0.229703,4.613529,3.979808)" />
|
||||
<linearGradient
|
||||
x1="18.971846"
|
||||
y1="14.452502"
|
||||
x2="44.524982"
|
||||
y2="41.792759"
|
||||
id="linearGradient4343"
|
||||
xlink:href="#linearGradient3377-76"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
id="linearGradient3377-76">
|
||||
<stop
|
||||
id="stop3379-5"
|
||||
style="stop-color:#faff2b;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop4345"
|
||||
style="stop-color:#fcb915;stop-opacity:1"
|
||||
offset="0.5" />
|
||||
<stop
|
||||
id="stop3381-7"
|
||||
style="stop-color:#c68708;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="145.64697"
|
||||
y1="79.160103"
|
||||
x2="175.6825"
|
||||
y2="108.75008"
|
||||
id="linearGradient4349"
|
||||
xlink:href="#linearGradient3377-76"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
id="linearGradient4482">
|
||||
<stop
|
||||
id="stop4484"
|
||||
style="stop-color:#faff2b;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop4486"
|
||||
style="stop-color:#fcb915;stop-opacity:1"
|
||||
offset="0.5" />
|
||||
<stop
|
||||
id="stop4488"
|
||||
style="stop-color:#c68708;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
cx="135.38333"
|
||||
cy="97.369568"
|
||||
r="19.467436"
|
||||
fx="135.38333"
|
||||
fy="97.369568"
|
||||
id="radialGradient4351"
|
||||
xlink:href="#linearGradient3377"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.97435,0.2250379,-0.4623105,2.0016728,48.487554,-127.99883)" />
|
||||
<linearGradient
|
||||
id="linearGradient3377">
|
||||
<stop
|
||||
id="stop3379"
|
||||
style="stop-color:#faff2b;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3381"
|
||||
style="stop-color:#ffaa00;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
cx="45.883327"
|
||||
cy="28.869568"
|
||||
r="19.467436"
|
||||
fx="45.883327"
|
||||
fy="28.869568"
|
||||
id="radialGradient4353"
|
||||
xlink:href="#linearGradient3377"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
id="linearGradient4495">
|
||||
<stop
|
||||
id="stop4497"
|
||||
style="stop-color:#faff2b;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop4499"
|
||||
style="stop-color:#ffaa00;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
xlink:href="#aigrd2-2"
|
||||
id="radialGradient2283-4"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.229703,0,0,0.229703,4.613529,3.979808)"
|
||||
cx="20.892099"
|
||||
cy="114.5684"
|
||||
fx="20.892099"
|
||||
fy="114.5684"
|
||||
r="5.256" />
|
||||
<radialGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
fy="114.5684"
|
||||
fx="20.892099"
|
||||
r="5.256"
|
||||
cy="114.5684"
|
||||
cx="20.892099"
|
||||
id="aigrd2-2">
|
||||
<stop
|
||||
id="stop15566-3"
|
||||
style="stop-color:#F0F0F0"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop15568-2"
|
||||
style="stop-color:#9a9a9a;stop-opacity:1.0000000;"
|
||||
offset="1.0000000" />
|
||||
</radialGradient>
|
||||
<radialGradient
|
||||
xlink:href="#aigrd3-1"
|
||||
id="radialGradient2285-2"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.229703,0,0,0.229703,4.613529,3.979808)"
|
||||
cx="20.892099"
|
||||
cy="64.567902"
|
||||
fx="20.892099"
|
||||
fy="64.567902"
|
||||
r="5.257" />
|
||||
<radialGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
fy="64.567902"
|
||||
fx="20.892099"
|
||||
r="5.257"
|
||||
cy="64.567902"
|
||||
cx="20.892099"
|
||||
id="aigrd3-1">
|
||||
<stop
|
||||
id="stop15573-6"
|
||||
style="stop-color:#F0F0F0"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop15575-8"
|
||||
style="stop-color:#9a9a9a;stop-opacity:1.0000000;"
|
||||
offset="1.0000000" />
|
||||
</radialGradient>
|
||||
<radialGradient
|
||||
r="38.158695"
|
||||
fy="7.2678967"
|
||||
fx="8.1435566"
|
||||
cy="7.2678967"
|
||||
cx="8.1435566"
|
||||
gradientTransform="matrix(1.2992848,0,0,1.4315068,3.2140525,-64.437909)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient15668-2"
|
||||
xlink:href="#linearGradient15662-7" />
|
||||
<linearGradient
|
||||
id="linearGradient15662-7">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1.0000000;"
|
||||
offset="0.0000000"
|
||||
id="stop15664-6" />
|
||||
<stop
|
||||
style="stop-color:#f8f8f8;stop-opacity:1.0000000;"
|
||||
offset="1.0000000"
|
||||
id="stop15666-1" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="86.70845"
|
||||
fy="35.736916"
|
||||
fx="33.966679"
|
||||
cy="35.736916"
|
||||
cx="33.966679"
|
||||
gradientTransform="matrix(1.3214205,0,0,1.4752426,-2.0839021,-66.146883)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient15658-4"
|
||||
xlink:href="#linearGradient259-5" />
|
||||
<linearGradient
|
||||
id="linearGradient259-5">
|
||||
<stop
|
||||
style="stop-color:#fafafa;stop-opacity:1.0000000;"
|
||||
offset="0.0000000"
|
||||
id="stop260-5" />
|
||||
<stop
|
||||
style="stop-color:#bbbbbb;stop-opacity:1.0000000;"
|
||||
offset="1.0000000"
|
||||
id="stop261-1" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="37.751713"
|
||||
fy="37.388847"
|
||||
fx="3.3431637"
|
||||
cy="37.388847"
|
||||
cx="3.3431637"
|
||||
gradientTransform="matrix(1.3321242,0,0,1.4633899,2.5298271,-65.230893)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient15656-7"
|
||||
xlink:href="#linearGradient269-1" />
|
||||
<linearGradient
|
||||
id="linearGradient269-1">
|
||||
<stop
|
||||
style="stop-color:#a3a3a3;stop-opacity:1.0000000;"
|
||||
offset="0.0000000"
|
||||
id="stop270-1" />
|
||||
<stop
|
||||
style="stop-color:#4c4c4c;stop-opacity:1.0000000;"
|
||||
offset="1.0000000"
|
||||
id="stop271-5" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient5048-7"
|
||||
id="linearGradient5027-1"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
|
||||
x1="302.85715"
|
||||
y1="366.64789"
|
||||
x2="302.85715"
|
||||
y2="609.50507" />
|
||||
<linearGradient
|
||||
id="linearGradient5048-7">
|
||||
<stop
|
||||
style="stop-color:black;stop-opacity:0;"
|
||||
offset="0"
|
||||
id="stop5050-4" />
|
||||
<stop
|
||||
id="stop5056-0"
|
||||
offset="0.5"
|
||||
style="stop-color:black;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:black;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop5052-9" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
xlink:href="#linearGradient5060-8"
|
||||
id="radialGradient5029-4"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
|
||||
cx="605.71429"
|
||||
cy="486.64789"
|
||||
fx="605.71429"
|
||||
fy="486.64789"
|
||||
r="117.14286" />
|
||||
<linearGradient
|
||||
id="linearGradient5060-8">
|
||||
<stop
|
||||
style="stop-color:black;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5062-8" />
|
||||
<stop
|
||||
style="stop-color:black;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop5064-2" />
|
||||
</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,112.7623,-872.8854)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient3663"
|
||||
xlink:href="#linearGradient5060-8" />
|
||||
<radialGradient
|
||||
r="117.14286"
|
||||
fy="486.64789"
|
||||
fx="605.71429"
|
||||
cy="486.64789"
|
||||
cx="605.71429"
|
||||
gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient4227"
|
||||
xlink:href="#linearGradient5060-8" />
|
||||
<radialGradient
|
||||
xlink:href="#linearGradient3999"
|
||||
id="radialGradient4005"
|
||||
cx="123.11044"
|
||||
cy="7.0833611"
|
||||
fx="123.11044"
|
||||
fy="7.0833611"
|
||||
r="11.846154"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.35714269,0.7142857,-1.3537553,0.6768774,100.50163,-81.878026)" />
|
||||
<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>
|
||||
<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
|
||||
y2="13.54708"
|
||||
x2="110.78806"
|
||||
y1="40.751484"
|
||||
x1="114.38387"
|
||||
gradientTransform="matrix(0.8125,0,0,0.84615385,0.2492882,10.115317)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3389-1"
|
||||
xlink:href="#linearGradient4029-5" />
|
||||
<linearGradient
|
||||
id="linearGradient4029-5">
|
||||
<stop
|
||||
style="stop-color:#555753;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop4031-2" />
|
||||
<stop
|
||||
style="stop-color:#babdb6;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop4033-7" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient4289"
|
||||
id="linearGradient3484"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.8125,0,0,0.84615385,0.2492882,10.115317)"
|
||||
x1="102.22456"
|
||||
y1="45.629101"
|
||||
x2="100.94191"
|
||||
y2="13.54708" />
|
||||
<linearGradient
|
||||
id="linearGradient4289">
|
||||
<stop
|
||||
style="stop-color:#888a85;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop4291" />
|
||||
<stop
|
||||
style="stop-color:#d3d7cf;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop4293" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="13.569667"
|
||||
x2="111.92233"
|
||||
y1="40.751484"
|
||||
x1="114.38387"
|
||||
gradientTransform="matrix(0.8125,0,0,0.84615385,-27.743611,10.096205)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3389"
|
||||
xlink:href="#linearGradient4029" />
|
||||
<linearGradient
|
||||
y2="12.365262"
|
||||
x2="97.249619"
|
||||
y1="45.629101"
|
||||
x1="102.22456"
|
||||
gradientTransform="matrix(0.8125,0,0,0.84615385,-27.743611,10.096205)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3387"
|
||||
xlink:href="#linearGradient3995" />
|
||||
</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
|
||||
id="g2062">
|
||||
<g
|
||||
id="g2033">
|
||||
<g
|
||||
transform="translate(-45.955657,1.2945347)"
|
||||
id="g3615">
|
||||
<path
|
||||
style="display:inline;fill:url(#linearGradient3387);fill-opacity:1;stroke:#042a2a;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 50.193891,47.557745 -6.03e-4,-29.979514 10.000603,1.979513 -6.03e-4,30.020491 z"
|
||||
id="path3185" />
|
||||
<path
|
||||
style="display:inline;fill:#34e0e2;stroke:#042a2a;stroke-width:1.99999988;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 50.193288,17.578231 8,-6 10,2 -7.999397,5.979513 z"
|
||||
id="path3973" />
|
||||
<path
|
||||
style="display:inline;fill:url(#linearGradient3389);fill-opacity:1;stroke:#042a2a;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 60.193891,19.557744 -6.03e-4,30.020491 8,-6 V 13.578231 Z"
|
||||
id="path3975" />
|
||||
<path
|
||||
style="display:inline;fill:none;stroke:#34e0e2;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 52.191721,45.883155 0.0016,-25.972329 5.994477,1.343305 -0.02219,25.991504 z"
|
||||
id="path3185-7" />
|
||||
<path
|
||||
style="display:inline;fill:none;stroke:#16d0d2;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 62.200392,20.560856 0.07129,24.998259 3.921607,-2.98088 0.0087,-25.013269 z"
|
||||
id="path3975-4" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(1.7061099,0.5884249)"
|
||||
id="g3630">
|
||||
<g
|
||||
id="g3622"
|
||||
transform="translate(-38.129929,0.94147973)">
|
||||
<path
|
||||
id="path3185-3"
|
||||
d="m 78.186788,47.576855 -6.03e-4,-29.979512 10.000603,1.979512 -6e-4,30.02049 z"
|
||||
style="display:inline;fill:url(#linearGradient3484);fill-opacity:1;stroke:#2e3436;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
|
||||
<path
|
||||
id="path3973-2"
|
||||
d="m 78.186185,17.597343 8.000003,-6 10,2 -7.9994,5.979512 z"
|
||||
style="display:inline;fill:#d3d7cf;stroke:#2e3436;stroke-width:1.99999988;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
|
||||
<path
|
||||
id="path3975-2"
|
||||
d="m 88.186788,19.576855 -6e-4,30.02049 8,-6 V 13.597343 Z"
|
||||
style="display:inline;fill:url(#linearGradient3389-1);fill-opacity:1;stroke:#2e3436;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
|
||||
<path
|
||||
id="path3185-7-1"
|
||||
d="m 80.184616,45.902265 0.002,-25.972328 5.994482,1.343305 -0.0222,25.991503 z"
|
||||
style="display:inline;fill:none;stroke:#d3d7cf;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
id="path3975-4-6"
|
||||
d="m 90.193288,20.579967 0.0713,24.998268 3.92161,-2.98089 0.009,-25.013267 z"
|
||||
style="display:inline;fill:none;stroke:#babdb6;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g2040">
|
||||
<g
|
||||
id="layer4"
|
||||
style="display:inline"
|
||||
transform="translate(0,16.894643)" />
|
||||
<path
|
||||
id="path2157"
|
||||
d="m 26.819029,8.6740883 v 0 c 0,0 10.04843,5.0531627 12.31257,5.8860687 l -12.43802,16.213145 12.43802,17.786893 -12.81439,7.513398"
|
||||
style="fill:none;stroke:#cc0000;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.60000002;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;stroke:#ef2929;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.60000002;stroke-opacity:1"
|
||||
d="m 26.819029,8.6740883 v 0 c 0,0 10.04843,5.0531627 12.31257,5.8860687 l -12.43802,16.213145 12.43802,17.786893 -12.81439,7.513398"
|
||||
id="path1946" />
|
||||
<path
|
||||
id="path3202"
|
||||
d="m 27.079329,13.202347 3.58181,-6.3012697 -9.40113,-1.3838495 z"
|
||||
style="fill:#ef2929;stroke:#cc0000" />
|
||||
<path
|
||||
id="path3200"
|
||||
d="m 31.163289,57.310406 -3.66615,-6.252569 -5.89901,7.44969 z"
|
||||
style="fill:#ef2929;stroke:#cc0000" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 28 KiB |
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 25 KiB |
812
src/Mod/TechDraw/Gui/TaskComplexSection.cpp
Normal file
812
src/Mod/TechDraw/Gui/TaskComplexSection.cpp
Normal file
@@ -0,0 +1,812 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2022 WandererFan <wandererfan@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
#endif // #ifndef _PreComp_
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
|
||||
#include <App/Document.h>
|
||||
#include <App/DocumentObject.h>
|
||||
#include <App/Link.h>
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Tools.h>
|
||||
#include <Base/Quantity.h>
|
||||
#include <Base/UnitsApi.h>
|
||||
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/BitmapFactory.h>
|
||||
#include <Gui/Command.h>
|
||||
#include <Gui/Control.h>
|
||||
#include <Gui/Document.h>
|
||||
#include <Gui/MainWindow.h>
|
||||
#include <Gui/Selection.h>
|
||||
#include <Gui/ViewProvider.h>
|
||||
#include <Gui/WaitCursor.h>
|
||||
|
||||
#include <Mod/TechDraw/App/DrawPage.h>
|
||||
#include <Mod/TechDraw/App/DrawUtil.h>
|
||||
#include <Mod/TechDraw/App/DrawView.h>
|
||||
#include <Mod/TechDraw/App/DrawViewPart.h>
|
||||
#include <Mod/TechDraw/App/DrawComplexSection.h>
|
||||
#include <Mod/TechDraw/App/Preferences.h>
|
||||
|
||||
#include <Mod/TechDraw/Gui/ui_TaskComplexSection.h>
|
||||
|
||||
#include "DrawGuiUtil.h"
|
||||
#include "Widgets/CompassWidget.h"
|
||||
#include "Widgets/VectorEditWidget.h"
|
||||
|
||||
#include "TaskComplexSection.h"
|
||||
|
||||
using namespace Gui;
|
||||
using namespace TechDraw;
|
||||
using namespace TechDrawGui;
|
||||
|
||||
//ctor for creation
|
||||
TaskComplexSection::TaskComplexSection(TechDraw::DrawPage* page,
|
||||
TechDraw::DrawViewPart* baseView,
|
||||
std::vector<App::DocumentObject*> shapes,
|
||||
std::vector<App::DocumentObject*> xShapes,
|
||||
App::DocumentObject* profileObject,
|
||||
std::vector<std::string> profileSubs) :
|
||||
ui(new Ui_TaskComplexSection),
|
||||
m_page(page),
|
||||
m_baseView(baseView),
|
||||
m_section(nullptr),
|
||||
m_shapes(shapes),
|
||||
m_xShapes(xShapes),
|
||||
m_profileObject(profileObject),
|
||||
m_profileSubs(profileSubs),
|
||||
m_dirName("Aligned"),
|
||||
m_createMode(true),
|
||||
m_applyDeferred(0),
|
||||
m_angle(0.0)
|
||||
{
|
||||
m_sectionName = std::string();
|
||||
m_doc = m_baseView->getDocument();
|
||||
|
||||
m_saveBaseName = m_baseView->getNameInDocument();
|
||||
m_savePageName = m_baseView->findParentPage()->getNameInDocument();
|
||||
m_localUnit = Base::Vector3d(0.0, 1.0, 0.0);
|
||||
|
||||
ui->setupUi(this);
|
||||
|
||||
saveSectionState();
|
||||
setUiPrimary();
|
||||
|
||||
m_applyDeferred = 0; //setting the direction widgets causes an increment of the deferred count,
|
||||
//so we reset the counter and the message.
|
||||
ui->lPendingUpdates->setText(QString());
|
||||
}
|
||||
|
||||
//ctor for edit
|
||||
TaskComplexSection::TaskComplexSection(TechDraw::DrawComplexSection* complexSection) :
|
||||
ui(new Ui_TaskComplexSection),
|
||||
m_page(nullptr),
|
||||
m_baseView(nullptr),
|
||||
m_section(complexSection),
|
||||
m_profileObject(nullptr),
|
||||
m_dirName("Aligned"),
|
||||
m_createMode(false),
|
||||
m_applyDeferred(0),
|
||||
m_angle(0.0)
|
||||
{
|
||||
m_sectionName = m_section->getNameInDocument();
|
||||
m_doc = m_section->getDocument();
|
||||
m_baseView = dynamic_cast<TechDraw::DrawViewPart*> (m_section->BaseView.getValue());
|
||||
if (m_baseView) {
|
||||
m_saveBaseName = m_baseView->getNameInDocument();
|
||||
m_savePageName = m_baseView->findParentPage()->getNameInDocument();
|
||||
}
|
||||
m_shapes = m_section->Source.getValues();
|
||||
m_xShapes = m_section->XSource.getValues();
|
||||
m_profileObject = m_section->CuttingToolWireObject.getValue();
|
||||
m_localUnit = Base::Vector3d(0.0, 1.0, 0.0);
|
||||
|
||||
ui->setupUi(this);
|
||||
|
||||
saveSectionState();
|
||||
setUiEdit();
|
||||
|
||||
m_applyDeferred = 0; //setting the direction widgets causes an increment of the deferred count,
|
||||
//so we reset the counter and the message.
|
||||
ui->lPendingUpdates->setText(QString());
|
||||
}
|
||||
|
||||
void TaskComplexSection::setUiPrimary()
|
||||
{
|
||||
setWindowTitle(QObject::tr("New Complex Section"));
|
||||
if (m_baseView) {
|
||||
ui->sbScale->setValue(m_baseView->getScale());
|
||||
ui->cmbScaleType->setCurrentIndex(m_baseView->ScaleType.getValue());
|
||||
} else {
|
||||
ui->sbScale->setValue(Preferences::scale());
|
||||
ui->cmbScaleType->setCurrentIndex(Preferences::scaleType());
|
||||
}
|
||||
ui->cmbStrategy->setCurrentIndex(0);
|
||||
|
||||
setUiCommon();
|
||||
|
||||
if (m_baseView) {
|
||||
ui->leBaseView->setText(Base::Tools::fromStdString(m_baseView->getNameInDocument()));
|
||||
//if there is a baseView, we don't know the sectionNormal yet and have to wait until
|
||||
//one is picked in the dialog
|
||||
Base::Vector3d defaultNormal(-1.0, 0.0, 0.0);
|
||||
m_saveNormal = defaultNormal;
|
||||
m_localUnit = defaultNormal;
|
||||
m_saveXDir = Base::Vector3d(0.0, 1.0, 0.0);
|
||||
ui->leBaseView->setText(Base::Tools::fromStdString(m_baseView->getNameInDocument()));
|
||||
m_viewDirectionWidget->setValue(defaultNormal * -1.0);
|
||||
} else {
|
||||
//if there is no baseView, we use the 3d view to determine the SectionNormal
|
||||
//and XDirection.
|
||||
std::pair<Base::Vector3d, Base::Vector3d> dirs = DrawGuiUtil::get3DDirAndRot();
|
||||
m_saveNormal = dirs.first;
|
||||
m_localUnit = dirs.first;
|
||||
m_saveXDir = dirs.second;
|
||||
m_viewDirectionWidget->setValue(m_saveNormal * -1.0); //this will propogate to m_compass
|
||||
}
|
||||
}
|
||||
|
||||
void TaskComplexSection::setUiEdit()
|
||||
{
|
||||
setWindowTitle(QObject::tr("Edit Complex Section"));
|
||||
|
||||
if (m_baseView) {
|
||||
ui->leBaseView->setText(Base::Tools::fromStdString(m_baseView->getNameInDocument()));
|
||||
}
|
||||
ui->cmbStrategy->setCurrentIndex(m_section->ProjectionStrategy.getValue());
|
||||
ui->leSymbol->setText(Base::Tools::fromStdString(m_section->SectionSymbol.getValue()));
|
||||
ui->sbScale->setValue(m_section->Scale.getValue());
|
||||
ui->cmbScaleType->setCurrentIndex(m_section->ScaleType.getValue());
|
||||
|
||||
setUiCommon();
|
||||
|
||||
Base::Vector3d sectionNormalVec = m_section->SectionNormal.getValue();
|
||||
if (m_baseView) {
|
||||
ui->leBaseView->setText(Base::Tools::fromStdString(m_baseView->getNameInDocument()));
|
||||
Base::Vector3d projectedViewDirection = m_baseView->projectPoint(sectionNormalVec, false);
|
||||
double viewAngle = atan2(-projectedViewDirection.y,
|
||||
-projectedViewDirection.x);
|
||||
m_compass->setDialAngle(viewAngle * 180.0 / M_PI);
|
||||
m_viewDirectionWidget->setValue(projectedViewDirection * -1.0);
|
||||
} else {
|
||||
//no local angle makes sense if there is no baseView?
|
||||
m_viewDirectionWidget->setValue(sectionNormalVec * -1.0);
|
||||
}
|
||||
}
|
||||
|
||||
void TaskComplexSection::setUiCommon()
|
||||
{
|
||||
ui->leSectionObjects->setText(sourcesToString());
|
||||
ui->leProfileObject->setText(Base::Tools::fromStdString(m_profileObject->getNameInDocument()) +
|
||||
QString::fromUtf8(" / ") +
|
||||
Base::Tools::fromStdString(m_profileObject->Label.getValue()));
|
||||
|
||||
m_compass = new CompassWidget(this);
|
||||
auto layout = ui->compassLayout;
|
||||
layout->addWidget(m_compass);
|
||||
|
||||
m_viewDirectionWidget = new VectorEditWidget(this);
|
||||
m_viewDirectionWidget->setLabel(QObject::tr("Current View Direction"));
|
||||
auto editLayout = ui->viewDirectionLayout;
|
||||
editLayout->addWidget(m_viewDirectionWidget);
|
||||
|
||||
connect(ui->pbRight, SIGNAL(clicked(bool)), m_compass, SLOT(setToEast()));
|
||||
connect(ui->pbLeft, SIGNAL(clicked(bool)), m_compass, SLOT(setToWest()));
|
||||
connect(ui->pbUp, SIGNAL(clicked(bool)), m_compass, SLOT(setToNorth()));
|
||||
connect(ui->pbDown, SIGNAL(clicked(bool)), m_compass, SLOT(setToSouth()));
|
||||
connect(m_compass, SIGNAL(angleChanged(double)), this, SLOT(slotChangeAngle(double)));
|
||||
|
||||
connect(ui->pbUp, SIGNAL(clicked(bool)), this, SLOT(onUpClicked()));
|
||||
connect(ui->pbDown, SIGNAL(clicked(bool)), this, SLOT(onDownClicked()));
|
||||
connect(ui->pbRight, SIGNAL(clicked(bool)), this, SLOT(onRightClicked()));
|
||||
connect(ui->pbLeft, SIGNAL(clicked(bool)), this, SLOT(onLeftClicked()));
|
||||
|
||||
connect(ui->pbUpdateNow, SIGNAL(clicked(bool)), this, SLOT(updateNowClicked()));
|
||||
connect(ui->cbLiveUpdate, SIGNAL(clicked(bool)), this, SLOT(liveUpdateClicked()));
|
||||
|
||||
connect(ui->pbSectionObjects, SIGNAL(clicked()), this, SLOT(onSectionObjectsUseSelectionClicked()));
|
||||
connect(ui->pbProfileObject, SIGNAL(clicked()), this, SLOT(onProfileObjectsUseSelectionClicked()));
|
||||
|
||||
connect(m_compass, SIGNAL(angleChanged(double)), this, SLOT(slotChangeAngle(double)));
|
||||
connect(m_viewDirectionWidget, SIGNAL(valueChanged(Base::Vector3d)),
|
||||
this, SLOT(slotViewDirectionChanged(Base::Vector3d)));
|
||||
}
|
||||
|
||||
//save the start conditions
|
||||
void TaskComplexSection::saveSectionState()
|
||||
{
|
||||
// Base::Console().Message("TCS::saveSectionState()\n");
|
||||
if (m_section) {
|
||||
m_saveSymbol = m_section->SectionSymbol.getValue();
|
||||
m_saveScale = m_section->getScale();
|
||||
m_saveScaleType = m_section->ScaleType.getValue();
|
||||
m_saveNormal = m_section->SectionNormal.getValue();
|
||||
m_saveDirection = m_section->Direction.getValue();
|
||||
m_localUnit = m_saveNormal;
|
||||
m_saveXDir = m_section->XDirection.getValue();
|
||||
m_saveOrigin = m_section->SectionOrigin.getValue();
|
||||
m_saveDirName = m_section->SectionDirection.getValueAsString();
|
||||
m_saved = true;
|
||||
}
|
||||
if (m_baseView) {
|
||||
m_shapes = m_baseView->Source.getValues();
|
||||
m_xShapes = m_baseView->XSource.getValues();
|
||||
}
|
||||
}
|
||||
|
||||
//restore the start conditions
|
||||
void TaskComplexSection::restoreSectionState()
|
||||
{
|
||||
// Base::Console().Message("TCS::restoreSectionState()\n");
|
||||
if (!m_section)
|
||||
return;
|
||||
|
||||
m_section->SectionSymbol.setValue(m_saveSymbol);
|
||||
m_section->Scale.setValue(m_saveScale);
|
||||
m_section->ScaleType.setValue(m_saveScaleType);
|
||||
m_section->SectionNormal.setValue(m_saveNormal);
|
||||
m_section->Direction.setValue(m_saveDirection);
|
||||
m_section->XDirection.setValue(m_saveXDir);
|
||||
m_section->SectionOrigin.setValue(m_saveOrigin);
|
||||
m_section->SectionDirection.setValue(m_saveDirName.c_str());
|
||||
}
|
||||
|
||||
void TaskComplexSection::onSectionObjectsUseSelectionClicked()
|
||||
{
|
||||
std::vector<Gui::SelectionObject> selection = Gui::Selection().getSelectionEx();
|
||||
std::vector<App::DocumentObject*> newSelection;
|
||||
std::vector<App::DocumentObject*> newXSelection;
|
||||
for (auto& sel : selection) {
|
||||
if (sel.getObject()->isDerivedFrom(App::LinkElement::getClassTypeId()) ||
|
||||
sel.getObject()->isDerivedFrom(App::LinkGroup::getClassTypeId()) ||
|
||||
sel.getObject()->isDerivedFrom(App::Link::getClassTypeId()) ) {
|
||||
newXSelection.push_back(sel.getObject());
|
||||
} else {
|
||||
newSelection.push_back(sel.getObject());
|
||||
}
|
||||
}
|
||||
m_shapes = newSelection;
|
||||
m_xShapes = newXSelection;
|
||||
ui->leSectionObjects->setText(sourcesToString());
|
||||
}
|
||||
|
||||
//the VectorEditWidget reports a change in direction
|
||||
void TaskComplexSection::slotViewDirectionChanged(Base::Vector3d newDirection)
|
||||
{
|
||||
// Base::Console().Message("TCS::slotViewDirectionChanged(%s)\n",
|
||||
// DrawUtil::formatVector(newDirection).c_str());
|
||||
Base::Vector3d projectedViewDirection = m_baseView->projectPoint(newDirection, false);
|
||||
projectedViewDirection.Normalize();
|
||||
double viewAngle = atan2(projectedViewDirection.y,
|
||||
projectedViewDirection.x);
|
||||
m_compass->setDialAngle(viewAngle * 180.0 / M_PI);
|
||||
checkAll(false);
|
||||
applyAligned(projectedViewDirection);
|
||||
}
|
||||
|
||||
//the CompassWidget reports the view direction. This is the reverse of the
|
||||
//SectionNormal
|
||||
void TaskComplexSection::slotChangeAngle(double newAngle)
|
||||
{
|
||||
// Base::Console().Message("TCS::slotAngleChanged(%.3f)\n", newAngle);
|
||||
double angleRadians = newAngle * M_PI / 180.0;
|
||||
if (m_baseView) {
|
||||
double unitX = cos(angleRadians);
|
||||
double unitY = sin(angleRadians);
|
||||
Base::Vector3d localUnit(unitX, unitY, 0.0);
|
||||
m_viewDirectionWidget->setValue(localUnit);
|
||||
checkAll(false);
|
||||
applyAligned(localUnit);
|
||||
} else {
|
||||
//save the angle for later use
|
||||
m_angle = angleRadians;
|
||||
}
|
||||
}
|
||||
void TaskComplexSection::onUpClicked()
|
||||
{
|
||||
// Base::Console().Message("TCS::onUpClicked()\n");
|
||||
checkAll(false);
|
||||
applyAligned(Base::Vector3d(0.0, 1.0, 0.0));
|
||||
}
|
||||
|
||||
void TaskComplexSection::onDownClicked()
|
||||
{
|
||||
// Base::Console().Message("TCS::onDownClicked()\n");
|
||||
checkAll(false);
|
||||
applyAligned(Base::Vector3d(0.0, -1.0, 0.0));
|
||||
}
|
||||
|
||||
void TaskComplexSection::onLeftClicked()
|
||||
{
|
||||
// Base::Console().Message("TCS::onLeftClicked()\n");
|
||||
checkAll(false);
|
||||
applyAligned(Base::Vector3d(-1.0, 0.0, 0.0));
|
||||
}
|
||||
|
||||
void TaskComplexSection::onRightClicked()
|
||||
{
|
||||
// Base::Console().Message("TCS::onRightClicked()\n");
|
||||
checkAll(false);
|
||||
applyAligned(Base::Vector3d(1.0, 0.0, 0.0));
|
||||
}
|
||||
|
||||
void TaskComplexSection::onIdentifierChanged()
|
||||
{
|
||||
checkAll(false);
|
||||
apply();
|
||||
}
|
||||
|
||||
void TaskComplexSection::onScaleChanged()
|
||||
{
|
||||
checkAll(false);
|
||||
apply();
|
||||
}
|
||||
|
||||
void TaskComplexSection::onProfileObjectsUseSelectionClicked()
|
||||
{
|
||||
std::vector<Gui::SelectionObject> selection = Gui::Selection().getSelectionEx();
|
||||
//check for single selection and ability to make profile from selected object
|
||||
if (!selection.empty()) {
|
||||
m_profileObject = selection.front().getObject();
|
||||
ui->leProfileObject->setText(Base::Tools::fromStdString(m_profileObject->getNameInDocument()) +
|
||||
QString::fromUtf8(" / ") +
|
||||
Base::Tools::fromStdString(m_profileObject->Label.getValue()));
|
||||
}
|
||||
}
|
||||
void TaskComplexSection::scaleTypeChanged(int index)
|
||||
{
|
||||
if (index == 0) {
|
||||
// Page Scale Type
|
||||
ui->sbScale->setEnabled(false);
|
||||
if (m_baseView->findParentPage()) {
|
||||
ui->sbScale->setValue(m_baseView->findParentPage()->Scale.getValue());
|
||||
ui->sbScale->setEnabled(false);
|
||||
}
|
||||
} else if (index == 1) {
|
||||
// Automatic Scale Type
|
||||
ui->sbScale->setEnabled(false);
|
||||
if (m_section) {
|
||||
ui->sbScale->setValue(m_section->autoScale());
|
||||
}
|
||||
} else if (index == 2) {
|
||||
// Custom Scale Type
|
||||
ui->sbScale->setEnabled(true);
|
||||
if (m_section) {
|
||||
ui->sbScale->setValue(m_section->Scale.getValue());
|
||||
ui->sbScale->setEnabled(true);
|
||||
}
|
||||
} else {
|
||||
Base::Console().Log("Error - TaskComplexSection::scaleTypeChanged - unknown scale type: %d\n", index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void TaskComplexSection::checkAll(bool check)
|
||||
{
|
||||
ui->pbUp->setChecked(check);
|
||||
ui->pbDown->setChecked(check);
|
||||
ui->pbRight->setChecked(check);
|
||||
ui->pbLeft->setChecked(check);
|
||||
}
|
||||
|
||||
void TaskComplexSection::enableAll(bool enable)
|
||||
{
|
||||
ui->leSymbol->setEnabled(enable);
|
||||
ui->sbScale->setEnabled(enable);
|
||||
ui->cmbScaleType->setEnabled(enable);
|
||||
QString qScaleType = ui->cmbScaleType->currentText();
|
||||
//Allow or prevent scale changing initially
|
||||
if (qScaleType == QString::fromUtf8("Custom")) {
|
||||
ui->sbScale->setEnabled(true);
|
||||
}
|
||||
else {
|
||||
ui->sbScale->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void TaskComplexSection::liveUpdateClicked() {
|
||||
apply(true);
|
||||
}
|
||||
|
||||
void TaskComplexSection::updateNowClicked() {
|
||||
apply(true);
|
||||
}
|
||||
|
||||
QString TaskComplexSection::sourcesToString()
|
||||
{
|
||||
QString result;
|
||||
QString separator(QString::fromUtf8(", "));
|
||||
QString currentSeparator;
|
||||
if (m_baseView) {
|
||||
for (auto& obj : m_baseView->Source.getValues()) {
|
||||
result += currentSeparator +
|
||||
Base::Tools::fromStdString(obj->getNameInDocument()) +
|
||||
QString::fromUtf8(" / ") +
|
||||
Base::Tools::fromStdString(obj->Label.getValue());
|
||||
currentSeparator = separator;
|
||||
}
|
||||
currentSeparator = QString();
|
||||
for (auto& obj : m_baseView->XSource.getValues()) {
|
||||
result += currentSeparator +
|
||||
Base::Tools::fromStdString(obj->getNameInDocument()) +
|
||||
QString::fromUtf8(" / ") +
|
||||
Base::Tools::fromStdString(obj->Label.getValue());
|
||||
}
|
||||
} else {
|
||||
for (auto& obj : m_shapes) {
|
||||
result += currentSeparator +
|
||||
Base::Tools::fromStdString(obj->getNameInDocument()) +
|
||||
QString::fromUtf8(" / ") +
|
||||
Base::Tools::fromStdString(obj->Label.getValue());
|
||||
}
|
||||
currentSeparator = QString();
|
||||
for (auto& obj : m_xShapes) {
|
||||
result += currentSeparator +
|
||||
Base::Tools::fromStdString(obj->getNameInDocument()) +
|
||||
QString::fromUtf8(" / ") +
|
||||
Base::Tools::fromStdString(obj->Label.getValue());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
bool TaskComplexSection::apply(bool forceUpdate)
|
||||
{
|
||||
// Base::Console().Message("TCS::apply() - liveUpdate: %d forece: %d\n",
|
||||
// ui->cbLiveUpdate->isChecked(), forceUpdate);
|
||||
if(!ui->cbLiveUpdate->isChecked() &&
|
||||
!forceUpdate) {
|
||||
//nothing to do
|
||||
m_applyDeferred++;
|
||||
QString msgLiteral = QString::fromUtf8(QT_TRANSLATE_NOOP("TaskPojGroup", " updates pending"));
|
||||
QString msgNumber = QString::number(m_applyDeferred);
|
||||
ui->lPendingUpdates->setText(msgNumber + msgLiteral);
|
||||
return false;
|
||||
}
|
||||
|
||||
Gui::WaitCursor wc;
|
||||
if (!m_section) {
|
||||
createComplexSection();
|
||||
}
|
||||
|
||||
if (isSectionValid()) {
|
||||
updateComplexSection();
|
||||
} else {
|
||||
failNoObject();
|
||||
}
|
||||
|
||||
m_section->recomputeFeature();
|
||||
if (isBaseValid()) {
|
||||
m_baseView->requestPaint();
|
||||
}
|
||||
|
||||
enableAll(true);
|
||||
checkAll(false);
|
||||
|
||||
wc.restoreCursor();
|
||||
m_applyDeferred = 0;
|
||||
ui->lPendingUpdates->setText(QString());
|
||||
return true;
|
||||
}
|
||||
|
||||
void TaskComplexSection::applyAligned(Base::Vector3d localUnit)
|
||||
{
|
||||
// Base::Console().Message("TCS::applyAligned(%s)\n",
|
||||
// DrawUtil::formatVector(localUnit).c_str());
|
||||
m_dirName = "Aligned";
|
||||
m_localUnit = localUnit;
|
||||
enableAll(true);
|
||||
apply();
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
|
||||
//pointer to created view is not returned, but stored in m_section
|
||||
void TaskComplexSection::createComplexSection()
|
||||
{
|
||||
// Base::Console().Message("TCS::createComplexSection()\n");
|
||||
|
||||
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Create ComplexSection"));
|
||||
if (!m_section) {
|
||||
m_sectionName = m_page->getDocument()->getUniqueObjectName("ComplexSection");
|
||||
std::string sectionType = "TechDraw::DrawComplexSection";
|
||||
|
||||
Command::doCommand(Command::Doc, "App.ActiveDocument.addObject('%s', '%s')",
|
||||
sectionType.c_str(), m_sectionName.c_str());
|
||||
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.addView(App.ActiveDocument.%s)",
|
||||
m_page->getNameInDocument(), m_sectionName.c_str());
|
||||
|
||||
QString qTemp = ui->leSymbol->text();
|
||||
std::string temp = Base::Tools::toStdString(qTemp);
|
||||
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.SectionSymbol = '%s'",
|
||||
m_sectionName.c_str(),
|
||||
temp.c_str());
|
||||
std::string lblText = "Section " +
|
||||
temp +
|
||||
" - " +
|
||||
temp;
|
||||
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.Label = '%s'",
|
||||
m_sectionName.c_str(),
|
||||
lblText.c_str());
|
||||
|
||||
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.Scale = %0.6f",
|
||||
m_sectionName.c_str(),
|
||||
ui->sbScale->value());
|
||||
int scaleType = ui->cmbScaleType->currentIndex();
|
||||
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.ScaleType = %d",
|
||||
m_sectionName.c_str(), scaleType);
|
||||
int projectionStrategy = ui->cmbStrategy->currentIndex();
|
||||
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.ProjectionStrategy = %d",
|
||||
m_sectionName.c_str(), projectionStrategy);
|
||||
|
||||
Command::doCommand(Command::Doc, "App.activeDocument().%s.SectionOrigin = FreeCAD.Vector(0.0, 0.0, 0.0)",
|
||||
m_sectionName.c_str());
|
||||
Command::doCommand(Command::Doc, "App.activeDocument().%s.SectionDirection = 'Aligned'",
|
||||
m_sectionName.c_str());
|
||||
|
||||
App::DocumentObject* newObj = m_page->getDocument()->getObject(m_sectionName.c_str());
|
||||
m_section = dynamic_cast<TechDraw::DrawComplexSection*>(newObj);
|
||||
if (!newObj || !m_section) {
|
||||
throw Base::RuntimeError("TaskComplexSection - new section object not found");
|
||||
}
|
||||
if (m_baseView) {
|
||||
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.BaseView = App.ActiveDocument.%s",
|
||||
m_sectionName.c_str(), m_baseView->getNameInDocument());
|
||||
if (m_localUnit.Length() != 0.0) {
|
||||
m_section->setCSFromBase(m_localUnit * -1.0);
|
||||
}
|
||||
m_section->Source.setValues(m_baseView->Source.getValues());
|
||||
m_section->XSource.setValues(m_baseView->XSource.getValues());
|
||||
} else {
|
||||
//if we have not changed the direction, we should use the 3d directions saved in the
|
||||
//constructor
|
||||
if (m_localUnit.IsEqual(m_saveNormal, EWTOLERANCE)) {
|
||||
m_section->SectionNormal.setValue(m_saveNormal);
|
||||
m_section->XDirection.setValue(m_saveXDir);
|
||||
} else {
|
||||
//if we have changed the direction, use the local unit to create a CS
|
||||
m_section->setCSFromLocalUnit(m_localUnit * -1.0);
|
||||
m_localUnit = m_saveNormal; //don't repeat this work next time through
|
||||
}
|
||||
m_section->Source.setValues(m_shapes);
|
||||
m_section->XSource.setValues(m_xShapes);
|
||||
}
|
||||
m_section->CuttingToolWireObject.setValue(m_profileObject);
|
||||
m_section->SectionDirection.setValue("Aligned");
|
||||
m_section->Source.setValues(m_shapes);
|
||||
m_section->XSource.setValues(m_xShapes);
|
||||
}
|
||||
Gui::Command::commitCommand();
|
||||
}
|
||||
|
||||
void TaskComplexSection::updateComplexSection()
|
||||
{
|
||||
// Base::Console().Message("TCS:;updateComplexSection()\n");
|
||||
if (!isSectionValid()) {
|
||||
failNoObject();
|
||||
return;
|
||||
}
|
||||
|
||||
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Edit SectionView"));
|
||||
if (m_section) {
|
||||
QString qTemp = ui->leSymbol->text();
|
||||
std::string temp = Base::Tools::toStdString(qTemp);
|
||||
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.SectionSymbol = '%s'",
|
||||
m_sectionName.c_str(),
|
||||
temp.c_str());
|
||||
std::string lblText = "Section " +
|
||||
temp +
|
||||
" - " +
|
||||
temp;
|
||||
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.Label = '%s'",
|
||||
m_sectionName.c_str(),
|
||||
lblText.c_str());
|
||||
|
||||
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.Scale = %0.6f",
|
||||
m_sectionName.c_str(),
|
||||
ui->sbScale->value());
|
||||
int scaleType = ui->cmbScaleType->currentIndex();
|
||||
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.ScaleType = %d",
|
||||
m_sectionName.c_str(), scaleType);
|
||||
int projectionStrategy = ui->cmbStrategy->currentIndex();
|
||||
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.ProjectionStrategy = %d",
|
||||
m_sectionName.c_str(), projectionStrategy);
|
||||
Command::doCommand(Command::Doc, "App.activeDocument().%s.SectionDirection = 'Aligned'",
|
||||
m_sectionName.c_str());
|
||||
m_section->CuttingToolWireObject.setValue(m_profileObject);
|
||||
m_section->SectionDirection.setValue("Aligned");
|
||||
if (m_baseView) {
|
||||
if (!m_localUnit.IsEqual(m_saveNormal, EWTOLERANCE) &&
|
||||
m_localUnit.Length() != 0.0) {
|
||||
//if we have changed the view direction (and by extension the
|
||||
//section normal, update the feature with the new value.
|
||||
//m_localUnit should always be valid, but will cause an exception
|
||||
//if it is null.
|
||||
m_section->setCSFromBase(m_localUnit * -1.0);
|
||||
}
|
||||
m_section->Source.setValues(m_baseView->Source.getValues());
|
||||
m_section->XSource.setValues(m_baseView->XSource.getValues());
|
||||
} else {
|
||||
//without a baseView, our choice of SectionNormal and XDirection may well be wrong
|
||||
//if we have not changed the direction, we leave things as they are
|
||||
if (!m_localUnit.IsEqual(m_saveNormal, EWTOLERANCE)) {
|
||||
//just do our best.
|
||||
m_section->setCSFromLocalUnit(m_localUnit * -1.0);
|
||||
m_localUnit = m_saveNormal; //don't repeat this work next time through
|
||||
}
|
||||
|
||||
m_section->Source.setValues(m_shapes);
|
||||
m_section->XSource.setValues(m_xShapes);
|
||||
}
|
||||
}
|
||||
Gui::Command::commitCommand();
|
||||
}
|
||||
|
||||
void TaskComplexSection::failNoObject(void)
|
||||
{
|
||||
QString qsectionName = Base::Tools::fromStdString(m_sectionName);
|
||||
QString qbaseName = Base::Tools::fromStdString(m_saveBaseName);
|
||||
QString msg = tr("Can not continue. Object * %1 or %2 not found.").arg(qsectionName, qbaseName);
|
||||
QMessageBox::critical(Gui::getMainWindow(), QObject::tr("Operation Failed"), msg);
|
||||
Gui::Control().closeDialog();
|
||||
}
|
||||
|
||||
bool TaskComplexSection::isBaseValid()
|
||||
{
|
||||
if (!m_baseView)
|
||||
return false;
|
||||
|
||||
App::DocumentObject* baseObj = m_doc->getObject(m_saveBaseName.c_str());
|
||||
if (!baseObj)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TaskComplexSection::isSectionValid()
|
||||
{
|
||||
if (!m_section)
|
||||
return false;
|
||||
|
||||
App::DocumentObject* sectionObj = m_doc->getObject(m_sectionName.c_str());
|
||||
if (!sectionObj)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
//******************************************************************************
|
||||
bool TaskComplexSection::accept()
|
||||
{
|
||||
// Base::Console().Message("TCS::accept()\n");
|
||||
apply(true);
|
||||
Gui::Command::doCommand(Gui::Command::Gui,"Gui.ActiveDocument.resetEdit()");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TaskComplexSection::reject()
|
||||
{
|
||||
if (!m_section) { //no section created, nothing to undo
|
||||
Gui::Command::doCommand(Gui::Command::Gui, "Gui.ActiveDocument.resetEdit()");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isSectionValid()) { //section !exist. nothing to undo
|
||||
if (isBaseValid()) {
|
||||
m_baseView->requestPaint();
|
||||
}
|
||||
Gui::Command::doCommand(Gui::Command::Gui, "Gui.ActiveDocument.resetEdit()");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_createMode) {
|
||||
std::string SectionName = m_section->getNameInDocument();
|
||||
Gui::Command::doCommand(Gui::Command::Gui,
|
||||
"App.ActiveDocument.%s.removeView(App.ActiveDocument.%s)",
|
||||
m_savePageName.c_str(), SectionName.c_str());
|
||||
Gui::Command::doCommand(Gui::Command::Gui,
|
||||
"App.ActiveDocument.removeObject('%s')",
|
||||
SectionName.c_str());
|
||||
} else {
|
||||
restoreSectionState();
|
||||
m_section->recomputeFeature();
|
||||
m_section->requestPaint();
|
||||
}
|
||||
|
||||
if (isBaseValid()) {
|
||||
m_baseView->requestPaint();
|
||||
}
|
||||
Gui::Command::updateActive();
|
||||
Gui::Command::doCommand(Gui::Command::Gui, "Gui.ActiveDocument.resetEdit()");
|
||||
|
||||
return false;}
|
||||
|
||||
void TaskComplexSection::changeEvent(QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::LanguageChange) {
|
||||
ui->retranslateUi(this);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
TaskDlgComplexSection::TaskDlgComplexSection(TechDraw::DrawPage* page,
|
||||
TechDraw::DrawViewPart *baseView,
|
||||
std::vector<App::DocumentObject*> shapes,
|
||||
std::vector<App::DocumentObject*> xShapes,
|
||||
App::DocumentObject* profileObject,
|
||||
std::vector<std::string> profileSubs)
|
||||
: TaskDialog()
|
||||
{
|
||||
widget = new TaskComplexSection(page, baseView, shapes, xShapes, profileObject, profileSubs);
|
||||
taskbox = new Gui::TaskView::TaskBox(Gui::BitmapFactory().pixmap("actions/TechDraw_ComplexSection"),
|
||||
widget->windowTitle(), true, nullptr);
|
||||
taskbox->groupLayout()->addWidget(widget);
|
||||
Content.push_back(taskbox);
|
||||
}
|
||||
|
||||
TaskDlgComplexSection::TaskDlgComplexSection(TechDraw::DrawComplexSection* complexSection)
|
||||
: TaskDialog()
|
||||
{
|
||||
widget = new TaskComplexSection(complexSection);
|
||||
taskbox = new Gui::TaskView::TaskBox(Gui::BitmapFactory().pixmap("actions/TechDraw_ComplexSection"),
|
||||
widget->windowTitle(), true, nullptr);
|
||||
taskbox->groupLayout()->addWidget(widget);
|
||||
Content.push_back(taskbox);
|
||||
}
|
||||
|
||||
TaskDlgComplexSection::~TaskDlgComplexSection()
|
||||
{
|
||||
}
|
||||
|
||||
void TaskDlgComplexSection::update()
|
||||
{
|
||||
// widget->updateTask();
|
||||
}
|
||||
|
||||
//==== calls from the TaskView ===============================================================
|
||||
void TaskDlgComplexSection::open()
|
||||
{
|
||||
}
|
||||
|
||||
bool TaskDlgComplexSection::accept()
|
||||
{
|
||||
widget->accept();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TaskDlgComplexSection::reject()
|
||||
{
|
||||
widget->reject();
|
||||
return true;
|
||||
}
|
||||
|
||||
#include <Mod/TechDraw/Gui/moc_TaskComplexSection.cpp>
|
||||
183
src/Mod/TechDraw/Gui/TaskComplexSection.h
Normal file
183
src/Mod/TechDraw/Gui/TaskComplexSection.h
Normal file
@@ -0,0 +1,183 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2022 WandererFan <wandererfan@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TECHDRAWGUI_TASKCOMPLEXSECTION_H
|
||||
#define TECHDRAWGUI_TASKCOMPLEXSECTION_H
|
||||
|
||||
#include <Mod/TechDraw/TechDrawGlobal.h>
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include <Base/Vector3D.h>
|
||||
#include <Gui/TaskView/TaskDialog.h>
|
||||
#include <Gui/TaskView/TaskView.h>
|
||||
|
||||
namespace App
|
||||
{
|
||||
class DocumentObject;
|
||||
}
|
||||
|
||||
namespace TechDraw
|
||||
{
|
||||
class DrawPage;
|
||||
class DrawView;
|
||||
class DrawViewPart;
|
||||
class DrawComplexSection;
|
||||
}
|
||||
|
||||
namespace TechDrawGui
|
||||
{
|
||||
class CompassWidget;
|
||||
class VectorEditWidget;
|
||||
|
||||
class Ui_TaskComplexSection;
|
||||
|
||||
class TaskComplexSection : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TaskComplexSection(TechDraw::DrawPage* page,
|
||||
TechDraw::DrawViewPart* baseView,
|
||||
std::vector<App::DocumentObject*> shapes,
|
||||
std::vector<App::DocumentObject*> xShapes,
|
||||
App::DocumentObject* profileObject,
|
||||
std::vector<std::string> profileSubs);
|
||||
TaskComplexSection(TechDraw::DrawComplexSection* complexSection);
|
||||
~TaskComplexSection() = default;
|
||||
|
||||
virtual bool accept();
|
||||
virtual bool reject();
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent *event) override;
|
||||
void saveSectionState();
|
||||
void restoreSectionState();
|
||||
|
||||
bool apply(bool forceUpdate = false);
|
||||
void applyQuick(std::string dir);
|
||||
void applyAligned(Base::Vector3d localUnit);
|
||||
|
||||
void setUiPrimary();
|
||||
void setUiEdit();
|
||||
void setUiCommon();
|
||||
|
||||
void checkAll(bool check);
|
||||
void enableAll(bool enable);
|
||||
|
||||
void failNoObject();
|
||||
bool isBaseValid();
|
||||
bool isSectionValid();
|
||||
|
||||
void updateUi();
|
||||
|
||||
protected Q_SLOTS:
|
||||
void onSectionObjectsUseSelectionClicked();
|
||||
void onProfileObjectsUseSelectionClicked();
|
||||
void onUpClicked();
|
||||
void onDownClicked();
|
||||
void onLeftClicked();
|
||||
void onRightClicked();
|
||||
void onIdentifierChanged();
|
||||
void onScaleChanged();
|
||||
void scaleTypeChanged(int index);
|
||||
void liveUpdateClicked();
|
||||
void updateNowClicked();
|
||||
void slotChangeAngle(double newAngle);
|
||||
void slotViewDirectionChanged(Base::Vector3d newDirection);
|
||||
|
||||
private:
|
||||
void createComplexSection();
|
||||
void updateComplexSection();
|
||||
|
||||
QString sourcesToString();
|
||||
std::unique_ptr<Ui_TaskComplexSection> ui;
|
||||
|
||||
TechDraw::DrawPage* m_page;
|
||||
App::Document* m_doc;
|
||||
TechDraw::DrawViewPart* m_baseView;
|
||||
TechDraw::DrawComplexSection* m_section;
|
||||
std::vector<App::DocumentObject*> m_shapes;
|
||||
std::vector<App::DocumentObject*> m_xShapes;
|
||||
App::DocumentObject* m_profileObject;
|
||||
std::vector<std::string> m_profileSubs;
|
||||
std::string m_dirName;
|
||||
std::string m_sectionName;
|
||||
Base::Vector3d m_saveNormal;
|
||||
Base::Vector3d m_saveXDir;
|
||||
std::string m_saveBaseName;
|
||||
std::string m_savePageName;
|
||||
std::string m_saveSymbol;
|
||||
std::string m_saveDirName;
|
||||
Base::Vector3d m_saveDirection;
|
||||
Base::Vector3d m_saveOrigin;
|
||||
double m_saveScale;
|
||||
int m_saveScaleType;
|
||||
bool m_saved;
|
||||
bool m_createMode;
|
||||
Base::Vector3d m_normal;
|
||||
|
||||
int m_applyDeferred;
|
||||
Base::Vector3d m_localUnit;
|
||||
CompassWidget* m_compass;
|
||||
double m_angle;
|
||||
VectorEditWidget* m_viewDirectionWidget;
|
||||
|
||||
};
|
||||
|
||||
class TaskDlgComplexSection : public Gui::TaskView::TaskDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TaskDlgComplexSection(TechDraw::DrawPage* page,
|
||||
TechDraw::DrawViewPart* baseView,
|
||||
std::vector<App::DocumentObject*> shapes,
|
||||
std::vector<App::DocumentObject*> xShapes,
|
||||
App::DocumentObject* profileObject,
|
||||
std::vector<std::string> profileSubs);
|
||||
TaskDlgComplexSection(TechDraw::DrawComplexSection* page);
|
||||
~TaskDlgComplexSection() override;
|
||||
|
||||
public:
|
||||
/// is called the TaskView when the dialog is opened
|
||||
void open() override;
|
||||
/// is called by the framework if an button is clicked which has no accept or reject role
|
||||
/// is called by the framework if the dialog is accepted (Ok)
|
||||
bool accept() override;
|
||||
/// is called by the framework if the dialog is rejected (Cancel)
|
||||
bool reject() override;
|
||||
/// is called by the framework if the user presses the help button
|
||||
bool isAllowedAlterDocument() const override
|
||||
{ return false; }
|
||||
void update();
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
TaskComplexSection * widget;
|
||||
Gui::TaskView::TaskBox* taskbox;
|
||||
};
|
||||
|
||||
} //namespace TechDrawGui
|
||||
|
||||
#endif // #ifndef TECHDRAWGUI_TASKCOMPLEXSECTION_H
|
||||
410
src/Mod/TechDraw/Gui/TaskComplexSection.ui
Normal file
410
src/Mod/TechDraw/Gui/TaskComplexSection.ui
Normal file
@@ -0,0 +1,410 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TechDrawGui::TaskComplexSection</class>
|
||||
<widget class="QWidget" name="TechDrawGui::TaskComplexSection">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>370</width>
|
||||
<height>612</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Complex Section</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="Resources/TechDraw.qrc">
|
||||
<normaloff>:/icons/actions/TechDraw_ComplexSection.svg</normaloff>:/icons/actions/TechDraw_ComplexSection.svg</iconset>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Object Selection</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Objects to section</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QPushButton" name="pbSectionObjects">
|
||||
<property name="text">
|
||||
<string>Use Selection</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Profile object</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="leProfileObject">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="leSectionObjects">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QPushButton" name="pbProfileObject">
|
||||
<property name="text">
|
||||
<string>Use Selection</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Section Parameters</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_4" columnstretch="1,1">
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="cmbScaleType">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Scale Page/Auto/Custom</string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Page</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Automatic</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Custom</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Scale</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Scale Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QDoubleSpinBox" name="sbScale">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Projection Strategy</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="cmbStrategy">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="currentText">
|
||||
<string>Offset</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Offset</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Aligned</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>NoParallel</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Identifier</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="leSymbol">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Identifier for this section</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>BaseView</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="leBaseView">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gbOrientation">
|
||||
<property name="title">
|
||||
<string>Set View Direction</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="viewDirectionLayout"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="quickPickLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbUp">
|
||||
<property name="toolTip">
|
||||
<string>Preset view direction looking up.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normalon>:/icons/actions/section-up.svg</normalon>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbDown">
|
||||
<property name="toolTip">
|
||||
<string>Preset view direction looking down.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normalon>:/icons/actions/section-down.svg</normalon>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbLeft">
|
||||
<property name="toolTip">
|
||||
<string>Preset view direction looking left.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normalon>:/icons/actions/section-left.svg</normalon>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbRight">
|
||||
<property name="toolTip">
|
||||
<string>Preset view direction looking right.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normalon>:/icons/actions/section-right.svg</normalon>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="compassLayout"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Preview</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="cbLiveUpdate">
|
||||
<property name="toolTip">
|
||||
<string>Check to update display after every property change.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Live Update</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="pbUpdateNow">
|
||||
<property name="toolTip">
|
||||
<string>Rebuild display now. May be slow for complex models.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Update Now</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="lPendingUpdates">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="Resources/TechDraw.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -30,7 +30,6 @@
|
||||
#include <QMessageBox>
|
||||
#endif // #ifndef _PreComp_
|
||||
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Tools.h>
|
||||
#include <Base/UnitsApi.h>
|
||||
@@ -58,7 +57,8 @@
|
||||
//#include "ViewProviderViewPart.h"
|
||||
|
||||
#include <Mod/TechDraw/Gui/ui_TaskSectionView.h>
|
||||
|
||||
#include "Widgets/CompassWidget.h"
|
||||
#include "Widgets/VectorEditWidget.h"
|
||||
#include "TaskSectionView.h"
|
||||
|
||||
using namespace Gui;
|
||||
@@ -71,10 +71,11 @@ TaskSectionView::TaskSectionView(TechDraw::DrawViewPart* base) :
|
||||
m_base(base),
|
||||
m_section(nullptr),
|
||||
m_saveScale(1.0),
|
||||
m_dirName(""),
|
||||
m_doc(nullptr),
|
||||
m_createMode(true),
|
||||
m_saved(false),
|
||||
m_abort(false)
|
||||
m_applyDeferred(0)
|
||||
{
|
||||
//existence of base is guaranteed by CmdTechDrawSectionView (Command.cpp)
|
||||
|
||||
@@ -85,15 +86,12 @@ TaskSectionView::TaskSectionView(TechDraw::DrawViewPart* base) :
|
||||
m_savePageName = m_base->findParentPage()->getNameInDocument();
|
||||
|
||||
ui->setupUi(this);
|
||||
|
||||
connect(ui->pbUp, SIGNAL(clicked(bool)), this, SLOT(onUpClicked()));
|
||||
connect(ui->pbDown, SIGNAL(clicked(bool)), this, SLOT(onDownClicked()));
|
||||
connect(ui->pbRight, SIGNAL(clicked(bool)), this, SLOT(onRightClicked()));
|
||||
connect(ui->pbLeft, SIGNAL(clicked(bool)), this, SLOT(onLeftClicked()));
|
||||
|
||||
setUiPrimary();
|
||||
}
|
||||
|
||||
m_applyDeferred = 0; //setting the direction widgets causes an increment of the deferred count,
|
||||
//so we reset the counter and the message.
|
||||
ui->lPendingUpdates->setText(QString());
|
||||
}
|
||||
|
||||
//ctor for edit
|
||||
TaskSectionView::TaskSectionView(TechDraw::DrawViewSection* section) :
|
||||
@@ -104,7 +102,7 @@ TaskSectionView::TaskSectionView(TechDraw::DrawViewSection* section) :
|
||||
m_doc(nullptr),
|
||||
m_createMode(false),
|
||||
m_saved(false),
|
||||
m_abort(false)
|
||||
m_applyDeferred(0)
|
||||
{
|
||||
//existence of section is guaranteed by ViewProviderViewSection.setEdit
|
||||
|
||||
@@ -112,76 +110,82 @@ TaskSectionView::TaskSectionView(TechDraw::DrawViewSection* section) :
|
||||
m_sectionName = m_section->getNameInDocument();
|
||||
App::DocumentObject* newObj = m_section->BaseView.getValue();
|
||||
m_base = dynamic_cast<TechDraw::DrawViewPart*>(newObj);
|
||||
if (!newObj || !m_base)
|
||||
if (!newObj || !m_base) {
|
||||
throw Base::RuntimeError("TaskSectionView - BaseView not found");
|
||||
}
|
||||
|
||||
m_saveBaseName = m_base->getNameInDocument();
|
||||
m_savePageName = m_base->findParentPage()->getNameInDocument();
|
||||
|
||||
ui->setupUi(this);
|
||||
|
||||
connect(ui->pbUp, SIGNAL(clicked(bool)), this, SLOT(onUpClicked()));
|
||||
connect(ui->pbDown, SIGNAL(clicked(bool)), this, SLOT(onDownClicked()));
|
||||
connect(ui->pbRight, SIGNAL(clicked(bool)), this, SLOT(onRightClicked()));
|
||||
connect(ui->pbLeft, SIGNAL(clicked(bool)), this, SLOT(onLeftClicked()));
|
||||
|
||||
m_dirName = m_section->SectionDirection.getValueAsString();
|
||||
saveSectionState();
|
||||
setUiEdit();
|
||||
|
||||
m_applyDeferred = 0; //setting the direction widgets causes an increment of the deferred count,
|
||||
//so we reset the counter and the message.
|
||||
ui->lPendingUpdates->setText(QString());
|
||||
}
|
||||
|
||||
void TaskSectionView::setUiPrimary()
|
||||
{
|
||||
// Base::Console().Message("TSV::setUiPrimary()\n");
|
||||
setWindowTitle(QObject::tr("Create Section View"));
|
||||
std::string temp = m_base->getNameInDocument();
|
||||
QString qTemp = Base::Tools::fromStdString(temp);
|
||||
ui->leBaseView->setText(qTemp);
|
||||
|
||||
|
||||
ui->sbScale->setValue(m_base->getScale());
|
||||
ui->cmbScaleType->setCurrentIndex(m_base->ScaleType.getValue());
|
||||
|
||||
//Allow or prevent scale changing initially
|
||||
if (m_base->ScaleType.isValue("Custom")) {
|
||||
ui->sbScale->setEnabled(true);
|
||||
}
|
||||
else {
|
||||
ui->sbScale->setEnabled(false);
|
||||
}
|
||||
|
||||
Base::Vector3d origin = m_base->getOriginalCentroid();
|
||||
ui->sbOrgX->setUnit(Base::Unit::Length);
|
||||
ui->sbOrgX->setValue(origin.x);
|
||||
ui->sbOrgY->setUnit(Base::Unit::Length);
|
||||
ui->sbOrgY->setValue(origin.y);
|
||||
ui->sbOrgZ->setUnit(Base::Unit::Length);
|
||||
ui->sbOrgZ->setValue(origin.z);
|
||||
setUiCommon(origin);
|
||||
|
||||
// before the user did not select an orientation,
|
||||
// the section properties cannot be changed
|
||||
this->setToolTip(QObject::tr("Select at first an orientation"));
|
||||
enableAll(false);
|
||||
|
||||
connect(ui->leSymbol, SIGNAL(editingFinished()), this, SLOT(onIdentifierChanged()));
|
||||
|
||||
// the UI file uses keyboardTracking = false so that a recomputation
|
||||
// will only be triggered when the arrow keys of the spinboxes are used
|
||||
connect(ui->sbScale, SIGNAL(valueChanged(double)), this, SLOT(onScaleChanged()));
|
||||
connect(ui->sbOrgX, SIGNAL(valueChanged(double)), this, SLOT(onXChanged()));
|
||||
connect(ui->sbOrgY, SIGNAL(valueChanged(double)), this, SLOT(onYChanged()));
|
||||
connect(ui->sbOrgZ, SIGNAL(valueChanged(double)), this, SLOT(onZChanged()));
|
||||
|
||||
connect(ui->cmbScaleType, SIGNAL(currentIndexChanged(int)), this, SLOT(scaleTypeChanged(int)));
|
||||
m_viewDirectionWidget->setValue(Base::Vector3d(1.0, 0.0, 0.0));
|
||||
}
|
||||
|
||||
void TaskSectionView::setUiEdit()
|
||||
{
|
||||
// Base::Console().Message("TSV::setUiEdit()\n");
|
||||
setWindowTitle(QObject::tr("Edit Section View"));
|
||||
std::string temp = m_section->SectionSymbol.getValue();
|
||||
QString qTemp = Base::Tools::fromStdString(temp);
|
||||
ui->leSymbol->setText(qTemp);
|
||||
|
||||
ui->sbScale->setValue(m_section->getScale());
|
||||
ui->cmbScaleType->setCurrentIndex(m_section->ScaleType.getValue());
|
||||
//Allow or prevent scale changing initially
|
||||
if (m_section->ScaleType.isValue("Custom")) {
|
||||
ui->sbScale->setEnabled(true);
|
||||
}
|
||||
else {
|
||||
ui->sbScale->setEnabled(false);
|
||||
}
|
||||
|
||||
Base::Vector3d origin = m_section->SectionOrigin.getValue();
|
||||
setUiCommon(origin);
|
||||
|
||||
// convert section normal to view angle
|
||||
Base::Vector3d sectionNormalVec = m_section->SectionNormal.getValue();
|
||||
Base::Vector3d projectedViewDirection = m_base->projectPoint(sectionNormalVec, false);
|
||||
double viewAngle = atan2(-projectedViewDirection.y,
|
||||
-projectedViewDirection.x);
|
||||
m_compass->setDialAngle(viewAngle * 180.0 / M_PI);
|
||||
m_viewDirectionWidget->setValue(sectionNormalVec * -1.0);
|
||||
}
|
||||
|
||||
void TaskSectionView::setUiCommon(Base::Vector3d origin)
|
||||
{
|
||||
std::string temp = m_base->getNameInDocument();
|
||||
QString qTemp = Base::Tools::fromStdString(temp);
|
||||
ui->leBaseView->setText(qTemp);
|
||||
|
||||
temp = m_section->SectionSymbol.getValue();
|
||||
qTemp = Base::Tools::fromStdString(temp);
|
||||
ui->leSymbol->setText(qTemp);
|
||||
ui->sbScale->setValue(m_section->getScale());
|
||||
ui->cmbScaleType->setCurrentIndex(m_section->ScaleType.getValue());
|
||||
|
||||
Base::Vector3d origin = m_section->SectionOrigin.getValue();
|
||||
ui->sbOrgX->setUnit(Base::Unit::Length);
|
||||
ui->sbOrgX->setValue(origin.x);
|
||||
ui->sbOrgY->setUnit(Base::Unit::Length);
|
||||
@@ -189,33 +193,58 @@ void TaskSectionView::setUiEdit()
|
||||
ui->sbOrgZ->setUnit(Base::Unit::Length);
|
||||
ui->sbOrgZ->setValue(origin.z);
|
||||
|
||||
enableAll(false);
|
||||
|
||||
connect(ui->leSymbol, SIGNAL(editingFinished()), this, SLOT(onIdentifierChanged()));
|
||||
|
||||
//TODO: use event filter instead of keyboard tracking to capture enter/return keys
|
||||
// the UI file uses keyboardTracking = false so that a recomputation
|
||||
// will only be triggered when the arrow keys of the spinboxes are used
|
||||
//if this is not done, recomputes are triggered on each key press giving
|
||||
//unaccceptable UX
|
||||
connect(ui->sbScale, SIGNAL(valueChanged(double)), this, SLOT(onScaleChanged()));
|
||||
connect(ui->sbOrgX, SIGNAL(valueChanged(double)), this, SLOT(onXChanged()));
|
||||
connect(ui->sbOrgY, SIGNAL(valueChanged(double)), this, SLOT(onYChanged()));
|
||||
connect(ui->sbOrgZ, SIGNAL(valueChanged(double)), this, SLOT(onZChanged()));
|
||||
|
||||
connect(ui->cmbScaleType, SIGNAL(currentIndexChanged(int)), this, SLOT(scaleTypeChanged(int)));
|
||||
|
||||
connect(ui->pbUp, SIGNAL(clicked(bool)), this, SLOT(onUpClicked()));
|
||||
connect(ui->pbDown, SIGNAL(clicked(bool)), this, SLOT(onDownClicked()));
|
||||
connect(ui->pbRight, SIGNAL(clicked(bool)), this, SLOT(onRightClicked()));
|
||||
connect(ui->pbLeft, SIGNAL(clicked(bool)), this, SLOT(onLeftClicked()));
|
||||
|
||||
connect(ui->pbUpdateNow, SIGNAL(clicked(bool)), this, SLOT(updateNowClicked()));
|
||||
connect(ui->cbLiveUpdate, SIGNAL(clicked(bool)), this, SLOT(liveUpdateClicked()));
|
||||
|
||||
m_compass = new CompassWidget(this);
|
||||
auto layout = ui->compassLayout;
|
||||
layout->addWidget(m_compass);
|
||||
connect(m_compass, SIGNAL(angleChanged(double)), this, SLOT(slotChangeAngle(double)));
|
||||
|
||||
m_viewDirectionWidget = new VectorEditWidget(this);
|
||||
m_viewDirectionWidget->setLabel(QObject::tr("Current View Direction"));
|
||||
auto editLayout = ui->viewDirectionLayout;
|
||||
editLayout->addWidget(m_viewDirectionWidget);
|
||||
connect(m_viewDirectionWidget, SIGNAL(valueChanged(Base::Vector3d)),
|
||||
this, SLOT(slotViewDirectionChanged(Base::Vector3d)));
|
||||
}
|
||||
|
||||
//save the start conditions
|
||||
void TaskSectionView::saveSectionState()
|
||||
{
|
||||
// Base::Console().Message("TSV::saveSectionState()\n");
|
||||
if (!m_section)
|
||||
return;
|
||||
|
||||
m_saveSymbol = m_section->SectionSymbol.getValue();
|
||||
m_saveScale = m_section->getScale();
|
||||
m_saveScaleType = m_section->ScaleType.getValue();
|
||||
m_saveNormal = m_section->SectionNormal.getValue();
|
||||
m_saveDirection = m_section->Direction.getValue();
|
||||
m_saveOrigin = m_section->SectionOrigin.getValue();
|
||||
m_saveDirName = m_section->SectionDirection.getValueAsString();
|
||||
m_saved = true;
|
||||
if (m_section) {
|
||||
m_saveSymbol = m_section->SectionSymbol.getValue();
|
||||
m_saveScale = m_section->getScale();
|
||||
m_saveScaleType = m_section->ScaleType.getValue();
|
||||
m_saveNormal = m_section->SectionNormal.getValue();
|
||||
m_normal = m_saveNormal;
|
||||
m_saveDirection = m_section->Direction.getValue();
|
||||
m_saveOrigin = m_section->SectionOrigin.getValue();
|
||||
m_saveDirName = m_section->SectionDirection.getValueAsString();
|
||||
m_saved = true;
|
||||
}
|
||||
}
|
||||
|
||||
//restore the start conditions
|
||||
@@ -234,36 +263,72 @@ void TaskSectionView::restoreSectionState()
|
||||
m_section->SectionDirection.setValue(m_saveDirName.c_str());
|
||||
}
|
||||
|
||||
//the VectorEditWidget reports a change in direction
|
||||
void TaskSectionView::slotViewDirectionChanged(Base::Vector3d newDirection)
|
||||
{
|
||||
// Base::Console().Message("TSV::slotViewDirectionChanged(%s)\n",
|
||||
// DrawUtil::formatVector(newDirection).c_str());
|
||||
Base::Vector3d projectedViewDirection = m_base->projectPoint(newDirection, false);
|
||||
projectedViewDirection.Normalize();
|
||||
double viewAngle = atan2(projectedViewDirection.y,
|
||||
projectedViewDirection.x);
|
||||
m_compass->setDialAngle(viewAngle * 180.0 / M_PI);
|
||||
checkAll(false);
|
||||
applyAligned(projectedViewDirection);
|
||||
}
|
||||
|
||||
//the CompassWidget reports that the view direction angle has changed
|
||||
void TaskSectionView::slotChangeAngle(double newAngle)
|
||||
{
|
||||
// Base::Console().Message("TSV::slotChangeAngle(%.3f)\n", newAngle);
|
||||
double angleRadians = newAngle * M_PI / 180.0;
|
||||
double unitX = cos(angleRadians);
|
||||
double unitY = sin(angleRadians);
|
||||
Base::Vector3d localUnit(unitX, unitY, 0.0);
|
||||
m_viewDirectionWidget->setValueNoNotify(localUnit);
|
||||
checkAll(false);
|
||||
applyAligned(localUnit);
|
||||
}
|
||||
|
||||
//preset view directions
|
||||
void TaskSectionView::onUpClicked()
|
||||
{
|
||||
// Base::Console().Message("TSV::onUpClicked()\n");
|
||||
m_compass->setToNorth();
|
||||
Base::Vector3d localUnit(0.0, 1.0, 0.0);
|
||||
m_viewDirectionWidget->setValue(localUnit);
|
||||
checkAll(false);
|
||||
ui->pbUp->setChecked(true);
|
||||
applyQuick("Up");
|
||||
applyAligned(localUnit);
|
||||
}
|
||||
|
||||
void TaskSectionView::onDownClicked()
|
||||
{
|
||||
// Base::Console().Message("TSV::onDownClicked()\n");
|
||||
m_compass->setToSouth();
|
||||
Base::Vector3d localUnit(0.0, -1.0, 0.0);
|
||||
m_viewDirectionWidget->setValue(localUnit);
|
||||
checkAll(false);
|
||||
ui->pbDown->setChecked(true);
|
||||
applyQuick("Down");
|
||||
applyAligned(localUnit);
|
||||
}
|
||||
|
||||
void TaskSectionView::onLeftClicked()
|
||||
{
|
||||
// Base::Console().Message("TSV::onLeftClicked()\n");
|
||||
m_compass->setToWest();
|
||||
Base::Vector3d localUnit(-1.0, 0.0, 0.0);
|
||||
m_viewDirectionWidget->setValue(localUnit);
|
||||
checkAll(false);
|
||||
ui->pbLeft->setChecked(true);
|
||||
applyQuick("Left");
|
||||
applyAligned(localUnit);
|
||||
}
|
||||
|
||||
void TaskSectionView::onRightClicked()
|
||||
{
|
||||
// Base::Console().Message("TSV::onRightClicked()\n");
|
||||
m_compass->setToEast();
|
||||
Base::Vector3d localUnit(1.0, 0.0, 0.0);
|
||||
m_viewDirectionWidget->setValue(localUnit);
|
||||
checkAll(false);
|
||||
ui->pbRight->setChecked(true);
|
||||
applyQuick("Right");
|
||||
applyAligned(localUnit);
|
||||
}
|
||||
|
||||
void TaskSectionView::onIdentifierChanged()
|
||||
@@ -278,18 +343,17 @@ void TaskSectionView::onScaleChanged()
|
||||
apply();
|
||||
}
|
||||
|
||||
//SectionOrigin changed
|
||||
void TaskSectionView::onXChanged()
|
||||
{
|
||||
checkAll(false);
|
||||
apply();
|
||||
}
|
||||
|
||||
void TaskSectionView::onYChanged()
|
||||
{
|
||||
checkAll(false);
|
||||
apply();
|
||||
}
|
||||
|
||||
void TaskSectionView::onZChanged()
|
||||
{
|
||||
checkAll(false);
|
||||
@@ -303,6 +367,7 @@ void TaskSectionView::scaleTypeChanged(int index)
|
||||
ui->sbScale->setEnabled(false);
|
||||
if (m_base->findParentPage()) {
|
||||
ui->sbScale->setValue(m_base->findParentPage()->Scale.getValue());
|
||||
ui->sbScale->setEnabled(false);
|
||||
}
|
||||
} else if (index == 1) {
|
||||
// Automatic Scale Type
|
||||
@@ -315,6 +380,7 @@ void TaskSectionView::scaleTypeChanged(int index)
|
||||
ui->sbScale->setEnabled(true);
|
||||
if (m_section) {
|
||||
ui->sbScale->setValue(m_section->Scale.getValue());
|
||||
ui->sbScale->setEnabled(true);
|
||||
}
|
||||
} else {
|
||||
Base::Console().Log("Error - TaskSectionView::scaleTypeChanged - unknown scale type: %d\n", index);
|
||||
@@ -338,25 +404,68 @@ void TaskSectionView::enableAll(bool enable)
|
||||
ui->sbOrgY->setEnabled(enable);
|
||||
ui->sbOrgZ->setEnabled(enable);
|
||||
ui->cmbScaleType->setEnabled(enable);
|
||||
QString qScaleType = ui->cmbScaleType->currentText();
|
||||
//Allow or prevent scale changing initially
|
||||
if (qScaleType == QString::fromUtf8("Custom")) {
|
||||
ui->sbScale->setEnabled(true);
|
||||
}
|
||||
else {
|
||||
ui->sbScale->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void TaskSectionView::liveUpdateClicked() {
|
||||
apply(true);
|
||||
}
|
||||
|
||||
void TaskSectionView::updateNowClicked() {
|
||||
apply(true);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
bool TaskSectionView::apply()
|
||||
bool TaskSectionView::apply(bool forceUpdate)
|
||||
{
|
||||
// Base::Console().Message("TSV::apply() - m_dirName: %s\n", m_dirName.c_str());
|
||||
// Base::Console().Message("TSV::apply() - liveUpdate: %d force: %d deferred: %d\n",
|
||||
// ui->cbLiveUpdate->isChecked(), forceUpdate, m_applyDeferred);
|
||||
if(!ui->cbLiveUpdate->isChecked() &&
|
||||
!forceUpdate) {
|
||||
//nothing to do
|
||||
m_applyDeferred++;
|
||||
QString msgLiteral = QString::fromUtf8(QT_TRANSLATE_NOOP("TaskPojGroup", " updates pending"));
|
||||
QString msgNumber = QString::number(m_applyDeferred);
|
||||
ui->lPendingUpdates->setText(msgNumber + msgLiteral);
|
||||
return false;
|
||||
}
|
||||
|
||||
Gui::WaitCursor wc;
|
||||
if (m_dirName.empty()) {
|
||||
std::string msg =
|
||||
//this should never happen
|
||||
std::string msg =
|
||||
Base::Tools::toStdString(tr("Nothing to apply. No section direction picked yet"));
|
||||
Base::Console().Error((msg + "\n").c_str());
|
||||
return false;
|
||||
}
|
||||
if (!m_section) //didn't create the feature yet
|
||||
//this can't happen as applyQuick has to be called by the direction
|
||||
//setting process
|
||||
return false;
|
||||
if (!m_section) {
|
||||
m_section = createSectionView();
|
||||
}
|
||||
|
||||
if (isSectionValid()) {
|
||||
updateSectionView();
|
||||
} else {
|
||||
failNoObject();
|
||||
}
|
||||
|
||||
m_section->recomputeFeature();
|
||||
if (isBaseValid()) {
|
||||
m_base->requestPaint();
|
||||
}
|
||||
|
||||
enableAll(true);
|
||||
checkAll(false);
|
||||
applyQuick(m_dirName);
|
||||
|
||||
wc.restoreCursor();
|
||||
m_applyDeferred = 0;
|
||||
ui->lPendingUpdates->setText(QString());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -364,39 +473,27 @@ void TaskSectionView::applyQuick(std::string dir)
|
||||
{
|
||||
// Base::Console().Message("TSV::applyQuick(%s)\n", dir.c_str());
|
||||
m_dirName = dir;
|
||||
if (!m_section)
|
||||
createSectionView();
|
||||
|
||||
if (!isSectionValid()) {
|
||||
failNoObject(m_sectionName);
|
||||
return;
|
||||
}
|
||||
|
||||
updateSectionView();
|
||||
enableAll(true);
|
||||
|
||||
m_section->recomputeFeature();
|
||||
if (isBaseValid())
|
||||
m_base->requestPaint();
|
||||
apply();
|
||||
}
|
||||
|
||||
void TaskSectionView::applyAligned()
|
||||
void TaskSectionView::applyAligned(Base::Vector3d localUnit)
|
||||
{
|
||||
Base::Console().Message("TSV::applyAligned() - not implemented yet\n");
|
||||
// Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Apply Aligned"));
|
||||
// Base::Console().Message("TSV::applyAligned()\n");
|
||||
m_dirName = "Aligned";
|
||||
//fiddle with directions here
|
||||
m_localUnit = localUnit;
|
||||
enableAll(true);
|
||||
apply();
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
|
||||
//pointer to created view is not returned, but stored in m_section
|
||||
void TaskSectionView::createSectionView()
|
||||
TechDraw::DrawViewSection* TaskSectionView::createSectionView(void)
|
||||
{
|
||||
// Base::Console().Message("TSV::createSectionView()\n");
|
||||
if (!isBaseValid()) {
|
||||
failNoObject(m_baseName);
|
||||
return;
|
||||
failNoObject();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string sectionName;
|
||||
@@ -416,7 +513,7 @@ void TaskSectionView::createSectionView()
|
||||
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.Source = App.ActiveDocument.%s.Source",
|
||||
m_sectionName.c_str(), baseName.c_str());
|
||||
Command::doCommand(Command::Doc,
|
||||
"App.ActiveDocument.%s.SectionOrigin = FreeCAD.Vector(%.3f, %.3f, %.3f)",
|
||||
"App.ActiveDocument.%s.SectionOrigin = FreeCAD.Vector(%.6f, %.6f, %.6f)",
|
||||
m_sectionName.c_str(),
|
||||
ui->sbOrgX->value().getValue(),
|
||||
ui->sbOrgY->value().getValue(),
|
||||
@@ -427,22 +524,32 @@ void TaskSectionView::createSectionView()
|
||||
int scaleType = ui->cmbScaleType->currentIndex();
|
||||
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.ScaleType = %d",
|
||||
m_sectionName.c_str(), scaleType);
|
||||
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.SectionDirection = '%s'",
|
||||
m_sectionName.c_str(), m_dirName.c_str());
|
||||
|
||||
App::DocumentObject* newObj = m_base->getDocument()->getObject(m_sectionName.c_str());
|
||||
m_section = dynamic_cast<TechDraw::DrawViewSection*>(newObj);
|
||||
if (!newObj || !m_section)
|
||||
if (!newObj || !m_section) {
|
||||
throw Base::RuntimeError("TaskSectionView - new section object not found");
|
||||
}
|
||||
if (m_dirName == "Aligned") {
|
||||
//m_localUnit is a view direction so we need to reverse it to make a
|
||||
//section normal
|
||||
m_section->setCSFromBase(m_localUnit * -1.0);
|
||||
} else {
|
||||
//Note: DirectionName is to be deprecated in the future
|
||||
m_section->setCSFromBase(m_dirName.c_str());
|
||||
}
|
||||
}
|
||||
Gui::Command::commitCommand();
|
||||
|
||||
return;
|
||||
return m_section;
|
||||
}
|
||||
|
||||
void TaskSectionView::updateSectionView()
|
||||
{
|
||||
// Base::Console().Message("TSV::updateSectionView() - m_sectionName: %s\n", m_sectionName.c_str());
|
||||
if (!isSectionValid()) {
|
||||
failNoObject(m_sectionName);
|
||||
failNoObject();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -474,18 +581,28 @@ void TaskSectionView::updateSectionView()
|
||||
int scaleType = ui->cmbScaleType->currentIndex();
|
||||
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.ScaleType = %d",
|
||||
m_sectionName.c_str(), scaleType);
|
||||
m_section->setCSFromBase(m_dirName.c_str());
|
||||
Command::doCommand(Command::Doc, "App.ActiveDocument.%s.SectionDirection = '%s'",
|
||||
m_sectionName.c_str(), m_dirName.c_str());
|
||||
if (m_dirName == "Aligned") {
|
||||
//m_localUnit is a view direction so we need to reverse it to make a
|
||||
//section normal
|
||||
m_section->setCSFromBase(m_localUnit * -1.0);
|
||||
} else {
|
||||
//Note: DirectionName is to be deprecated in the future
|
||||
m_section->setCSFromBase(m_dirName.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
Gui::Command::commitCommand();
|
||||
}
|
||||
|
||||
void TaskSectionView::failNoObject(std::string objectName)
|
||||
void TaskSectionView::failNoObject(void)
|
||||
{
|
||||
QString qObjectName = Base::Tools::fromStdString(objectName);
|
||||
QString msg = tr("Can not continue. Object * %1 * not found.").arg(qObjectName);
|
||||
QString qsectionName = Base::Tools::fromStdString(m_sectionName);
|
||||
QString qbaseName = Base::Tools::fromStdString(m_baseName);
|
||||
QString msg = tr("Can not continue. Object * %1 or %2 not found.").arg(qsectionName, qbaseName);
|
||||
QMessageBox::critical(Gui::getMainWindow(), QObject::tr("Operation Failed"), msg);
|
||||
Gui::Control().closeDialog();
|
||||
m_abort = true;
|
||||
}
|
||||
|
||||
bool TaskSectionView::isBaseValid()
|
||||
@@ -517,12 +634,8 @@ bool TaskSectionView::isSectionValid()
|
||||
bool TaskSectionView::accept()
|
||||
{
|
||||
// Base::Console().Message("TSV::accept()\n");
|
||||
if (m_abort) {
|
||||
return true;
|
||||
}
|
||||
apply();
|
||||
Gui::Command::updateActive();
|
||||
Gui::Command::doCommand(Gui::Command::Gui, "Gui.ActiveDocument.resetEdit()");
|
||||
apply(true);
|
||||
Gui::Command::doCommand(Gui::Command::Gui,"Gui.ActiveDocument.resetEdit()");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -589,6 +702,7 @@ TaskDlgSectionView::TaskDlgSectionView(TechDraw::DrawViewSection* section) :
|
||||
widget = new TaskSectionView(section);
|
||||
taskbox = new Gui::TaskView::TaskBox(Gui::BitmapFactory().pixmap("actions/TechDraw_SectionView"),
|
||||
widget->windowTitle(), true, nullptr);
|
||||
|
||||
taskbox->groupLayout()->addWidget(widget);
|
||||
Content.push_back(taskbox);
|
||||
}
|
||||
|
||||
@@ -39,6 +39,9 @@ namespace TechDraw {
|
||||
namespace TechDrawGui
|
||||
{
|
||||
|
||||
class CompassWidget;
|
||||
class VectorEditWidget;
|
||||
|
||||
class TaskSectionView : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -56,20 +59,21 @@ protected:
|
||||
void saveSectionState();
|
||||
void restoreSectionState();
|
||||
|
||||
bool apply();
|
||||
bool apply(bool forceUpdate = false);
|
||||
void applyQuick(std::string dir);
|
||||
void applyAligned();
|
||||
void applyAligned(Base::Vector3d localUnit);
|
||||
|
||||
void createSectionView();
|
||||
TechDraw::DrawViewSection* createSectionView();
|
||||
void updateSectionView();
|
||||
|
||||
void setUiPrimary();
|
||||
void setUiEdit();
|
||||
void setUiCommon(Base::Vector3d origin);
|
||||
|
||||
void checkAll(bool check);
|
||||
void enableAll(bool enable);
|
||||
|
||||
void failNoObject(std::string objectName);
|
||||
void failNoObject();
|
||||
bool isBaseValid();
|
||||
bool isSectionValid();
|
||||
|
||||
@@ -84,6 +88,10 @@ protected Q_SLOTS:
|
||||
void onYChanged();
|
||||
void onZChanged();
|
||||
void scaleTypeChanged(int index);
|
||||
void liveUpdateClicked();
|
||||
void updateNowClicked();
|
||||
void slotChangeAngle(double newAngle);
|
||||
void slotViewDirectionChanged(Base::Vector3d newDirection);
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui_TaskSectionView> ui;
|
||||
@@ -113,8 +121,10 @@ private:
|
||||
std::string m_saveBaseName;
|
||||
std::string m_savePageName;
|
||||
|
||||
bool m_abort;
|
||||
|
||||
int m_applyDeferred;
|
||||
Base::Vector3d m_localUnit;
|
||||
CompassWidget* m_compass;
|
||||
VectorEditWidget* m_viewDirectionWidget;
|
||||
};
|
||||
|
||||
class TaskDlgSectionView : public Gui::TaskView::TaskDialog
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>370</width>
|
||||
<height>368</height>
|
||||
<height>508</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@@ -82,7 +82,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<item row="2" column="2">
|
||||
<widget class="QComboBox" name="cmbScaleType">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
@@ -140,6 +140,9 @@
|
||||
<property name="toolTip">
|
||||
<string>Scale factor for the section view</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="keyboardTracking">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
@@ -157,7 +160,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
@@ -167,11 +170,14 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<widget class="QGroupBox" name="gbOrientation">
|
||||
<property name="title">
|
||||
<string>Section Orientation</string>
|
||||
<string>Set View Direction</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="viewDirectionLayout"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
@@ -183,7 +189,7 @@
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Looking up</string>
|
||||
<string>Preset view direction looking up.</string>
|
||||
</property>
|
||||
<property name="statusTip">
|
||||
<string/>
|
||||
@@ -219,7 +225,7 @@
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Looking down</string>
|
||||
<string>Preset view direction looking down.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
@@ -249,7 +255,7 @@
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Looking left</string>
|
||||
<string>Preset view direction looking left.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
@@ -279,7 +285,7 @@
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Looking right</string>
|
||||
<string>Preset view direction looking right.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
@@ -302,6 +308,9 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="compassLayout"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -313,14 +322,14 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<widget class="QGroupBox" name="gbPlane">
|
||||
<property name="toolTip">
|
||||
<string>Position from the 3D origin of the object in the view</string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Section Plane Location</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<layout class="QVBoxLayout" name="verticalLayoutPlane">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
@@ -369,6 +378,9 @@
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="keyboardTracking">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
@@ -410,6 +422,9 @@
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="keyboardTracking">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
@@ -451,6 +466,9 @@
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="keyboardTracking">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
@@ -464,6 +482,56 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gbUpdate">
|
||||
<property name="title">
|
||||
<string>Preview</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayoutUpdate">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="pbUpdateNow">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Rebuild display now. May be slow for complex models.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Update Now</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="cbLiveUpdate">
|
||||
<property name="toolTip">
|
||||
<string>Check to update display after every property change.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Live Update</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="lPendingUpdates">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
@@ -474,7 +542,7 @@
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="Resources/TechDraw.qrc"/>
|
||||
<include location="../../../../../../Documents/FreeCAD/Stash/Gui_SectionDlg/Resources/TechDraw.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -76,6 +76,7 @@ ViewProviderViewPart::ViewProviderViewPart()
|
||||
static const char *group = "Lines";
|
||||
static const char *dgroup = "Decoration";
|
||||
static const char *hgroup = "Highlight";
|
||||
static const char *sgroup = "Section Line";
|
||||
|
||||
//default line weights
|
||||
|
||||
@@ -104,12 +105,14 @@ ViewProviderViewPart::ViewProviderViewPart()
|
||||
ADD_PROPERTY_TYPE(CenterScale, (defScale), dgroup, App::Prop_None, "Center mark size adjustment, if enabled");
|
||||
|
||||
//properties that affect Section Line
|
||||
ADD_PROPERTY_TYPE(ShowSectionLine ,(true) ,dgroup, App::Prop_None, "Show/hide section line if applicable");
|
||||
ADD_PROPERTY_TYPE(ShowSectionLine ,(true) ,sgroup, App::Prop_None, "Show/hide section line if applicable");
|
||||
SectionLineStyle.setEnums(LineStyleEnums);
|
||||
ADD_PROPERTY_TYPE(SectionLineStyle, (PreferencesGui::sectionLineStyle()), dgroup, App::Prop_None,
|
||||
ADD_PROPERTY_TYPE(SectionLineStyle, (PreferencesGui::sectionLineStyle()), sgroup, App::Prop_None,
|
||||
"Set section line style if applicable");
|
||||
ADD_PROPERTY_TYPE(SectionLineColor, (prefSectionColor()), dgroup, App::Prop_None,
|
||||
ADD_PROPERTY_TYPE(SectionLineColor, (prefSectionColor()), sgroup, App::Prop_None,
|
||||
"Set section line color if applicable");
|
||||
ADD_PROPERTY_TYPE(SectionLineMarks, (PreferencesGui::sectionLineMarks()), sgroup, App::Prop_None,
|
||||
"Show marks at direction changes for ComplexSection");
|
||||
|
||||
//properties that affect Detail Highlights
|
||||
HighlightLineStyle.setEnums(LineStyleEnums);
|
||||
@@ -139,6 +142,7 @@ void ViewProviderViewPart::onChanged(const App::Property* prop)
|
||||
prop == &(ShowSectionLine) ||
|
||||
prop == &(SectionLineStyle) ||
|
||||
prop == &(SectionLineColor) ||
|
||||
prop == &(SectionLineMarks) ||
|
||||
prop == &(HighlightLineStyle) ||
|
||||
prop == &(HighlightLineColor) ||
|
||||
prop == &(HorizCenterLine) ||
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
|
||||
#ifndef DRAWINGGUI_VIEWPROVIDERVIEWPART_H
|
||||
#define DRAWINGGUI_VIEWPROVIDERVIEWPART_H
|
||||
|
||||
#include <Mod/TechDraw/TechDrawGlobal.h>
|
||||
|
||||
#include <Mod/TechDraw/TechDrawGlobal.h>
|
||||
|
||||
#include <App/PropertyUnits.h>
|
||||
|
||||
@@ -55,6 +55,7 @@ public:
|
||||
App::PropertyBool ShowSectionLine;
|
||||
App::PropertyEnumeration SectionLineStyle;
|
||||
App::PropertyColor SectionLineColor;
|
||||
App::PropertyBool SectionLineMarks;
|
||||
App::PropertyEnumeration HighlightLineStyle;
|
||||
App::PropertyColor HighlightLineColor;
|
||||
App::PropertyFloat HighlightAdjust;
|
||||
|
||||
@@ -36,10 +36,12 @@
|
||||
#include <Gui/Control.h>
|
||||
#include <Gui/Selection.h>
|
||||
|
||||
#include <Mod/TechDraw/App/DrawComplexSection.h>
|
||||
#include <Mod/TechDraw/App/DrawGeomHatch.h>
|
||||
#include <Mod/TechDraw/App/DrawHatch.h>
|
||||
|
||||
#include "TaskSectionView.h"
|
||||
#include "TaskComplexSection.h"
|
||||
#include "ViewProviderViewSection.h"
|
||||
#include "QGIView.h"
|
||||
|
||||
@@ -123,6 +125,12 @@ bool ViewProviderViewSection::setEdit(int ModNum)
|
||||
}
|
||||
// clear the selection (convenience)
|
||||
Gui::Selection().clearSelection();
|
||||
|
||||
auto dcs = dynamic_cast<TechDraw::DrawComplexSection*>(getViewObject());
|
||||
if (dcs) {
|
||||
Gui::Control().showDialog(new TaskDlgComplexSection(dcs));
|
||||
return true;
|
||||
}
|
||||
Gui::Control().showDialog(new TaskDlgSectionView(getViewObject()));
|
||||
return true;
|
||||
}
|
||||
@@ -133,7 +141,6 @@ bool ViewProviderViewSection::doubleClicked()
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ViewProviderViewSection::getParameters()
|
||||
{
|
||||
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
|
||||
|
||||
242
src/Mod/TechDraw/Gui/Widgets/CompassDialWidget.cpp
Normal file
242
src/Mod/TechDraw/Gui/Widgets/CompassDialWidget.cpp
Normal file
@@ -0,0 +1,242 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2022 WandererFan <wandererfan@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
//largely based on a python widget from:
|
||||
//https://github.com/tcalmant/demo-ipopo-qt/blob/master/pc/details/compass.py
|
||||
|
||||
#include <Mod/TechDraw/TechDrawGlobal.h>
|
||||
|
||||
#include <QtGui>
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Tools.h>
|
||||
|
||||
#include "CompassDialWidget.h"
|
||||
|
||||
using namespace TechDrawGui;
|
||||
using CardinalMap = std::map<int, std::string>;
|
||||
|
||||
CompassDialWidget::CompassDialWidget(QWidget* parent) : QWidget(parent),
|
||||
m_markInterval(15),
|
||||
m_defaultSize(75),
|
||||
m_defaultMargin(10),
|
||||
m_designRadius(64)
|
||||
{
|
||||
setObjectName(QString::fromUtf8("Compass"));
|
||||
m_rect = QRect(0, 0, m_defaultSize, m_defaultSize);
|
||||
m_angle = 0.0;
|
||||
m_margin = m_defaultMargin;
|
||||
m_designDiameter = 2 * m_designRadius;
|
||||
|
||||
QSizePolicy sizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||
sizePolicy.setHorizontalStretch(1);
|
||||
sizePolicy.setVerticalStretch(1);
|
||||
setSizePolicy(sizePolicy);
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
QSize CompassDialWidget::sizeHint() const
|
||||
{
|
||||
return m_rect.size();
|
||||
}
|
||||
|
||||
QSize CompassDialWidget::minimumSizeHint() const
|
||||
{
|
||||
return QRect(0, 0, m_defaultSize, m_defaultSize).size();
|
||||
}
|
||||
|
||||
void CompassDialWidget::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
QPainter painter(this);
|
||||
drawWidget(painter);
|
||||
QWidget::paintEvent(event);
|
||||
}
|
||||
|
||||
void CompassDialWidget::drawWidget(QPainter& painter)
|
||||
{
|
||||
painter.setRenderHint(QPainter::Antialiasing, true);
|
||||
|
||||
// Draw the background
|
||||
drawBackground(painter);
|
||||
|
||||
//Draw the cardinal points
|
||||
drawMarkings(painter);
|
||||
|
||||
//Draw the needle
|
||||
drawNeedle(painter);
|
||||
}
|
||||
|
||||
void CompassDialWidget::drawBackground(QPainter& painter)
|
||||
{
|
||||
painter.save();
|
||||
painter.setPen(QPen(Qt::NoPen));
|
||||
// Clear the background
|
||||
painter.fillRect(m_rect, palette().brush((QPalette::Window)));
|
||||
painter.restore();
|
||||
}
|
||||
|
||||
//Draws the cardinal points on painter. This widget was designed such that
|
||||
//the dial gradations extend to 50 units from center and the compass point text
|
||||
//begins at 52 units from the center. With the font size set to 12 pixels, this
|
||||
//gives a design area of a circle with a radius of approximately 64 units. All of
|
||||
//the constants reflect this design size.
|
||||
void CompassDialWidget::drawMarkings(QPainter& painter)
|
||||
{
|
||||
CardinalMap CompassPointText( { {0, "Y"}, {45, "XY"}, {90, "X"}, {135, "X-Y"}, {180, "-Y"},
|
||||
{225, "-X-Y"}, {270, "-X"}, {315, "-XY"} } );
|
||||
painter.save();
|
||||
int markInterval(15);
|
||||
|
||||
//Move to the center of the compass
|
||||
painter.translate(width() / 2, height() / 2);
|
||||
double scale = std::min((float) width() / (float) (m_designDiameter + 2.0 * m_margin),
|
||||
(float) height() / (float) (m_designDiameter + 2.0 * m_margin));
|
||||
painter.scale(scale, scale);
|
||||
|
||||
// Setup the fonts and the painter
|
||||
QFont widgetFont = font();
|
||||
widgetFont.setPixelSize(12);
|
||||
QFontMetrics metrics(widgetFont);
|
||||
|
||||
//outer circle
|
||||
int circleWidth = 2.0 * (m_designRadius + m_margin);
|
||||
int circleHeight = 2.0 * (m_designRadius + m_margin);
|
||||
QRect circleRect(-circleWidth / 2, -circleHeight / 2, circleWidth, circleHeight);
|
||||
painter.drawEllipse(circleRect);
|
||||
|
||||
painter.setFont(widgetFont);
|
||||
painter.setPen(QPen(palette().color(QPalette::WindowText)));
|
||||
|
||||
int iDegree = 0;
|
||||
while ( iDegree < 360 ) {
|
||||
if (iDegree % 45 == 0) {
|
||||
//Named direction (every 45°)
|
||||
painter.drawLine(0, -40, 0, -50); //this has to depend on m_rect or size?
|
||||
QString qPointText = Base::Tools::fromStdString(CompassPointText.at(iDegree));
|
||||
painter.drawText(-metrics.boundingRect(qPointText).width() / 2.0, -52, qPointText);
|
||||
// what is -52? line end point y = -50 + 2 for margin?
|
||||
} else {
|
||||
//Small line
|
||||
painter.drawLine(0, -45, 0, -50);
|
||||
}
|
||||
|
||||
//Next line (+15°)
|
||||
painter.rotate(markInterval);
|
||||
iDegree += markInterval;
|
||||
}
|
||||
|
||||
painter.restore();
|
||||
}
|
||||
|
||||
//Draws a needle on painter
|
||||
void CompassDialWidget::drawNeedle(QPainter& painter)
|
||||
{
|
||||
painter.save();
|
||||
|
||||
//Move to the center of the compass
|
||||
painter.translate(width() / 2, height() / 2);
|
||||
|
||||
//Rotate to the correct angle
|
||||
painter.rotate(m_angle);
|
||||
double scale = std::min((float) width() / (float) (m_designDiameter + 2.0 * m_margin),
|
||||
(float) height() / (float) (m_designDiameter + 2.0 * m_margin));
|
||||
painter.scale(scale, scale);
|
||||
|
||||
//Setup the painter
|
||||
QPen needlePen(palette().color(QPalette::WindowText));
|
||||
needlePen.setWidth(2);
|
||||
needlePen.setStyle(Qt::DashDotLine);
|
||||
painter.setPen(needlePen);
|
||||
painter.setBrush(palette().color(QPalette::WindowText));
|
||||
|
||||
//Draw the section line
|
||||
int sectionLineExtent(25);
|
||||
painter.drawLine(0, sectionLineExtent, 0, -sectionLineExtent);
|
||||
needlePen.setStyle(Qt::SolidLine);
|
||||
painter.setPen(needlePen);
|
||||
int viewDirectionExtent(15);
|
||||
painter.drawLine(-viewDirectionExtent, sectionLineExtent, 0, sectionLineExtent);
|
||||
painter.drawLine(-viewDirectionExtent, -sectionLineExtent, 0, -sectionLineExtent);
|
||||
|
||||
//Draw the arrowheads of the needle section line
|
||||
needlePen.setWidth(1);
|
||||
needlePen.setStyle(Qt::SolidLine);
|
||||
painter.setPen(needlePen);
|
||||
int arrowLength(5);
|
||||
int arrowWidth(3); //actual 1/2 width
|
||||
painter.drawPolygon(
|
||||
QPolygon( { QPoint(0, sectionLineExtent),
|
||||
QPoint(-arrowLength, sectionLineExtent + arrowWidth),
|
||||
QPoint(-arrowLength, sectionLineExtent - arrowWidth),
|
||||
QPoint(0, sectionLineExtent) } ) );
|
||||
painter.drawPolygon(
|
||||
QPolygon( { QPoint(0, -sectionLineExtent),
|
||||
QPoint(-arrowLength, -(sectionLineExtent + arrowWidth)),
|
||||
QPoint(-arrowLength, -(sectionLineExtent - arrowWidth)),
|
||||
QPoint(0, -sectionLineExtent) } ) );
|
||||
|
||||
//draw the actual needle
|
||||
needlePen.setStyle(Qt::SolidLine);
|
||||
painter.setPen(needlePen);
|
||||
painter.setBrush(palette().color(QPalette::BrightText));
|
||||
int needleExtent(40);
|
||||
painter.drawPolygon(
|
||||
QPolygon( { QPoint(needleExtent, 0),
|
||||
QPoint(0, 5),
|
||||
QPoint(-15, 2),
|
||||
QPoint(-15, -2),
|
||||
QPoint(0, -5),
|
||||
QPoint(needleExtent, 0) } ) );
|
||||
|
||||
//draw needle pivot
|
||||
painter.setBrush(palette().color(QPalette::WindowText));
|
||||
int pivotSize(4);
|
||||
QRect pivotRect(-pivotSize / 2, -pivotSize / 2, pivotSize, pivotSize);
|
||||
painter.drawEllipse(pivotRect);
|
||||
|
||||
//draw needle point
|
||||
painter.setBrush(QBrush(Qt::red));
|
||||
int pointLength(5);
|
||||
int pointWidth(3);
|
||||
painter.drawPolygon(
|
||||
QPolygon( { QPoint(needleExtent, 0),
|
||||
QPoint(needleExtent - pointLength, pointWidth),
|
||||
QPoint(needleExtent - pointLength, -pointWidth),
|
||||
QPoint(needleExtent, 0) } ) );
|
||||
|
||||
painter.restore();
|
||||
}
|
||||
|
||||
//convert a conventional angle to a Qt angle and set the dial accordingly
|
||||
void CompassDialWidget::setAngle(double newAngle)
|
||||
{
|
||||
m_angle = fmod(360.0 - newAngle, 360.0);
|
||||
repaint();
|
||||
}
|
||||
|
||||
void CompassDialWidget::setSize(int newSize)
|
||||
{
|
||||
m_rect = QRect(0, 0, newSize, newSize);
|
||||
repaint();
|
||||
}
|
||||
71
src/Mod/TechDraw/Gui/Widgets/CompassDialWidget.h
Normal file
71
src/Mod/TechDraw/Gui/Widgets/CompassDialWidget.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2022 WandererFan <wandererfan@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
//based on a python widget from:
|
||||
//https://github.com/tcalmant/demo-ipopo-qt/blob/master/pc/details/compass.py
|
||||
|
||||
#ifndef COMPASSDIALWIDGET_H
|
||||
#define COMPASSDIALWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QSize>
|
||||
|
||||
namespace TechDrawGui {
|
||||
|
||||
class CompassDialWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CompassDialWidget(QWidget* parent = 0);
|
||||
~CompassDialWidget() = default;
|
||||
|
||||
QSize sizeHint() const override;
|
||||
QSize minimumSizeHint() const override;
|
||||
double angle() const { return m_angle; }
|
||||
void setAngle(double newAngle);
|
||||
void setSize(int newSize);
|
||||
|
||||
public Q_SLOTS:
|
||||
void slotChangeAngle(double angle) { setAngle(angle); }
|
||||
void resetAngle() { setAngle(0.0); }
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
void drawWidget(QPainter& painter);
|
||||
void drawNeedle(QPainter& painter);
|
||||
void drawMarkings(QPainter& painter);
|
||||
void drawBackground(QPainter& painter);
|
||||
|
||||
private:
|
||||
QRect m_rect;
|
||||
double m_angle;
|
||||
double m_margin;
|
||||
double m_markInterval;
|
||||
int m_defaultSize;
|
||||
int m_defaultMargin;
|
||||
int m_designRadius;
|
||||
int m_designDiameter;
|
||||
};
|
||||
|
||||
} //namespace TechDrawGui
|
||||
#endif // COMPASSDIALWIDGET_H
|
||||
254
src/Mod/TechDraw/Gui/Widgets/CompassWidget.cpp
Normal file
254
src/Mod/TechDraw/Gui/Widgets/CompassWidget.cpp
Normal file
@@ -0,0 +1,254 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2022 WandererFan <wandererfan@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
// The CompassWidget has several children widgets - a CompassDialWidget, a fine
|
||||
// adjustment QDoubleSpinBox and a QPushButton that acts as an enter key
|
||||
// for the spin box.
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <QApplication>
|
||||
#include <QLabel>
|
||||
#include <QObject>
|
||||
#include <QPushButton>
|
||||
#include <QtGui>
|
||||
#include <QtWidgets/QDoubleSpinBox>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
#endif
|
||||
|
||||
#include <Mod/TechDraw/TechDrawGlobal.h>
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Tools.h>
|
||||
|
||||
#include "CompassDialWidget.h"
|
||||
#include "CompassWidget.h"
|
||||
|
||||
using namespace TechDrawGui;
|
||||
|
||||
CompassWidget::CompassWidget(QWidget *parent)
|
||||
: QWidget(parent), m_minimumWidth(200), m_minimumHeight(200), m_defaultMargin(10), m_angle(0.0),
|
||||
m_advanceIncrement(10.0)
|
||||
{
|
||||
setObjectName(QString::fromUtf8("Compass"));
|
||||
m_rect = QRect(0, 0, m_minimumWidth, m_minimumHeight);
|
||||
buildWidget();
|
||||
compassDial->setSize(m_minimumHeight - 2 * m_defaultMargin);
|
||||
|
||||
connect(pbUseCompassSetting, &QPushButton::pressed, this, &CompassWidget::slotUseSpinboxValue);
|
||||
dsbAngle->installEventFilter(this);
|
||||
|
||||
connect(pbCWAdvance, &QPushButton::pressed, this, &CompassWidget::slotCWAdvance);
|
||||
connect(pbCCWAdvance, &QPushButton::pressed, this, &CompassWidget::slotCCWAdvance);
|
||||
}
|
||||
|
||||
//trap Enter press in dsbAngle so as not to invoke task accept processing
|
||||
bool CompassWidget::eventFilter(QObject *target, QEvent *event)
|
||||
{
|
||||
if (target == dsbAngle) {
|
||||
if (event->type() == QEvent::KeyPress) {
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
|
||||
if (keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) {
|
||||
dsbAngle->interpretText();
|
||||
slotSpinBoxEnter(dsbAngle->value());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return QWidget::eventFilter(target, event);
|
||||
}
|
||||
|
||||
void CompassWidget::buildWidget()
|
||||
{
|
||||
resize(m_minimumWidth, m_minimumHeight);
|
||||
QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
|
||||
sizePolicy.setHorizontalStretch(0);
|
||||
sizePolicy.setVerticalStretch(0);
|
||||
sizePolicy.setHeightForWidth(sizePolicy.hasHeightForWidth());
|
||||
setSizePolicy(sizePolicy);
|
||||
setMinimumSize(QSize(m_minimumWidth, m_minimumHeight));
|
||||
compassLayout = new QVBoxLayout(this);
|
||||
compassLayout->setObjectName(QString::fromUtf8("CompassLayout"));
|
||||
|
||||
compassDialLayout = new QHBoxLayout();
|
||||
compassDialLayout->setObjectName(QString::fromUtf8("compassDialLayout"));
|
||||
|
||||
pbCWAdvance = new QPushButton(this);
|
||||
pbCWAdvance->setObjectName(QString::fromUtf8("pbCWAdvance"));
|
||||
QIcon icon1;
|
||||
icon1.addFile(QString::fromUtf8(":/icons/arrow-cw.svg"), QSize(), QIcon::Normal, QIcon::On);
|
||||
pbCWAdvance->setIcon(icon1);
|
||||
compassDialLayout->addWidget(pbCWAdvance);
|
||||
|
||||
compassDial = new CompassDialWidget(this);
|
||||
compassDial->setObjectName(QString::fromUtf8("CompassDial"));
|
||||
compassDialLayout->addWidget(compassDial);
|
||||
|
||||
pbCCWAdvance = new QPushButton(this);
|
||||
pbCCWAdvance->setObjectName(QString::fromUtf8("pbCCWAdvance"));
|
||||
QIcon icon2;
|
||||
icon2.addFile(QString::fromUtf8(":/icons/arrow-ccw.svg"), QSize(), QIcon::Normal, QIcon::On);
|
||||
pbCCWAdvance->setIcon(icon2);
|
||||
compassDialLayout->addWidget(pbCCWAdvance);
|
||||
|
||||
compassDialLayout->setStretch(1, 2);
|
||||
compassLayout->addLayout(compassDialLayout);
|
||||
|
||||
compassControlLayout = new QHBoxLayout();
|
||||
compassControlLayout->setObjectName(QString::fromUtf8("compassControlLayout"));
|
||||
compassControlLabel = new QLabel(this);
|
||||
compassControlLabel->setObjectName(QString::fromUtf8("compassControlLabel"));
|
||||
QSizePolicy sizePolicy2(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||
sizePolicy2.setHorizontalStretch(0);
|
||||
sizePolicy2.setVerticalStretch(0);
|
||||
sizePolicy2.setHeightForWidth(compassControlLabel->sizePolicy().hasHeightForWidth());
|
||||
compassControlLabel->setSizePolicy(sizePolicy2);
|
||||
|
||||
compassControlLayout->addWidget(compassControlLabel);
|
||||
|
||||
dsbAngle = new QDoubleSpinBox(this);
|
||||
dsbAngle->setObjectName(QString::fromUtf8("dsbAngle"));
|
||||
sizePolicy2.setHeightForWidth(dsbAngle->sizePolicy().hasHeightForWidth());
|
||||
dsbAngle->setSizePolicy(sizePolicy2);
|
||||
dsbAngle->setMinimumSize(QSize(75, 26));
|
||||
dsbAngle->setMouseTracking(true);
|
||||
dsbAngle->setFocusPolicy(Qt::ClickFocus);
|
||||
dsbAngle->setAlignment(Qt::AlignRight | Qt::AlignTrailing | Qt::AlignVCenter);
|
||||
dsbAngle->setKeyboardTracking(false);
|
||||
dsbAngle->setSuffix(QString::fromUtf8("\302\260"));
|
||||
dsbAngle->setMaximum(360.000000000000000);
|
||||
dsbAngle->setMinimum(-360.000000000000000);
|
||||
|
||||
compassControlLayout->addWidget(dsbAngle);
|
||||
|
||||
pbUseCompassSetting = new QPushButton(this);
|
||||
pbUseCompassSetting->setObjectName(QString::fromUtf8("pbUseCompassSetting"));
|
||||
QIcon icon;
|
||||
icon.addFile(QString::fromUtf8(":/icons/edit_OK.svg"), QSize(), QIcon::Normal, QIcon::On);
|
||||
pbUseCompassSetting->setIcon(icon);
|
||||
pbUseCompassSetting->setText(QString());
|
||||
|
||||
compassControlLayout->addWidget(pbUseCompassSetting);
|
||||
|
||||
compassControlLayout->setStretch(0, 3);
|
||||
compassControlLayout->setStretch(1, 2);
|
||||
|
||||
compassLayout->addLayout(compassControlLayout);
|
||||
|
||||
retranslateUi();
|
||||
}
|
||||
|
||||
void CompassWidget::retranslateUi()
|
||||
{
|
||||
compassControlLabel->setText(
|
||||
QApplication::translate("CompassWidget", "View Direction as Angle", nullptr));
|
||||
#ifndef QT_NO_TOOLTIP
|
||||
dsbAngle->setToolTip(QApplication::translate(
|
||||
"CompassWidget", "The view direction angle relative to +X in the BaseView.", nullptr));
|
||||
pbUseCompassSetting->setToolTip(QApplication::translate(
|
||||
"CompassWidget", "Use the current view direction to set the Section Normal.", nullptr));
|
||||
pbCWAdvance->setToolTip(QApplication::translate(
|
||||
"CompassWidget", "Advance the view direction in clockwise direction.", nullptr));
|
||||
pbCCWAdvance->setToolTip(QApplication::translate(
|
||||
"CompassWidget", "Advance the view direction in anti-clockwise direction.", nullptr));
|
||||
#endif// QT_NO_TOOLTIP
|
||||
}
|
||||
|
||||
QSize CompassWidget::sizeHint() const { return m_rect.size(); }
|
||||
|
||||
QSize CompassWidget::minimumSizeHint() const
|
||||
{
|
||||
return QRect(0, 0, m_minimumWidth, m_minimumHeight).size();
|
||||
}
|
||||
|
||||
void CompassWidget::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
QWidget::paintEvent(event);
|
||||
}
|
||||
|
||||
//general purpose angle update from external source.
|
||||
void CompassWidget::setDialAngle(double newAngle)
|
||||
{
|
||||
// Base::Console().Message("CW::setDialAngle(%.3f)\n", newAngle);
|
||||
m_angle = newAngle;
|
||||
if (compassDial) {
|
||||
compassDial->setAngle(m_angle);
|
||||
}
|
||||
if (dsbAngle) {
|
||||
dsbAngle->setValue(m_angle);
|
||||
}
|
||||
}
|
||||
|
||||
//slot for updates from spinbox arrows or typing.
|
||||
void CompassWidget::slotSpinBoxUpdate(double newAngle)
|
||||
{
|
||||
// Base::Console().Message("CW::slotSpinBoxUpdate(%.3f)\n", newAngle);
|
||||
m_angle = newAngle;
|
||||
Q_EMIT angleChanged(m_angle);
|
||||
if (compassDial) {
|
||||
compassDial->setAngle(m_angle);
|
||||
}
|
||||
}
|
||||
|
||||
//slot for updates from spinbox on Enter/Return press.
|
||||
void CompassWidget::slotSpinBoxEnter(double newAngle)
|
||||
{
|
||||
// Base::Console().Message("CW::slotSpinBoxEnter(%.3f)\n", newAngle);
|
||||
if (dsbAngle) {
|
||||
m_angle = newAngle;
|
||||
Q_EMIT angleChanged(m_angle);
|
||||
if (compassDial) {
|
||||
compassDial->setAngle(m_angle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//slot for OK button press
|
||||
void CompassWidget::slotUseSpinboxValue()
|
||||
{
|
||||
// Base::Console().Message("CW::slotUseSpinboxValue()\n");
|
||||
if (dsbAngle) {
|
||||
dsbAngle->interpretText();
|
||||
m_angle = dsbAngle->value();
|
||||
Q_EMIT angleChanged(m_angle);
|
||||
}
|
||||
if (compassDial) {
|
||||
compassDial->setAngle(m_angle);
|
||||
}
|
||||
}
|
||||
|
||||
void CompassWidget::slotCWAdvance()
|
||||
{
|
||||
double angle = m_angle - m_advanceIncrement;
|
||||
if (angle < -360.0) {
|
||||
angle = angle + 360.0;
|
||||
}
|
||||
setDialAngle(angle);
|
||||
}
|
||||
|
||||
void CompassWidget::slotCCWAdvance()
|
||||
{
|
||||
double angle = m_angle + m_advanceIncrement;
|
||||
setDialAngle(fmod(angle, 360.0));
|
||||
}
|
||||
|
||||
void CompassWidget::setAdvanceIncrement(double newIncrement) { m_advanceIncrement = newIncrement; }
|
||||
105
src/Mod/TechDraw/Gui/Widgets/CompassWidget.h
Normal file
105
src/Mod/TechDraw/Gui/Widgets/CompassWidget.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2022 WandererFan <wandererfan@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef COMPASSWIDGET_H
|
||||
#define COMPASSWIDGET_H
|
||||
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QKeyEvent>
|
||||
#include <QWidget>
|
||||
#include <QSize>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QLabel;
|
||||
class QHBoxLayout;
|
||||
class QPushButton;
|
||||
class QVBoxLayout;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace TechDrawGui {
|
||||
|
||||
class CompassDialWidget;
|
||||
|
||||
class CompassWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY( double angle READ dialAngle WRITE setDialAngle NOTIFY angleChanged)
|
||||
|
||||
public:
|
||||
CompassWidget(QWidget* parent = 0);
|
||||
~CompassWidget() = default;
|
||||
|
||||
QSize sizeHint() const override;
|
||||
QSize minimumSizeHint() const override;
|
||||
bool eventFilter(QObject *target, QEvent *event) override;
|
||||
void retranslateUi();
|
||||
double dialAngle() const { return m_angle; }
|
||||
void setDialAngle(double newAngle);
|
||||
void setAdvanceIncrement(double newIncrement);
|
||||
double advanceIncrement() const { return m_advanceIncrement; }
|
||||
|
||||
Q_SIGNALS:
|
||||
void angleChanged(double angle);
|
||||
void angleSet(double angle);
|
||||
|
||||
public Q_SLOTS:
|
||||
void slotChangeAngle(double angle) { setDialAngle(angle); }
|
||||
void slotSpinBoxUpdate(double newAngle);
|
||||
void slotSpinBoxEnter(double newAngle);
|
||||
void slotUseSpinboxValue();
|
||||
void resetAngle() { setDialAngle(0.0); } //conventional angles
|
||||
void setToEast() { setDialAngle(0.0); }
|
||||
void setToNorth() { setDialAngle(90.0); }
|
||||
void setToWest() { setDialAngle(180.0); }
|
||||
void setToSouth() { setDialAngle(270.0); }
|
||||
void slotCWAdvance();
|
||||
void slotCCWAdvance();
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
void buildWidget();
|
||||
double changeAngleConvention(double CWY) const;
|
||||
|
||||
private:
|
||||
QRect m_rect;
|
||||
int m_minimumWidth;
|
||||
int m_minimumHeight;
|
||||
int m_defaultMargin;
|
||||
double m_angle;
|
||||
double m_advanceIncrement;
|
||||
|
||||
QVBoxLayout* compassLayout;
|
||||
QHBoxLayout* compassDialLayout;
|
||||
QHBoxLayout* compassControlLayout;
|
||||
|
||||
CompassDialWidget* compassDial;
|
||||
// DoubleSpinBoxNoEnter* dsbAngle;
|
||||
QDoubleSpinBox* dsbAngle;
|
||||
QLabel* compassControlLabel;
|
||||
QPushButton* pbUseCompassSetting;
|
||||
QPushButton* pbCWAdvance;
|
||||
QPushButton* pbCCWAdvance;
|
||||
};
|
||||
|
||||
} //namespace TechDrawGui
|
||||
#endif // COMPASSWIDGET_H
|
||||
|
||||
265
src/Mod/TechDraw/Gui/Widgets/VectorEditWidget.cpp
Normal file
265
src/Mod/TechDraw/Gui/Widgets/VectorEditWidget.cpp
Normal file
@@ -0,0 +1,265 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2022 WandererFan <wandererfan@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
// A widget for editing Vector3d without taking up too much space in the UI.
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <QApplication>
|
||||
#include <QLabel>
|
||||
#include <QObject>
|
||||
#include <QPushButton>
|
||||
#include <QtGui>
|
||||
#include <QVBoxLayout>
|
||||
#include <QGridLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QSpacerItem>
|
||||
#include <QToolButton>
|
||||
#endif
|
||||
|
||||
#include <Mod/TechDraw/TechDrawGlobal.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Tools.h>
|
||||
#include <Base/UnitsApi.h>
|
||||
|
||||
#include <Gui/SpinBox.h>
|
||||
|
||||
#include <Mod/TechDraw/App/DrawUtil.h>
|
||||
|
||||
#include "VectorEditWidget.h"
|
||||
|
||||
using namespace TechDrawGui;
|
||||
using namespace TechDraw;
|
||||
|
||||
VectorEditWidget::VectorEditWidget(QWidget* parent) : QWidget(parent),
|
||||
m_minimumWidth(200),
|
||||
m_minimumHeight(30),
|
||||
m_expandedHeight(155),
|
||||
m_blockNotify(false)
|
||||
{
|
||||
m_size = QSize(m_minimumWidth, m_minimumHeight);
|
||||
setObjectName(QString::fromUtf8("VectorEdit"));
|
||||
buildWidget();
|
||||
|
||||
connect(tbExpand, SIGNAL(toggled(bool)), this, SLOT(slotExpandButtonToggled(bool)));
|
||||
connect(dsbX, SIGNAL(valueChanged(double)), this, SLOT(xValueChanged(double)));
|
||||
connect(dsbY, SIGNAL(valueChanged(double)), this, SLOT(yValueChanged(double)));
|
||||
connect(dsbZ, SIGNAL(valueChanged(double)), this, SLOT(zValueChanged(double)));
|
||||
|
||||
dsbX->installEventFilter(this);
|
||||
dsbY->installEventFilter(this);
|
||||
dsbZ->installEventFilter(this);
|
||||
}
|
||||
|
||||
//trap Enter press in dsb? so as not to invoke task accept processing
|
||||
bool VectorEditWidget::eventFilter(QObject *target, QEvent *event)
|
||||
{
|
||||
if (target == dsbX ||
|
||||
target == dsbY ||
|
||||
target == dsbZ) {
|
||||
if (event->type() == QEvent::KeyPress) {
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
|
||||
if (keyEvent->key() == Qt::Key_Return ||
|
||||
keyEvent->key() == Qt::Key_Enter) {
|
||||
QDoubleSpinBox* dsb = static_cast<QDoubleSpinBox*>(target);
|
||||
dsb->interpretText();
|
||||
Q_EMIT dsb->valueChanged(dsb->value());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return QWidget::eventFilter(target, event);
|
||||
}
|
||||
void VectorEditWidget::setLabel(std::string newLabel)
|
||||
{
|
||||
QString qNewLabelString = Base::Tools::fromStdString(newLabel);
|
||||
lvectorName->setText(qNewLabelString);
|
||||
}
|
||||
|
||||
void VectorEditWidget::setLabel(QString newLabel)
|
||||
{
|
||||
lvectorName->setText(newLabel);
|
||||
}
|
||||
|
||||
void VectorEditWidget::setValue(Base::Vector3d newValue)
|
||||
{
|
||||
// Base::Console().Message("VEW::setValue(%s)\n", DrawUtil::formatVector(newValue).c_str());
|
||||
m_value = newValue;
|
||||
dsbX->setValue(m_value.x);
|
||||
dsbY->setValue(m_value.y);
|
||||
dsbZ->setValue(m_value.z);
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
void VectorEditWidget::setValueNoNotify(Base::Vector3d newValue)
|
||||
{
|
||||
// Base::Console().Message("VEW::setValue(%s)\n", DrawUtil::formatVector(newValue).c_str());
|
||||
m_value = newValue;
|
||||
m_blockNotify = true;
|
||||
dsbX->setValue(m_value.x);
|
||||
dsbY->setValue(m_value.y);
|
||||
dsbZ->setValue(m_value.z);
|
||||
m_blockNotify = false;
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
void VectorEditWidget::slotExpandButtonToggled(bool checked)
|
||||
{
|
||||
// Base::Console().Message("VEW::slotExpand - checked: %d\n", checked);
|
||||
if (checked) {
|
||||
vectorEditLayout->addLayout(VectorEditItemLayout);
|
||||
vectorEditLayout->addItem(verticalSpacer);
|
||||
m_size = QSize(m_minimumWidth, m_expandedHeight);
|
||||
|
||||
} else {
|
||||
vectorEditLayout->removeItem(VectorEditItemLayout);
|
||||
vectorEditLayout->removeItem(verticalSpacer);
|
||||
m_size = QSize(m_minimumWidth, m_minimumHeight);
|
||||
}
|
||||
}
|
||||
|
||||
void VectorEditWidget::xValueChanged(double newValue)
|
||||
{
|
||||
// Base::Console().Message("VEW::xValueChanged(%.3f)\n", newValue);
|
||||
m_value.x = newValue;
|
||||
updateDisplay();
|
||||
if (!m_blockNotify) {
|
||||
Q_EMIT valueChanged(m_value);
|
||||
}
|
||||
}
|
||||
void VectorEditWidget::yValueChanged(double newValue)
|
||||
{
|
||||
// Base::Console().Message("VEW::yValueChanged(%.3f)\n", newValue);
|
||||
m_value.y = newValue;
|
||||
updateDisplay();
|
||||
if (!m_blockNotify) {
|
||||
Q_EMIT valueChanged(m_value);
|
||||
}
|
||||
}
|
||||
void VectorEditWidget::zValueChanged(double newValue)
|
||||
{
|
||||
// Base::Console().Message("VEW::zValueChanged(%.3f)\n", newValue);
|
||||
m_value.z = newValue;
|
||||
updateDisplay();
|
||||
if (!m_blockNotify) {
|
||||
Q_EMIT valueChanged(m_value);
|
||||
}
|
||||
}
|
||||
|
||||
void VectorEditWidget::updateDisplay()
|
||||
{
|
||||
// Base::Console().Message("VEW::updateDisplay() - m_value: %s\n", DrawUtil::formatVector(m_value).c_str());
|
||||
QString qNewDisplayString = Base::Tools::fromStdString(DrawUtil::formatVector(m_value));
|
||||
leVectorDisplay->setText(qNewDisplayString);
|
||||
}
|
||||
|
||||
QSize VectorEditWidget::minimumSizeHint() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
void VectorEditWidget::buildWidget()
|
||||
{
|
||||
if (objectName().isEmpty())
|
||||
setObjectName(QString::fromUtf8("VectorEdit"));
|
||||
QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
|
||||
setSizePolicy(sizePolicy);
|
||||
|
||||
vectorEditLayout = new QVBoxLayout(this);
|
||||
vectorEditLayout->setObjectName(QString::fromUtf8("vectorEditLayout"));
|
||||
vectorEditLayout->setContentsMargins(0, 0, 0, 0);
|
||||
VectorEditButtonLayout = new QHBoxLayout();
|
||||
VectorEditButtonLayout->setSpacing(0);
|
||||
VectorEditButtonLayout->setObjectName(QString::fromUtf8("VectorEditButtonLayout"));
|
||||
|
||||
lvectorName = new QLabel(this);
|
||||
lvectorName->setObjectName(QString::fromUtf8("lvectorName"));
|
||||
VectorEditButtonLayout->addWidget(lvectorName);
|
||||
|
||||
leVectorDisplay = new QLineEdit(this);
|
||||
leVectorDisplay->setObjectName(QString::fromUtf8("leVectorDisplay"));
|
||||
VectorEditButtonLayout->addWidget(leVectorDisplay);
|
||||
|
||||
tbExpand = new QToolButton(this);
|
||||
tbExpand->setObjectName(QString::fromUtf8("tbExpand"));
|
||||
tbExpand->setText(QString::fromUtf8("..."));
|
||||
tbExpand->setCheckable(true);
|
||||
VectorEditButtonLayout->addWidget(tbExpand);
|
||||
|
||||
VectorEditButtonLayout->setStretch(0, 1);
|
||||
VectorEditButtonLayout->setStretch(1, 1);
|
||||
vectorEditLayout->addLayout(VectorEditButtonLayout);
|
||||
|
||||
VectorEditItemLayout = new QGridLayout();
|
||||
VectorEditItemLayout->setObjectName(QString::fromUtf8("VectorEditItemLayout"));
|
||||
|
||||
lX = new QLabel();
|
||||
lX->setObjectName(QString::fromUtf8("lX"));
|
||||
lX->setText(QString::fromUtf8("X:"));
|
||||
VectorEditItemLayout->addWidget(lX, 0, 0, 1, 1);
|
||||
|
||||
dsbX = new Gui::DoubleSpinBox();
|
||||
dsbX->setObjectName(QString::fromUtf8("dsbX"));
|
||||
dsbX->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
|
||||
dsbX->setKeyboardTracking(false);
|
||||
dsbX->setMaximum(std::numeric_limits<double>::max());
|
||||
dsbX->setMinimum(std::numeric_limits<double>::lowest());
|
||||
dsbX->setDecimals(Base::UnitsApi::getDecimals());
|
||||
VectorEditItemLayout->addWidget(dsbX, 0, 1, 1, 1);
|
||||
|
||||
lY = new QLabel();
|
||||
lY->setObjectName(QString::fromUtf8("lY"));
|
||||
lY->setText(QString::fromUtf8("Y:"));
|
||||
VectorEditItemLayout->addWidget(lY, 1, 0, 1, 1);
|
||||
|
||||
dsbY = new Gui::DoubleSpinBox();
|
||||
dsbY->setObjectName(QString::fromUtf8("dsbY"));
|
||||
dsbY->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
|
||||
dsbY->setKeyboardTracking(false);
|
||||
dsbY->setMaximum(std::numeric_limits<double>::max());
|
||||
dsbY->setMinimum(std::numeric_limits<double>::lowest());
|
||||
dsbY->setDecimals(Base::UnitsApi::getDecimals());
|
||||
VectorEditItemLayout->addWidget(dsbY, 1, 1, 1, 1);
|
||||
|
||||
lZ = new QLabel();
|
||||
lZ->setObjectName(QString::fromUtf8("lZ"));
|
||||
lZ->setText(QString::fromUtf8("Z:"));
|
||||
VectorEditItemLayout->addWidget(lZ, 2, 0, 1, 1);
|
||||
|
||||
dsbZ = new Gui::DoubleSpinBox();
|
||||
dsbZ->setObjectName(QString::fromUtf8("dsbZ"));
|
||||
dsbZ->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
|
||||
dsbZ->setKeyboardTracking(false);
|
||||
dsbZ->setMaximum(std::numeric_limits<double>::max());
|
||||
dsbZ->setMinimum(std::numeric_limits<double>::lowest());
|
||||
dsbZ->setDecimals(Base::UnitsApi::getDecimals());
|
||||
VectorEditItemLayout->addWidget(dsbZ, 2, 1, 1, 1);
|
||||
|
||||
verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
|
||||
}
|
||||
|
||||
|
||||
107
src/Mod/TechDraw/Gui/Widgets/VectorEditWidget.h
Normal file
107
src/Mod/TechDraw/Gui/Widgets/VectorEditWidget.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2022 WandererFan <wandererfan@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef VECTOREDITWIDGET_H
|
||||
#define VECTOREDITWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QSize>
|
||||
#include <QString>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QVBoxLayout;
|
||||
class QHBoxLayout;
|
||||
class QGridLayout;
|
||||
class QLabel;
|
||||
class QLineEdit;
|
||||
class QToolButton;
|
||||
class QSpacerItem;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Gui {
|
||||
class DoubleSpinBox;
|
||||
}
|
||||
|
||||
#include <Base/Vector3D.h>
|
||||
|
||||
namespace TechDrawGui {
|
||||
|
||||
class VectorEditWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
VectorEditWidget(QWidget* parent = 0);
|
||||
~VectorEditWidget() = default;
|
||||
|
||||
QSize minimumSizeHint() const override;
|
||||
bool eventFilter(QObject *target, QEvent *event) override;
|
||||
|
||||
void setLabel(std::string newLabel);
|
||||
void setLabel(QString newLabel);
|
||||
Base::Vector3d value() const { return m_value; }
|
||||
|
||||
Q_SIGNALS:
|
||||
void valueChanged(Base::Vector3d newValue);
|
||||
|
||||
public Q_SLOTS:
|
||||
void setValue(Base::Vector3d newValue);
|
||||
void setValueNoNotify(Base::Vector3d newValue);
|
||||
|
||||
protected:
|
||||
void buildWidget();
|
||||
|
||||
protected Q_SLOTS:
|
||||
void slotExpandButtonToggled(bool checked);
|
||||
void xValueChanged(double newValue);
|
||||
void yValueChanged(double newValue);
|
||||
void zValueChanged(double newValue);
|
||||
|
||||
void updateDisplay();
|
||||
|
||||
private:
|
||||
int m_minimumWidth;
|
||||
int m_minimumHeight;
|
||||
int m_expandedHeight;
|
||||
bool m_blockNotify;
|
||||
|
||||
QSize m_size;
|
||||
|
||||
Base::Vector3d m_value;
|
||||
|
||||
QVBoxLayout *vectorEditLayout;
|
||||
QHBoxLayout *VectorEditButtonLayout;
|
||||
QLabel *lvectorName;
|
||||
QLineEdit *leVectorDisplay;
|
||||
QToolButton *tbExpand;
|
||||
QGridLayout *VectorEditItemLayout;
|
||||
Gui::DoubleSpinBox *dsbX;
|
||||
Gui::DoubleSpinBox *dsbY;
|
||||
Gui::DoubleSpinBox *dsbZ;
|
||||
QLabel *lX;
|
||||
QLabel *lY;
|
||||
QLabel *lZ;
|
||||
QSpacerItem *verticalSpacer;
|
||||
};
|
||||
|
||||
} //namespace TechDrawGui
|
||||
#endif // VECTOREDITWIDGET_H
|
||||
@@ -189,6 +189,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const
|
||||
*draw << "TechDraw_ActiveView";
|
||||
*draw << "TechDraw_ProjectionGroup";
|
||||
*draw << "TechDraw_SectionView";
|
||||
*draw << "TechDraw_ComplexSection";
|
||||
*draw << "TechDraw_DetailView";
|
||||
*draw << "Separator";
|
||||
*draw << "TechDraw_DraftView";
|
||||
@@ -245,7 +246,9 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
|
||||
*views << "TechDraw_View";
|
||||
*views << "TechDraw_ActiveView";
|
||||
*views << "TechDraw_ProjectionGroup";
|
||||
*views << "TechDraw_SectionView";
|
||||
*views << "TechDraw_SectionGroup";
|
||||
// *views << "TechDraw_SectionView";
|
||||
// *views << "TechDraw_ComplexSection";
|
||||
*views << "TechDraw_DetailView";
|
||||
*views << "TechDraw_DraftView";
|
||||
*views << "TechDraw_ArchView";
|
||||
@@ -389,9 +392,10 @@ Gui::ToolBarItem* Workbench::setupCommandBars() const
|
||||
views->setCommand("Views");
|
||||
*views << "TechDraw_View";
|
||||
*views << "TechDraw_ActiveView";
|
||||
// *views << "TechDraw_NewMulti"; //deprecated
|
||||
*views << "TechDraw_ProjectionGroup";
|
||||
*views << "TechDraw_SectionView";
|
||||
*views << "TechDraw_SectionGroup";
|
||||
// *views << "TechDraw_SectionView";
|
||||
// *views << "TechDraw_ComplexSection";
|
||||
*views << "TechDraw_DetailView";
|
||||
*views << "TechDraw_DraftView";
|
||||
*views << "TechDraw_SpreadsheetView";
|
||||
|
||||
Reference in New Issue
Block a user