diff --git a/src/Base/Builder3D.cpp b/src/Base/Builder3D.cpp index 617682a00..94a61c121 100644 --- a/src/Base/Builder3D.cpp +++ b/src/Base/Builder3D.cpp @@ -426,6 +426,17 @@ void InventorBuilder::endPoints(void) result << Base::blanks(indent) << "]" << std::endl; indent -= 2; result << Base::blanks(indent) << "}" << std::endl; +} + +/** + * Adds an SoPointSet node after creating an SoCordinate3 node with + * beginPoints() and endPoints(). + * @see startPoints() + * @see beginPoints() + * @see endPoints() + */ +void InventorBuilder::addPointSet(void) +{ result << Base::blanks(indent) << "PointSet { } " << std::endl; } diff --git a/src/Base/Builder3D.h b/src/Base/Builder3D.h index 0f2a2a359..0181790cf 100644 --- a/src/Base/Builder3D.h +++ b/src/Base/Builder3D.h @@ -164,6 +164,8 @@ public: void addPoint(const Vector3f &vec); /// ends the points set operation void endPoints(void); + /// add an SoPointSet node + void addPointSet(void); //@} /** @name Line/Direction handling */ diff --git a/src/Base/Vector3D.cpp b/src/Base/Vector3D.cpp index fbc197f55..03239a858 100644 --- a/src/Base/Vector3D.cpp +++ b/src/Base/Vector3D.cpp @@ -194,7 +194,7 @@ Vector3<_Precision>& Vector3<_Precision>::ProjToPlane (const Vector3<_Precision> const Vector3<_Precision> &rclNorm) { Vector3<_Precision> clTemp(rclNorm); - *this = *this - (clTemp *= ((*this - rclBase) * clTemp)); + *this = *this - (clTemp *= ((*this - rclBase) * clTemp) / clTemp.Sqr()); return *this; } @@ -202,7 +202,7 @@ template _Precision Vector3<_Precision>::DistanceToPlane (const Vector3<_Precision> &rclBase, const Vector3<_Precision> &rclNorm) const { - return (*this - rclBase) * rclNorm; + return ((*this - rclBase) * rclNorm) / rclNorm.Length(); } template @@ -361,7 +361,7 @@ template Vector3<_Precision> & Vector3<_Precision>::Normalize (void) { _Precision fLen = Length (); - if (fLen != 0.0f) { + if (fLen != (_Precision)0.0 && fLen != (_Precision)1.0) { x /= fLen; y /= fLen; z /= fLen; diff --git a/src/Base/VectorPy.xml b/src/Base/VectorPy.xml index 55d35848e..4171ac2a1 100644 --- a/src/Base/VectorPy.xml +++ b/src/Base/VectorPy.xml @@ -73,6 +73,11 @@ Deliver the distance of the point to a given line + + + Deliver the distance of the point to a given line segment + + Deliver the distance of the point to a given plane diff --git a/src/Base/VectorPyImp.cpp b/src/Base/VectorPyImp.cpp index ee19a947f..b5546ca7a 100644 --- a/src/Base/VectorPyImp.cpp +++ b/src/Base/VectorPyImp.cpp @@ -401,6 +401,31 @@ PyObject* VectorPy::distanceToLine(PyObject *args) return Py::new_reference_to(dist); } +PyObject* VectorPy::distanceToLineSegment(PyObject *args) +{ + PyObject *base, *line; + if (!PyArg_ParseTuple(args, "OO",&base, &line)) + return 0; + if (!PyObject_TypeCheck(base, &(VectorPy::Type))) { + PyErr_SetString(PyExc_TypeError, "First arg must be Vector"); + return 0; + } + if (!PyObject_TypeCheck(line, &(VectorPy::Type))) { + PyErr_SetString(PyExc_TypeError, "Second arg must be Vector"); + return 0; + } + + VectorPy* base_vec = static_cast(base); + VectorPy* line_vec = static_cast(line); + + VectorPy::PointerType this_ptr = reinterpret_cast(_pcTwinPointer); + VectorPy::PointerType base_ptr = reinterpret_cast(base_vec->_pcTwinPointer); + VectorPy::PointerType line_ptr = reinterpret_cast(line_vec->_pcTwinPointer); + + Vector3d v = this_ptr->DistanceToLineSegment(*base_ptr, *line_ptr); + return new VectorPy(v); +} + PyObject* VectorPy::distanceToPlane(PyObject *args) { PyObject *base, *line; diff --git a/src/Mod/Part/App/modelRefine.cpp b/src/Mod/Part/App/modelRefine.cpp index 1b66050c2..365641c6d 100644 --- a/src/Mod/Part/App/modelRefine.cpp +++ b/src/Mod/Part/App/modelRefine.cpp @@ -39,18 +39,15 @@ #include #include #include -#include #include #include #include -#include #include -#include #include -#include #include #include #include +#include #include "modelRefine.h" using namespace ModelRefine; @@ -118,49 +115,6 @@ namespace ModelRefine }; } -void BoundaryEdgeSplitter::split(const EdgeVectorType &edgesIn) -{ - std::list edges; - std::copy(edgesIn.begin(), edgesIn.end(), back_inserter(edges)); - while(!edges.empty()) - { - TopoDS_Vertex destination = TopExp::FirstVertex(edges.front(), Standard_True); - TopoDS_Vertex lastVertex = TopExp::LastVertex(edges.front(), Standard_True); - EdgeVectorType boundary; - boundary.push_back(edges.front()); - edges.pop_front(); - //single edge closed check. - if (destination.IsSame(lastVertex)) - { - groupedEdges.push_back(boundary); - continue; - } - - bool closedSignal(false); - std::list::iterator it; - for (it = edges.begin(); it != edges.end();) - { - TopoDS_Vertex currentVertex = TopExp::FirstVertex(*it, Standard_True); - if (lastVertex.IsSame(currentVertex)) - { - boundary.push_back(*it); - lastVertex = TopExp::LastVertex(*it, Standard_True); - edges.erase(it); - it = edges.begin(); - if (lastVertex.IsSame(destination)) - { - closedSignal = true; - break; - } - continue; - } - ++it; - } - if (closedSignal) - groupedEdges.push_back(boundary); - } -} - //////////////////////////////////////////////////////////////////////////////////////////// void FaceTypeSplitter::addShell(const TopoDS_Shell &shellIn) @@ -319,6 +273,53 @@ GeomAbs_SurfaceType FaceTypedBase::getFaceType(const TopoDS_Face &faceIn) return surfaceTest.GetType(); } +void FaceTypedBase::boundarySplit(const FaceVectorType &facesIn, std::vector &boundariesOut) const +{ + EdgeVectorType bEdges; + boundaryEdges(facesIn, bEdges); + + std::list edges; + std::copy(bEdges.begin(), bEdges.end(), back_inserter(edges)); + while(!edges.empty()) + { + TopoDS_Vertex destination = TopExp::FirstVertex(edges.front(), Standard_True); + TopoDS_Vertex lastVertex = TopExp::LastVertex(edges.front(), Standard_True); + EdgeVectorType boundary; + boundary.push_back(edges.front()); + edges.pop_front(); + //single edge closed check. + if (destination.IsSame(lastVertex)) + { + boundariesOut.push_back(boundary); + continue; + } + + bool closedSignal(false); + std::list::iterator it; + for (it = edges.begin(); it != edges.end();) + { + TopoDS_Vertex currentVertex = TopExp::FirstVertex(*it, Standard_True); + if (lastVertex.IsSame(currentVertex)) + { + boundary.push_back(*it); + lastVertex = TopExp::LastVertex(*it, Standard_True); + edges.erase(it); + it = edges.begin(); + if (lastVertex.IsSame(destination)) + { + closedSignal = true; + break; + } + continue; + } + ++it; + } + if (closedSignal) + boundariesOut.push_back(boundary); + } +} + + /////////////////////////////////////////////////////////////////////////////////////////////////////// FaceTypedPlane::FaceTypedPlane() : FaceTypedBase(GeomAbs_Plane) @@ -344,15 +345,10 @@ GeomAbs_SurfaceType FaceTypedPlane::getType() const TopoDS_Face FaceTypedPlane::buildFace(const FaceVectorType &faces) const { - EdgeVectorType bEdges; - boundaryEdges(faces, bEdges); - - BoundaryEdgeSplitter bSplitter; - bSplitter.split(bEdges); - std::vector wires; - std::vector splitEdges = bSplitter.getGroupedEdges(); + std::vector splitEdges; + this->boundarySplit(faces, splitEdges); if (splitEdges.empty()) return TopoDS_Face(); std::vector::iterator splitIt; @@ -424,8 +420,111 @@ GeomAbs_SurfaceType FaceTypedCylinder::getType() const TopoDS_Face FaceTypedCylinder::buildFace(const FaceVectorType &faces) const { - //to do. - return TopoDS_Face(); + std::vector boundaries; + boundarySplit(faces, boundaries); + static TopoDS_Face dummy; + if (boundaries.size() < 1) + return dummy; + + //take one face and remove all the wires. + TopoDS_Face workFace = faces.at(0); + ShapeBuild_ReShape reshaper; + TopExp_Explorer it; + for (it.Init(workFace, TopAbs_WIRE); it.More(); it.Next()) + reshaper.Remove(it.Current()); + workFace = TopoDS::Face(reshaper.Apply(workFace)); + if (workFace.IsNull()) + return TopoDS_Face(); + + ShapeFix_Face faceFixer(workFace); + + //makes wires + std::vector::iterator boundaryIt; + for (boundaryIt = boundaries.begin(); boundaryIt != boundaries.end(); ++boundaryIt) + { + BRepLib_MakeWire wireMaker; + EdgeVectorType::iterator it; + for (it = (*boundaryIt).begin(); it != (*boundaryIt).end(); ++it) + wireMaker.Add(*it); + if (wireMaker.Error() != BRepLib_WireDone) + continue; + faceFixer.Add(wireMaker.Wire()); + } + if (faceFixer.Perform() > ShapeExtend_DONE5) + return TopoDS_Face(); + return faceFixer.Face(); +} + +void FaceTypedCylinder::boundarySplit(const FaceVectorType &facesIn, std::vector &boundariesOut) const +{ + //get all the seam edges + EdgeVectorType seamEdges; + FaceVectorType::const_iterator faceIt; + for (faceIt = facesIn.begin(); faceIt != facesIn.end(); ++faceIt) + { + TopExp_Explorer explorer; + for (explorer.Init(*faceIt, TopAbs_EDGE); explorer.More(); explorer.Next()) + { + ShapeAnalysis_Edge edgeCheck; + if(edgeCheck.IsSeam(TopoDS::Edge(explorer.Current()), *faceIt)) + seamEdges.push_back(TopoDS::Edge(explorer.Current())); + } + } + + //normal edges. + EdgeVectorType normalEdges; + ModelRefine::boundaryEdges(facesIn, normalEdges); + + //put seam edges in front.the idea is that we always want to traverse along a seam edge if possible. + std::list sortedEdges; + std::copy(normalEdges.begin(), normalEdges.end(), back_inserter(sortedEdges)); + std::copy(seamEdges.begin(), seamEdges.end(), front_inserter(sortedEdges)); + + while (!sortedEdges.empty()) + { + //detecting closed boundary works best if we start off of the seam edges. + TopoDS_Vertex destination = TopExp::FirstVertex(sortedEdges.back(), Standard_True); + TopoDS_Vertex lastVertex = TopExp::LastVertex(sortedEdges.back(), Standard_True); + bool closedSignal(false); + std::list boundary; + boundary.push_back(sortedEdges.back()); + sortedEdges.pop_back(); + + std::list::iterator sortedIt; + for (sortedIt = sortedEdges.begin(); sortedIt != sortedEdges.end();) + { + TopoDS_Vertex currentVertex = TopExp::FirstVertex(*sortedIt, Standard_True); + + //Seam edges lie on top of each other. i.e. same. and we remove every match from the list + //so we don't actually ever compare the same edge. + if ((*sortedIt).IsSame(boundary.back())) + { + ++sortedIt; + continue; + } + if (lastVertex.IsSame(currentVertex)) + { + boundary.push_back(*sortedIt); + lastVertex = TopExp::LastVertex(*sortedIt, Standard_True); + if (lastVertex.IsSame(destination)) + { + closedSignal = true; + sortedEdges.erase(sortedIt); + break; + } + sortedEdges.erase(sortedIt); + sortedIt = sortedEdges.begin(); + continue; + } + ++sortedIt; + } + if (closedSignal) + { + EdgeVectorType temp; + std::copy(boundary.begin(), boundary.end(), std::back_inserter(temp)); + boundariesOut.push_back(temp); + } + } } FaceTypedCylinder& ModelRefine::getCylinderObject() @@ -446,7 +545,7 @@ bool FaceUniter::process() if (workShell.IsNull()) return false; typeObjects.push_back(&getPlaneObject()); -// typeObjects.push_back(&getCylinderObject()); + typeObjects.push_back(&getCylinderObject()); //add more face types. ModelRefine::FaceTypeSplitter splitter; diff --git a/src/Mod/Part/App/modelRefine.h b/src/Mod/Part/App/modelRefine.h index c008b3053..ed1267f98 100644 --- a/src/Mod/Part/App/modelRefine.h +++ b/src/Mod/Part/App/modelRefine.h @@ -61,6 +61,7 @@ namespace ModelRefine static GeomAbs_SurfaceType getFaceType(const TopoDS_Face &faceIn); protected: + virtual void boundarySplit(const FaceVectorType &facesIn, std::vector &boundariesOut) const; GeomAbs_SurfaceType surfaceType; }; @@ -85,6 +86,9 @@ namespace ModelRefine virtual GeomAbs_SurfaceType getType() const; virtual TopoDS_Face buildFace(const FaceVectorType &faces) const; friend FaceTypedCylinder& getCylinderObject(); + + protected: + virtual void boundarySplit(const FaceVectorType &facesIn, std::vector &boundariesOut) const; }; FaceTypedCylinder& getCylinderObject(); @@ -134,17 +138,6 @@ namespace ModelRefine std::vector equalityVector; }; - class BoundaryEdgeSplitter - { - public: - BoundaryEdgeSplitter(){} - void split(const EdgeVectorType &edgesIn); - const std::vector& getGroupedEdges(){return groupedEdges;} - - private: - std::vector groupedEdges; - }; - class FaceUniter { private: diff --git a/src/Mod/Points/App/PointsPyImp.cpp b/src/Mod/Points/App/PointsPyImp.cpp index e596a45e6..75df742c8 100644 --- a/src/Mod/Points/App/PointsPyImp.cpp +++ b/src/Mod/Points/App/PointsPyImp.cpp @@ -120,6 +120,7 @@ PyObject* PointsPy::writeInventor(PyObject * args) for (Points::PointKernel::const_iterator it = kernel->begin(); it != kernel->end(); ++it) builder.addPoint((float)it->x,(float)it->y,(float)it->z); builder.endPoints(); + builder.addPointSet(); builder.close(); return Py::new_reference_to(Py::String(result.str())); diff --git a/src/Mod/Sketcher/Gui/SketchOrientationDialog.cpp b/src/Mod/Sketcher/Gui/SketchOrientationDialog.cpp index d9e7872dd..22f7576bc 100644 --- a/src/Mod/Sketcher/Gui/SketchOrientationDialog.cpp +++ b/src/Mod/Sketcher/Gui/SketchOrientationDialog.cpp @@ -23,9 +23,11 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include #endif +#include #include #include @@ -34,9 +36,16 @@ using namespace SketcherGui; -SketchOrientationDialog::SketchOrientationDialog(void) +SketchOrientationDialog::SketchOrientationDialog(void) + : QDialog(Gui::getMainWindow()), ui(new Ui_SketchOrientationDialog) { + ui->setupUi(this); + onPreview(); + connect(ui->Reverse_checkBox, SIGNAL(clicked(bool)), this, SLOT(onPreview())); + connect(ui->XY_radioButton , SIGNAL(clicked(bool)), this, SLOT(onPreview())); + connect(ui->XZ_radioButton , SIGNAL(clicked(bool)), this, SLOT(onPreview())); + connect(ui->YZ_radioButton , SIGNAL(clicked(bool)), this, SLOT(onPreview())); } SketchOrientationDialog::~SketchOrientationDialog() @@ -44,51 +53,70 @@ SketchOrientationDialog::~SketchOrientationDialog() } -int SketchOrientationDialog::exec() +void SketchOrientationDialog::accept() { - //Gui::MDIView *mdi = Gui::Application::Instance->activeDocument()->getActiveView(); - //Gui::View3DInventorViewer *viewer = static_cast(mdi)->getViewer(); - - QDialog dlg(Gui::getMainWindow()); - - Ui::SketchOrientationDialog ui_SketchOrientationDialog; - ui_SketchOrientationDialog.setupUi(&dlg); - - int res; - if (res=dlg.exec()) { - double offset = ui_SketchOrientationDialog.Offset_doubleSpinBox->value(); - bool reverse = ui_SketchOrientationDialog.Reverse_checkBox->isChecked(); - if (ui_SketchOrientationDialog.XY_radioButton->isChecked()) { - if (reverse) { - Pos = Base::Placement(Base::Vector3d(0,0,offset),Base::Rotation(-1.0,0.0,0.0,0.0)); - DirType = 1; - } - else { - Pos = Base::Placement(Base::Vector3d(0,0,offset),Base::Rotation()); - DirType = 0; - } + double offset = ui->Offset_doubleSpinBox->value(); + bool reverse = ui->Reverse_checkBox->isChecked(); + if (ui->XY_radioButton->isChecked()) { + if (reverse) { + Pos = Base::Placement(Base::Vector3d(0,0,offset),Base::Rotation(-1.0,0.0,0.0,0.0)); + DirType = 1; } - else if (ui_SketchOrientationDialog.XZ_radioButton->isChecked()) { - if (reverse) { - Pos = Base::Placement(Base::Vector3d(0,offset,0),Base::Rotation(Base::Vector3d(0,sqrt(2.0)/2.0,sqrt(2.0)/2.0),M_PI)); - DirType = 3; - } - else { - Pos = Base::Placement(Base::Vector3d(0,offset,0),Base::Rotation(Base::Vector3d(-1,0,0),1.5*M_PI)); - DirType = 2; - } + else { + Pos = Base::Placement(Base::Vector3d(0,0,offset),Base::Rotation()); + DirType = 0; } - else if (ui_SketchOrientationDialog.YZ_radioButton->isChecked()) { - if (reverse) { - Pos = Base::Placement(Base::Vector3d(offset,0,0),Base::Rotation(-0.5,0.5,0.5,-0.5)); - DirType = 5; - } - else { - Pos = Base::Placement(Base::Vector3d(offset,0,0),Base::Rotation(0.5,0.5,0.5,0.5)); - DirType = 4; - } + } + else if (ui->XZ_radioButton->isChecked()) { + if (reverse) { + Pos = Base::Placement(Base::Vector3d(0,offset,0),Base::Rotation(Base::Vector3d(0,sqrt(2.0)/2.0,sqrt(2.0)/2.0),M_PI)); + DirType = 3; + } + else { + Pos = Base::Placement(Base::Vector3d(0,offset,0),Base::Rotation(Base::Vector3d(-1,0,0),1.5*M_PI)); + DirType = 2; + } + } + else if (ui->YZ_radioButton->isChecked()) { + if (reverse) { + Pos = Base::Placement(Base::Vector3d(offset,0,0),Base::Rotation(-0.5,0.5,0.5,-0.5)); + DirType = 5; + } + else { + Pos = Base::Placement(Base::Vector3d(offset,0,0),Base::Rotation(0.5,0.5,0.5,0.5)); + DirType = 4; } } - return res; + QDialog::accept(); } + +void SketchOrientationDialog::onPreview() +{ + std::string icon; + bool reverse = ui->Reverse_checkBox->isChecked(); + if (ui->XY_radioButton->isChecked()) { + if (reverse) + icon = "view-bottom"; + else + icon = "view-top"; + } + else if (ui->XZ_radioButton->isChecked()) { + if (reverse) + icon = "view-rear"; + else + icon = "view-front"; + } + else if (ui->YZ_radioButton->isChecked()) { + if (reverse) + icon = "view-left"; + else + icon = "view-right"; + } + + ui->previewLabel->setPixmap( + Gui::BitmapFactory().pixmapFromSvg(icon.c_str(), + ui->previewLabel->size())); +} + +#include "moc_SketchOrientationDialog.cpp" diff --git a/src/Mod/Sketcher/Gui/SketchOrientationDialog.h b/src/Mod/Sketcher/Gui/SketchOrientationDialog.h index 0dd3cf070..4865ee7bd 100644 --- a/src/Mod/Sketcher/Gui/SketchOrientationDialog.h +++ b/src/Mod/Sketcher/Gui/SketchOrientationDialog.h @@ -24,20 +24,31 @@ #define SKETCHERGUI_SketchOrientationDialog_H #include +#include namespace SketcherGui { -class SketchOrientationDialog { +class Ui_SketchOrientationDialog; +class SketchOrientationDialog : public QDialog +{ + Q_OBJECT + public: SketchOrientationDialog(void); ~SketchOrientationDialog(); - int exec(); - Base::Placement Pos; int DirType; - + + void accept(); + +protected Q_SLOTS: + void onPreview(); + +private: + Ui_SketchOrientationDialog* ui; }; } + #endif // SKETCHERGUI_SketchOrientationDialog_H diff --git a/src/Mod/Sketcher/Gui/SketchOrientationDialog.ui b/src/Mod/Sketcher/Gui/SketchOrientationDialog.ui index d8b55e229..dd0e5f69c 100644 --- a/src/Mod/Sketcher/Gui/SketchOrientationDialog.ui +++ b/src/Mod/Sketcher/Gui/SketchOrientationDialog.ui @@ -1,7 +1,7 @@ - SketchOrientationDialog - + SketcherGui::SketchOrientationDialog + 0 @@ -13,8 +13,8 @@ Choose orientation - - + + Sketch orientation @@ -47,14 +47,33 @@ - + + + + + 48 + 48 + + + + + 48 + 48 + + + + Preview + + + + Reverse direction - + @@ -81,7 +100,7 @@ - + Qt::Horizontal @@ -98,7 +117,7 @@ buttonBox accepted() - SketchOrientationDialog + SketcherGui::SketchOrientationDialog accept() @@ -114,7 +133,7 @@ buttonBox rejected() - SketchOrientationDialog + SketcherGui::SketchOrientationDialog reject()