clean up GeomHatch feature, gui & dialog

Refactor code, allow dialog to edit feature, update graphics on change
prep for dash line start positioning.
This commit is contained in:
WandererFan
2017-03-27 21:10:33 -04:00
committed by wmayer
parent c2033723a9
commit bf4a80dad5
16 changed files with 703 additions and 388 deletions

View File

@@ -68,6 +68,7 @@
#include "HatchLine.h"
#include "DrawUtil.h"
#include "Geometry.h"
#include "DrawPage.h"
#include "DrawViewPart.h"
#include "DrawViewSection.h"
#include "DrawGeomHatch.h"
@@ -94,6 +95,9 @@ DrawGeomHatch::DrawGeomHatch(void)
ADD_PROPERTY_TYPE(NamePattern,(""),vgroup,App::Prop_None,"The name of the pattern");
ADD_PROPERTY_TYPE(ScalePattern,(1.0),vgroup,App::Prop_None,"GeomHatch pattern size adjustment");
ScalePattern.setConstraints(&scaleRange);
m_saveFile = "";
m_saveName = "";
getParameters();
@@ -105,28 +109,18 @@ DrawGeomHatch::~DrawGeomHatch()
void DrawGeomHatch::onChanged(const App::Property* prop)
{
if (prop == &Source ) {
if (prop == &Source ) {
if (!isRestoring()) {
DrawGeomHatch::execute();
DrawGeomHatch::execute();
}
}
if (isRestoring()) {
if ((prop == &FilePattern) || //make sure right pattern gets loaded at start up
(prop == &NamePattern)) {
DrawGeomHatch::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);
}
}
}
App::DocumentObject::onChanged(prop);
}
@@ -148,7 +142,23 @@ short DrawGeomHatch::mustExecute() const
App::DocumentObjectExecReturn *DrawGeomHatch::execute(void)
{
//save names & check if different
if ((!FilePattern.isEmpty()) &&
(!NamePattern.isEmpty())) {
if ((m_saveFile != FilePattern.getValue()) ||
(m_saveName != NamePattern.getValue())) {
m_saveFile = FilePattern.getValue();
m_saveName = NamePattern.getValue();
std::vector<PATLineSpec> specs = getDecodedSpecsFromFile();
m_lineSets.clear();
for (auto& hl: specs) {
//hl.dump("hl from file");
LineSet ls;
ls.setPATLineSpec(hl);
m_lineSets.push_back(ls);
}
}
}
return App::DocumentObject::StdReturn;
}
@@ -159,7 +169,7 @@ DrawViewPart* DrawGeomHatch::getSourceView(void) const
return result;
}
std::vector<HatchLine> DrawGeomHatch::getDecodedSpecsFromFile()
std::vector<PATLineSpec> DrawGeomHatch::getDecodedSpecsFromFile()
{
std::string fileSpec = FilePattern.getValue();
std::string myPattern = NamePattern.getValue();
@@ -167,49 +177,265 @@ std::vector<HatchLine> DrawGeomHatch::getDecodedSpecsFromFile()
}
//!get all the specification lines and decode them into HatchLine structures
//!get all the specification lines and decode them into PATLineSpec structures
/*static*/
std::vector<HatchLine> DrawGeomHatch::getDecodedSpecsFromFile(std::string fileSpec, std::string myPattern)
std::vector<PATLineSpec> DrawGeomHatch::getDecodedSpecsFromFile(std::string fileSpec, std::string myPattern)
{
std::vector<HatchLine> result;
std::vector<PATLineSpec> result;
Base::FileInfo fi(fileSpec);
if (!fi.isReadable()) {
Base::Console().Error("DrawGeomHatch::getDecodedSpecsFromFile not able to open %s!\n",fileSpec.c_str());
return result;
}
result = HatchLine::getSpecsForPattern(fileSpec,myPattern);
result = PATLineSpec::getSpecsForPattern(fileSpec,myPattern);
return result;
}
std::vector<LineSet> DrawGeomHatch::getDrawableLines(int i) //get the drawable lines for face i
std::vector<LineSet> DrawGeomHatch::getTrimmedLines(int i) //get the trimmed hatch lines for face i
{
std::vector<LineSet> result;
DrawViewPart* source = getSourceView();
if (!source ||
!source->hasGeometry()) {
Base::Console().Message("TRACE - DC::getDrawableLines - no source geometry\n");
Base::Console().Message("TRACE - DGH::getTrimmedLines - no source geometry\n");
return result;
}
return getDrawableLines(source, m_lineSets,i, ScalePattern.getValue());
return getTrimmedLines(source, m_lineSets,i, ScalePattern.getValue());
}
/* static */
std::vector<LineSet> DrawGeomHatch::getDrawableLines(DrawViewPart* source, std::vector<LineSet> lineSets, int iface, double scale )
//! get hatch lines trimmed to face outline
std::vector<LineSet> DrawGeomHatch::getTrimmedLines(DrawViewPart* source, std::vector<LineSet> lineSets, int iface, double scale )
{
std::vector<LineSet> result;
//is source is a section?
if (lineSets.empty()) {
Base::Console().Log("INFO - DGH::getTrimmedLines - no LineSets!\n");
return result;
}
TopoDS_Face face = extractFace(source,iface);
Bnd_Box bBox;
BRepBndLib::Add(face, bBox);
bBox.SetGap(0.0);
for (auto& ls: lineSets) {
PATLineSpec hl = ls.getPATLineSpec();
std::vector<TopoDS_Edge> candidates = DrawGeomHatch::makeEdgeOverlay(hl, bBox, scale); //completely cover face bbox with lines
//make Compound for this linespec
BRep_Builder builder;
TopoDS_Compound Comp;
builder.MakeCompound(Comp);
for (auto& c: candidates) {
builder.Add(Comp, c);
}
//Common(Compound,Face)
BRepAlgoAPI_Common mkCommon(face, Comp);
if ((!mkCommon.IsDone()) ||
(mkCommon.Shape().IsNull()) ) {
Base::Console().Log("INFO - DGH::getTrimmedLines - Common creation failed\n");
return result;
}
TopoDS_Shape common = mkCommon.Shape();
Bnd_Box overlayBox;
overlayBox.SetGap(0.0);
BRepBndLib::Add(common, overlayBox);
ls.setBBox(overlayBox);
//get resulting edges
std::vector<TopoDS_Edge> resultEdges;
TopTools_IndexedMapOfShape mapOfEdges;
TopExp::MapShapes(common, TopAbs_EDGE, mapOfEdges);
for ( int i = 1 ; i <= mapOfEdges.Extent() ; i++ ) { //remember, TopExp makes no promises about the order it finds edges
const TopoDS_Edge& edge = TopoDS::Edge(mapOfEdges(i));
if (edge.IsNull()) {
Base::Console().Log("INFO - DGH::getTrimmedLines - edge: %d is NULL\n",i);
continue;
}
resultEdges.push_back(edge);
}
std::vector<TechDrawGeometry::BaseGeom*> resultGeoms;
int i = 0;
for (auto& e: resultEdges) {
TechDrawGeometry::BaseGeom* base = BaseGeom::baseFactory(e);
if (base == nullptr) {
Base::Console().Log("FAIL - DGH::getTrimmedLines - baseFactory failed for edge: %d\n",i);
throw Base::Exception("DGH::getTrimmedLines - baseFactory failed");
}
resultGeoms.push_back(base);
i++;
}
ls.setEdges(resultEdges);
ls.setGeoms(resultGeoms);
result.push_back(ls);
}
return result;
}
/* static */
std::vector<TopoDS_Edge> DrawGeomHatch::makeEdgeOverlay(PATLineSpec hl, Bnd_Box b, double scale)
{
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() * scale;
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);
}
double slope = hl.getSlope();
if (angle == 0.0) { //odd case 1: horizontal lines
double y = origin.y;
int repeatUp = (int) ceil(((maxY - y)/interval) + 1);
int repeatDown = (int) ceil(((y - minY)/interval) + 1);
int repeatTotal = repeatUp + repeatDown;
// make repeats
for (int i = 0; i < repeatTotal; i++) {
Base::Vector3d newStart(minX,minY + float(i)*interval,0);
Base::Vector3d newEnd(maxX,minY + float(i)*interval,0);
TopoDS_Edge newLine = makeLine(newStart,newEnd);
result.push_back(newLine);
}
} else if ((angle == 90.0) ||
(angle == -90.0)) { //odd case 2: vertical lines
double x = origin.x;
int repeatRight = (int) ceil(((maxX - x)/interval) + 1);
int repeatLeft = (int) ceil(((x - minX)/interval) + 1);
int repeatTotal = repeatRight + repeatLeft;
// make repeats
for (int i = 0; i < repeatTotal; i++) {
Base::Vector3d newStart(minX + float(i)*interval,minY,0);
Base::Vector3d newEnd(minX + float(i)*interval,maxY,0);
TopoDS_Edge newLine = makeLine(newStart,newEnd);
result.push_back(newLine);
}
//TODO: check if this makes 2-3 extra lines. might be some "left" lines on "right" side of vv
} else if (angle > 0) { //oblique (bottom left -> top right)
//ex: 60,0,0,0,4.0,25,-25
// Base::Console().Message("TRACE - DGH-makeEdgeOverlay - making angle > 0\n");
double xLeftAtom = origin.x + (minY - origin.y)/slope; //the "atom" is the fill line that passes through the
//pattern-origin (not necc. R2 origin)
double xRightAtom = origin.x + (maxY - origin.y)/slope;
int repeatRight = (int) ceil(((maxX - xLeftAtom)/interval) + 1);
int repeatLeft = (int) ceil(((xRightAtom - minX)/interval) + 1);
double leftStartX = xLeftAtom - (repeatLeft * interval);
double leftEndX = xRightAtom - (repeatLeft * interval);
int repeatTotal = repeatRight + repeatLeft;
//make repeats
for (int i = 0; i < repeatTotal; i++) {
Base::Vector3d newStart(leftStartX + (float(i) * interval),minY,0);
Base::Vector3d newEnd (leftEndX + (float(i) * interval),maxY,0);
TopoDS_Edge newLine = makeLine(newStart,newEnd);
result.push_back(newLine);
}
} else { //oblique (bottom right -> top left)
// ex: -60,0,0,0,4.0,25.0,-12.5,12.5,-6
// Base::Console().Message("TRACE - DGH-makeEdgeOverlay - making angle < 0\n");
double xRightAtom = origin.x + ((minY - origin.y)/slope); //x-coord of left end of Atom line
double xLeftAtom = origin.x + ((maxY - origin.y)/slope); //x-coord of right end of Atom line
int repeatRight = (int) ceil(((maxX - xLeftAtom)/interval) + 1); //number of lines to Right of Atom
int repeatLeft = (int) ceil(((xRightAtom - minX)/interval) + 1);//number of lines to Left of Atom
double leftEndX = xLeftAtom - (repeatLeft * interval);
double leftStartX = xRightAtom - (repeatLeft * interval);
int repeatTotal = repeatRight + repeatLeft;
// make repeats
for (int i = 0; i < repeatTotal; i++) {
Base::Vector3d newStart(leftStartX + float(i)*interval,minY,0);
Base::Vector3d newEnd(leftEndX + float(i)*interval,maxY,0);
TopoDS_Edge newLine = makeLine(newStart,newEnd);
result.push_back(newLine);
}
}
return result;
}
TopoDS_Edge DrawGeomHatch::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;
}
//! get all the untrimed hatchlines for a face
//! these will be clipped to shape on the gui side
std::vector<LineSet> DrawGeomHatch::getFaceOverlay(int fdx)
{
// Base::Console().Message("TRACE - DGH::getFaceOverlay(%d)\n",fdx);
std::vector<LineSet> result;
DrawViewPart* source = getSourceView();
if (!source ||
!source->hasGeometry()) {
Base::Console().Message("TRACE - DGH::getFaceOverlay - no source geometry\n");
return result;
}
TopoDS_Face face = extractFace(source,fdx);
Bnd_Box bBox;
BRepBndLib::Add(face, bBox);
bBox.SetGap(0.0);
for (auto& ls: m_lineSets) {
PATLineSpec hl = ls.getPATLineSpec();
std::vector<TopoDS_Edge> candidates = DrawGeomHatch::makeEdgeOverlay(hl, bBox, ScalePattern.getValue());
std::vector<TechDrawGeometry::BaseGeom*> resultGeoms;
int i = 0;
for (auto& e: candidates) {
TechDrawGeometry::BaseGeom* base = BaseGeom::baseFactory(e);
if (base == nullptr) {
Base::Console().Log("FAIL - DGH::getFaceOverlay - baseFactory failed for edge: %d\n",i);
throw Base::Exception("DGH::getFaceOverlay - baseFactory failed");
}
resultGeoms.push_back(base);
i++;
}
ls.setEdges(candidates);
ls.setGeoms(resultGeoms);
result.push_back(ls);
}
return result;
}
/* static */
//! get TopoDS_Face(iface) from DVP
TopoDS_Face DrawGeomHatch::extractFace(DrawViewPart* source, int iface )
{
TopoDS_Face result;
//is source a section?
DrawViewSection* section = dynamic_cast<DrawViewSection*>(source);
bool usingSection = false;
if (section != nullptr) {
usingSection = true;
}
if (lineSets.empty()) {
Base::Console().Log("INFO - DC::getDrawableLines - no LineSets!\n");
return result;
}
std::vector<TopoDS_Wire> faceWires;
if (usingSection) {
@@ -229,176 +455,14 @@ std::vector<LineSet> DrawGeomHatch::getDrawableLines(DrawViewPart* source, std::
mkFace.Add(*itWire);
}
if (!mkFace.IsDone()) {
Base::Console().Log("INFO - DC::getDrawableLines - face creation failed\n");
Base::Console().Log("INFO - DGH::extractFace - face creation failed\n");
return result;
}
TopoDS_Face face = mkFace.Face();
Bnd_Box bBox;
BRepBndLib::Add(face, bBox);
bBox.SetGap(0.0);
for (auto& ls: lineSets) {
HatchLine hl = ls.getHatchLine();
std::vector<TopoDS_Edge> candidates = DrawGeomHatch::makeEdgeOverlay(hl, bBox, scale);
//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().Log("INFO - 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().Log("INFO - DC::getDrawableLines - edge: %d is NULL\n",i);
continue;
}
TechDrawGeometry::BaseGeom* base = BaseGeom::baseFactory(edge);
if (base == nullptr) {
Base::Console().Log("FAIL - 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);
}
result = mkFace.Face();
return result;
}
/* static */
std::vector<TopoDS_Edge> DrawGeomHatch::makeEdgeOverlay(HatchLine hl, Bnd_Box b, double scale)
{
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 interval = hl.getInterval() * scale;
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 DrawGeomHatch::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;
}
void DrawGeomHatch::getParameters(void)
{
//this is probably "/build/data/Mod/TechDraw/PAT"
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/PAT");

View File

@@ -29,6 +29,7 @@
#include <App/PropertyFile.h>
class TopoDS_Edge;
class TopoDS_Face;
class Bnd_Box;
namespace TechDrawGeometry
@@ -39,7 +40,7 @@ class BaseGeom;
namespace TechDraw
{
class DrawViewPart;
class HatchLine;
class PATLineSpec;
class LineSet;
class DashSet;
@@ -66,17 +67,21 @@ public:
DrawViewPart* getSourceView(void) const;
std::vector<LineSet> getDrawableLines(int i = 0);
static std::vector<LineSet> getDrawableLines(DrawViewPart* dvp, std::vector<LineSet> lineSets, int iface, double scale);
std::vector<LineSet> getFaceOverlay(int i = 0);
std::vector<LineSet> getTrimmedLines(int i = 0);
static std::vector<LineSet> getTrimmedLines(DrawViewPart* dvp, std::vector<LineSet> lineSets, int iface, double scale);
static std::vector<TopoDS_Edge> makeEdgeOverlay(HatchLine hl, Bnd_Box bBox, double scale);
static std::vector<TopoDS_Edge> makeEdgeOverlay(PATLineSpec hl, Bnd_Box bBox, double scale);
static TopoDS_Edge makeLine(Base::Vector3d s, Base::Vector3d e);
static std::vector<HatchLine> getDecodedSpecsFromFile(std::string fileSpec, std::string myPattern);
static std::vector<PATLineSpec> getDecodedSpecsFromFile(std::string fileSpec, std::string myPattern);
static TopoDS_Face extractFace(DrawViewPart* source, int iface );
protected:
void getParameters(void);
std::vector<HatchLine> getDecodedSpecsFromFile();
std::vector<PATLineSpec> getDecodedSpecsFromFile();
std::vector<LineSet> m_lineSets;
std::string m_saveFile;
std::string m_saveName;
private:
static App::PropertyFloatConstraint::Constraints scaleRange;

View File

@@ -539,7 +539,7 @@ Base::Vector3d DrawViewSection::getSectionVector (const std::string sectionName)
std::vector<LineSet> DrawViewSection::getDrawableLines(int i)
{
std::vector<LineSet> result;
result = DrawGeomHatch::getDrawableLines(this,m_lineSets,i,HatchScale.getValue());
result = DrawGeomHatch::getTrimmedLines(this,m_lineSets,i,HatchScale.getValue());
return result;
}

View File

@@ -30,7 +30,9 @@
#include <stdexcept>
#endif
#include <TopoDS_Vertex.hxx>
#include <TopoDS_Edge.hxx>
#include <TopExp.hxx>
#include <Base/Console.h>
#include <Base/Vector3D.h>
@@ -42,23 +44,80 @@
using namespace TechDraw;
HatchLine::HatchLine()
double LineSet::getMinX(void)
{
double xMin,yMin,zMin,xMax,yMax,zMax;
m_box.Get(xMin,yMin,zMin,xMax,yMax,zMax);
return xMin;
}
double LineSet::getMinY(void)
{
double xMin,yMin,zMin,xMax,yMax,zMax;
m_box.Get(xMin,yMin,zMin,xMax,yMax,zMax);
return yMin;
}
double LineSet::getMaxX(void)
{
double xMin,yMin,zMin,xMax,yMax,zMax;
m_box.Get(xMin,yMin,zMin,xMax,yMax,zMax);
return xMax;
}
double LineSet::getMaxY(void)
{
double xMin,yMin,zMin,xMax,yMax,zMax;
m_box.Get(xMin,yMin,zMin,xMax,yMax,zMax);
return yMax;
}
bool LineSet::isDashed(void)
{
bool result = m_hatchLine.isDashed();
return result;
}
//TODO: needs to incorporate deltaX parameter
//! calculates the apparent start point for dashed lines
Base::Vector3d LineSet::calcApparentStart(TechDrawGeometry::BaseGeom* g)
{
Base::Vector3d result;
Base::Vector3d start(g->getStartPoint().x,g->getStartPoint().y,0.0);
double angle = getPATLineSpec().getAngle();
if (angle == 0.0) { //horizontal
result = Base::Vector3d(getMinX(),start.y,0.0);
} else if ((angle == 90.0) ||
(angle == -90.0)) { //vertical
result = Base::Vector3d(start.x,getMinY(),0.0);
} else {
double slope = getPATLineSpec().getSlope();
double y = getMinY();
double x = ((y - start.y) / slope) + start.x;
result = Base::Vector3d(x,y,0);
}
return result;
}
//*******************************************
PATLineSpec::PATLineSpec()
{
init();
}
HatchLine::HatchLine(std::string& lineSpec)
PATLineSpec::PATLineSpec(std::string& lineSpec)
{
init();
load(lineSpec);
}
HatchLine::~HatchLine()
PATLineSpec::~PATLineSpec()
{
}
void HatchLine::init(void)
void PATLineSpec::init(void)
{
m_angle = 0.0;
m_origin = Base::Vector3d(0.0,0.0,0.0);
@@ -66,11 +125,11 @@ void HatchLine::init(void)
m_offset = 0.0;
}
void HatchLine::load(std::string& lineSpec)
void PATLineSpec::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() );
Base::Console().Message( "PATLineSpec::load(%s) invalid entry in pattern\n",lineSpec.c_str() );
return;
}
m_angle = values[0];
@@ -78,11 +137,13 @@ void HatchLine::load(std::string& lineSpec)
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> dash;
dash.insert(std::end(dash), std::begin(values) + 5, std::end(values));
m_dashParms = DashSpec(dash);
}
}
std::vector<double> HatchLine::split(std::string line)
std::vector<double> PATLineSpec::split(std::string line)
{
std::vector<double> result;
std::stringstream lineStream(line);
@@ -101,25 +162,26 @@ std::vector<double> HatchLine::split(std::string line)
return result;
}
void HatchLine::dump(char* title)
void PATLineSpec::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());
// std::stringstream ss;
// for (auto& d: m_dashParms) {
// ss << d << ", ";
// }
// ss << "end";
// Base::Console().Message( "DashSpec: %s\n",ss.str().c_str());
m_dashParms.dump("dashspec");
}
//static class methods
std::vector<HatchLine> HatchLine::getSpecsForPattern(std::string& parmFile, std::string& parmName)
std::vector<PATLineSpec> PATLineSpec::getSpecsForPattern(std::string& parmFile, std::string& parmName)
{
std::vector<HatchLine> result;
std::vector<PATLineSpec> result;
std::vector<std::string> lineSpecs;
std::ifstream inFile;
inFile.open (parmFile, std::ifstream::in);
@@ -137,15 +199,15 @@ std::vector<HatchLine> HatchLine::getSpecsForPattern(std::string& parmFile, std:
return result;
}
//decode definition lines into HatchLine objects
//decode definition lines into PATLineSpec objects
for (auto& l: lineSpecs) {
HatchLine hl(l);
PATLineSpec hl(l);
result.push_back(hl);
}
return result;
}
bool HatchLine::findPatternStart(std::ifstream& inFile, std::string& parmName)
bool PATLineSpec::findPatternStart(std::ifstream& inFile, std::string& parmName)
{
bool result = false;
while ( inFile.good() ){
@@ -176,7 +238,7 @@ bool HatchLine::findPatternStart(std::ifstream& inFile, std::string& parmName)
}
//get the definition lines for this pattern
std::vector<std::string> HatchLine::loadPatternDef(std::ifstream& inFile)
std::vector<std::string> PATLineSpec::loadPatternDef(std::ifstream& inFile)
{
std::vector<std::string> result;
while ( inFile.good() ){
@@ -196,7 +258,7 @@ std::vector<std::string> HatchLine::loadPatternDef(std::ifstream& inFile)
return result;
}
std::vector<std::string> HatchLine::getPatternList(std::string& parmFile)
std::vector<std::string> PATLineSpec::getPatternList(std::string& parmFile)
{
std::vector<std::string> result;
std::ifstream inFile;
@@ -225,6 +287,26 @@ std::vector<std::string> HatchLine::getPatternList(std::string& parmFile)
return result;
}
double PATLineSpec::getSlope(void)
{
double angle = 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);
}
double slope = tan(angle * M_PI/180.0);
return slope;
}
bool PATLineSpec::isDashed(void)
{
bool result = !m_dashParms.empty();
return result;
}
//********************************************************
void DashSpec::dump(char* title)
{

View File

@@ -19,6 +19,8 @@
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
//! HatchLine - Classes related to processing PAT files
#ifndef _TechDraw_HATCHLINE_H_
#define _TechDraw_HATCHLINE_H_
@@ -29,9 +31,12 @@
#include <vector>
#include <string>
#include <TopoDS_Edge.hxx>
#include <Bnd_Box.hxx>
#include <Base/Vector3D.h>
class TopoDS_Edge;
//class TopoDS_Edge;
//class Bnd_Box;
namespace TechDrawGeometry
{
@@ -43,15 +48,32 @@ namespace TechDraw
class DrawViewPart;
class DrawUtil;
//DashSpec is the parsed portion of a PATLineSpec related to mark/space/dot
class TechDrawExport 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();}
double length(void);
void dump(char* title);
private:
std::vector<double> m_parms;
};
// HatchLine is the result of parsing a line from PAT file into accessible parameters
// e /HatchLine/PATSpecLine/
class TechDrawExport HatchLine
//! PATLineSpec is the result of parsing a singleline from PAT file into accessible parameters
class TechDrawExport PATLineSpec
{
public:
HatchLine();
HatchLine(std::string& lineSpec);
~HatchLine();
PATLineSpec();
PATLineSpec(std::string& lineSpec);
~PATLineSpec();
void load(std::string& lineSpec);
@@ -61,10 +83,12 @@ public:
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 std::vector<PATLineSpec> 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);
bool isDashed(void);
void dump(char* title);
@@ -76,48 +100,45 @@ private:
Base::Vector3d m_origin;
double m_interval;
double m_offset;
std::vector<double> m_dashParms; //why isn't this a DashSpec object?
DashSpec m_dashParms;
};
// a LineSet is all the generated edges for 1 HatchLine for 1 Face
//! a LineSet is all the generated edges for 1 PATLineSpec for 1 Face
class TechDrawExport LineSet
{
public:
LineSet() {}
~LineSet() {}
void setHatchLine(HatchLine s) { m_hatchLine = s; }
void setPATLineSpec(PATLineSpec s) { m_hatchLine = s; }
void setEdges(std::vector<TopoDS_Edge> e) {m_edges = e;}
void setGeoms(std::vector<TechDrawGeometry::BaseGeom*> g) {m_geoms = g;}
void setBBox(Bnd_Box bb) {m_box = bb;}
HatchLine getHatchLine(void) { return m_hatchLine; }
std::vector<double> getDashSpec(void) { return m_hatchLine.getDashParms();}
PATLineSpec getPATLineSpec(void) { return m_hatchLine; }
double getOffset(void) { return m_hatchLine.getOffset(); }
double getAngle(void) { return m_hatchLine.getAngle(); }
DashSpec getDashSpec(void) { return m_hatchLine.getDashParms();}
std::vector<TopoDS_Edge> getEdges(void) { return m_edges; }
TopoDS_Edge getEdge(int i) {return m_edges.at(i);}
std::vector<TechDrawGeometry::BaseGeom*> getGeoms(void) { return m_geoms; }
//void clearGeom(void);
Base::Vector3d calcApparentStart(TechDrawGeometry::BaseGeom* g);
Bnd_Box getBBox(void) {return m_box;}
double getMinX(void);
double getMaxX(void);
double getMinY(void);
double getMaxY(void);
bool isDashed(void);
private:
std::vector<TopoDS_Edge> m_edges;
std::vector<TechDrawGeometry::BaseGeom*> m_geoms;
HatchLine m_hatchLine;
PATLineSpec m_hatchLine;
Bnd_Box m_box;
};
class TechDrawExport 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