Initial working version of geometric crosshatch/PAT files

This commit is contained in:
WandererFan
2017-01-13 10:31:51 -05:00
parent 974032dd91
commit 33479bd4e3
35 changed files with 1826 additions and 74 deletions

View File

@@ -31,6 +31,7 @@
#include "DrawViewSymbol.h"
#include "DrawViewClip.h"
#include "DrawHatch.h"
#include "DrawCrosshatch.h"
#include "DrawViewDraft.h"
#include "DrawViewArch.h"
#include "DrawViewSpreadsheet.h"
@@ -84,6 +85,7 @@ PyMODINIT_FUNC initTechDraw()
TechDraw::DrawViewClip ::init();
TechDraw::DrawHatch ::init();
TechDraw::DrawCrosshatch ::init();
TechDraw::DrawViewDraft ::init();
TechDraw::DrawViewArch ::init();
TechDraw::DrawViewImage ::init();

View File

@@ -37,6 +37,7 @@ generate_from_xml(DrawViewSymbolPy)
generate_from_xml(DrawViewClipPy)
generate_from_xml(DrawViewDimensionPy)
generate_from_xml(DrawHatchPy)
generate_from_xml(DrawCrosshatchPy)
generate_from_xml(DrawViewCollectionPy)
generate_from_xml(DrawProjGroupPy)
generate_from_xml(DrawProjGroupItemPy)
@@ -74,6 +75,8 @@ SET(Draw_SRCS
DrawViewSection.h
DrawHatch.cpp
DrawHatch.h
DrawCrosshatch.cpp
DrawCrosshatch.h
DrawViewDraft.cpp
DrawViewDraft.h
DrawViewArch.cpp
@@ -92,6 +95,8 @@ SET(TechDraw_SRCS
DrawUtil.h
Cube.cpp
Cube.h
HatchLine.cpp
HatchLine.h
PreCompiled.cpp
PreCompiled.h
EdgeWalker.cpp
@@ -128,6 +133,8 @@ SET(Python_SRCS
DrawViewDimensionPyImp.cpp
DrawHatchPy.xml
DrawHatchPyImp.cpp
DrawCrosshatchPy.xml
DrawCrosshatchPyImp.cpp
DrawViewCollectionPy.xml
DrawViewCollectionPyImp.cpp
DrawProjGroupPy.xml

View File

@@ -0,0 +1,445 @@
/***************************************************************************
* Copyright (c) 2015 WandererFan <wandererfan@gmail.com> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <sstream>
#include <iomanip>
#include <cmath>
# include <QFile>
# include <QFileInfo>
#include <gp_Pln.hxx>
#include <gp_Pnt.hxx>
#include <Bnd_Box.hxx>
#include <BRepBndLib.hxx>
#include <BRep_Builder.hxx>
#include <BRepAlgoAPI_Common.hxx>
#include <BRepBuilderAPI_MakeVertex.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <Standard_PrimitiveTypes.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopoDS_Wire.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Compound.hxx>
#include <TopExp_Explorer.hxx>
#include <TopTools.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
#include <TopExp.hxx>
#endif
#include <App/Application.h>
#include <Base/Console.h>
#include <Base/Exception.h>
#include <Base/FileInfo.h>
#include <Base/Parameter.h>
#include "HatchLine.h"
#include "DrawUtil.h"
#include "Geometry.h"
#include "DrawViewPart.h"
#include "DrawCrosshatch.h"
#include <Mod/TechDraw/App/DrawCrosshatchPy.h> // generated from DrawCrosshatchPy.xml
using namespace TechDraw;
using namespace TechDrawGeometry;
using namespace std;
PROPERTY_SOURCE(TechDraw::DrawCrosshatch, App::DocumentObject)
DrawCrosshatch::DrawCrosshatch(void)
{
static const char *vgroup = "Crosshatch";
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Colors");
App::Color fcColor;
fcColor.setPackedValue(hGrp->GetUnsigned("Crosshatch", 0x00000000));
ADD_PROPERTY_TYPE(DirProjection ,(0,0,1.0) ,vgroup,App::Prop_None,"Projection direction when Crosshatch was defined"); //sb RO?
ADD_PROPERTY_TYPE(Source,(0),vgroup,(App::PropertyType)(App::Prop_None),"The View + Face to be crosshatched");
ADD_PROPERTY_TYPE(FilePattern ,(""),vgroup,App::Prop_None,"The crosshatch pattern file for this area");
ADD_PROPERTY_TYPE(NamePattern,(""),vgroup,App::Prop_None,"The name of the pattern");
ADD_PROPERTY_TYPE(ScalePattern,(1.0),vgroup,App::Prop_None,"Crosshatch pattern size adjustment");
// ADD_PROPERTY_TYPE(ColorPattern,(fcColor),vgroup,App::Prop_None,"The color of the pattern"); //to vp?
// ADD_PROPERTY_TYPE(WeightPattern,(0.0),vgroup,App::Prop_None,"Crosshatch pattern line thickness");
// ADD_PROPERTY_TYPE(LineSpecs,(""),vgroup,App::Prop_None,"Pattern line specifications"); //this sb RO or removed?
DirProjection.setStatus(App::Property::ReadOnly,true);
//this is probably "/build/data/Mod/TechDraw/PAT"
hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/PAT");
std::string defaultDir = App::Application::getResourceDir() + "Mod/TechDraw/PAT/";
std::string defaultFileName = defaultDir + "FCStd.pat";
QString patternFileName = QString::fromStdString(hGrp->GetASCII("FilePattern",defaultFileName.c_str()));
if (patternFileName.isEmpty()) {
patternFileName = QString::fromStdString(defaultFileName);
}
QFileInfo tfi(patternFileName);
if (tfi.isReadable()) {
FilePattern.setValue(patternFileName.toUtf8().constData());
}
hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/PAT");
std::string defaultNamePattern = "Diamond";
NamePattern.setValue(hGrp->GetASCII("NamePattern",defaultNamePattern.c_str()));
}
DrawCrosshatch::~DrawCrosshatch()
{
}
void DrawCrosshatch::onChanged(const App::Property* prop)
{
if (prop == &Source ) {
if (!isRestoring()) {
DrawCrosshatch::execute();
}
}
if (prop == &FilePattern ||
prop == &NamePattern ) {
if ((!FilePattern.isEmpty()) &&
(!NamePattern.isEmpty())) {
std::vector<HatchLine> specs = getDecodedSpecsFromFile();
m_lineSets.clear();
for (auto& hl: specs) {
//hl.dump("hl from file");
LineSet ls;
ls.setHatchLine(hl);
m_lineSets.push_back(ls);
}
}
}
if (prop == &ScalePattern) {
if (!isRestoring()) {
adviseParent(); //just need to have the parent redraw on Gui side. handle through VPDC::updateData
}
}
App::DocumentObject::onChanged(prop);
}
short DrawCrosshatch::mustExecute() const
{
short result = 0;
if (!isRestoring()) {
result = (Source.isTouched() ||
FilePattern.isTouched() ||
NamePattern.isTouched() );
}
if (result) {
return result;
}
return App::DocumentObject::mustExecute();
}
App::DocumentObjectExecReturn *DrawCrosshatch::execute(void)
{
DrawViewPart* source = getSourceView();
if (!source) {
return App::DocumentObject::StdReturn;
}
if (!source->hasGeometry()) {
return App::DocumentObject::StdReturn;
}
Base::Vector3d sourceDir = source->Direction.getValue();
Base::Vector3d ourDir = DirProjection.getValue();
if (sourceDir != ourDir) {
Base::Console().Warning("Pattern %s may be incorrect due to source %d Direction change.\n",
getNameInDocument(),source->getNameInDocument());
}
adviseParent();
return App::DocumentObject::StdReturn;
}
void DrawCrosshatch::adviseParent(void) const
{
//if the hatch changes, the source has to change too. actually only the source's QGVI has to change.
DrawViewPart* parent = getSourceView();
if (parent) {
parent->touch();
parent->recomputeFeature();
}
}
DrawViewPart* DrawCrosshatch::getSourceView(void) const
{
App::DocumentObject* obj = Source.getValue();
DrawViewPart* result = dynamic_cast<DrawViewPart*>(obj);
return result;
}
//!get all the specification lines and decode them into HatchLine structures
std::vector<HatchLine> DrawCrosshatch::getDecodedSpecsFromFile()
{
std::vector<HatchLine> result;
std::string fileSpec = FilePattern.getValue();
std::string myPattern = NamePattern.getValue();
Base::FileInfo fi(fileSpec);
if (!fi.isReadable()) {
Base::Console().Error("DrawCrosshatch::getDecodedSpecsFromFile not able to open %s!\n",fileSpec.c_str());
return result;
}
result = HatchLine::getSpecsForPattern(fileSpec,myPattern);
return result;
}
std::vector<LineSet> DrawCrosshatch::getDrawableLines()
{
std::vector<LineSet> result;
DrawViewPart* source = getSourceView();
if (!source ||
!source->hasGeometry()) {
Base::Console().Message("TRACE - DC::getDrawableLines - no source geometry\n");
return result;
}
if (m_lineSets.empty()) {
Base::Console().Message("TRACE - DC::getDrawableLines - no LineSets!\n");
return result;
}
//get geometry for linked Face
const std::vector<std::string> &subElements = Source.getSubValues();
int idx = DrawUtil::getIndexFromName(subElements[0]);
//build wire(s) from geometry
std::vector<TopoDS_Wire> faceWires = source->getWireForFace(idx);
gp_Pln plane = source->getProjPlane();
BRepBuilderAPI_MakeFace mkFace(plane, faceWires.front(), true);
std::vector<TopoDS_Wire>::iterator itWire = ++faceWires.begin(); //starting with second wire
for (; itWire != faceWires.end(); itWire++) {
mkFace.Add(*itWire);
}
if (!mkFace.IsDone()) {
Base::Console().Message("TRACE - DC::getDrawableLines - face creation failed\n");
return result;
}
TopoDS_Face face = mkFace.Face();
Bnd_Box bBox;
BRepBndLib::Add(face, bBox);
bBox.SetGap(0.0);
// face & box are done!
for (auto& ls: m_lineSets) {
HatchLine hl = ls.getHatchLine();
std::vector<TopoDS_Edge> candidates = DrawCrosshatch::makeEdgeOverlay(hl, bBox);
//make Compound for this linespec
BRep_Builder builder;
TopoDS_Compound Comp;
builder.MakeCompound(Comp);
for (auto& c: candidates) {
builder.Add(Comp, c);
}
//Common Compound with Face
BRepAlgoAPI_Common mkCommon(face, Comp);
if ((!mkCommon.IsDone()) ||
(mkCommon.Shape().IsNull()) ) {
Base::Console().Message("TRACE - DC::getDrawableLines - Common creation failed\n");
return result;
}
TopoDS_Shape common = mkCommon.Shape();
//Save edges from Common
std::vector<TopoDS_Edge> resultEdges;
std::vector<TechDrawGeometry::BaseGeom*> resultGeoms;
TopTools_IndexedMapOfShape mapOfEdges;
TopExp::MapShapes(common, TopAbs_EDGE, mapOfEdges);
for ( int i = 1 ; i <= mapOfEdges.Extent() ; i++ ) {
const TopoDS_Edge& edge = TopoDS::Edge(mapOfEdges(i));
if (edge.IsNull()) {
Base::Console().Message("TRACE - DC::getDrawableLines - edge: %d is NULL\n",i);
continue;
}
TechDrawGeometry::BaseGeom* base = BaseGeom::baseFactory(edge);
if (base == nullptr) {
Base::Console().Message("TRACE - DC::getDrawableLines - baseFactory failed for edge: %d\n",i);
throw Base::Exception("GeometryObject::addGeomFromCompound - baseFactory failed");
}
resultGeoms.push_back(base);
resultEdges.push_back(edge);
}
ls.setEdges(resultEdges);
ls.setGeoms(resultGeoms);
result.push_back(ls);
}
return result;
}
std::vector<TopoDS_Edge> DrawCrosshatch::makeEdgeOverlay(HatchLine hl, Bnd_Box b)
{
std::vector<TopoDS_Edge> result;
double minX,maxX,minY,maxY,minZ,maxZ;
b.Get(minX,minY,minZ,maxX,maxY,maxZ);
Base::Vector3d start;
Base::Vector3d end;
Base::Vector3d origin = hl.getOrigin();
double interval = hl.getInterval() * ScalePattern.getValue();
double angle = hl.getAngle();
//only dealing with angles -180:180 for now
if (angle > 90.0) {
angle = -(180.0 - angle);
} else if (angle < -90.0) {
angle = (180 + angle);
}
angle = -angle; //not sure why this is required? inverted Y?
double slope = tan(angle * M_PI/180.0);
if (angle == 0.0) { //odd case 1: horizontal lines
double y = origin.y;
double x1 = minX;
double x2 = maxX;
start = Base::Vector3d(x1,y,0);
end = Base::Vector3d(x2,y,0);
int repeatUp = (int) ceil(((maxY - y)/interval) + 1);
int repeatDown = (int) ceil(((y - minY)/interval) + 1);
// make up repeats
int i;
for (i = 1; i < repeatUp; i++) {
Base::Vector3d newStart(minX,y + float(i)*interval,0);
Base::Vector3d newEnd(maxX,y + float(i)*interval,0);
TopoDS_Edge newLine = makeLine(newStart,newEnd);
result.push_back(newLine);
}
// make down repeats
for (i = 1; i < repeatDown; i++) {
Base::Vector3d newStart(minX, y - float(i)*interval,0);
Base::Vector3d newEnd(maxX, y - float(i)*interval,0);
TopoDS_Edge newLine = makeLine(newStart,newEnd);
result.push_back(newLine);
}
} else if (angle > 0) { //bottomleft - topright
double xRightAtom = origin.x + ((maxY - origin.y)/slope);
double xLeftAtom = origin.x + ((minY - origin.y)/slope);
start = Base::Vector3d(xLeftAtom,minY,0);
end = Base::Vector3d(xRightAtom,maxY,0);
int repeatRight = (int) ceil(((maxX - xLeftAtom)/interval) + 1);
int repeatLeft = (int) ceil(((xRightAtom - minX)/interval) + 1);
// make right repeats
int i;
for (i = 1; i < repeatRight; i++) {
Base::Vector3d newStart(start.x + float(i)*interval,minY,0);
Base::Vector3d newEnd(end.x + float(i)*interval,maxY,0);
TopoDS_Edge newLine = makeLine(newStart,newEnd);
result.push_back(newLine);
}
// make left repeats
for (i = 1; i < repeatLeft; i++) {
Base::Vector3d newStart(start.x - float(i)*interval,minY,0);
Base::Vector3d newEnd(end.x - float(i)*interval,maxY,0);
TopoDS_Edge newLine = makeLine(newStart,newEnd);
result.push_back(newLine);
}
} else { //topleft - bottomright
double x2 = origin.x + (maxY - origin.y)/slope;
double x1 = origin.x + (minY - origin.y)/slope;
start = Base::Vector3d(x2,maxY,0);
end = Base::Vector3d(x1,minY,0);
int repeatRight = (int) ceil(((maxX - start.x)/interval) + 1);
int repeatLeft = (int) ceil(((end.x - minX)/interval) + 1);
// make right repeats
int i;
for (i = 1; i < repeatRight; i++) {
Base::Vector3d newStart(start.x + float(i)*interval,maxY,0);
Base::Vector3d newEnd(end.x + float(i)*interval,minY,0);
TopoDS_Edge newLine = makeLine(newStart,newEnd);
result.push_back(newLine);
}
// make left repeats
for (i = 1; i < repeatLeft; i++) {
Base::Vector3d newStart(start.x - float(i)*interval,maxY,0);
Base::Vector3d newEnd(end.x - float(i)*interval,minY,0);
TopoDS_Edge newLine = makeLine(newStart,newEnd);
result.push_back(newLine);
}
}
//atom is centre line in a set of pattern lines.
TopoDS_Edge atom = makeLine(start,end);
result.push_back(atom);
return result;
}
TopoDS_Edge DrawCrosshatch::makeLine(Base::Vector3d s, Base::Vector3d e)
{
TopoDS_Edge result;
gp_Pnt start(s.x,s.y,0.0);
gp_Pnt end(e.x,e.y,0.0);
TopoDS_Vertex v1 = BRepBuilderAPI_MakeVertex(start);
TopoDS_Vertex v2 = BRepBuilderAPI_MakeVertex(end);
BRepBuilderAPI_MakeEdge makeEdge1(v1,v2);
result = makeEdge1.Edge();
return result;
}
PyObject *DrawCrosshatch::getPyObject(void)
{
if (PythonObject.is(Py::_None())) {
PythonObject = Py::Object(new DrawCrosshatchPy(this),true);
}
return Py::new_reference_to(PythonObject);
}
// Python Drawing feature ---------------------------------------------------------
namespace App {
/// @cond DOXERR
PROPERTY_SOURCE_TEMPLATE(TechDraw::DrawCrosshatchPython, TechDraw::DrawCrosshatch)
template<> const char* TechDraw::DrawCrosshatchPython::getViewProviderName(void) const {
return "TechDrawGui::ViewProviderCrosshatch";
}
/// @endcond
// explicit template instantiation
template class TechDrawExport FeaturePythonT<TechDraw::DrawCrosshatch>;
}

View File

@@ -0,0 +1,85 @@
/***************************************************************************
* Copyright (c) 2017 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 _TechDraw_DrawCrosshatch_h_
#define _TechDraw_DrawCrosshatch_h_
# include <App/DocumentObject.h>
# include <App/FeaturePython.h>
# include <App/PropertyLinks.h>
#include <App/PropertyFile.h>
#include "HatchLine.h"
#include "Geometry.h"
class TopoDS_Edge;
class Bnd_Box;
namespace TechDraw
{
class DrawViewPart;
class TechDrawExport DrawCrosshatch : public App::DocumentObject
{
PROPERTY_HEADER(TechDraw::DrawCrosshatch);
public:
DrawCrosshatch();
virtual ~DrawCrosshatch();
App::PropertyVector DirProjection; //Source is only valid for original projection?
App::PropertyLinkSub Source; //the dvp & face this crosshatch belongs to
App::PropertyFile FilePattern;
App::PropertyString NamePattern;
App::PropertyFloat ScalePattern;
// App::PropertyFloat WeightPattern;
// App::PropertyColor ColorPattern;
// App::PropertyStringList LineSpecs;
virtual short mustExecute() const;
virtual App::DocumentObjectExecReturn *execute(void);
virtual void onChanged(const App::Property* prop);
virtual const char* getViewProviderName(void) const {
return "TechDrawGui::ViewProviderCrosshatch";
}
virtual PyObject *getPyObject(void);
std::vector<LineSet> getDrawableLines();
DrawViewPart* getSourceView(void) const;
void adviseParent(void) const; //don't like this!
protected:
TopoDS_Edge makeLine(Base::Vector3d s, Base::Vector3d e);
std::vector<HatchLine> getDecodedSpecsFromFile();
std::vector<TopoDS_Edge> makeEdgeOverlay(HatchLine hl, Bnd_Box bBox);
std::vector<LineSet> m_lineSets;
private:
};
typedef App::FeaturePythonT<DrawCrosshatch> DrawCrosshatchPython;
} //namespace TechDraw
#endif

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport
Father="DocumentObjectPy"
Name="DrawCrosshatchPy"
Twin="DrawCrosshatch"
TwinPointer="DrawCrosshatch"
Include="Mod/TechDraw/App/DrawCrosshatch.h"
Namespace="TechDraw"
FatherInclude="App/DocumentObjectPy.h"
FatherNamespace="App">
<Documentation>
<Author Licence="LGPL" Name="WandererFan" EMail="wandererfan@gmail.com" />
<UserDocu>Feature for creating and manipulating Technical Drawing Crosshatch areas</UserDocu>
</Documentation>
<CustomAttributes />
</PythonExport>
</GenerateModel>

View File

@@ -0,0 +1,32 @@
#include "PreCompiled.h"
#include "DrawCrosshatch.h"
// inclusion of the generated files (generated out of DrawCrosshatchPy.xml)
#include <Mod/TechDraw/App/DrawCrosshatchPy.h>
#include <Mod/TechDraw/App/DrawCrosshatchPy.cpp>
using namespace TechDraw;
// returns a string which represents the object e.g. when printed in python
std::string DrawCrosshatchPy::representation(void) const
{
return std::string("<DrawCrosshatch object>");
}
PyObject *DrawCrosshatchPy::getCustomAttributes(const char* /*attr*/) const
{
return 0;
}
int DrawCrosshatchPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
{
return 0;
}

View File

@@ -69,7 +69,7 @@ DrawHatch::DrawHatch(void)
std::string defaultDir = App::Application::getResourceDir() + "Mod/Drawing/patterns/";
std::string defaultFileName = defaultDir + "simple.svg";
QString patternFileName = QString::fromStdString(hGrp->GetASCII("PatternFile",defaultFileName.c_str()));
QString patternFileName = QString::fromStdString(hGrp->GetASCII("FileHatch",defaultFileName.c_str()));
if (patternFileName.isEmpty()) {
patternFileName = QString::fromStdString(defaultFileName);
}

View File

@@ -292,6 +292,10 @@ void DrawPage::onDocumentRestored()
if (part != nullptr &&
!part->hasGeometry()) {
part->execute();
// std::vector<App::DocumentObject*> parent = part->getInList();
// for (auto& p: parent) {
// p->touch();
// }
}
}
//second, make sure all the Dimensions have been executed so Measurements have References

View File

@@ -1042,6 +1042,7 @@ void DrawProjGroup::onDocumentRestored()
}
std::string viewRot = Cube::dirToView(rotFront);
std::string config = viewDir + viewRot;
//find(config) or try/catch
try {
config = m_dirRotToConfig.at(config);
setConfig(config);

View File

@@ -33,6 +33,7 @@
#include <BRepAdaptor_Curve.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepLib.hxx>
#include <BRepLProp_CurveTool.hxx>
#include <BRepLProp_CLProps.hxx>
#include <BRepExtrema_DistShapeShape.hxx>
@@ -83,6 +84,7 @@
#include "GeometryObject.h"
#include "DrawViewPart.h"
#include "DrawHatch.h"
#include "DrawCrosshatch.h"
#include "EdgeWalker.h"
@@ -147,19 +149,17 @@ App::DocumentObjectExecReturn *DrawViewPart::execute(void)
{
App::DocumentObject *link = Source.getValue();
if (!link) {
return new App::DocumentObjectExecReturn("FVP - No Source object linked");
return new App::DocumentObjectExecReturn("DVP - No Source object linked");
}
if (!link->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
return new App::DocumentObjectExecReturn("FVP - Linked object is not a Part object");
return new App::DocumentObjectExecReturn("DVP - Linked object is not a Part object");
}
TopoDS_Shape shape = static_cast<Part::Feature*>(link)->Shape.getShape().getShape();
if (shape.IsNull()) {
return new App::DocumentObjectExecReturn("FVP - Linked shape object is empty");
return new App::DocumentObjectExecReturn("DVP - Linked shape object is empty");
}
//Base::Console().Message("TRACE - DVP::execute() - %s - %s - dir: %s\n",getNameInDocument(), Label.getValue(),DrawUtil::formatVector(Direction.getValue()).c_str());
(void) DrawView::execute(); //make sure Scale is up to date
@@ -391,7 +391,6 @@ void DrawViewPart::extractFaces()
}
}
std::vector<TechDraw::DrawHatch*> DrawViewPart::getHatches() const
{
std::vector<TechDraw::DrawHatch*> result;
@@ -405,6 +404,19 @@ std::vector<TechDraw::DrawHatch*> DrawViewPart::getHatches() const
return result;
}
std::vector<TechDraw::DrawCrosshatch*> DrawViewPart::getCrosshatches() const
{
std::vector<TechDraw::DrawCrosshatch*> result;
std::vector<App::DocumentObject*> children = getInList();
for (std::vector<App::DocumentObject*>::iterator it = children.begin(); it != children.end(); ++it) {
if ((*it)->getTypeId().isDerivedFrom(DrawCrosshatch::getClassTypeId())) {
TechDraw::DrawCrosshatch* cross = dynamic_cast<TechDraw::DrawCrosshatch*>(*it);
result.push_back(cross);
}
}
return result;
}
const std::vector<TechDrawGeometry::Vertex *> & DrawViewPart::getVertexGeometry() const
{
return geometryObject->getVertexGeometry();
@@ -450,6 +462,8 @@ TechDrawGeometry::Vertex* DrawViewPart::getProjVertexByIndex(int idx) const
return geoms.at(idx);
}
//this is never used!!
//! returns existing geometry of 2D Face(idx)
//version 1 Face has 1 wire
std::vector<TechDrawGeometry::BaseGeom*> DrawViewPart::getProjFaceByIndex(int idx) const
@@ -467,6 +481,29 @@ std::vector<TechDrawGeometry::BaseGeom*> DrawViewPart::getProjFaceByIndex(int id
return result;
}
std::vector<TopoDS_Wire> DrawViewPart::getWireForFace(int idx) const
{
// Base::Console().Message("TRACE - DVP::getWireForFace(%d)\n",idx);
std::vector<TopoDS_Wire> result;
std::vector<TopoDS_Edge> edges;
const std::vector<TechDrawGeometry::Face *>& faces = getFaceGeometry();
TechDrawGeometry::Face * ourFace = faces.at(idx);
for (auto& w:ourFace->wires) {
edges.clear();
int i = 0;
for (auto& g:w->geoms) {
edges.push_back(g->occEdge);
// DrawUtil::dumpEdge("DVP Face edge",i,g->occEdge);
i++;
}
TopoDS_Wire occwire = EdgeWalker::makeCleanWire(edges);
// BRepLib::BuildCurves3d(occwire); //probably don't need this
result.push_back(occwire);
}
// Base::Console().Message("TRACE - DVP::getWireForFace(%d) returns %d wires\n",idx,result.size());
return result;
}
Base::BoundBox3d DrawViewPart::getBoundingBox() const
{
@@ -570,12 +607,24 @@ const std::vector<TechDrawGeometry::BaseGeom *> DrawViewPart::getVisibleFaceEdg
return geometryObject->getVisibleFaceEdges(SmoothVisible.getValue(),SeamVisible.getValue());
}
//is this really the projection plane??
gp_Pln DrawViewPart::getProjPlane() const
{
Base::Vector3d plnPnt(0.0,0.0,0.0);
Base::Vector3d plnNorm = Direction.getValue();
gp_Ax2 viewAxis = getViewAxis(plnPnt,plnNorm,false);
gp_Ax3 viewAxis3(viewAxis);
return gp_Pln(viewAxis3);
}
void DrawViewPart::getRunControl()
{
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/General");
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/RunControl");
m_sectionEdges = hGrp->GetBool("ShowSectionEdges", 1l);
m_handleFaces = hGrp->GetBool("HandleFaces", 1l);
//Base::Console().Message("TRACE - DVP::getRunControl - handleFaces: %d\n",m_handleFaces);
}
bool DrawViewPart::handleFaces(void)

View File

@@ -40,6 +40,7 @@
#include "DrawProjectSplit.h"
class gp_Pnt;
class gp_Pln;
namespace TechDrawGeometry
{
@@ -51,6 +52,7 @@ class Face;
namespace TechDraw {
class DrawHatch;
class DrawCrosshatch;
}
namespace TechDraw
@@ -91,6 +93,7 @@ public:
std::vector<TechDraw::DrawHatch*> getHatches(void) const;
std::vector<TechDraw::DrawCrosshatch*> getCrosshatches(void) const;
//TODO: are there use-cases for Python access to TechDrawGeometry???
@@ -136,6 +139,10 @@ public:
//return PyObject as DrawViewPartPy
virtual PyObject *getPyObject(void);
bool isDeleting(void) { return nowDeleting; }
gp_Pln getProjPlane(void) const;
std::vector<TopoDS_Wire> getWireForFace(int idx) const;
protected:
TechDrawGeometry::GeometryObject *geometryObject;

View File

@@ -545,7 +545,7 @@ void DrawViewSection::getParameters()
std::string defaultDir = App::Application::getResourceDir() + "Mod/Drawing/patterns/";
std::string defaultFileName = defaultDir + "simple.svg";
QString patternFileName = QString::fromStdString(hGrp->GetASCII("PatternFile",defaultFileName.c_str()));
QString patternFileName = QString::fromStdString(hGrp->GetASCII("FileHatch",defaultFileName.c_str()));
if (patternFileName.isEmpty()) {
patternFileName = QString::fromStdString(defaultFileName);
}

View File

@@ -265,7 +265,7 @@ std::vector<TopoDS_Wire> EdgeWalker::getResultNoDups()
return fw;
}
//* static *//
//! make a clean wire with sorted, oriented, connected, etc edges
TopoDS_Wire EdgeWalker::makeCleanWire(std::vector<TopoDS_Edge> edges, double tol)
{

View File

@@ -175,7 +175,7 @@ public:
int findUniqueVert(TopoDS_Vertex vx, std::vector<TopoDS_Vertex> &uniqueVert);
std::vector<TopoDS_Wire> sortStrip(std::vector<TopoDS_Wire> fw, bool includeBiggest);
std::vector<TopoDS_Wire> sortWiresBySize(std::vector<TopoDS_Wire>& w, bool reverse = false);
TopoDS_Wire makeCleanWire(std::vector<TopoDS_Edge> edges, double tol = 0.10);
static TopoDS_Wire makeCleanWire(std::vector<TopoDS_Edge> edges, double tol = 0.10);
std::vector<int> getEmbeddingRowIx(int v);
std::vector<edge_t> getEmbeddingRow(int v);

View File

@@ -161,7 +161,8 @@ void GeometryObject::projectShape(const TopoDS_Shape& input,
HLRAlgo_Projector projector( viewAxis );
brep_hlr->Projector(projector);
brep_hlr->Update();
brep_hlr->Hide();
brep_hlr->Hide(); //XXXX: what happens if we don't call Hide()?? and only look at VCompound?
// WF: you get back all the edges in the shape, but very fast!!
}
catch (...) {
Standard_Failure::Raise("GeometryObject::projectShape - error occurred while projecting shape");

View File

@@ -0,0 +1,237 @@
/***************************************************************************
* Copyright (c) 2017 Wandererfan <wandererfan@gmail.com> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#include <sstream>
#include <iomanip>
#include <QFile>
#include <QFileInfo>
#include <stdexcept>
#endif
#include <Base/Console.h>
#include "DrawUtil.h"
#include "HatchLine.h"
using namespace TechDraw;
HatchLine::HatchLine()
{
init();
}
HatchLine::HatchLine(std::string& lineSpec)
{
init();
load(lineSpec);
}
HatchLine::~HatchLine()
{
}
void HatchLine::init(void)
{
m_angle = 0.0;
m_origin = Base::Vector3d(0.0,0.0,0.0);
m_interval = 1.0;
m_offset = 0.0;
}
void HatchLine::load(std::string& lineSpec)
{
std::vector<double> values = split(lineSpec);
if (values.size() < 5) {
Base::Console().Message( "HatchLine::load(%s) invalid entry in pattern\n",lineSpec.c_str() );
return;
}
m_angle = values[0];
m_origin = Base::Vector3d(values[1],values[2],0.0);
m_offset = values[3];
m_interval = values[4];
if (values.size() > 5) {
m_dashParms.insert(std::end(m_dashParms), std::begin(values) + 5, std::end(values));
}
}
std::vector<double> HatchLine::split(std::string line)
{
std::vector<double> result;
std::stringstream lineStream(line);
std::string cell;
while(std::getline(lineStream,cell, ','))
{
try {
result.push_back(std::stod(cell));
}
catch (const std::invalid_argument& ia) {
Base::Console().Warning("Invalid number in cell: %s (%s) \n",cell.c_str(),ia.what());
result.push_back(0.0);
}
}
return result;
}
void HatchLine::dump(char* title)
{
Base::Console().Message( "DUMP: %s\n",title);
Base::Console().Message( "Angle: %.3f\n", m_angle);
Base::Console().Message( "Origin: %s\n",DrawUtil::formatVector(m_origin).c_str());
Base::Console().Message( "Offset: %.3f\n",m_offset);
Base::Console().Message( "Interval: %.3f\n",m_interval);
std::stringstream ss;
for (auto& d: m_dashParms) {
ss << d << ", ";
}
ss << "end";
Base::Console().Message( "DashSpec: %s\n",ss.str().c_str());
}
//static class methods
std::vector<HatchLine> HatchLine::getSpecsForPattern(std::string& parmFile, std::string& parmName)
{
std::vector<HatchLine> result;
std::vector<std::string> lineSpecs;
std::ifstream inFile;
inFile.open (parmFile, std::ifstream::in);
if(!inFile.is_open()) {
Base::Console().Message( "Cannot open input file.\n");
return result;
}
//get all the definition lines for this pattern
bool status = findPatternStart(inFile, parmName);
if (status) {
lineSpecs = loadPatternDef(inFile);
} else {
Base::Console().Message( "Could not find pattern: %s\n",parmName.c_str() );
return result;
}
//decode definition lines into HatchLine objects
for (auto& l: lineSpecs) {
HatchLine hl(l);
result.push_back(hl);
}
return result;
}
bool HatchLine::findPatternStart(std::ifstream& inFile, std::string& parmName)
{
bool result = false;
while ( inFile.good() ){
std::string line;
std::getline(inFile,line);
std::string nameTag = line.substr(0,1);
std::string patternName;
unsigned long int commaPos;
if ((nameTag == ";") ||
(nameTag == " ") ||
(line.empty()) ) { //is cr/lf empty?
continue;
} else if (nameTag == "*") {
commaPos = line.find(",",1);
if (commaPos != std::string::npos) {
patternName = line.substr(1,commaPos-1);
} else {
patternName = line.substr(1);
}
if (patternName == parmName) {
//this is our pattern
result = true;
break;
}
}
} //endwhile
return result;
}
//get the definition lines for this pattern
std::vector<std::string> HatchLine::loadPatternDef(std::ifstream& inFile)
{
std::vector<std::string> result;
while ( inFile.good() ){
std::string line;
std::getline(inFile,line);
std::string nameTag = line.substr(0,1);
if ((nameTag == ";") ||
(nameTag == " ") ||
(line.empty()) ) { //is cr/lf empty?
continue;
} else if (nameTag == "*") {
break;
} else { //dataline
result.push_back(line);
}
}
return result;
}
std::vector<std::string> HatchLine::getPatternList(std::string& parmFile)
{
std::vector<std::string> result;
std::ifstream inFile;
inFile.open (parmFile, std::ifstream::in);
if(!inFile.is_open()) {
Base::Console().Message( "Cannot open input file.\n");
return result;
}
while ( inFile.good() ){
std::string line;
std::getline(inFile,line);
std::string nameTag = line.substr(0,1); //dupl code here
unsigned long int commaPos;
if (nameTag == "*") { //found a pattern
commaPos = line.find(",",1);
std::string patternName;
if (commaPos != std::string::npos) {
patternName = line.substr(1,commaPos-1);
} else {
patternName = line.substr(1);
}
result.push_back(patternName);
}
}
return result;
}
//********************************************************
void DashSpec::dump(char* title)
{
std::stringstream ss;
ss << title << ": " ;
for (auto& p: m_parms) {
ss << p << ", ";
}
Base::Console().Message("DUMP - DashSpec - %s\n",ss.str().c_str());
}

View File

@@ -0,0 +1,117 @@
/***************************************************************************
* Copyright (c) 2017 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 _TechDraw_HATCHLINE_H_
#define _TechDraw_HATCHLINE_H_
#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <string>
#include <Base/Vector3D.h>
#include "Geometry.h"
namespace TechDraw
{
class DrawViewPart;
class DrawUtil;
// HatchLine is the result of parsing a line from PAT file into accessible parameters
class HatchLine
{
public:
HatchLine();
HatchLine(std::string& lineSpec);
~HatchLine();
void load(std::string& lineSpec);
double getAngle(void) {return m_angle;}
Base::Vector3d getOrigin(void) {return m_origin;}
double getInterval(void) {return m_interval;}
double getOffset(void) {return m_offset;}
std::vector<double> getDashParms(void) {return m_dashParms;};
static std::vector<HatchLine> getSpecsForPattern(std::string& parmFile, std::string& parmName);
static bool findPatternStart(std::ifstream& inFile, std::string& parmName);
static std::vector<std::string> loadPatternDef(std::ifstream& inFile);
static std::vector<std::string> getPatternList(std::string& parmFile);
void dump(char* title);
private:
void init(void);
std::vector<double> split(std::string line);
double m_angle;
Base::Vector3d m_origin;
double m_interval;
double m_offset;
std::vector<double> m_dashParms; //why isn't this a DashSpec object?
};
// a LineSet is all the generated edges for a HatchLine
class LineSet
{
public:
LineSet() {}
~LineSet() {}
void setHatchLine(HatchLine s) { m_hatchLine = s; }
void setEdges(std::vector<TopoDS_Edge> e) {m_edges = e;}
void setGeoms(std::vector<TechDrawGeometry::BaseGeom*> g) {m_geoms = g;}
HatchLine getHatchLine(void) { return m_hatchLine; }
std::vector<double> getDashSpec(void) { return m_hatchLine.getDashParms();}
std::vector<TopoDS_Edge> getEdges(void) { return m_edges; }
std::vector<TechDrawGeometry::BaseGeom*> getGeoms(void) { return m_geoms; }
private:
std::vector<TopoDS_Edge> m_edges;
std::vector<TechDrawGeometry::BaseGeom*> m_geoms;
HatchLine m_hatchLine;
};
class DashSpec
{
public:
DashSpec() {}
DashSpec(std::vector<double> p) { m_parms = p; }
~DashSpec() {}
double get(int i) {return m_parms.at(i); }
std::vector<double> get(void) {return m_parms;}
bool empty(void) {return m_parms.empty();}
int size(void) {return m_parms.size();}
void dump(char* title);
private:
std::vector<double> m_parms;
};
} //end namespace
#endif