Merge branch 'master' into sketcherMoveColorsToPrefs
This commit is contained in:
+1
-1
@@ -7,7 +7,7 @@
|
||||
- [Install Xcode Command line tools](#install-xcode-cli-tools)
|
||||
- [Install Conda](#install-conda)
|
||||
- [Run the shell script](#run-the-shell-script)
|
||||
- [Building FreeCAD on macOS using homebrew packages with & without formual file](#homebrew-build-fc-on-macos)
|
||||
- [Building FreeCAD on macOS using homebrew packages with & without formula file](#homebrew-build-fc-on-macos)
|
||||
- [Requirements](#homebrew-requirements)
|
||||
- [Install required FreeCAD dependencies](#homebrew-install-required-deps)
|
||||
- [Limitations of using freecad formula file](#homebrew-limits-of-formula-file)
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
#include <NCollection_Map.hxx>
|
||||
#include <Standard_ErrorHandler.hxx>
|
||||
#include <Standard_ProgramError.hxx>
|
||||
#include <Standard_Version.hxx>
|
||||
#include <TColStd_MapOfInteger.hxx>
|
||||
#include <TopExp.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
@@ -700,7 +701,13 @@ double NETGENPlugin_Mesher::GetDefaultMinSize(const TopoDS_Shape& geom,
|
||||
BRep_Tool::Triangulation ( TopoDS::Face( fExp.Current() ), loc);
|
||||
if ( triangulation.IsNull() ) continue;
|
||||
const double fTol = BRep_Tool::Tolerance( TopoDS::Face( fExp.Current() ));
|
||||
#if OCC_VERSION_HEX < 0x070600
|
||||
const TColgp_Array1OfPnt& points = triangulation->Nodes();
|
||||
#else
|
||||
auto points = [&triangulation](Standard_Integer index) {
|
||||
return triangulation->Node(index);
|
||||
};
|
||||
#endif
|
||||
const Poly_Array1OfTriangle& trias = triangulation->Triangles();
|
||||
for ( int iT = trias.Lower(); iT <= trias.Upper(); ++iT )
|
||||
{
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@
|
||||
|
||||
#include <GEOMUtils.hxx>
|
||||
|
||||
#undef _Precision_HeaderFile
|
||||
//#undef _Precision_HeaderFile
|
||||
#include <BRepBndLib.hxx>
|
||||
#include <BRepPrimAPI_MakeBox.hxx>
|
||||
#include <Bnd_Box.hxx>
|
||||
|
||||
+5
-2
@@ -38,10 +38,13 @@
|
||||
#include <GC_MakeSegment.hxx>
|
||||
#include <GeomAPI_ExtremaCurveCurve.hxx>
|
||||
#include <Geom_Line.hxx>
|
||||
#include <IntAna_IntConicQuad.hxx>
|
||||
#include <IntAna_Quadric.hxx>
|
||||
#include <gp_Cone.hxx>
|
||||
#include <gp_Cylinder.hxx>
|
||||
#include <gp_Lin.hxx>
|
||||
#include <gp_Pln.hxx>
|
||||
#include <gp_Sphere.hxx>
|
||||
#include <IntAna_IntConicQuad.hxx>
|
||||
#include <IntAna_Quadric.hxx>
|
||||
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include <Poly_Array1OfTriangle.hxx>
|
||||
#include <Poly_PolygonOnTriangulation.hxx>
|
||||
#include <Poly_Triangulation.hxx>
|
||||
#include <Standard_Version.hxx>
|
||||
#include <TColgp_Array1OfPnt.hxx>
|
||||
#include <TopExp.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
@@ -318,13 +319,26 @@ namespace // internal utils
|
||||
{
|
||||
myFaceTol = SMESH_MesherHelper::MaxTolerance( face );
|
||||
myTree = triaTree;
|
||||
#if OCC_VERSION_HEX < 0x070600
|
||||
myNodes = & tr->Nodes();
|
||||
#else
|
||||
TColgp_Array1OfPnt* trNodes = new TColgp_Array1OfPnt( 1, tr->NbNodes() );
|
||||
for (Standard_Integer i = myNodes->Lower(); i <= myNodes->Upper(); i++)
|
||||
{
|
||||
trNodes->SetValue(i, tr->Node(i));
|
||||
}
|
||||
myNodes = trNodes;
|
||||
myOwnNodes = true;
|
||||
#endif
|
||||
myPolyTrias = & tr->Triangles();
|
||||
myTriasDeflection = tr->Deflection();
|
||||
if ( !loc.IsIdentity() ) // transform nodes if necessary
|
||||
{
|
||||
TColgp_Array1OfPnt* trsfNodes = new TColgp_Array1OfPnt( myNodes->Lower(), myNodes->Upper() );
|
||||
trsfNodes->Assign( *myNodes );
|
||||
#if OCC_VERSION_HEX >= 0x070600
|
||||
delete myNodes; // it's already a copy
|
||||
#endif
|
||||
myNodes = trsfNodes;
|
||||
myOwnNodes = true;
|
||||
const gp_Trsf& trsf = loc;
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
#include <Geom_Surface.hxx>
|
||||
#include <NCollection_DefineArray2.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <Quantity_Parameter.hxx>
|
||||
#include <Standard_Real.hxx>
|
||||
#include <TColStd_SequenceOfInteger.hxx>
|
||||
#include <TColStd_SequenceOfReal.hxx>
|
||||
#include <TColgp_SequenceOfXY.hxx>
|
||||
|
||||
@@ -44,7 +44,10 @@
|
||||
#include "SMESH_subMeshEventListener.hxx"
|
||||
#include "StdMeshers_FaceSide.hxx"
|
||||
|
||||
#include <Standard_Version.hxx>
|
||||
#if OCC_VERSION_HEX < 0x070600
|
||||
#include <Adaptor3d_HSurface.hxx>
|
||||
#endif
|
||||
#include <BRepAdaptor_Curve2d.hxx>
|
||||
#include <BRepAdaptor_Surface.hxx>
|
||||
#include <BRepLProp_SLProps.hxx>
|
||||
@@ -1340,8 +1343,13 @@ namespace VISCOUS_3D
|
||||
//case GeomAbs_SurfaceOfExtrusion:
|
||||
case GeomAbs_OffsetSurface:
|
||||
{
|
||||
#if OCC_VERSION_HEX < 0x070600
|
||||
Handle(Adaptor3d_HSurface) base = surface.BasisSurface();
|
||||
return getRovolutionAxis( base->Surface(), axis );
|
||||
#else
|
||||
Handle(Adaptor3d_Surface) base = surface.BasisSurface();
|
||||
return getRovolutionAxis( *base, axis );
|
||||
#endif
|
||||
}
|
||||
default: return false;
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ Base::Placement ComplexGeoData::getPlacement() const
|
||||
Base::Rotation(mat));
|
||||
}
|
||||
|
||||
void ComplexGeoData::getLinesFromSubelement(const Segment*,
|
||||
void ComplexGeoData::getLinesFromSubElement(const Segment*,
|
||||
std::vector<Base::Vector3d> &Points,
|
||||
std::vector<Line> &lines) const
|
||||
{
|
||||
@@ -105,7 +105,7 @@ void ComplexGeoData::getLinesFromSubelement(const Segment*,
|
||||
(void)lines;
|
||||
}
|
||||
|
||||
void ComplexGeoData::getFacesFromSubelement(const Segment*,
|
||||
void ComplexGeoData::getFacesFromSubElement(const Segment*,
|
||||
std::vector<Base::Vector3d> &Points,
|
||||
std::vector<Base::Vector3d> &PointNormals,
|
||||
std::vector<Facet> &faces) const
|
||||
|
||||
@@ -85,12 +85,12 @@ public:
|
||||
/// get subelement by combined name
|
||||
virtual Segment* getSubElementByName(const char* Name) const;
|
||||
/** Get lines from segment */
|
||||
virtual void getLinesFromSubelement(
|
||||
virtual void getLinesFromSubElement(
|
||||
const Segment*,
|
||||
std::vector<Base::Vector3d> &Points,
|
||||
std::vector<Line> &lines) const;
|
||||
/** Get faces from segment */
|
||||
virtual void getFacesFromSubelement(
|
||||
virtual void getFacesFromSubElement(
|
||||
const Segment*,
|
||||
std::vector<Base::Vector3d> &Points,
|
||||
std::vector<Base::Vector3d> &PointNormals,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
Name="ComplexGeoDataPy"
|
||||
Twin="ComplexGeoData"
|
||||
Include="App/ComplexGeoData.h"
|
||||
TwinPointer="ComplexGeoData"
|
||||
TwinPointer="ComplexGeoData"
|
||||
Namespace="Data"
|
||||
FatherInclude="Base/PersistencePy.h"
|
||||
FatherNamespace="Base"
|
||||
@@ -14,34 +14,79 @@
|
||||
<Author Licence="LGPL" Name="Juergen Riegel" EMail="[email protected]" />
|
||||
<UserDocu>Father of all complex geometric data types</UserDocu>
|
||||
</Documentation>
|
||||
<Methode Name="getFacesFromSubelement" Const="true">
|
||||
<Methode Name="getElementTypes" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Return a list of element types</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="countSubElements" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Return the number of elements of a type</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="getFacesFromSubElement" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Return vertexes and faces from a sub-element</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Attribute Name="BoundBox" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Get the BoundBox of the object</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="BoundBox" Type="Object" />
|
||||
</Attribute>
|
||||
<Attribute Name="Placement" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Get the current transformation of the object as placement</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Placement" Type="Object" />
|
||||
</Attribute>
|
||||
<Attribute Name="Matrix" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Get the current transformation of the object as matrix</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Matrix" Type="Object" />
|
||||
</Attribute>
|
||||
<Attribute Name="Tag">
|
||||
<Documentation>
|
||||
<UserDocu>Geometry Tag</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Tag" Type="Int"/>
|
||||
</Attribute>
|
||||
<Methode Name="getLinesFromSubElement" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Return vertexes and lines from a sub-element</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="getPoints" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Return a tuple of points and normals with a given accuracy</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="getLines" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Return a tuple of points and lines with a given accuracy</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="getFaces" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Return a tuple of points and triangles with a given accuracy</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="applyTranslation">
|
||||
<Documentation>
|
||||
<UserDocu>Apply an additional translation to the placement</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="applyRotation">
|
||||
<Documentation>
|
||||
<UserDocu>Apply an additional rotation to the placement</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="transformGeometry">
|
||||
<Documentation>
|
||||
<UserDocu>Apply a transformation to the underlying geometry</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Attribute Name="BoundBox" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Get the BoundBox of the object</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="BoundBox" Type="Object" />
|
||||
</Attribute>
|
||||
<Attribute Name="CenterOfGravity" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Get the center of gravity</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="CenterOfGravity" Type="Object" />
|
||||
</Attribute>
|
||||
<Attribute Name="Placement" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Get the current transformation of the object as placement</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Placement" Type="Object" />
|
||||
</Attribute>
|
||||
<Attribute Name="Tag">
|
||||
<Documentation>
|
||||
<UserDocu>Geometry Tag</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Tag" Type="Int"/>
|
||||
</Attribute>
|
||||
</PythonExport>
|
||||
</GenerateModel>
|
||||
|
||||
+264
-36
@@ -22,6 +22,9 @@
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <memory>
|
||||
#endif
|
||||
|
||||
#include "ComplexGeoData.h"
|
||||
|
||||
@@ -38,29 +41,195 @@ using namespace Data;
|
||||
using namespace Base;
|
||||
|
||||
// returns a string which represent the object e.g. when printed in python
|
||||
std::string ComplexGeoDataPy::representation(void) const
|
||||
std::string ComplexGeoDataPy::representation() const
|
||||
{
|
||||
return std::string("<ComplexGeoData object>");
|
||||
}
|
||||
|
||||
PyObject* ComplexGeoDataPy::getFacesFromSubelement(PyObject *args)
|
||||
PyObject* ComplexGeoDataPy::getElementTypes(PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return nullptr;
|
||||
|
||||
std::vector<const char*> types = getComplexGeoDataPtr()->getElementTypes();
|
||||
Py::List list;
|
||||
for (auto it : types) {
|
||||
list.append(Py::String(it));
|
||||
}
|
||||
return Py::new_reference_to(list);
|
||||
}
|
||||
|
||||
PyObject* ComplexGeoDataPy::countSubElements(PyObject *args)
|
||||
{
|
||||
char *type;
|
||||
int index;
|
||||
if (!PyArg_ParseTuple(args, "si", &type, &index))
|
||||
return 0;
|
||||
if (!PyArg_ParseTuple(args, "s", &type))
|
||||
return nullptr;
|
||||
|
||||
try {
|
||||
unsigned long count = getComplexGeoDataPtr()->countSubElements(type);
|
||||
return Py::new_reference_to(Py::Long(count));
|
||||
}
|
||||
catch (...) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "failed to count sub-elements from object");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
PyObject* ComplexGeoDataPy::getFacesFromSubElement(PyObject *args)
|
||||
{
|
||||
char *type;
|
||||
unsigned long index;
|
||||
if (!PyArg_ParseTuple(args, "sk", &type, &index))
|
||||
return nullptr;
|
||||
|
||||
std::vector<Base::Vector3d> points;
|
||||
std::vector<Base::Vector3d> normals;
|
||||
std::vector<Data::ComplexGeoData::Facet> facets;
|
||||
try {
|
||||
Data::Segment* segm = getComplexGeoDataPtr()->getSubElement(type, index);
|
||||
getComplexGeoDataPtr()->getFacesFromSubelement(segm, points, normals, facets);
|
||||
delete segm;
|
||||
std::unique_ptr<Data::Segment> segm(getComplexGeoDataPtr()->getSubElement(type, index));
|
||||
getComplexGeoDataPtr()->getFacesFromSubElement(segm.get(), points, normals, facets);
|
||||
}
|
||||
catch (...) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "failed to get sub-element from object");
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Py::Tuple tuple(2);
|
||||
Py::List vertex;
|
||||
for (std::vector<Base::Vector3d>::const_iterator it = points.begin();
|
||||
it != points.end(); ++it)
|
||||
vertex.append(Py::asObject(new Base::VectorPy(*it)));
|
||||
tuple.setItem(0, vertex);
|
||||
Py::List facet;
|
||||
for (std::vector<Data::ComplexGeoData::Facet>::const_iterator
|
||||
it = facets.begin(); it != facets.end(); ++it) {
|
||||
Py::Tuple f(3);
|
||||
f.setItem(0,Py::Int(int(it->I1)));
|
||||
f.setItem(1,Py::Int(int(it->I2)));
|
||||
f.setItem(2,Py::Int(int(it->I3)));
|
||||
facet.append(f);
|
||||
}
|
||||
tuple.setItem(1, facet);
|
||||
return Py::new_reference_to(tuple);
|
||||
}
|
||||
|
||||
PyObject* ComplexGeoDataPy::getLinesFromSubElement(PyObject *args)
|
||||
{
|
||||
char *type;
|
||||
int index;
|
||||
if (!PyArg_ParseTuple(args, "si", &type, &index))
|
||||
return nullptr;
|
||||
|
||||
std::vector<Base::Vector3d> points;
|
||||
std::vector<Data::ComplexGeoData::Line> lines;
|
||||
try {
|
||||
std::unique_ptr<Data::Segment> segm(getComplexGeoDataPtr()->getSubElement(type, index));
|
||||
getComplexGeoDataPtr()->getLinesFromSubElement(segm.get(), points, lines);
|
||||
}
|
||||
catch (...) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "failed to get sub-element from object");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Py::Tuple tuple(2);
|
||||
Py::List vertex;
|
||||
for (std::vector<Base::Vector3d>::const_iterator it = points.begin();
|
||||
it != points.end(); ++it)
|
||||
vertex.append(Py::asObject(new Base::VectorPy(*it)));
|
||||
tuple.setItem(0, vertex);
|
||||
Py::List line;
|
||||
for (std::vector<Data::ComplexGeoData::Line>::const_iterator
|
||||
it = lines.begin(); it != lines.end(); ++it) {
|
||||
Py::Tuple l(2);
|
||||
l.setItem(0,Py::Int((int)it->I1));
|
||||
l.setItem(1,Py::Int((int)it->I2));
|
||||
line.append(l);
|
||||
}
|
||||
tuple.setItem(1, line);
|
||||
return Py::new_reference_to(tuple);
|
||||
}
|
||||
|
||||
PyObject* ComplexGeoDataPy::getPoints(PyObject *args)
|
||||
{
|
||||
double accuracy = 0.05;
|
||||
if (!PyArg_ParseTuple(args, "d", &accuracy))
|
||||
return nullptr;
|
||||
|
||||
std::vector<Base::Vector3d> points;
|
||||
std::vector<Base::Vector3d> normals;
|
||||
try {
|
||||
getComplexGeoDataPtr()->getPoints(points, normals, accuracy);
|
||||
}
|
||||
catch (...) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "failed to get sub-element from object");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Py::Tuple tuple(2);
|
||||
Py::List vertex;
|
||||
for (std::vector<Base::Vector3d>::const_iterator it = points.begin();
|
||||
it != points.end(); ++it) {
|
||||
vertex.append(Py::asObject(new Base::VectorPy(*it)));
|
||||
}
|
||||
tuple.setItem(0, vertex);
|
||||
|
||||
Py::List normal;
|
||||
for (std::vector<Base::Vector3d>::const_iterator it = normals.begin();
|
||||
it != normals.end(); ++it) {
|
||||
vertex.append(Py::asObject(new Base::VectorPy(*it)));
|
||||
}
|
||||
tuple.setItem(1, normal);
|
||||
return Py::new_reference_to(tuple);
|
||||
}
|
||||
|
||||
PyObject* ComplexGeoDataPy::getLines(PyObject *args)
|
||||
{
|
||||
double accuracy = 0.05;
|
||||
if (!PyArg_ParseTuple(args, "d", &accuracy))
|
||||
return nullptr;
|
||||
|
||||
std::vector<Base::Vector3d> points;
|
||||
std::vector<Data::ComplexGeoData::Line> lines;
|
||||
try {
|
||||
getComplexGeoDataPtr()->getLines(points, lines, accuracy);
|
||||
}
|
||||
catch (...) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "failed to get sub-element from object");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Py::Tuple tuple(2);
|
||||
Py::List vertex;
|
||||
for (std::vector<Base::Vector3d>::const_iterator it = points.begin();
|
||||
it != points.end(); ++it)
|
||||
vertex.append(Py::asObject(new Base::VectorPy(*it)));
|
||||
tuple.setItem(0, vertex);
|
||||
Py::List line;
|
||||
for (std::vector<Data::ComplexGeoData::Line>::const_iterator
|
||||
it = lines.begin(); it != lines.end(); ++it) {
|
||||
Py::Tuple l(2);
|
||||
l.setItem(0,Py::Int((int)it->I1));
|
||||
l.setItem(1,Py::Int((int)it->I2));
|
||||
line.append(l);
|
||||
}
|
||||
tuple.setItem(1, line);
|
||||
return Py::new_reference_to(tuple);
|
||||
}
|
||||
|
||||
PyObject* ComplexGeoDataPy::getFaces(PyObject *args)
|
||||
{
|
||||
double accuracy = 0.05;
|
||||
if (!PyArg_ParseTuple(args, "d", &accuracy))
|
||||
return nullptr;
|
||||
|
||||
std::vector<Base::Vector3d> points;
|
||||
std::vector<Data::ComplexGeoData::Facet> facets;
|
||||
try {
|
||||
getComplexGeoDataPtr()->getFaces(points, facets, accuracy);
|
||||
}
|
||||
catch (...) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "failed to get sub-element from object");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Py::Tuple tuple(2);
|
||||
@@ -82,17 +251,76 @@ PyObject* ComplexGeoDataPy::getFacesFromSubelement(PyObject *args)
|
||||
return Py::new_reference_to(tuple);
|
||||
}
|
||||
|
||||
Py::Object ComplexGeoDataPy::getBoundBox(void) const
|
||||
PyObject* ComplexGeoDataPy::applyTranslation(PyObject *args)
|
||||
{
|
||||
PyObject *obj;
|
||||
if (!PyArg_ParseTuple(args, "O!", &(Base::VectorPy::Type),&obj))
|
||||
return nullptr;
|
||||
|
||||
try {
|
||||
Base::Vector3d move = static_cast<Base::VectorPy*>(obj)->value();
|
||||
getComplexGeoDataPtr()->applyTranslation(move);
|
||||
Py_Return;
|
||||
}
|
||||
catch (...) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "failed to apply rotation");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
PyObject* ComplexGeoDataPy::applyRotation(PyObject *args)
|
||||
{
|
||||
PyObject *obj;
|
||||
if (!PyArg_ParseTuple(args, "O!", &(Base::RotationPy::Type),&obj))
|
||||
return nullptr;
|
||||
|
||||
try {
|
||||
Base::Rotation rot = static_cast<Base::RotationPy*>(obj)->value();
|
||||
getComplexGeoDataPtr()->applyRotation(rot);
|
||||
Py_Return;
|
||||
}
|
||||
catch (...) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "failed to apply rotation");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
PyObject* ComplexGeoDataPy::transformGeometry(PyObject *args)
|
||||
{
|
||||
PyObject *obj;
|
||||
if (!PyArg_ParseTuple(args, "O!", &(Base::MatrixPy::Type),&obj))
|
||||
return nullptr;
|
||||
|
||||
try {
|
||||
Base::Matrix4D mat = static_cast<Base::MatrixPy*>(obj)->value();
|
||||
getComplexGeoDataPtr()->transformGeometry(mat);
|
||||
Py_Return;
|
||||
}
|
||||
catch (...) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "failed to transform geometry");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Py::Object ComplexGeoDataPy::getBoundBox() const
|
||||
{
|
||||
return Py::BoundingBox(getComplexGeoDataPtr()->getBoundBox());
|
||||
}
|
||||
|
||||
Py::Object ComplexGeoDataPy::getPlacement(void) const
|
||||
Py::Object ComplexGeoDataPy::getCenterOfGravity() const
|
||||
{
|
||||
Base::Vector3d center;
|
||||
if (getComplexGeoDataPtr()->getCenterOfGravity(center))
|
||||
return Py::Vector(center);
|
||||
throw Py::RuntimeError("Cannot get center of gravity");
|
||||
}
|
||||
|
||||
Py::Object ComplexGeoDataPy::getPlacement() const
|
||||
{
|
||||
return Py::Placement(getComplexGeoDataPtr()->getPlacement());
|
||||
}
|
||||
|
||||
void ComplexGeoDataPy::setPlacement(Py::Object arg)
|
||||
void ComplexGeoDataPy::setPlacement(Py::Object arg)
|
||||
{
|
||||
PyObject* p = arg.ptr();
|
||||
if (PyObject_TypeCheck(p, &(Base::PlacementPy::Type))) {
|
||||
@@ -106,40 +334,40 @@ void ComplexGeoDataPy::setPlacement(Py::Object arg)
|
||||
}
|
||||
}
|
||||
|
||||
Py::Object ComplexGeoDataPy::getMatrix(void) const
|
||||
Py::Int ComplexGeoDataPy::getTag() const
|
||||
{
|
||||
return Py::Matrix(getComplexGeoDataPtr()->getTransform());
|
||||
}
|
||||
|
||||
// FIXME would be better to call it setTransform() as in all other interfaces...
|
||||
void ComplexGeoDataPy::setMatrix(Py::Object arg)
|
||||
{
|
||||
PyObject* p = arg.ptr();
|
||||
if (PyObject_TypeCheck(p, &(Base::MatrixPy::Type))) {
|
||||
Base::Matrix4D mat = static_cast<Base::MatrixPy*>(p)->value();
|
||||
getComplexGeoDataPtr()->setTransform(mat);
|
||||
}
|
||||
else {
|
||||
std::string error = std::string("type must be 'Matrix', not ");
|
||||
error += p->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
}
|
||||
}
|
||||
|
||||
Py::Int ComplexGeoDataPy::getTag() const {
|
||||
return Py::Int(getComplexGeoDataPtr()->Tag);
|
||||
}
|
||||
|
||||
void ComplexGeoDataPy::setTag(Py::Int tag) {
|
||||
void ComplexGeoDataPy::setTag(Py::Int tag)
|
||||
{
|
||||
getComplexGeoDataPtr()->Tag = tag;
|
||||
}
|
||||
|
||||
PyObject *ComplexGeoDataPy::getCustomAttributes(const char* /*attr*/) const
|
||||
PyObject* ComplexGeoDataPy::getCustomAttributes(const char* attr) const
|
||||
{
|
||||
return 0;
|
||||
// Support for backward compatibility
|
||||
if (strcmp(attr, "Matrix") == 0) {
|
||||
Py::Matrix mat(getComplexGeoDataPtr()->getTransform());
|
||||
return Py::new_reference_to(mat);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int ComplexGeoDataPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
|
||||
int ComplexGeoDataPy::setCustomAttributes(const char* attr, PyObject* obj)
|
||||
{
|
||||
// Support for backward compatibility
|
||||
if (strcmp(attr, "Matrix") == 0) {
|
||||
if (PyObject_TypeCheck(obj, &(Base::MatrixPy::Type))) {
|
||||
Base::Matrix4D mat = static_cast<Base::MatrixPy*>(obj)->value();
|
||||
getComplexGeoDataPtr()->setTransform(mat);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
std::string error = std::string("type must be 'Matrix', not ");
|
||||
error += obj->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
<hr>
|
||||
|
||||
<h3><a name="_TocCoin3D"></a>Coin3D</h3>
|
||||
<p>Web site: <a href="https://bitbucket.org/Coin3D/coin/">https://bitbucket.org/Coin3D/coin/</a></p>
|
||||
<p>Web site: <a href="https://coin3d.github.io">https://coin3d.github.io</a></p>
|
||||
<p>Copyright: Coin is copyright (C) 1998-2013 Kongsberg Oil & Gas Technologies AS</p>
|
||||
<p>License: BSD-3-clause</p>
|
||||
<pre>
|
||||
|
||||
+48
-1
@@ -30,6 +30,7 @@
|
||||
#include <Gui/Command.h>
|
||||
#include <exception>
|
||||
#include <type_traits>
|
||||
#include <typeinfo>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
namespace Gui {
|
||||
@@ -40,11 +41,24 @@ public:
|
||||
static std::string str(const std::string& s) {
|
||||
return s;
|
||||
}
|
||||
static std::string str(const char* s) {
|
||||
return s;
|
||||
}
|
||||
static std::string str(const QString& s) {
|
||||
return s.toStdString();
|
||||
}
|
||||
static std::string str(const std::stringstream& s) {
|
||||
return s.str();
|
||||
}
|
||||
static std::string str(const std::ostringstream& s) {
|
||||
return s.str();
|
||||
}
|
||||
static std::string str(const std::ostream& s) {
|
||||
return dynamic_cast<const std::ostringstream&>(s).str();
|
||||
if (typeid(s) == typeid(std::ostringstream))
|
||||
return dynamic_cast<const std::ostringstream&>(s).str();
|
||||
else if (typeid(s) == typeid(std::stringstream))
|
||||
return dynamic_cast<const std::stringstream&>(s).str();
|
||||
throw Base::TypeError("Not a std::stringstream or std::ostringstream");
|
||||
}
|
||||
static std::string toStr(boost::format& f) {
|
||||
return f.str();
|
||||
@@ -152,6 +166,39 @@ inline void cmdAppDocument(const App::DocumentObject* obj, T&& cmd) {
|
||||
_cmdDocument(Gui::Command::Doc, obj, "App", std::forward<T>(cmd));
|
||||
}
|
||||
|
||||
/** Runs a command for accessing a document's attribute or method
|
||||
* @param doc: pointer to a Document
|
||||
* @param cmd: command string, supporting printf like formatter
|
||||
*
|
||||
* Example:
|
||||
* @code{.cpp}
|
||||
* cmdAppDocumentArgs(obj, "addObject('%s')", "Part::Feature");
|
||||
* @endcode
|
||||
*
|
||||
* Translates to command (assuming obj's document name is 'DocName':
|
||||
* @code{.py}
|
||||
* App.getDocument('DocName').addObject('Part::Feature')
|
||||
* @endcode
|
||||
*/
|
||||
template<typename...Args>
|
||||
void cmdAppDocumentArgs(const App::Document* doc, const std::string& cmd, Args&&... args) {
|
||||
std::string _cmd;
|
||||
try {
|
||||
boost::format fmt(cmd);
|
||||
_cmd = FormatString::toStr(fmt, std::forward<Args>(args)...);
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.getDocument('%s').%s",
|
||||
doc->getName(), _cmd.c_str());
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
Base::Console().Error("%s: %s\n", e.what(), cmd.c_str());
|
||||
}
|
||||
catch (const Base::Exception&) {
|
||||
Base::Console().Error("App.getDocument('%s').%s\n",
|
||||
doc->getName(), _cmd.c_str());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/** Runs a command for accessing an object's Gui::Document attribute or method
|
||||
* This function is an alternative to FCMD_VOBJ_DOC_CMD
|
||||
* @param obj: pointer to a DocumentObject
|
||||
|
||||
@@ -2824,7 +2824,7 @@ static std::vector<std::string> getBoxSelection(
|
||||
continue;
|
||||
std::vector<Base::Vector3d> points;
|
||||
std::vector<Data::ComplexGeoData::Line> lines;
|
||||
data->getLinesFromSubelement(segment.get(),points,lines);
|
||||
data->getLinesFromSubElement(segment.get(),points,lines);
|
||||
if(lines.empty()) {
|
||||
if(points.empty())
|
||||
continue;
|
||||
|
||||
+13
-9
@@ -633,24 +633,27 @@ bool MainWindow::closeAllDocuments (bool close)
|
||||
auto docs = App::GetApplication().getDocuments();
|
||||
try {
|
||||
docs = App::Document::getDependentDocuments(docs, true);
|
||||
}catch(Base::Exception &e) {
|
||||
}
|
||||
catch(Base::Exception &e) {
|
||||
e.ReportException();
|
||||
}
|
||||
|
||||
bool checkModify = true;
|
||||
bool saveAll = false;
|
||||
int failedSaves = 0;
|
||||
for(auto doc : docs) {
|
||||
|
||||
for (auto doc : docs) {
|
||||
auto gdoc = Application::Instance->getDocument(doc);
|
||||
if(!gdoc)
|
||||
if (!gdoc)
|
||||
continue;
|
||||
if(!gdoc->canClose(false))
|
||||
if (!gdoc->canClose(false))
|
||||
return false;
|
||||
if(!gdoc->isModified()
|
||||
if (!gdoc->isModified()
|
||||
|| doc->testStatus(App::Document::PartialDoc)
|
||||
|| doc->testStatus(App::Document::TempDoc))
|
||||
continue;
|
||||
bool save = saveAll;
|
||||
if(!save && checkModify) {
|
||||
if (!save && checkModify) {
|
||||
int res = confirmSave(doc->Label.getStrValue().c_str(), this, docs.size()>1);
|
||||
switch (res)
|
||||
{
|
||||
@@ -658,6 +661,7 @@ bool MainWindow::closeAllDocuments (bool close)
|
||||
return false;
|
||||
case ConfirmSaveResult::SaveAll:
|
||||
saveAll = true;
|
||||
/* FALLTHRU */
|
||||
case ConfirmSaveResult::Save:
|
||||
save = true;
|
||||
break;
|
||||
@@ -666,7 +670,7 @@ bool MainWindow::closeAllDocuments (bool close)
|
||||
}
|
||||
}
|
||||
|
||||
if(save && !gdoc->save())
|
||||
if (save && !gdoc->save())
|
||||
failedSaves++;
|
||||
}
|
||||
|
||||
@@ -681,9 +685,9 @@ bool MainWindow::closeAllDocuments (bool close)
|
||||
return false;
|
||||
}
|
||||
|
||||
if(close)
|
||||
if (close)
|
||||
App::GetApplication().closeAllDocuments();
|
||||
// d->mdiArea->closeAllSubWindows();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -505,14 +505,14 @@ void AboutDialog::showLibraryInformation()
|
||||
// Coin3D
|
||||
li.name = QLatin1String("Coin3D");
|
||||
li.href = baseurl + QLatin1String("#_TocCoin3D");
|
||||
li.url = QLatin1String("https://bitbucket.org/Coin3D/coin/");
|
||||
li.url = QLatin1String("https://coin3d.github.io");
|
||||
li.version = QLatin1String(COIN_VERSION);
|
||||
libInfo << li;
|
||||
|
||||
// Eigen3
|
||||
li.name = QLatin1String("Eigen3");
|
||||
li.href = baseurl + QLatin1String("#_TocEigen3");
|
||||
li.url = QLatin1String("http://eigen.tuxfamily.org/");
|
||||
li.url = QLatin1String("http://eigen.tuxfamily.org");
|
||||
li.version = QString::fromLatin1(FC_EIGEN3_VERSION);
|
||||
libInfo << li;
|
||||
|
||||
|
||||
@@ -250,6 +250,11 @@ void ToolBarManager::setup(ToolBarItem* toolBarItems)
|
||||
(*it)->hide();
|
||||
(*it)->toggleViewAction()->setVisible(false);
|
||||
}
|
||||
|
||||
hPref = App::GetApplication().GetUserParameter().GetGroup("BaseApp")
|
||||
->GetGroup("Preferences")->GetGroup("General");
|
||||
bool lockToolBars = hPref->GetBool("LockToolBars", false);
|
||||
setMovable(!lockToolBars);
|
||||
}
|
||||
|
||||
void ToolBarManager::setup(ToolBarItem* item, QToolBar* toolbar) const
|
||||
@@ -314,6 +319,12 @@ void ToolBarManager::restoreState() const
|
||||
toolbar->setVisible(hPref->GetBool(toolbarName.constData(), toolbar->isVisible()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
hPref = App::GetApplication().GetUserParameter().GetGroup("BaseApp")
|
||||
->GetGroup("Preferences")->GetGroup("General");
|
||||
bool lockToolBars = hPref->GetBool("LockToolBars", false);
|
||||
setMovable(!lockToolBars);
|
||||
}
|
||||
|
||||
void ToolBarManager::retranslate() const
|
||||
@@ -327,6 +338,13 @@ void ToolBarManager::retranslate() const
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::ToolBarManager::setMovable(bool moveable) const
|
||||
{
|
||||
for (auto& tb : toolBars()) {
|
||||
tb->setMovable(moveable);
|
||||
}
|
||||
}
|
||||
|
||||
QToolBar* ToolBarManager::findToolBar(const QList<QToolBar*>& toolbars, const QString& item) const
|
||||
{
|
||||
for (QList<QToolBar*>::ConstIterator it = toolbars.begin(); it != toolbars.end(); ++it) {
|
||||
|
||||
@@ -80,6 +80,8 @@ public:
|
||||
void restoreState() const;
|
||||
void retranslate() const;
|
||||
|
||||
void setMovable(bool movable) const;
|
||||
|
||||
protected:
|
||||
void setup(ToolBarItem*, QToolBar*) const;
|
||||
/** Returns a list of all currently existing toolbars. */
|
||||
|
||||
+29
-40
@@ -26,6 +26,7 @@
|
||||
# include <QAction>
|
||||
# include <QColorDialog>
|
||||
# include <QDesktopWidget>
|
||||
# include <QDesktopServices>
|
||||
# include <QDialogButtonBox>
|
||||
# include <QDrag>
|
||||
# include <QEventLoop>
|
||||
@@ -594,6 +595,7 @@ struct ColorButtonP
|
||||
bool allowChange;
|
||||
bool autoChange;
|
||||
bool drawFrame;
|
||||
bool allowTransparency;
|
||||
bool modal;
|
||||
bool dirty;
|
||||
|
||||
@@ -602,6 +604,7 @@ struct ColorButtonP
|
||||
, allowChange(true)
|
||||
, autoChange(false)
|
||||
, drawFrame(true)
|
||||
, allowTransparency(false)
|
||||
, modal(true)
|
||||
, dirty(true)
|
||||
{
|
||||
@@ -671,6 +674,21 @@ bool ColorButton::drawFrame() const
|
||||
return d->drawFrame;
|
||||
}
|
||||
|
||||
void Gui::ColorButton::setAllowTransparency(bool allow)
|
||||
{
|
||||
d->allowTransparency = allow;
|
||||
if (d->cd)
|
||||
d->cd->setOption(QColorDialog::ColorDialogOption::ShowAlphaChannel, allow);
|
||||
}
|
||||
|
||||
bool Gui::ColorButton::allowTransparency() const
|
||||
{
|
||||
if (d->cd)
|
||||
return d->cd->testOption(QColorDialog::ColorDialogOption::ShowAlphaChannel);
|
||||
else
|
||||
return d->allowTransparency;
|
||||
}
|
||||
|
||||
void ColorButton::setModal(bool b)
|
||||
{
|
||||
d->modal = b;
|
||||
@@ -763,6 +781,7 @@ void ColorButton::onChooseColor()
|
||||
QColor currentColor = d->col;
|
||||
QColorDialog cd(d->col, this);
|
||||
cd.setOptions(QColorDialog::DontUseNativeDialog);
|
||||
cd.setOption(QColorDialog::ColorDialogOption::ShowAlphaChannel, d->allowTransparency);
|
||||
|
||||
if (d->autoChange) {
|
||||
connect(&cd, SIGNAL(currentColorChanged(const QColor &)),
|
||||
@@ -788,6 +807,7 @@ void ColorButton::onChooseColor()
|
||||
d->old = d->col;
|
||||
d->cd = new QColorDialog(d->col, this);
|
||||
d->cd->setOptions(QColorDialog::DontUseNativeDialog);
|
||||
d->cd->setOption(QColorDialog::ColorDialogOption::ShowAlphaChannel, d->allowTransparency);
|
||||
d->cd->setAttribute(Qt::WA_DeleteOnClose);
|
||||
connect(d->cd, SIGNAL(rejected()),
|
||||
this, SLOT(onRejected()));
|
||||
@@ -812,16 +832,15 @@ void ColorButton::onRejected()
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
UrlLabel::UrlLabel(QWidget * parent, Qt::WindowFlags f)
|
||||
: QLabel(parent, f)
|
||||
UrlLabel::UrlLabel(QWidget* parent, Qt::WindowFlags f)
|
||||
: QLabel(parent, f)
|
||||
, _url (QStringLiteral("http://localhost"))
|
||||
, _launchExternal(true)
|
||||
{
|
||||
_url = QString::fromLatin1("http://localhost");
|
||||
setToolTip(this->_url);
|
||||
|
||||
if (qApp->styleSheet().isEmpty()) {
|
||||
setStyleSheet(QString::fromLatin1("Gui--UrlLabel {color: #0000FF;text-decoration: underline;}"));
|
||||
}
|
||||
setToolTip(this->_url);
|
||||
setCursor(Qt::PointingHandCursor);
|
||||
if (qApp->styleSheet().isEmpty())
|
||||
setStyleSheet(QStringLiteral("Gui--UrlLabel {color: #0000FF;text-decoration: underline;}"));
|
||||
}
|
||||
|
||||
UrlLabel::~UrlLabel()
|
||||
@@ -833,40 +852,10 @@ void Gui::UrlLabel::setLaunchExternal(bool l)
|
||||
_launchExternal = l;
|
||||
}
|
||||
|
||||
void UrlLabel::enterEvent ( QEvent * )
|
||||
{
|
||||
setCursor(Qt::PointingHandCursor);
|
||||
}
|
||||
|
||||
void UrlLabel::leaveEvent ( QEvent * )
|
||||
{
|
||||
setCursor(Qt::ArrowCursor);
|
||||
}
|
||||
|
||||
void UrlLabel::mouseReleaseEvent (QMouseEvent *)
|
||||
void UrlLabel::mouseReleaseEvent(QMouseEvent*)
|
||||
{
|
||||
if (_launchExternal) {
|
||||
// The webbrowser Python module allows to start the system browser in an OS-independent way
|
||||
Base::PyGILStateLocker lock;
|
||||
PyObject* module = PyImport_ImportModule("webbrowser");
|
||||
if (module) {
|
||||
// get the methods dictionary and search for the 'open' method
|
||||
PyObject* dict = PyModule_GetDict(module);
|
||||
PyObject* func = PyDict_GetItemString(dict, "open");
|
||||
if (func) {
|
||||
PyObject* args = Py_BuildValue("(s)", (const char*)this->_url.toLatin1());
|
||||
#if PY_VERSION_HEX < 0x03090000
|
||||
PyObject* result = PyEval_CallObject(func, args);
|
||||
#else
|
||||
PyObject* result = PyObject_CallObject(func, args);
|
||||
#endif
|
||||
// decrement the args and module reference
|
||||
Py_XDECREF(result);
|
||||
Py_DECREF(args);
|
||||
Py_DECREF(module);
|
||||
}
|
||||
}
|
||||
}
|
||||
QDesktopServices::openUrl(this->_url);
|
||||
else {
|
||||
// Someone else will deal with it...
|
||||
Q_EMIT linkClicked(_url);
|
||||
|
||||
+4
-2
@@ -203,6 +203,7 @@ class GuiExport ColorButton : public QPushButton
|
||||
Q_PROPERTY( QColor color READ color WRITE setColor )
|
||||
Q_PROPERTY( bool allowChangeColor READ allowChangeColor WRITE setAllowChangeColor )
|
||||
Q_PROPERTY( bool drawFrame READ drawFrame WRITE setDrawFrame )
|
||||
Q_PROPERTY( bool allowTransparency READ allowTransparency WRITE setAllowTransparency)
|
||||
|
||||
public:
|
||||
ColorButton(QWidget* parent = 0);
|
||||
@@ -217,6 +218,9 @@ public:
|
||||
void setDrawFrame(bool);
|
||||
bool drawFrame() const;
|
||||
|
||||
void setAllowTransparency(bool);
|
||||
bool allowTransparency() const;
|
||||
|
||||
void setModal(bool);
|
||||
bool isModal() const;
|
||||
|
||||
@@ -272,8 +276,6 @@ public Q_SLOTS:
|
||||
void setLaunchExternal(bool l);
|
||||
|
||||
protected:
|
||||
void enterEvent ( QEvent * );
|
||||
void leaveEvent ( QEvent * );
|
||||
void mouseReleaseEvent ( QMouseEvent * );
|
||||
|
||||
private:
|
||||
|
||||
@@ -562,7 +562,7 @@ void StdWorkbench::setupContextMenu(const char* recipient, MenuItem* item) const
|
||||
*item << "Separator" << "Std_SetAppearance" << "Std_ToggleVisibility"
|
||||
<< "Std_ToggleSelectability" << "Std_TreeSelection"
|
||||
<< "Std_RandomColor" << "Separator" << "Std_Delete"
|
||||
<< "Std_SendToPythonConsole";
|
||||
<< "Std_SendToPythonConsole" << "Std_TransformManip";
|
||||
}
|
||||
}
|
||||
else if (strcmp(recipient,"Tree") == 0)
|
||||
|
||||
@@ -200,11 +200,14 @@ class CommandAddonManager:
|
||||
m.setWindowIcon(QtGui.QIcon(":/icons/AddonManager.svg"))
|
||||
m.setText(translate("AddonsInstaller",
|
||||
"You must restart FreeCAD for changes to take "
|
||||
"effect. Press Ok to restart FreeCAD now, or "
|
||||
"Cancel to restart later."))
|
||||
"effect."))
|
||||
m.setIcon(m.Warning)
|
||||
m.setStandardButtons(m.Ok | m.Cancel)
|
||||
m.setDefaultButton(m.Cancel)
|
||||
okBtn = m.button(QtGui.QMessageBox.StandardButton.Ok)
|
||||
cancelBtn = m.button(QtGui.QMessageBox.StandardButton.Cancel)
|
||||
okBtn.setText(translate("AddonsInstaller","Restart now"))
|
||||
cancelBtn.setText(translate("AddonsInstaller","Restart later"))
|
||||
ret = m.exec_()
|
||||
if ret == m.Ok:
|
||||
shutil.rmtree(self.macro_repo_dir, onerror=self.remove_readonly)
|
||||
|
||||
+107
-46
@@ -51,37 +51,83 @@ class ArchWorkbench(FreeCADGui.Workbench):
|
||||
import Draft_rc
|
||||
import DraftTools
|
||||
import DraftGui
|
||||
from draftguitools import gui_circulararray
|
||||
from draftguitools import gui_polararray
|
||||
from draftguitools import gui_orthoarray
|
||||
from draftguitools import gui_arrays
|
||||
import Arch_rc
|
||||
import Arch
|
||||
|
||||
from ArchStructure import _ArchStructureGroupCommand
|
||||
from ArchAxis import _ArchAxisGroupCommand
|
||||
from ArchPanel import CommandPanelGroup
|
||||
from ArchMaterial import _ArchMaterialToolsCommand
|
||||
from ArchPipe import _ArchPipeGroupCommand
|
||||
|
||||
stru_group = _ArchStructureGroupCommand
|
||||
axis_group = _ArchAxisGroupCommand
|
||||
pan_group = CommandPanelGroup
|
||||
mat_group = _ArchMaterialToolsCommand
|
||||
pipe_group = _ArchPipeGroupCommand
|
||||
|
||||
# Set up command lists
|
||||
self.archtools = ["Arch_Wall", "Arch_StructureTools", "Arch_Rebar",
|
||||
"Arch_CurtainWall","Arch_BuildingPart",
|
||||
"Arch_Project", "Arch_Site", "Arch_Building",
|
||||
"Arch_Floor", "Arch_Reference",
|
||||
"Arch_Window", "Arch_Roof", "Arch_AxisTools",
|
||||
"Arch_SectionPlane", "Arch_Space", "Arch_Stairs",
|
||||
"Arch_PanelTools", "Arch_Equipment",
|
||||
"Arch_Frame", "Arch_Fence", "Arch_Truss",
|
||||
"Arch_Profile","Arch_MaterialTools",
|
||||
"Arch_Schedule", "Arch_PipeTools",
|
||||
"Arch_CutPlane", "Arch_CutLine",
|
||||
"Arch_Add", "Arch_Remove", "Arch_Survey"]
|
||||
self.utilities = ["Arch_Component", "Arch_CloneComponent",
|
||||
"Arch_SplitMesh", "Arch_MeshToShape",
|
||||
"Arch_SelectNonSolidMeshes", "Arch_RemoveShape",
|
||||
"Arch_CloseHoles", "Arch_MergeWalls", "Arch_Check",
|
||||
"Arch_ToggleIfcBrepFlag", "Arch_3Views",
|
||||
"Arch_IfcSpreadsheet", "Arch_ToggleSubs"]
|
||||
self.archtools = ["Arch_Wall",
|
||||
([QT_TRANSLATE_NOOP("Arch", "Structure tools")],
|
||||
list(stru_group.GetCommands(stru_group))), # tuple len=2: submenu
|
||||
("Arch_StructureTools", ), # tuple len=1: toolbar flyout
|
||||
"Arch_Rebar_Submenu", # will be replaced or removed
|
||||
"Arch_Rebar", # may be replaced
|
||||
"Arch_CurtainWall",
|
||||
"Arch_BuildingPart",
|
||||
"Arch_Project",
|
||||
"Arch_Site",
|
||||
"Arch_Building",
|
||||
"Arch_Floor",
|
||||
"Arch_Reference",
|
||||
"Arch_Window",
|
||||
"Arch_Roof",
|
||||
([QT_TRANSLATE_NOOP("Arch", "Axis tools")],
|
||||
list(axis_group.GetCommands(axis_group))),
|
||||
("Arch_AxisTools", ),
|
||||
"Arch_SectionPlane",
|
||||
"Arch_Space",
|
||||
"Arch_Stairs",
|
||||
([QT_TRANSLATE_NOOP("Arch", "Panel tools")],
|
||||
list(pan_group.GetCommands(pan_group))),
|
||||
("Arch_PanelTools", ),
|
||||
"Arch_Equipment",
|
||||
"Arch_Frame",
|
||||
"Arch_Fence",
|
||||
"Arch_Truss",
|
||||
"Arch_Profile",
|
||||
([QT_TRANSLATE_NOOP("Arch", "Material tools")],
|
||||
list(mat_group.GetCommands(mat_group))),
|
||||
("Arch_MaterialTools", ),
|
||||
"Arch_Schedule",
|
||||
([QT_TRANSLATE_NOOP("Arch", "Pipe tools")],
|
||||
list(pipe_group.GetCommands(pipe_group))),
|
||||
("Arch_PipeTools", ),
|
||||
"Arch_CutPlane",
|
||||
"Arch_CutLine",
|
||||
"Arch_Add",
|
||||
"Arch_Remove",
|
||||
"Arch_Survey"]
|
||||
|
||||
self.utilities = ["Arch_Component",
|
||||
"Arch_CloneComponent",
|
||||
"Arch_SplitMesh",
|
||||
"Arch_MeshToShape",
|
||||
"Arch_SelectNonSolidMeshes",
|
||||
"Arch_RemoveShape",
|
||||
"Arch_CloseHoles",
|
||||
"Arch_MergeWalls",
|
||||
"Arch_Check",
|
||||
"Arch_ToggleIfcBrepFlag",
|
||||
"Arch_3Views",
|
||||
"Arch_IfcSpreadsheet",
|
||||
"Arch_ToggleSubs"]
|
||||
|
||||
# Add the rebar tools from the Reinforcement addon, if available
|
||||
try:
|
||||
import RebarTools
|
||||
except Exception:
|
||||
del self.archtools[3] # remove "Arch_Rebar_Submenu"
|
||||
pass
|
||||
else:
|
||||
class RebarGroupCommand:
|
||||
@@ -97,42 +143,57 @@ class ArchWorkbench(FreeCADGui.Workbench):
|
||||
def IsActive(self):
|
||||
return not FreeCAD.ActiveDocument is None
|
||||
FreeCADGui.addCommand('Arch_RebarTools', RebarGroupCommand())
|
||||
self.archtools[2] = "Arch_RebarTools"
|
||||
self.archtools[3] = ([QT_TRANSLATE_NOOP("Arch", "Rebar tools")],
|
||||
RebarTools.RebarCommands + ["Arch_Rebar"])
|
||||
self.archtools[4] = ("Arch_RebarTools", )
|
||||
|
||||
# Set up Draft command lists
|
||||
import draftutils.init_tools as it
|
||||
self.draft_drawing_commands = it.get_draft_drawing_commands()
|
||||
self.draft_annotation_commands = it.get_draft_annotation_commands()
|
||||
self.draft_modification_commands = it.get_draft_modification_commands()
|
||||
self.draft_utility_commands = it.get_draft_utility_commands_menu()
|
||||
self.draft_context_commands = it.get_draft_context_commands()
|
||||
self.draft_line_commands = it.get_draft_line_commands()
|
||||
self.draft_utility_commands = it.get_draft_utility_commands()
|
||||
|
||||
# Set up toolbars
|
||||
self.appendToolbar(QT_TRANSLATE_NOOP("Workbench", "Arch tools"), self.archtools)
|
||||
self.appendToolbar(QT_TRANSLATE_NOOP("Draft", "Draft creation tools"), self.draft_drawing_commands)
|
||||
self.appendToolbar(QT_TRANSLATE_NOOP("Draft", "Draft annotation tools"), self.draft_annotation_commands)
|
||||
self.appendToolbar(QT_TRANSLATE_NOOP("Draft", "Draft modification tools"), self.draft_modification_commands)
|
||||
it.init_toolbar(self,
|
||||
QT_TRANSLATE_NOOP("Workbench", "Arch tools"),
|
||||
self.archtools)
|
||||
it.init_toolbar(self,
|
||||
QT_TRANSLATE_NOOP("Draft", "Draft creation tools"),
|
||||
self.draft_drawing_commands)
|
||||
it.init_toolbar(self,
|
||||
QT_TRANSLATE_NOOP("Draft", "Draft annotation tools"),
|
||||
self.draft_annotation_commands)
|
||||
it.init_toolbar(self,
|
||||
QT_TRANSLATE_NOOP("Draft", "Draft modification tools"),
|
||||
self.draft_modification_commands)
|
||||
|
||||
# Set up menus
|
||||
self.appendMenu([QT_TRANSLATE_NOOP("arch", "&Arch"),
|
||||
QT_TRANSLATE_NOOP("arch", "Utilities")],
|
||||
self.utilities)
|
||||
self.appendMenu(QT_TRANSLATE_NOOP("arch", "&Arch"), self.archtools)
|
||||
it.init_menu(self,
|
||||
[QT_TRANSLATE_NOOP("Arch", "&Arch"),
|
||||
QT_TRANSLATE_NOOP("Arch", "Utilities")],
|
||||
self.utilities)
|
||||
it.init_menu(self,
|
||||
[QT_TRANSLATE_NOOP("Arch", "&Arch")],
|
||||
self.archtools)
|
||||
it.init_menu(self,
|
||||
[QT_TRANSLATE_NOOP("Arch", "&Draft"),
|
||||
QT_TRANSLATE_NOOP("Arch", "Creation")],
|
||||
self.draft_drawing_commands)
|
||||
it.init_menu(self,
|
||||
[QT_TRANSLATE_NOOP("Arch", "&Draft"),
|
||||
QT_TRANSLATE_NOOP("Arch", "Annotation")],
|
||||
self.draft_annotation_commands)
|
||||
it.init_menu(self,
|
||||
[QT_TRANSLATE_NOOP("Arch", "&Draft"),
|
||||
QT_TRANSLATE_NOOP("Arch", "Modification")],
|
||||
self.draft_modification_commands)
|
||||
it.init_menu(self,
|
||||
[QT_TRANSLATE_NOOP("Arch", "&Draft"),
|
||||
QT_TRANSLATE_NOOP("Arch", "Utilities")],
|
||||
self.draft_utility_commands)
|
||||
|
||||
self.appendMenu([QT_TRANSLATE_NOOP("arch", "&Draft"),
|
||||
QT_TRANSLATE_NOOP("arch", "Creation")],
|
||||
self.draft_drawing_commands)
|
||||
self.appendMenu([QT_TRANSLATE_NOOP("arch", "&Draft"),
|
||||
QT_TRANSLATE_NOOP("arch", "Annotation")],
|
||||
self.draft_annotation_commands)
|
||||
self.appendMenu([QT_TRANSLATE_NOOP("arch", "&Draft"),
|
||||
QT_TRANSLATE_NOOP("arch", "Modification")],
|
||||
self.draft_modification_commands)
|
||||
self.appendMenu([QT_TRANSLATE_NOOP("arch", "&Draft"),
|
||||
QT_TRANSLATE_NOOP("arch", "Utilities")],
|
||||
self.draft_utility_commands
|
||||
+ self.draft_context_commands)
|
||||
FreeCADGui.addIconPath(":/icons")
|
||||
FreeCADGui.addLanguagePath(":/translations")
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ namespace dcm {
|
||||
* @{ */
|
||||
|
||||
/**
|
||||
* @brief Exeption for property errors
|
||||
* @brief Exception for property errors
|
||||
*
|
||||
* This exception is thrown when a property related error is detected, for example if a objects is ask for a
|
||||
* property which it does not own. This exceptions own the error-code range from 300-399.
|
||||
|
||||
@@ -422,9 +422,9 @@ if App.GuiUp:
|
||||
from draftviewproviders.view_text import (ViewProviderText,
|
||||
ViewProviderDraftText)
|
||||
|
||||
from draftobjects.hatch import (Draft_Hatch_Object)
|
||||
from draftmake.make_hatch import (make_hatch, makeHatch)
|
||||
from draftobjects.hatch import (Hatch)
|
||||
from draftmake.make_hatch import (make_hatch)
|
||||
if App.GuiUp:
|
||||
from draftviewproviders.view_hatch import (Draft_Hatch_ViewProvider)
|
||||
from draftviewproviders.view_hatch import (ViewProviderDraftHatch)
|
||||
|
||||
## @}
|
||||
|
||||
+26
-10
@@ -95,22 +95,38 @@ class DraftWorkbench(FreeCADGui.Workbench):
|
||||
self.drawing_commands = it.get_draft_drawing_commands()
|
||||
self.annotation_commands = it.get_draft_annotation_commands()
|
||||
self.modification_commands = it.get_draft_modification_commands()
|
||||
self.utility_commands_menu = it.get_draft_utility_commands_menu()
|
||||
self.utility_commands_toolbar = it.get_draft_utility_commands_toolbar()
|
||||
self.context_commands = it.get_draft_context_commands()
|
||||
self.line_commands = it.get_draft_line_commands()
|
||||
self.utility_commands = it.get_draft_utility_commands()
|
||||
self.utility_small = it.get_draft_small_commands()
|
||||
|
||||
# Set up toolbars
|
||||
self.appendToolbar(QT_TRANSLATE_NOOP("Draft", "Draft creation tools"), self.drawing_commands)
|
||||
self.appendToolbar(QT_TRANSLATE_NOOP("Draft", "Draft annotation tools"), self.annotation_commands)
|
||||
self.appendToolbar(QT_TRANSLATE_NOOP("Draft", "Draft modification tools"), self.modification_commands)
|
||||
self.appendToolbar(QT_TRANSLATE_NOOP("Draft", "Draft utility tools"), self.utility_small)
|
||||
it.init_toolbar(self,
|
||||
QT_TRANSLATE_NOOP("Draft", "Draft creation tools"),
|
||||
self.drawing_commands)
|
||||
it.init_toolbar(self,
|
||||
QT_TRANSLATE_NOOP("Draft", "Draft annotation tools"),
|
||||
self.annotation_commands)
|
||||
it.init_toolbar(self,
|
||||
QT_TRANSLATE_NOOP("Draft", "Draft modification tools"),
|
||||
self.modification_commands)
|
||||
it.init_toolbar(self,
|
||||
QT_TRANSLATE_NOOP("Draft", "Draft utility tools"),
|
||||
self.utility_commands_toolbar)
|
||||
|
||||
# Set up menus
|
||||
self.appendMenu(QT_TRANSLATE_NOOP("Draft", "&Drafting"), self.drawing_commands)
|
||||
self.appendMenu(QT_TRANSLATE_NOOP("Draft", "&Annotation"), self.annotation_commands)
|
||||
self.appendMenu(QT_TRANSLATE_NOOP("Draft", "&Modification"), self.modification_commands)
|
||||
self.appendMenu(QT_TRANSLATE_NOOP("Draft", "&Utilities"), self.utility_commands + self.context_commands)
|
||||
it.init_menu(self,
|
||||
[QT_TRANSLATE_NOOP("Draft", "&Drafting")],
|
||||
self.drawing_commands)
|
||||
it.init_menu(self,
|
||||
[QT_TRANSLATE_NOOP("Draft", "&Annotation")],
|
||||
self.annotation_commands)
|
||||
it.init_menu(self,
|
||||
[QT_TRANSLATE_NOOP("Draft", "&Modification")],
|
||||
self.modification_commands)
|
||||
it.init_menu(self,
|
||||
[QT_TRANSLATE_NOOP("Draft", "&Utilities")],
|
||||
self.utility_commands_menu)
|
||||
|
||||
# Set up preferences pages
|
||||
if hasattr(FreeCADGui, "draftToolBar"):
|
||||
|
||||
@@ -17,7 +17,16 @@
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
@@ -252,9 +261,9 @@
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
<zorder/>
|
||||
<zorder/>
|
||||
<zorder/>
|
||||
<zorder></zorder>
|
||||
<zorder></zorder>
|
||||
<zorder></zorder>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -323,6 +332,25 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="checkBox_3">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>If checked, the outline of a human figure is displayed at the bottom left corner of the grid. This option is only effective if the BIM workbench is installed and if &quot;Show grid border&quot; option is enabled.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show human figure</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>gridShowHuman</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Draft</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="checkBox_2">
|
||||
<property name="toolTip">
|
||||
@@ -525,7 +553,7 @@
|
||||
<property name="toolTip">
|
||||
<string>The color of the grid</string>
|
||||
</property>
|
||||
<property name="color">
|
||||
<property name="color" stdset="0">
|
||||
<color>
|
||||
<red>50</red>
|
||||
<green>50</green>
|
||||
@@ -572,7 +600,16 @@
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_16" stretch="0,0,0">
|
||||
<property name="margin">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
@@ -618,22 +655,31 @@
|
||||
<property name="value">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="displayIntegerBase">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>DraftEditMaxObjects</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Draft</cstring>
|
||||
</property>
|
||||
<property name="displayIntegerBase" stdset="0">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,0,0">
|
||||
<property name="margin">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
|
||||
@@ -25,10 +25,11 @@
|
||||
|
||||
import os
|
||||
import FreeCAD
|
||||
import draftguitools.gui_base as gui_base
|
||||
|
||||
from draftutils.translate import translate, QT_TRANSLATE_NOOP
|
||||
|
||||
|
||||
class Draft_Hatch:
|
||||
class Draft_Hatch(gui_base.GuiCommandSimplest):
|
||||
|
||||
|
||||
def GetResources(self):
|
||||
@@ -36,7 +37,7 @@ class Draft_Hatch:
|
||||
return {'Pixmap' : "Draft_Hatch",
|
||||
'MenuText': QT_TRANSLATE_NOOP("Draft_Hatch", "Hatch"),
|
||||
'Accel': "H, A",
|
||||
'ToolTip' : QT_TRANSLATE_NOOP("Draft_Hatch", "Create hatches on selected faces")}
|
||||
'ToolTip' : QT_TRANSLATE_NOOP("Draft_Hatch", "Creates hatches on the faces of a selected object")}
|
||||
|
||||
def Activated(self):
|
||||
|
||||
@@ -89,7 +90,7 @@ class Draft_Hatch_TaskPanel:
|
||||
# create new hatch object
|
||||
FreeCAD.ActiveDocument.openTransaction("Create Hatch")
|
||||
FreeCADGui.addModule("Draft")
|
||||
cmd = "Draft.makeHatch("
|
||||
cmd = "Draft.make_hatch("
|
||||
cmd += "baseobject=FreeCAD.ActiveDocument.getObject(\""+self.baseobj.Name
|
||||
cmd += "\"),filename=\""+self.form.File.property("fileName")
|
||||
cmd += "\",pattern=\""+self.form.Pattern.currentText()
|
||||
|
||||
@@ -125,7 +125,7 @@ class Rectangle(gui_base_original.Creator):
|
||||
self.commit(translate("draft", "Create Plane"),
|
||||
_cmd_list)
|
||||
else:
|
||||
_cmd = 'Draft.makeRectangle'
|
||||
_cmd = 'Draft.make_rectangle'
|
||||
_cmd += '('
|
||||
_cmd += 'length=' + str(length) + ', '
|
||||
_cmd += 'height=' + str(height) + ', '
|
||||
|
||||
@@ -85,6 +85,9 @@ class Text(gui_base_original.Creator):
|
||||
|
||||
def createObject(self):
|
||||
"""Create the actual object in the current document."""
|
||||
rot, sup, pts, fil = self.getStrings()
|
||||
base = pts[1:-1]
|
||||
|
||||
text_list = self.text
|
||||
text_list = [text.replace("\"","\\\"") for text in text_list]
|
||||
|
||||
@@ -108,9 +111,12 @@ class Text(gui_base_original.Creator):
|
||||
_cmd = 'Draft.make_text'
|
||||
_cmd += '('
|
||||
_cmd += string + ', '
|
||||
_cmd += 'placement=' + DraftVecUtils.toString(self.node[0])
|
||||
_cmd += 'placement=pl'
|
||||
_cmd += ')'
|
||||
_cmd_list = ['_text_ = ' + _cmd,
|
||||
_cmd_list = ['pl = FreeCAD.Placement()',
|
||||
'pl.Rotation.Q = ' + rot,
|
||||
'pl.Base = ' + base,
|
||||
'_text_ = ' + _cmd,
|
||||
'Draft.autogroup(_text_)',
|
||||
'FreeCAD.ActiveDocument.recompute()']
|
||||
self.commit(translate("draft", "Create Text"),
|
||||
|
||||
@@ -1009,6 +1009,13 @@ class gridTracker(Tracker):
|
||||
self.coords2 = coin.SoCoordinate3()
|
||||
self.lines2 = coin.SoLineSet() # big squares
|
||||
|
||||
# human figure
|
||||
mat_human = coin.SoMaterial()
|
||||
mat_human.transparency.setValue(0.3*(1-gtrans))
|
||||
mat_human.diffuseColor.setValue(col)
|
||||
self.coords_human = coin.SoCoordinate3()
|
||||
self.human = coin.SoLineSet()
|
||||
|
||||
# axes
|
||||
mat3 = coin.SoMaterial()
|
||||
mat3.transparency.setValue(gtrans)
|
||||
@@ -1030,6 +1037,9 @@ class gridTracker(Tracker):
|
||||
s.addChild(mat2)
|
||||
s.addChild(self.coords2)
|
||||
s.addChild(self.lines2)
|
||||
s.addChild(mat_human)
|
||||
s.addChild(self.coords_human)
|
||||
s.addChild(self.human)
|
||||
s.addChild(mbind3)
|
||||
s.addChild(mat3)
|
||||
s.addChild(self.coords3)
|
||||
@@ -1105,17 +1115,6 @@ class gridTracker(Tracker):
|
||||
self.text2.string = txt
|
||||
self.textpos1.translation.setValue((-bound+self.space,-border+self.space,z))
|
||||
self.textpos2.translation.setValue((-bound-self.space,-bound+self.space,z))
|
||||
# human from BIM workbench
|
||||
loc = FreeCAD.Vector(-bound+self.space/2,-bound+self.space/2,0)
|
||||
try:
|
||||
import BimProject
|
||||
hpts = BimProject.getHuman(loc)
|
||||
except Exception:
|
||||
# BIM not installed
|
||||
pass
|
||||
else:
|
||||
mpts.extend([tuple(p) for p in hpts])
|
||||
midx.append(len(hpts))
|
||||
else:
|
||||
self.text1.string = " "
|
||||
self.text2.string = " "
|
||||
@@ -1130,8 +1129,36 @@ class gridTracker(Tracker):
|
||||
self.coords3.point.setValues(apts)
|
||||
#self.lines3.numVertices.setValues(aidx)
|
||||
self.pts = pts
|
||||
self.displayHumanFigure()
|
||||
self.setAxesColor()
|
||||
|
||||
def displayHumanFigure(self):
|
||||
""" Display the human figure at the grid corner.
|
||||
The silhouette is displayed only if:
|
||||
- BIM Workbench is available;
|
||||
- preference BaseApp/Preferences/Mod/Draft/gridShowHuman is True;
|
||||
- the working plane normal is vertical.
|
||||
"""
|
||||
numlines = self.numlines // self.mainlines // 2 * 2 * self.mainlines
|
||||
bound = (numlines // 2) * self.space
|
||||
pts = []
|
||||
pidx = []
|
||||
param = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
|
||||
if param.GetBool("gridShowHuman", True) and \
|
||||
FreeCAD.DraftWorkingPlane.axis.getAngle(FreeCAD.Vector(0,0,1)) < 0.001:
|
||||
try:
|
||||
import BimProject
|
||||
loc = FreeCAD.Vector(-bound+self.space/2,-bound+self.space/2,0)
|
||||
hpts = BimProject.getHuman(loc)
|
||||
pts.extend([tuple(p) for p in hpts])
|
||||
pidx.append(len(hpts))
|
||||
except Exception:
|
||||
# BIM not installed
|
||||
return
|
||||
self.human.numVertices.deleteValues(0)
|
||||
self.coords_human.point.setValues(pts)
|
||||
self.human.numVertices.setValues(pidx)
|
||||
|
||||
def setAxesColor(self):
|
||||
"""set axes color"""
|
||||
cols = [0,0]
|
||||
@@ -1180,6 +1207,7 @@ class gridTracker(Tracker):
|
||||
P = FreeCAD.DraftWorkingPlane.position
|
||||
self.trans.rotation.setValue([Q[0], Q[1], Q[2], Q[3]])
|
||||
self.trans.translation.setValue([P.x, P.y, P.z])
|
||||
self.displayHumanFigure()
|
||||
self.setAxesColor()
|
||||
self.on()
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ if App.GuiUp:
|
||||
from draftviewproviders.view_base import ViewProviderDraft
|
||||
|
||||
|
||||
def make_ellipse(majradius, minradius, placement=None, face=True, support=None):
|
||||
def make_ellipse(majradius, minradius, placement=None, face=None, support=None):
|
||||
"""make_ellipse(majradius, minradius, [placement], [face], [support])
|
||||
|
||||
Makes an ellipse with the given major and minor radius, and optionally
|
||||
|
||||
@@ -23,12 +23,12 @@
|
||||
"""This module contains FreeCAD commands for the Draft workbench"""
|
||||
|
||||
import FreeCAD
|
||||
from draftobjects.hatch import Draft_Hatch_Object
|
||||
from draftviewproviders.view_hatch import Draft_Hatch_ViewProvider
|
||||
from draftobjects.hatch import Hatch
|
||||
from draftviewproviders.view_hatch import ViewProviderDraftHatch
|
||||
|
||||
def makeHatch(baseobject, filename, pattern, scale, rotation):
|
||||
def make_hatch(baseobject, filename, pattern, scale, rotation):
|
||||
|
||||
"""makeHatch(baseobject, filename, pattern, scale, rotation): Creates and returns a
|
||||
"""make_hatch(baseobject, filename, pattern, scale, rotation): Creates and returns a
|
||||
hatch object made by applying the given pattern of the given PAT file to the faces of
|
||||
the given base object. Given scale and rotation factors are applied to the hatch object.
|
||||
The result is a Part-based object created in the active document."""
|
||||
@@ -36,13 +36,11 @@ def makeHatch(baseobject, filename, pattern, scale, rotation):
|
||||
if not FreeCAD.ActiveDocument:
|
||||
return
|
||||
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Hatch")
|
||||
Draft_Hatch_Object(obj)
|
||||
Hatch(obj)
|
||||
obj.Base = baseobject
|
||||
obj.File = filename
|
||||
obj.Pattern = pattern
|
||||
obj.Scale = scale
|
||||
obj.Rotation = rotation
|
||||
if FreeCAD.GuiUp:
|
||||
Draft_Hatch_ViewProvider(obj.ViewObject)
|
||||
|
||||
make_hatch = makeHatch
|
||||
ViewProviderDraftHatch(obj.ViewObject)
|
||||
|
||||
@@ -30,7 +30,7 @@ from draftutils.translate import translate, QT_TRANSLATE_NOOP
|
||||
|
||||
|
||||
|
||||
class Draft_Hatch_Object:
|
||||
class Hatch:
|
||||
|
||||
|
||||
def __init__(self,obj):
|
||||
@@ -41,12 +41,6 @@ class Draft_Hatch_Object:
|
||||
def setProperties(self,obj):
|
||||
|
||||
pl = obj.PropertiesList
|
||||
if not "Placement" in pl:
|
||||
obj.addProperty("App::PropertyPlacement","Placement","Hatch",
|
||||
QT_TRANSLATE_NOOP("App::Property","The placement of this object"))
|
||||
if not "Shape" in pl:
|
||||
obj.addProperty("Part::PropertyPartShape","Shape","Hatch",
|
||||
QT_TRANSLATE_NOOP("App::Property","The shape of this object"))
|
||||
if not "Base" in pl:
|
||||
obj.addProperty("App::PropertyLink","Base","Hatch",
|
||||
QT_TRANSLATE_NOOP("App::Property","The base object used by this object"))
|
||||
@@ -103,23 +97,30 @@ class Draft_Hatch_Object:
|
||||
pla = obj.Placement
|
||||
shapes = []
|
||||
for face in obj.Base.Shape.Faces:
|
||||
face = face.copy()
|
||||
if obj.Translate:
|
||||
bpoint = face.CenterOfMass
|
||||
norm = face.normalAt(0,0)
|
||||
fpla = FreeCAD.Placement(bpoint,FreeCAD.Rotation(FreeCAD.Vector(0,0,1),norm))
|
||||
face.Placement = face.Placement.multiply(fpla.inverse())
|
||||
if obj.Rotation:
|
||||
face.rotate(FreeCAD.Vector(),FreeCAD.Vector(0,0,1),obj.Rotation)
|
||||
shape = TechDraw.makeGeomHatch(face,obj.Scale,obj.Pattern,obj.File)
|
||||
if obj.Rotation:
|
||||
shape.rotate(FreeCAD.Vector(),FreeCAD.Vector(0,0,1),-obj.Rotation)
|
||||
if obj.Translate:
|
||||
shape.Placement = shape.Placement.multiply(fpla)
|
||||
shapes.append(shape)
|
||||
if face.findPlane(): # Only planar faces.
|
||||
face = face.copy()
|
||||
if obj.Translate:
|
||||
e = face.Edges[0] # Todo: check for almost zero-length edge.
|
||||
sta = e.firstVertex().Point
|
||||
end = e.lastVertex().Point
|
||||
u = end.sub(sta).normalize()
|
||||
w = face.normalAt(0, 0)
|
||||
v = w.cross(u)
|
||||
m = FreeCAD.Matrix(u.x, v.x, w.x, sta.x,
|
||||
u.y, v.y, w.y, sta.y,
|
||||
u.z, v.z, w.z, sta.z,
|
||||
0.0, 0.0, 0.0, 1.0)
|
||||
face = face.transformGeometry(m.inverse()).Faces[0]
|
||||
if obj.Rotation.Value:
|
||||
face.rotate(FreeCAD.Vector(), FreeCAD.Vector(0,0,1), -obj.Rotation)
|
||||
shape = TechDraw.makeGeomHatch(face, obj.Scale, obj.Pattern, obj.File)
|
||||
if obj.Rotation.Value:
|
||||
shape.rotate(FreeCAD.Vector(), FreeCAD.Vector(0,0,1), obj.Rotation)
|
||||
if obj.Translate:
|
||||
shape = shape.transformGeometry(m)
|
||||
shapes.append(shape)
|
||||
if shapes:
|
||||
obj.Shape = Part.makeCompound(shapes)
|
||||
obj.Placement = pla
|
||||
|
||||
def getPatterns(self,filename):
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# ***************************************************************************
|
||||
# * (c) 2020 Eliud Cabrera Castillo <[email protected]> *
|
||||
# * Copyright (c) 2020 Eliud Cabrera Castillo <[email protected]> *
|
||||
# * Copyright (c) 2021 FreeCAD Developers *
|
||||
# * *
|
||||
# * This file is part of the FreeCAD CAx development system. *
|
||||
# * *
|
||||
@@ -20,13 +21,9 @@
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
"""Provides lists of commands in order to set up toolbars of the workbench.
|
||||
|
||||
This module returns lists of commands, so that the toolbars
|
||||
can be initialized by Draft, and by other workbenches.
|
||||
These commands should be defined in `DraftTools`, and in the individual
|
||||
modules in `draftguitools`.
|
||||
"""
|
||||
"""Provides functions and lists of commands to set up Draft menus and toolbars."""
|
||||
|
||||
## @package init_tools
|
||||
# \ingroup draftutils
|
||||
# \brief Provides lists of commands to set up toolbars of the workbench.
|
||||
@@ -40,137 +37,188 @@ from PySide.QtCore import QT_TRANSLATE_NOOP
|
||||
|
||||
def get_draft_drawing_commands():
|
||||
"""Return the drawing commands list."""
|
||||
return ["Draft_Line", "Draft_Wire", "Draft_Fillet",
|
||||
"Draft_ArcTools",
|
||||
"Draft_Circle", "Draft_Ellipse", "Draft_Rectangle",
|
||||
"Draft_Polygon", "Draft_BSpline", "Draft_BezierTools",
|
||||
"Draft_Point", "Draft_Facebinder",
|
||||
"Draft_ShapeString","Draft_Hatch"]
|
||||
from draftguitools import gui_arcs
|
||||
from draftguitools import gui_beziers
|
||||
arc_group = gui_arcs.ArcGroup
|
||||
bez_group = gui_beziers.BezierGroup
|
||||
|
||||
return ["Draft_Line",
|
||||
"Draft_Wire",
|
||||
"Draft_Fillet",
|
||||
([QT_TRANSLATE_NOOP("Draft", "Arc tools")],
|
||||
list(arc_group.GetCommands(arc_group))), # tuple len=2: submenu
|
||||
("Draft_ArcTools", ), # tuple len=1: toolbar flyout
|
||||
"Draft_Circle",
|
||||
"Draft_Ellipse",
|
||||
"Draft_Rectangle",
|
||||
"Draft_Polygon",
|
||||
"Draft_BSpline",
|
||||
([QT_TRANSLATE_NOOP("Draft", "Bezier tools")],
|
||||
list(bez_group.GetCommands(bez_group))),
|
||||
("Draft_BezierTools", ),
|
||||
"Draft_Point",
|
||||
"Draft_Facebinder",
|
||||
"Draft_ShapeString",
|
||||
"Draft_Hatch"]
|
||||
|
||||
|
||||
def get_draft_annotation_commands():
|
||||
"""Return the annotation commands list."""
|
||||
return ["Draft_Text", "Draft_Dimension",
|
||||
"Draft_Label", "Draft_AnnotationStyleEditor"]
|
||||
|
||||
|
||||
def get_draft_array_commands():
|
||||
"""Return the array commands list."""
|
||||
return ["Draft_ArrayTools"]
|
||||
|
||||
|
||||
def get_draft_small_commands():
|
||||
"""Return a list with only some utilities."""
|
||||
return ["Draft_Layer",
|
||||
"Draft_WorkingPlaneProxy",
|
||||
"Draft_ToggleDisplayMode",
|
||||
"Draft_AddNamedGroup",
|
||||
"Draft_AddToGroup",
|
||||
"Draft_SelectGroup",
|
||||
"Draft_AddConstruction"]
|
||||
return ["Draft_Text",
|
||||
"Draft_Dimension",
|
||||
"Draft_Label",
|
||||
"Draft_AnnotationStyleEditor"]
|
||||
|
||||
|
||||
def get_draft_modification_commands():
|
||||
"""Return the modification commands list."""
|
||||
lst = ["Draft_Move", "Draft_Rotate",
|
||||
"Draft_Scale", "Draft_Mirror",
|
||||
"Draft_Offset", "Draft_Trimex",
|
||||
"Draft_Stretch",
|
||||
"Separator",
|
||||
"Draft_Clone"]
|
||||
lst += get_draft_array_commands()
|
||||
lst += ["Separator",
|
||||
"Draft_Edit", "Draft_SubelementHighlight",
|
||||
from draftguitools import gui_arrays
|
||||
arr_group = gui_arrays.ArrayGroup
|
||||
|
||||
return ["Draft_Move",
|
||||
"Draft_Rotate",
|
||||
"Draft_Scale",
|
||||
"Draft_Mirror",
|
||||
"Draft_Offset",
|
||||
"Draft_Trimex",
|
||||
"Draft_Stretch",
|
||||
"Separator",
|
||||
"Draft_Join", "Draft_Split",
|
||||
"Draft_Upgrade", "Draft_Downgrade",
|
||||
"Draft_Clone",
|
||||
([QT_TRANSLATE_NOOP("Draft", "Array tools")],
|
||||
list(arr_group.GetCommands(arr_group))), # tuple len=2: submenu
|
||||
("Draft_ArrayTools", ), # tuple len=1: toolbar flyout
|
||||
"Separator",
|
||||
"Draft_WireToBSpline", "Draft_Draft2Sketch",
|
||||
"Draft_Slope", "Draft_FlipDimension",
|
||||
"Draft_Edit",
|
||||
"Draft_SubelementHighlight",
|
||||
"Separator",
|
||||
"Draft_Join",
|
||||
"Draft_Split",
|
||||
"Draft_Upgrade",
|
||||
"Draft_Downgrade",
|
||||
"Separator",
|
||||
"Draft_WireToBSpline",
|
||||
"Draft_Draft2Sketch",
|
||||
"Draft_Slope",
|
||||
"Draft_FlipDimension",
|
||||
"Separator",
|
||||
"Draft_Shape2DView"]
|
||||
return lst
|
||||
|
||||
|
||||
def get_draft_context_commands():
|
||||
"""Return the context menu commands list."""
|
||||
return ["Draft_ApplyStyle", "Draft_ToggleDisplayMode",
|
||||
"Draft_AddNamedGroup", "Draft_AddToGroup", "Draft_SelectGroup",
|
||||
"Draft_SelectPlane", "Draft_ShowSnapBar",
|
||||
"Draft_ToggleGrid", "Draft_SetStyle"]
|
||||
|
||||
|
||||
def get_draft_line_commands():
|
||||
"""Return the line commands list."""
|
||||
return ["Draft_UndoLine", "Draft_FinishLine",
|
||||
"Draft_CloseLine"]
|
||||
|
||||
|
||||
def get_draft_utility_commands():
|
||||
"""Return the utility commands list."""
|
||||
return ["Draft_Layer",
|
||||
"Draft_Heal",
|
||||
def get_draft_utility_commands_menu():
|
||||
"""Return the utility commands list for the menu."""
|
||||
return ["Draft_SetStyle",
|
||||
"Draft_ApplyStyle",
|
||||
"Separator",
|
||||
"Draft_Layer",
|
||||
"Draft_AddNamedGroup",
|
||||
"Draft_AddToGroup",
|
||||
"Draft_SelectGroup",
|
||||
"Draft_ToggleConstructionMode",
|
||||
"Draft_ToggleContinueMode",
|
||||
"Draft_AddConstruction",
|
||||
"Separator",
|
||||
"Draft_ToggleDisplayMode",
|
||||
"Draft_ToggleGrid",
|
||||
"Draft_SelectPlane",
|
||||
"Draft_WorkingPlaneProxy",
|
||||
"Draft_AddConstruction"]
|
||||
"Separator",
|
||||
"Draft_Heal",
|
||||
"Draft_ToggleContinueMode",
|
||||
"Draft_ShowSnapBar"]
|
||||
|
||||
|
||||
def get_draft_utility_commands_toolbar():
|
||||
"""Return the utility commands list for the toolbar."""
|
||||
return ["Draft_Layer",
|
||||
"Draft_AddNamedGroup",
|
||||
"Draft_AddToGroup",
|
||||
"Draft_SelectGroup",
|
||||
"Draft_AddConstruction",
|
||||
"Draft_ToggleDisplayMode",
|
||||
"Draft_WorkingPlaneProxy"]
|
||||
|
||||
|
||||
def get_draft_snap_commands():
|
||||
"""Return the snapping commands list."""
|
||||
return ['Draft_Snap_Lock',
|
||||
'Draft_Snap_Endpoint', 'Draft_Snap_Midpoint',
|
||||
'Draft_Snap_Center', 'Draft_Snap_Angle',
|
||||
'Draft_Snap_Intersection', 'Draft_Snap_Perpendicular',
|
||||
'Draft_Snap_Extension', 'Draft_Snap_Parallel',
|
||||
'Draft_Snap_Special', 'Draft_Snap_Near',
|
||||
'Draft_Snap_Ortho', 'Draft_Snap_Grid',
|
||||
'Draft_Snap_WorkingPlane', 'Draft_Snap_Dimensions',
|
||||
'Separator', 'Draft_ToggleGrid'
|
||||
]
|
||||
'Draft_Snap_Endpoint',
|
||||
'Draft_Snap_Midpoint',
|
||||
'Draft_Snap_Center',
|
||||
'Draft_Snap_Angle',
|
||||
'Draft_Snap_Intersection',
|
||||
'Draft_Snap_Perpendicular',
|
||||
'Draft_Snap_Extension',
|
||||
'Draft_Snap_Parallel',
|
||||
'Draft_Snap_Special',
|
||||
'Draft_Snap_Near',
|
||||
'Draft_Snap_Ortho',
|
||||
'Draft_Snap_Grid',
|
||||
'Draft_Snap_WorkingPlane',
|
||||
'Draft_Snap_Dimensions',
|
||||
'Separator', 'Draft_ToggleGrid']
|
||||
|
||||
|
||||
def init_draft_toolbars(workbench):
|
||||
"""Initialize the Draft toolbars.
|
||||
def get_draft_context_commands():
|
||||
"""Return the context menu commands list."""
|
||||
return ["Draft_ApplyStyle",
|
||||
"Draft_ToggleDisplayMode",
|
||||
"Draft_AddNamedGroup",
|
||||
"Draft_AddToGroup",
|
||||
"Draft_SelectGroup",
|
||||
"Draft_SelectPlane",
|
||||
"Draft_ShowSnapBar",
|
||||
"Draft_ToggleGrid",
|
||||
"Draft_SetStyle"]
|
||||
|
||||
|
||||
def get_draft_line_commands():
|
||||
"""Return the line commands list."""
|
||||
return ["Draft_UndoLine",
|
||||
"Draft_FinishLine",
|
||||
"Draft_CloseLine"]
|
||||
|
||||
|
||||
def init_toolbar(workbench, toolbar, cmd_list):
|
||||
"""Initialize a toolbar.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
workbench: Gui.Workbench
|
||||
The workbench class on which the commands have to be available.
|
||||
If called from within the `Initialize` method
|
||||
of a workbench class defined inside `InitGui.py`,
|
||||
it can be used as `setup_draft_toolbars(self)`.
|
||||
The workbench. The commands from cmd_list must be available.
|
||||
|
||||
toolbar: string
|
||||
The name of the toolbar.
|
||||
|
||||
cmd_list: list of strings or list of strings and tuples
|
||||
See f.e. the return value of get_draft_drawing_commands.
|
||||
"""
|
||||
workbench.appendToolbar(QT_TRANSLATE_NOOP("Draft",
|
||||
"Draft creation tools"),
|
||||
get_draft_drawing_commands())
|
||||
workbench.appendToolbar(QT_TRANSLATE_NOOP("Draft",
|
||||
"Draft annotation tools"),
|
||||
get_draft_annotation_commands())
|
||||
workbench.appendToolbar(QT_TRANSLATE_NOOP("Draft",
|
||||
"Draft modification tools"),
|
||||
get_draft_modification_commands())
|
||||
for cmd in cmd_list:
|
||||
if isinstance(cmd, tuple):
|
||||
if len(cmd) == 1:
|
||||
workbench.appendToolbar(toolbar, [cmd[0]])
|
||||
else:
|
||||
workbench.appendToolbar(toolbar, [cmd])
|
||||
|
||||
|
||||
def init_draft_menus(workbench):
|
||||
"""Initialize the Draft menus.
|
||||
def init_menu(workbench, menu_list, cmd_list):
|
||||
"""Initialize a menu.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
workbench: Gui.Workbench
|
||||
The workbench class on which the commands have to be available.
|
||||
If called from within the `Initialize` method
|
||||
of a workbench class defined inside `InitGui.py`,
|
||||
it can be used as `setup_draft_menus(self)`.
|
||||
The workbench. The commands from cmd_list must be available.
|
||||
|
||||
menu_list: list of strings
|
||||
The main and optional submenu(s). The commands, and additional
|
||||
submenus (if any), are added to the last (sub)menu in the list.
|
||||
|
||||
cmd_list: list of strings or list of strings and tuples
|
||||
See f.e. the return value of get_draft_drawing_commands.
|
||||
"""
|
||||
workbench.appendMenu(QT_TRANSLATE_NOOP("Draft", "&Drafting"),
|
||||
get_draft_drawing_commands())
|
||||
workbench.appendMenu(QT_TRANSLATE_NOOP("Draft", "&Annotation"),
|
||||
get_draft_annotation_commands())
|
||||
workbench.appendMenu(QT_TRANSLATE_NOOP("Draft", "&Modification"),
|
||||
get_draft_modification_commands())
|
||||
workbench.appendMenu(QT_TRANSLATE_NOOP("Draft", "&Utilities"),
|
||||
get_draft_utility_commands()
|
||||
+ get_draft_context_commands())
|
||||
for cmd in cmd_list:
|
||||
if isinstance(cmd, tuple):
|
||||
if len(cmd) == 2:
|
||||
workbench.appendMenu(menu_list + cmd[0], cmd[1])
|
||||
else:
|
||||
workbench.appendMenu(menu_list, [cmd])
|
||||
|
||||
## @}
|
||||
|
||||
@@ -27,7 +27,7 @@ import os
|
||||
import FreeCAD
|
||||
from draftguitools.gui_hatch import Draft_Hatch_TaskPanel
|
||||
|
||||
class Draft_Hatch_ViewProvider:
|
||||
class ViewProviderDraftHatch:
|
||||
|
||||
|
||||
def __init__(self,vobj):
|
||||
|
||||
@@ -64,10 +64,7 @@
|
||||
#include <BRep_Tool.hxx>
|
||||
|
||||
#include <BRepAdaptor_CompCurve.hxx>
|
||||
#include <BRepAdaptor_HCompCurve.hxx>
|
||||
#include <Approx_Curve3d.hxx>
|
||||
#include <BRepAdaptor_HCurve.hxx>
|
||||
#include <BRepAdaptor_HCurve.hxx>
|
||||
#include <Geom_BSplineCurve.hxx>
|
||||
#include <Geom_BezierCurve.hxx>
|
||||
#include <GeomConvert_BSplineCurveToBezierCurve.hxx>
|
||||
@@ -75,11 +72,19 @@
|
||||
#include <Geom2d_BSplineCurve.hxx>
|
||||
#include <BRepLProp_CLProps.hxx>
|
||||
#include <Standard_Failure.hxx>
|
||||
#include <Standard_Version.hxx>
|
||||
#if OCC_VERSION_HEX < 0x070600
|
||||
#include <BRepAdaptor_HCurve.hxx>
|
||||
#endif
|
||||
|
||||
#include "DrawingExport.h"
|
||||
#include <Base/Tools.h>
|
||||
#include <Base/Vector3D.h>
|
||||
|
||||
#if OCC_VERSION_HEX >= 0x070600
|
||||
using BRepAdaptor_HCurve = BRepAdaptor_Curve;
|
||||
#endif
|
||||
|
||||
using namespace Drawing;
|
||||
using namespace std;
|
||||
|
||||
|
||||
@@ -61,10 +61,7 @@
|
||||
#include <BRepMesh_IncrementalMesh.hxx>
|
||||
#include <BRepLib.hxx>
|
||||
#include <BRepAdaptor_CompCurve.hxx>
|
||||
#include <BRepAdaptor_HCompCurve.hxx>
|
||||
#include <Approx_Curve3d.hxx>
|
||||
#include <BRepAdaptor_HCurve.hxx>
|
||||
#include <BRepAdaptor_HCurve.hxx>
|
||||
#include <Geom_BSplineCurve.hxx>
|
||||
#include <Geom_BezierCurve.hxx>
|
||||
#include <GeomConvert_BSplineCurveToBezierCurve.hxx>
|
||||
|
||||
@@ -36,8 +36,6 @@
|
||||
# include <BRepAdaptor_Curve.hxx>
|
||||
# include <GCPnts_AbscissaPoint.hxx>
|
||||
# include <Adaptor3d_IsoCurve.hxx>
|
||||
# include <Adaptor3d_HSurface.hxx>
|
||||
# include <BRepAdaptor_HSurface.hxx>
|
||||
# include <BRepAdaptor_Surface.hxx>
|
||||
# include <GProp_GProps.hxx>
|
||||
# include <BRepGProp.hxx>
|
||||
@@ -51,6 +49,11 @@
|
||||
# include <Geom_Plane.hxx>
|
||||
# include <Geom_Line.hxx>
|
||||
# include <Precision.hxx>
|
||||
# include <Standard_Version.hxx>
|
||||
# if OCC_VERSION_HEX < 0x070600
|
||||
# include <Adaptor3d_HSurface.hxx>
|
||||
# include <BRepAdaptor_HSurface.hxx>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "FemConstraint.h"
|
||||
@@ -74,6 +77,11 @@ double round(double r) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OCC_VERSION_HEX >= 0x070600
|
||||
using Adaptor3d_HSurface = Adaptor3d_Surface;
|
||||
using BRepAdaptor_HSurface = BRepAdaptor_Surface;
|
||||
#endif
|
||||
|
||||
PROPERTY_SOURCE(Fem::Constraint, App::DocumentObject)
|
||||
|
||||
Constraint::Constraint()
|
||||
|
||||
@@ -32,8 +32,6 @@
|
||||
#include <BRepAdaptor_Surface.hxx>
|
||||
#include <GCPnts_AbscissaPoint.hxx>
|
||||
#include <Adaptor3d_IsoCurve.hxx>
|
||||
#include <Adaptor3d_HSurface.hxx>
|
||||
#include <BRepAdaptor_HSurface.hxx>
|
||||
#include <GProp_GProps.hxx>
|
||||
#include <BRepGProp.hxx>
|
||||
#include <TopoDS_Vertex.hxx>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -49,7 +49,7 @@ class _Analysis(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_Analysis, self).__init__()
|
||||
self.menuetext = "Analysis container"
|
||||
self.menutext = "Analysis container"
|
||||
self.accel = "S, A"
|
||||
self.tooltip = "Creates an analysis container with standard solver CalculiX"
|
||||
self.is_active = "with_document"
|
||||
@@ -74,7 +74,7 @@ class _ClippingPlaneAdd(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_ClippingPlaneAdd, self).__init__()
|
||||
self.menuetext = "Clipping plane on face"
|
||||
self.menutext = "Clipping plane on face"
|
||||
self.tooltip = "Add a clipping plane on a selected face"
|
||||
self.is_active = "with_document"
|
||||
|
||||
@@ -119,11 +119,11 @@ class _ClippingPlaneAdd(CommandManager):
|
||||
|
||||
|
||||
class _ClippingPlaneRemoveAll(CommandManager):
|
||||
"The FEM_ClippingPlaneemoveAll command definition"
|
||||
"The FEM_ClippingPlaneRemoveAll command definition"
|
||||
|
||||
def __init__(self):
|
||||
super(_ClippingPlaneRemoveAll, self).__init__()
|
||||
self.menuetext = "Remove all clipping planes"
|
||||
self.menutext = "Remove all clipping planes"
|
||||
self.tooltip = "Remove all clipping planes"
|
||||
self.is_active = "with_document"
|
||||
|
||||
@@ -143,7 +143,7 @@ class _ConstantVacuumPermittivity(CommandManager):
|
||||
def __init__(self):
|
||||
super(_ConstantVacuumPermittivity, self).__init__()
|
||||
self.pixmap = "fem-solver-analysis-thermomechanical.svg"
|
||||
self.menuetext = "Constant vacuum permittivity"
|
||||
self.menutext = "Constant vacuum permittivity"
|
||||
self.tooltip = "Creates a FEM constant vacuum permittivity to overwrite standard value"
|
||||
self.is_active = "with_document"
|
||||
self.is_active = "with_analysis"
|
||||
@@ -156,7 +156,7 @@ class _ConstraintBodyHeatSource(CommandManager):
|
||||
def __init__(self):
|
||||
super(_ConstraintBodyHeatSource, self).__init__()
|
||||
self.pixmap = "FEM_ConstraintHeatflux" # the heatflux icon is used
|
||||
self.menuetext = "Constraint body heat source"
|
||||
self.menutext = "Constraint body heat source"
|
||||
self.tooltip = "Creates a FEM constraint body heat source"
|
||||
self.is_active = "with_analysis"
|
||||
self.do_activated = "add_obj_on_gui_noset_edit"
|
||||
@@ -167,7 +167,7 @@ class _ConstraintCentrif(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_ConstraintCentrif, self).__init__()
|
||||
self.menuetext = "Constraint centrif"
|
||||
self.menutext = "Constraint centrif"
|
||||
self.tooltip = "Creates a FEM constraint centrif"
|
||||
self.is_active = "with_analysis"
|
||||
self.do_activated = "add_obj_on_gui_set_edit"
|
||||
@@ -178,7 +178,7 @@ class _ConstraintElectrostaticPotential(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_ConstraintElectrostaticPotential, self).__init__()
|
||||
self.menuetext = "Constraint electrostatic potential"
|
||||
self.menutext = "Constraint electrostatic potential"
|
||||
self.tooltip = "Creates a FEM constraint electrostatic potential"
|
||||
self.is_active = "with_analysis"
|
||||
self.do_activated = "add_obj_on_gui_set_edit"
|
||||
@@ -189,7 +189,7 @@ class _ConstraintFlowVelocity(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_ConstraintFlowVelocity, self).__init__()
|
||||
self.menuetext = "Constraint flow velocity"
|
||||
self.menutext = "Constraint flow velocity"
|
||||
self.tooltip = "Creates a FEM constraint flow velocity"
|
||||
self.is_active = "with_analysis"
|
||||
self.do_activated = "add_obj_on_gui_set_edit"
|
||||
@@ -200,7 +200,7 @@ class _ConstraintInitialFlowVelocity(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_ConstraintInitialFlowVelocity, self).__init__()
|
||||
self.menuetext = "Constraint initial flow velocity"
|
||||
self.menutext = "Constraint initial flow velocity"
|
||||
self.tooltip = "Creates a FEM constraint initial flow velocity"
|
||||
self.is_active = "with_analysis"
|
||||
self.do_activated = "add_obj_on_gui_set_edit"
|
||||
@@ -211,7 +211,7 @@ class _ConstraintSectionPrint(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_ConstraintSectionPrint, self).__init__()
|
||||
self.menuetext = "Constraint sectionprint"
|
||||
self.menutext = "Constraint sectionprint"
|
||||
self.tooltip = "Creates a FEM constraint sectionprint"
|
||||
self.is_active = "with_analysis"
|
||||
self.do_activated = "add_obj_on_gui_set_edit"
|
||||
@@ -222,7 +222,7 @@ class _ConstraintSelfWeight(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_ConstraintSelfWeight, self).__init__()
|
||||
self.menuetext = "Constraint self weight"
|
||||
self.menutext = "Constraint self weight"
|
||||
self.tooltip = "Creates a FEM constraint self weight"
|
||||
self.is_active = "with_analysis"
|
||||
self.do_activated = "add_obj_on_gui_noset_edit"
|
||||
@@ -233,7 +233,7 @@ class _ConstraintTie(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_ConstraintTie, self).__init__()
|
||||
self.menuetext = "Constraint tie"
|
||||
self.menutext = "Constraint tie"
|
||||
self.tooltip = "Creates a FEM constraint tie"
|
||||
self.is_active = "with_analysis"
|
||||
self.do_activated = "add_obj_on_gui_set_edit"
|
||||
@@ -244,7 +244,7 @@ class _ElementFluid1D(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_ElementFluid1D, self).__init__()
|
||||
self.menuetext = "Fluid section for 1D flow"
|
||||
self.menutext = "Fluid section for 1D flow"
|
||||
self.tooltip = "Creates a FEM fluid section for 1D flow"
|
||||
self.is_active = "with_analysis"
|
||||
self.do_activated = "add_obj_on_gui_set_edit"
|
||||
@@ -255,7 +255,7 @@ class _ElementGeometry1D(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_ElementGeometry1D, self).__init__()
|
||||
self.menuetext = "Beam cross section"
|
||||
self.menutext = "Beam cross section"
|
||||
self.tooltip = "Creates a FEM beam cross section"
|
||||
self.is_active = "with_analysis"
|
||||
self.do_activated = "add_obj_on_gui_set_edit"
|
||||
@@ -266,7 +266,7 @@ class _ElementGeometry2D(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_ElementGeometry2D, self).__init__()
|
||||
self.menuetext = "Shell plate thickness"
|
||||
self.menutext = "Shell plate thickness"
|
||||
self.tooltip = "Creates a FEM shell plate thickness"
|
||||
self.is_active = "with_analysis"
|
||||
self.do_activated = "add_obj_on_gui_set_edit"
|
||||
@@ -277,7 +277,7 @@ class _ElementRotation1D(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_ElementRotation1D, self).__init__()
|
||||
self.menuetext = "Beam rotation"
|
||||
self.menutext = "Beam rotation"
|
||||
self.tooltip = "Creates a FEM beam rotation"
|
||||
self.is_active = "with_analysis"
|
||||
self.do_activated = "add_obj_on_gui_noset_edit"
|
||||
@@ -288,7 +288,7 @@ class _EquationElectrostatic(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_EquationElectrostatic, self).__init__()
|
||||
self.menuetext = "Electrostatic equation"
|
||||
self.menutext = "Electrostatic equation"
|
||||
self.tooltip = "Creates a FEM equation for electrostatic"
|
||||
self.is_active = "with_solver_elmer"
|
||||
self.do_activated = "add_obj_on_gui_selobj_noset_edit"
|
||||
@@ -299,7 +299,7 @@ class _EquationElasticity(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_EquationElasticity, self).__init__()
|
||||
self.menuetext = "Elasticity equation"
|
||||
self.menutext = "Elasticity equation"
|
||||
self.tooltip = "Creates a FEM equation for elasticity"
|
||||
self.is_active = "with_solver_elmer"
|
||||
self.do_activated = "add_obj_on_gui_selobj_noset_edit"
|
||||
@@ -310,7 +310,7 @@ class _EquationFlow(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_EquationFlow, self).__init__()
|
||||
self.menuetext = "Flow equation"
|
||||
self.menutext = "Flow equation"
|
||||
self.tooltip = "Creates a FEM equation for flow"
|
||||
self.is_active = "with_solver_elmer"
|
||||
self.do_activated = "add_obj_on_gui_selobj_noset_edit"
|
||||
@@ -321,7 +321,7 @@ class _EquationFlux(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_EquationFlux, self).__init__()
|
||||
self.menuetext = "Flux equation"
|
||||
self.menutext = "Flux equation"
|
||||
self.tooltip = "Creates a FEM equation for flux"
|
||||
self.is_active = "with_solver_elmer"
|
||||
self.do_activated = "add_obj_on_gui_selobj_noset_edit"
|
||||
@@ -332,7 +332,7 @@ class _EquationElectricforce(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_EquationElectricforce, self).__init__()
|
||||
self.menuetext = "Electricforce equation"
|
||||
self.menutext = "Electricforce equation"
|
||||
self.tooltip = "Creates a FEM equation for electric forces"
|
||||
self.is_active = "with_solver_elmer"
|
||||
self.do_activated = "add_obj_on_gui_selobj_noset_edit"
|
||||
@@ -343,7 +343,7 @@ class _EquationHeat(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_EquationHeat, self).__init__()
|
||||
self.menuetext = "Heat equation"
|
||||
self.menutext = "Heat equation"
|
||||
self.tooltip = "Creates a FEM equation for heat"
|
||||
self.is_active = "with_solver_elmer"
|
||||
self.do_activated = "add_obj_on_gui_selobj_noset_edit"
|
||||
@@ -355,7 +355,7 @@ class _Examples(CommandManager):
|
||||
def __init__(self):
|
||||
super(_Examples, self).__init__()
|
||||
self.pixmap = "FemWorkbench"
|
||||
self.menuetext = "Open FEM examples"
|
||||
self.menutext = "Open FEM examples"
|
||||
self.tooltip = "Open FEM examples"
|
||||
self.is_active = "always"
|
||||
|
||||
@@ -370,7 +370,7 @@ class _MaterialEditor(CommandManager):
|
||||
def __init__(self):
|
||||
super(_MaterialEditor, self).__init__()
|
||||
self.pixmap = "Arch_Material_Group"
|
||||
self.menuetext = "Material editor"
|
||||
self.menutext = "Material editor"
|
||||
self.tooltip = "Opens the FreeCAD material editor"
|
||||
self.is_active = "always"
|
||||
|
||||
@@ -384,7 +384,7 @@ class _MaterialFluid(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_MaterialFluid, self).__init__()
|
||||
self.menuetext = "Material for fluid"
|
||||
self.menutext = "Material for fluid"
|
||||
self.tooltip = "Creates a FEM material for fluid"
|
||||
self.is_active = "with_analysis"
|
||||
self.do_activated = "add_obj_on_gui_set_edit"
|
||||
@@ -395,7 +395,7 @@ class _MaterialMechanicalNonlinear(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_MaterialMechanicalNonlinear, self).__init__()
|
||||
self.menuetext = "Nonlinear mechanical material"
|
||||
self.menutext = "Nonlinear mechanical material"
|
||||
self.tooltip = "Creates a nonlinear mechanical material"
|
||||
self.is_active = "with_material_solid"
|
||||
|
||||
@@ -459,7 +459,7 @@ class _MaterialReinforced(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_MaterialReinforced, self).__init__()
|
||||
self.menuetext = "Reinforced material (concrete)"
|
||||
self.menutext = "Reinforced material (concrete)"
|
||||
self.tooltip = "Creates a material for reinforced matrix material such as concrete"
|
||||
self.is_active = "with_analysis"
|
||||
self.do_activated = "add_obj_on_gui_set_edit"
|
||||
@@ -470,7 +470,7 @@ class _MaterialSolid(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_MaterialSolid, self).__init__()
|
||||
self.menuetext = "Material for solid"
|
||||
self.menutext = "Material for solid"
|
||||
self.accel = "M, S"
|
||||
self.tooltip = "Creates a FEM material for solid"
|
||||
self.is_active = "with_analysis"
|
||||
@@ -482,7 +482,7 @@ class _FEMMesh2Mesh(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_FEMMesh2Mesh, self).__init__()
|
||||
self.menuetext = "FEM mesh to mesh"
|
||||
self.menutext = "FEM mesh to mesh"
|
||||
self.tooltip = "Convert the surface of a FEM mesh to a mesh"
|
||||
self.is_active = "with_femmesh_andor_res"
|
||||
|
||||
@@ -523,7 +523,7 @@ class _MeshBoundaryLayer(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_MeshBoundaryLayer, self).__init__()
|
||||
self.menuetext = "FEM mesh boundary layer"
|
||||
self.menutext = "FEM mesh boundary layer"
|
||||
self.tooltip = "Creates a FEM mesh boundary layer"
|
||||
self.is_active = "with_gmsh_femmesh"
|
||||
self.do_activated = "add_obj_on_gui_selobj_set_edit"
|
||||
@@ -534,7 +534,7 @@ class _MeshClear(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_MeshClear, self).__init__()
|
||||
self.menuetext = "Clear FEM mesh"
|
||||
self.menutext = "Clear FEM mesh"
|
||||
self.tooltip = "Clear the Mesh of a FEM mesh object"
|
||||
self.is_active = "with_femmesh"
|
||||
|
||||
@@ -553,7 +553,7 @@ class _MeshDisplayInfo(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_MeshDisplayInfo, self).__init__()
|
||||
self.menuetext = "Display FEM mesh info"
|
||||
self.menutext = "Display FEM mesh info"
|
||||
self.tooltip = "Display FEM mesh info"
|
||||
self.is_active = "with_femmesh"
|
||||
|
||||
@@ -576,7 +576,7 @@ class _MeshGmshFromShape(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_MeshGmshFromShape, self).__init__()
|
||||
self.menuetext = "FEM mesh from shape by Gmsh"
|
||||
self.menutext = "FEM mesh from shape by Gmsh"
|
||||
self.tooltip = "Create a FEM mesh from a shape by Gmsh mesher"
|
||||
self.is_active = "with_part_feature"
|
||||
|
||||
@@ -615,7 +615,7 @@ class _MeshGroup(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_MeshGroup, self).__init__()
|
||||
self.menuetext = "FEM mesh group"
|
||||
self.menutext = "FEM mesh group"
|
||||
self.tooltip = "Creates a FEM mesh group"
|
||||
self.is_active = "with_gmsh_femmesh"
|
||||
self.do_activated = "add_obj_on_gui_selobj_set_edit"
|
||||
@@ -626,7 +626,7 @@ class _MeshNetgenFromShape(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_MeshNetgenFromShape, self).__init__()
|
||||
self.menuetext = "FEM mesh from shape by Netgen"
|
||||
self.menutext = "FEM mesh from shape by Netgen"
|
||||
self.tooltip = "Create a FEM mesh from a solid or face shape by Netgen internal mesher"
|
||||
self.is_active = "with_part_feature"
|
||||
|
||||
@@ -665,7 +665,7 @@ class _MeshRegion(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_MeshRegion, self).__init__()
|
||||
self.menuetext = "FEM mesh region"
|
||||
self.menutext = "FEM mesh region"
|
||||
self.tooltip = "Creates a FEM mesh region"
|
||||
self.is_active = "with_gmsh_femmesh"
|
||||
self.do_activated = "add_obj_on_gui_selobj_set_edit"
|
||||
@@ -676,7 +676,7 @@ class _ResultShow(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_ResultShow, self).__init__()
|
||||
self.menuetext = "Show result"
|
||||
self.menutext = "Show result"
|
||||
self.accel = "R, S"
|
||||
self.tooltip = "Shows and visualizes selected result data"
|
||||
self.is_active = "with_selresult"
|
||||
@@ -690,7 +690,7 @@ class _ResultsPurge(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_ResultsPurge, self).__init__()
|
||||
self.menuetext = "Purge results"
|
||||
self.menutext = "Purge results"
|
||||
self.accel = "R, P"
|
||||
self.tooltip = "Purges all results from active analysis"
|
||||
self.is_active = "with_results"
|
||||
@@ -706,7 +706,7 @@ class _SolverCxxtools(CommandManager):
|
||||
def __init__(self):
|
||||
super(_SolverCxxtools, self).__init__()
|
||||
self.pixmap = "FEM_SolverStandard"
|
||||
self.menuetext = "Solver CalculiX Standard"
|
||||
self.menutext = "Solver CalculiX Standard"
|
||||
self.accel = "S, X"
|
||||
self.tooltip = "Creates a standard FEM solver CalculiX with ccx tools"
|
||||
self.is_active = "with_analysis"
|
||||
@@ -741,7 +741,7 @@ class _SolverCalculix(CommandManager):
|
||||
def __init__(self):
|
||||
super(_SolverCalculix, self).__init__()
|
||||
self.pixmap = "FEM_SolverStandard"
|
||||
self.menuetext = "Solver CalculiX (new framework)"
|
||||
self.menutext = "Solver CalculiX (new framework)"
|
||||
self.accel = "S, C"
|
||||
self.tooltip = "Creates a FEM solver CalculiX new framework (less result error handling)"
|
||||
self.is_active = "with_analysis"
|
||||
@@ -754,7 +754,7 @@ class _SolverControl(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_SolverControl, self).__init__()
|
||||
self.menuetext = "Solver job control"
|
||||
self.menutext = "Solver job control"
|
||||
self.accel = "S, T"
|
||||
self.tooltip = "Changes solver attributes and runs the calculations for the selected solver"
|
||||
self.is_active = "with_solver"
|
||||
@@ -768,7 +768,7 @@ class _SolverElmer(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_SolverElmer, self).__init__()
|
||||
self.menuetext = "Solver Elmer"
|
||||
self.menutext = "Solver Elmer"
|
||||
self.accel = "S, E"
|
||||
self.tooltip = "Creates a FEM solver Elmer"
|
||||
self.is_active = "with_analysis"
|
||||
@@ -781,7 +781,7 @@ class _SolverMystran(CommandManager):
|
||||
def __init__(self):
|
||||
super(_SolverMystran, self).__init__()
|
||||
self.pixmap = "FEM_SolverStandard"
|
||||
self.menuetext = "Solver Mystran"
|
||||
self.menutext = "Solver Mystran"
|
||||
self.accel = "S, M"
|
||||
self.tooltip = "Creates a FEM solver Mystran"
|
||||
self.is_active = "with_analysis"
|
||||
@@ -793,7 +793,7 @@ class _SolverRun(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_SolverRun, self).__init__()
|
||||
self.menuetext = "Run solver calculations"
|
||||
self.menutext = "Run solver calculations"
|
||||
self.accel = "S, R"
|
||||
self.tooltip = "Runs the calculations for the selected solver"
|
||||
self.is_active = "with_solver"
|
||||
@@ -810,7 +810,7 @@ class _SolverZ88(CommandManager):
|
||||
|
||||
def __init__(self):
|
||||
super(_SolverZ88, self).__init__()
|
||||
self.menuetext = "Solver Z88"
|
||||
self.menutext = "Solver Z88"
|
||||
self.accel = "S, Z"
|
||||
self.tooltip = "Creates a FEM solver Z88"
|
||||
self.is_active = "with_analysis"
|
||||
|
||||
@@ -46,9 +46,9 @@ class CommandManager(object):
|
||||
|
||||
self.command = "FEM" + self.__class__.__name__
|
||||
self.pixmap = self.command
|
||||
self.menuetext = self.__class__.__name__.lstrip("_")
|
||||
self.menutext = self.__class__.__name__.lstrip("_")
|
||||
self.accel = ""
|
||||
self.tooltip = "Creates a {}".format(self.menuetext)
|
||||
self.tooltip = "Creates a {}".format(self.menutext)
|
||||
self.resources = None
|
||||
|
||||
self.is_active = None
|
||||
@@ -61,7 +61,7 @@ class CommandManager(object):
|
||||
if self.resources is None:
|
||||
self.resources = {
|
||||
"Pixmap": self.pixmap,
|
||||
"MenuText": QtCore.QT_TRANSLATE_NOOP(self.command, self.menuetext),
|
||||
"MenuText": QtCore.QT_TRANSLATE_NOOP(self.command, self.menutext),
|
||||
"Accel": self.accel,
|
||||
"ToolTip": QtCore.QT_TRANSLATE_NOOP(self.command, self.tooltip)
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ def write(
|
||||
mesh_pynas_code += missing_code_pnynasmesh
|
||||
|
||||
# pynas file
|
||||
basefilename = filename[:len(filename) - 4] # TODO basename is more failsave
|
||||
basefilename = filename[:len(filename) - 4] # TODO basename is more failsafe
|
||||
pynasf = open(basefilename + ".py", "w")
|
||||
pynasf.write("# written by FreeCAD\n\n\n")
|
||||
pynasf.write("from pyNastran.bdf.bdf import BDF\n")
|
||||
|
||||
@@ -195,7 +195,7 @@ class _SolverDlg(object):
|
||||
|
||||
# set the binary path to the FreeCAD defaults
|
||||
# ATM pure unix shell commands without path names are used as standard
|
||||
# TODO the binaries provieded with the FreeCAD distribution should be found
|
||||
# TODO the binaries provided with the FreeCAD distribution should be found
|
||||
# without any additional user input
|
||||
# see ccxttols, it works for Windows and Linux there
|
||||
binary = self.default
|
||||
|
||||
@@ -55,19 +55,30 @@ class FemInputWriter():
|
||||
self.analysis_type = self.solver_obj.AnalysisType
|
||||
self.document = self.analysis.Document
|
||||
# working dir
|
||||
self.dir_name = dir_name
|
||||
# if dir_name was not given or if it exists but is not empty: create a temporary dir
|
||||
# Purpose: makes sure the analysis can be run even on wired situation
|
||||
if not dir_name:
|
||||
make_tmp_dir = False
|
||||
if dir_name is None:
|
||||
FreeCAD.Console.PrintWarning(
|
||||
"Error: FemInputWriter has no working_dir --> "
|
||||
"we are going to make a temporary one!\n"
|
||||
"Error: The working_dir in base input file writer class was not set. "
|
||||
"A temporary directory is used.\n"
|
||||
)
|
||||
self.dir_name = self.document.TransientDir.replace(
|
||||
"\\", "/"
|
||||
) + "/FemAnl_" + analysis_obj.Uid[-4:]
|
||||
if not os.path.isdir(self.dir_name):
|
||||
os.mkdir(self.dir_name)
|
||||
make_tmp_dir = True
|
||||
elif not os.path.isdir(dir_name):
|
||||
FreeCAD.Console.PrintWarning(
|
||||
"Error: The working_dir: '{}' given to "
|
||||
"base input file writer class does not exist. "
|
||||
"A temporary directory is used.\n".format(dir_name)
|
||||
)
|
||||
make_tmp_dir = True
|
||||
if make_tmp_dir is True:
|
||||
from tempfile import mkdtemp
|
||||
dir_name = mkdtemp(prefix="fcfem_")
|
||||
FreeCAD.Console.PrintWarning(
|
||||
"The working directory '{}' was created and will be used."
|
||||
.format(dir_name)
|
||||
)
|
||||
self.dir_name = dir_name
|
||||
|
||||
# new class attributes
|
||||
self.fc_ver = FreeCAD.Version()
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
# include <TDF_LabelSequence.hxx>
|
||||
# include <TDF_ChildIterator.hxx>
|
||||
# include <TDataStd_Name.hxx>
|
||||
# include <Quantity_Color.hxx>
|
||||
# include <Quantity_ColorRGBA.hxx>
|
||||
# include <STEPCAFControl_Reader.hxx>
|
||||
# include <STEPControl_Writer.hxx>
|
||||
# include <IGESCAFControl_Reader.hxx>
|
||||
@@ -95,6 +95,17 @@
|
||||
#include <App/DocumentObject.h>
|
||||
#include <App/DocumentObjectGroup.h>
|
||||
|
||||
#if OCC_VERSION_HEX >= 0x070500
|
||||
// See https://dev.opencascade.org/content/occt-3d-viewer-becomes-srgb-aware
|
||||
# define OCC_COLOR_SPACE Quantity_TOC_sRGB
|
||||
#else
|
||||
# define OCC_COLOR_SPACE Quantity_TOC_RGB
|
||||
#endif
|
||||
|
||||
static inline Quantity_ColorRGBA convertColor(const App::Color &c)
|
||||
{
|
||||
return Quantity_ColorRGBA(Quantity_Color(c.r, c.g, c.b, OCC_COLOR_SPACE), 1.0 - c.a);
|
||||
}
|
||||
|
||||
using namespace Import;
|
||||
|
||||
@@ -284,7 +295,7 @@ int ExportOCAF::saveShape(Part::Feature* part, const std::vector<App::Color>& co
|
||||
*/
|
||||
|
||||
// Add color information
|
||||
Quantity_Color col;
|
||||
Quantity_ColorRGBA col;
|
||||
|
||||
std::set<int> face_index;
|
||||
TopTools_IndexedMapOfShape faces;
|
||||
@@ -317,11 +328,7 @@ int ExportOCAF::saveShape(Part::Feature* part, const std::vector<App::Color>& co
|
||||
|
||||
if (!faceLabel.IsNull()) {
|
||||
const App::Color& color = colors[index-1];
|
||||
Standard_Real mat[3];
|
||||
mat[0] = color.r;
|
||||
mat[1] = color.g;
|
||||
mat[2] = color.b;
|
||||
col.SetValues(mat[0],mat[1],mat[2],Quantity_TOC_RGB);
|
||||
col = convertColor(color);
|
||||
aColorTool->SetColor(faceLabel, col, XCAFDoc_ColorSurf);
|
||||
}
|
||||
}
|
||||
@@ -330,11 +337,7 @@ int ExportOCAF::saveShape(Part::Feature* part, const std::vector<App::Color>& co
|
||||
}
|
||||
else if (!colors.empty()) {
|
||||
App::Color color = colors.front();
|
||||
Standard_Real mat[3];
|
||||
mat[0] = color.r;
|
||||
mat[1] = color.g;
|
||||
mat[2] = color.b;
|
||||
col.SetValues(mat[0],mat[1],mat[2],Quantity_TOC_RGB);
|
||||
col = convertColor(color);
|
||||
aColorTool->SetColor(shapeLabel, col, XCAFDoc_ColorGen);
|
||||
}
|
||||
|
||||
@@ -400,7 +403,7 @@ void ExportOCAF::reallocateFreeShape(std::vector <App::DocumentObject*> hierarch
|
||||
TopoDS_Shape baseShape = part->Shape.getValue();
|
||||
|
||||
// Add color information
|
||||
Quantity_Color col;
|
||||
Quantity_ColorRGBA col;
|
||||
|
||||
std::set<int> face_index;
|
||||
TopTools_IndexedMapOfShape faces;
|
||||
@@ -433,11 +436,7 @@ void ExportOCAF::reallocateFreeShape(std::vector <App::DocumentObject*> hierarch
|
||||
|
||||
if (!faceLabel.IsNull()) {
|
||||
const App::Color& color = colors[index-1];
|
||||
Standard_Real mat[3];
|
||||
mat[0] = color.r;
|
||||
mat[1] = color.g;
|
||||
mat[2] = color.b;
|
||||
col.SetValues(mat[0],mat[1],mat[2],Quantity_TOC_RGB);
|
||||
col = convertColor(color);
|
||||
aColorTool->SetColor(faceLabel, col, XCAFDoc_ColorSurf);
|
||||
}
|
||||
}
|
||||
@@ -447,11 +446,7 @@ void ExportOCAF::reallocateFreeShape(std::vector <App::DocumentObject*> hierarch
|
||||
}
|
||||
else if (!colors.empty()) {
|
||||
App::Color color = colors.front();
|
||||
Standard_Real mat[3];
|
||||
mat[0] = color.r;
|
||||
mat[1] = color.g;
|
||||
mat[2] = color.b;
|
||||
col.SetValues(mat[0],mat[1],mat[2],Quantity_TOC_RGB);
|
||||
col = convertColor(color);
|
||||
aColorTool->SetColor(label, col, XCAFDoc_ColorGen);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
|
||||
#include <Approx_Curve3d.hxx>
|
||||
#include <BRepAdaptor_Curve.hxx>
|
||||
#include <BRepAdaptor_HCurve.hxx>
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRepBuilderAPI_MakeVertex.hxx>
|
||||
@@ -47,6 +46,7 @@
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#include <Standard_Version.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include <TopoDS_Vertex.hxx>
|
||||
@@ -55,6 +55,9 @@
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include <TColgp_Array1OfPnt.hxx>
|
||||
#if OCC_VERSION_HEX < 0x070600
|
||||
#include <BRepAdaptor_HCurve.hxx>
|
||||
#endif
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Parameter.h>
|
||||
@@ -68,6 +71,10 @@
|
||||
|
||||
using namespace Import;
|
||||
|
||||
#if OCC_VERSION_HEX >= 0x070600
|
||||
using BRepAdaptor_HCurve = BRepAdaptor_Curve;
|
||||
#endif
|
||||
|
||||
|
||||
//******************************************************************************
|
||||
// reading
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
# include <TDF_LabelSequence.hxx>
|
||||
# include <TDF_ChildIterator.hxx>
|
||||
# include <TDataStd_Name.hxx>
|
||||
# include <Quantity_Color.hxx>
|
||||
# include <Quantity_ColorRGBA.hxx>
|
||||
# include <STEPCAFControl_Reader.hxx>
|
||||
# include <STEPControl_Writer.hxx>
|
||||
# include <IGESCAFControl_Reader.hxx>
|
||||
@@ -108,6 +108,23 @@
|
||||
|
||||
using namespace Import;
|
||||
|
||||
#if OCC_VERSION_HEX >= 0x070500
|
||||
// See https://dev.opencascade.org/content/occt-3d-viewer-becomes-srgb-aware
|
||||
# define OCC_COLOR_SPACE Quantity_TOC_sRGB
|
||||
#else
|
||||
# define OCC_COLOR_SPACE Quantity_TOC_RGB
|
||||
#endif
|
||||
|
||||
static inline App::Color convertColor(const Quantity_ColorRGBA &c)
|
||||
{
|
||||
Standard_Real r, g, b;
|
||||
c.GetRGB().Values(r, g, b, OCC_COLOR_SPACE);
|
||||
return App::Color(static_cast<float>(r),
|
||||
static_cast<float>(g),
|
||||
static_cast<float>(b),
|
||||
1.0f - static_cast<float>(c.Alpha()));
|
||||
}
|
||||
|
||||
#define OCAF_KEEP_PLACEMENT
|
||||
|
||||
ImportOCAF::ImportOCAF(Handle(TDocStd_Document) h, App::Document* d, const std::string& name)
|
||||
@@ -439,14 +456,12 @@ void ImportOCAF::createShape(const TopoDS_Shape& aShape, const TopLoc_Location&
|
||||
|
||||
void ImportOCAF::loadColors(Part::Feature* part, const TopoDS_Shape& aShape)
|
||||
{
|
||||
Quantity_Color aColor;
|
||||
Quantity_ColorRGBA aColor;
|
||||
App::Color color(0.8f,0.8f,0.8f);
|
||||
if (aColorTool->GetColor(aShape, XCAFDoc_ColorGen, aColor) ||
|
||||
aColorTool->GetColor(aShape, XCAFDoc_ColorSurf, aColor) ||
|
||||
aColorTool->GetColor(aShape, XCAFDoc_ColorCurv, aColor)) {
|
||||
color.r = (float)aColor.Red();
|
||||
color.g = (float)aColor.Green();
|
||||
color.b = (float)aColor.Blue();
|
||||
color = convertColor(aColor);
|
||||
std::vector<App::Color> colors;
|
||||
colors.push_back(color);
|
||||
applyColors(part, colors);
|
||||
@@ -468,9 +483,7 @@ void ImportOCAF::loadColors(Part::Feature* part, const TopoDS_Shape& aShape)
|
||||
aColorTool->GetColor(xp.Current(), XCAFDoc_ColorSurf, aColor) ||
|
||||
aColorTool->GetColor(xp.Current(), XCAFDoc_ColorCurv, aColor)) {
|
||||
int index = faces.FindIndex(xp.Current());
|
||||
color.r = (float)aColor.Red();
|
||||
color.g = (float)aColor.Green();
|
||||
color.b = (float)aColor.Blue();
|
||||
color = convertColor(aColor);
|
||||
faceColors[index-1] = color;
|
||||
found_face_color = true;
|
||||
}
|
||||
@@ -551,7 +564,7 @@ void ImportXCAF::createShape(const TopoDS_Shape& shape, bool perface, bool setna
|
||||
part = static_cast<Part::Feature*>(doc->addObject("Part::Feature", default_name.c_str()));
|
||||
part->Label.setValue(default_name);
|
||||
part->Shape.setValue(shape);
|
||||
std::map<Standard_Integer, Quantity_Color>::const_iterator jt;
|
||||
std::map<Standard_Integer, Quantity_ColorRGBA>::const_iterator jt;
|
||||
jt = myColorMap.find(shape.HashCode(INT_MAX));
|
||||
|
||||
App::Color partColor(0.8f,0.8f,0.8f);
|
||||
@@ -596,11 +609,7 @@ void ImportXCAF::createShape(const TopoDS_Shape& shape, bool perface, bool setna
|
||||
jt = myColorMap.find(xp.Current().HashCode(INT_MAX));
|
||||
if (jt != myColorMap.end()) {
|
||||
int index = faces.FindIndex(xp.Current());
|
||||
App::Color color;
|
||||
color.r = (float)jt->second.Red();
|
||||
color.g = (float)jt->second.Green();
|
||||
color.b = (float)jt->second.Blue();
|
||||
faceColors[index-1] = color;
|
||||
faceColors[index-1] = convertColor(jt->second);
|
||||
found_face_color = true;
|
||||
}
|
||||
xp.Next();
|
||||
@@ -653,7 +662,7 @@ void ImportXCAF::loadShapes(const TDF_Label& label)
|
||||
}
|
||||
|
||||
// getting color
|
||||
Quantity_Color col;
|
||||
Quantity_ColorRGBA col;
|
||||
if (hColors->GetColor(label, XCAFDoc_ColorGen, col) ||
|
||||
hColors->GetColor(label, XCAFDoc_ColorSurf, col) ||
|
||||
hColors->GetColor(label, XCAFDoc_ColorCurv, col)) {
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include <TDocStd_Document.hxx>
|
||||
#include <XCAFDoc_ColorTool.hxx>
|
||||
#include <XCAFDoc_ShapeTool.hxx>
|
||||
#include <Quantity_Color.hxx>
|
||||
#include <Quantity_ColorRGBA.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
#include <TDF_LabelMapHasher.hxx>
|
||||
#include <climits>
|
||||
@@ -117,7 +117,7 @@ private:
|
||||
std::map<Standard_Integer, TopoDS_Shape> myShells;
|
||||
std::map<Standard_Integer, TopoDS_Shape> myCompds;
|
||||
std::map<Standard_Integer, TopoDS_Shape> myShapes;
|
||||
std::map<Standard_Integer, Quantity_Color> myColorMap;
|
||||
std::map<Standard_Integer, Quantity_ColorRGBA> myColorMap;
|
||||
std::map<Standard_Integer, std::string> myNameMap;
|
||||
};
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
# include <TDF_LabelSequence.hxx>
|
||||
# include <TDF_ChildIterator.hxx>
|
||||
# include <TDataStd_Name.hxx>
|
||||
# include <Quantity_Color.hxx>
|
||||
# include <Quantity_ColorRGBA.hxx>
|
||||
# include <TopoDS_Iterator.hxx>
|
||||
# include <Interface_Static.hxx>
|
||||
# include <TDF_AttributeSequence.hxx>
|
||||
@@ -50,6 +50,7 @@
|
||||
|
||||
#include <XCAFDoc_ShapeMapTool.hxx>
|
||||
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <Base/Parameter.h>
|
||||
@@ -71,12 +72,40 @@
|
||||
#include <App/DocumentObject.h>
|
||||
#include <App/DocumentObjectGroup.h>
|
||||
|
||||
#if OCC_VERSION_HEX >= 0x070500
|
||||
// See https://dev.opencascade.org/content/occt-3d-viewer-becomes-srgb-aware
|
||||
# define OCC_COLOR_SPACE Quantity_TOC_sRGB
|
||||
#else
|
||||
# define OCC_COLOR_SPACE Quantity_TOC_RGB
|
||||
#endif
|
||||
|
||||
FC_LOG_LEVEL_INIT("Import",true,true)
|
||||
|
||||
using namespace Import;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
static inline App::Color convertColor(const Quantity_ColorRGBA &c)
|
||||
{
|
||||
Standard_Real r, g, b;
|
||||
c.GetRGB().Values(r, g, b, OCC_COLOR_SPACE);
|
||||
return App::Color(static_cast<float>(r),
|
||||
static_cast<float>(g),
|
||||
static_cast<float>(b),
|
||||
1.0f - static_cast<float>(c.Alpha()));
|
||||
}
|
||||
|
||||
static inline Quantity_ColorRGBA convertColor(const App::Color &c)
|
||||
{
|
||||
return Quantity_ColorRGBA(Quantity_Color(c.r, c.g, c.b, OCC_COLOR_SPACE), 1.0f - c.a);
|
||||
}
|
||||
|
||||
static inline std::ostream& operator<<(std::ostream& os, const Quantity_ColorRGBA &c) {
|
||||
App::Color color = convertColor(c);
|
||||
auto toHex = [](float v) {return boost::format("%02X") % static_cast<int>(v*255);};
|
||||
return os << "#" << toHex(color.r) << toHex(color.g) << toHex(color.b) << toHex(color.a);
|
||||
}
|
||||
|
||||
static std::string labelName(TDF_Label label) {
|
||||
std::string txt;
|
||||
Handle(TDataStd_Name) name;
|
||||
@@ -116,13 +145,13 @@ static void printLabel(TDF_Label label, Handle(XCAFDoc_ShapeTool) aShapeTool,
|
||||
ss << ", " << Part::TopoShape::shapeName(shape.ShapeType(),true);
|
||||
}
|
||||
if(aShapeTool->IsShape(label)) {
|
||||
Quantity_Color c;
|
||||
Quantity_ColorRGBA c;
|
||||
if(aColorTool->GetColor(label,XCAFDoc_ColorGen,c))
|
||||
ss << ", gc: " << c.StringName(c.Name());
|
||||
ss << ", gc: " << c;
|
||||
if(aColorTool->GetColor(label,XCAFDoc_ColorSurf,c))
|
||||
ss << ", sc: " << c.StringName(c.Name());
|
||||
ss << ", sc: " << c;
|
||||
if(aColorTool->GetColor(label,XCAFDoc_ColorCurv,c))
|
||||
ss << ", cc: " << c.StringName(c.Name());
|
||||
ss << ", cc: " << c;
|
||||
}
|
||||
|
||||
ss << std::endl;
|
||||
@@ -229,12 +258,11 @@ void ImportOCAF2::setObjectName(Info &info, TDF_Label label) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ImportOCAF2::getColor(const TopoDS_Shape &shape, Info &info, bool check, bool noDefault) {
|
||||
bool ret = false;
|
||||
Quantity_Color aColor;
|
||||
Quantity_ColorRGBA aColor;
|
||||
if(aColorTool->GetColor(shape, XCAFDoc_ColorSurf, aColor)) {
|
||||
App::Color c(aColor.Red(),aColor.Green(),aColor.Blue());
|
||||
App::Color c = convertColor(aColor);
|
||||
if(!check || info.faceColor!=c) {
|
||||
info.faceColor = c;
|
||||
info.hasFaceColor = true;
|
||||
@@ -242,7 +270,7 @@ bool ImportOCAF2::getColor(const TopoDS_Shape &shape, Info &info, bool check, bo
|
||||
}
|
||||
}
|
||||
if(!noDefault && !info.hasFaceColor && aColorTool->GetColor(shape, XCAFDoc_ColorGen, aColor)) {
|
||||
App::Color c(aColor.Red(),aColor.Green(),aColor.Blue());
|
||||
App::Color c = convertColor(aColor);
|
||||
if(!check || info.faceColor!=c) {
|
||||
info.faceColor = c;
|
||||
info.hasFaceColor = true;
|
||||
@@ -250,7 +278,7 @@ bool ImportOCAF2::getColor(const TopoDS_Shape &shape, Info &info, bool check, bo
|
||||
}
|
||||
}
|
||||
if(aColorTool->GetColor(shape, XCAFDoc_ColorCurv, aColor)) {
|
||||
App::Color c(aColor.Red(),aColor.Green(),aColor.Blue());
|
||||
App::Color c = convertColor(aColor);
|
||||
// Some STEP include a curve color with the same value of the face
|
||||
// color. And this will look weird in FC. So for shape with face
|
||||
// we'll ignore the curve color, if it is the same as the face color.
|
||||
@@ -365,15 +393,15 @@ bool ImportOCAF2::createObject(App::Document *doc, TDF_Label label,
|
||||
|
||||
bool foundFaceColor=false,foundEdgeColor=false;
|
||||
App::Color faceColor,edgeColor;
|
||||
Quantity_Color aColor;
|
||||
Quantity_ColorRGBA aColor;
|
||||
if(aColorTool->GetColor(l, XCAFDoc_ColorSurf, aColor) ||
|
||||
aColorTool->GetColor(l, XCAFDoc_ColorGen, aColor))
|
||||
{
|
||||
faceColor = App::Color(aColor.Red(),aColor.Green(),aColor.Blue());
|
||||
faceColor = convertColor(aColor);
|
||||
foundFaceColor = true;
|
||||
}
|
||||
if(aColorTool->GetColor(l, XCAFDoc_ColorCurv, aColor)) {
|
||||
edgeColor = App::Color(aColor.Red(),aColor.Green(),aColor.Blue());
|
||||
edgeColor = convertColor(aColor);
|
||||
foundEdgeColor = true;
|
||||
if(j==0 && foundFaceColor && faceColors.size() && edgeColor==faceColor) {
|
||||
// Do not set edge the same color as face
|
||||
@@ -648,11 +676,11 @@ void ImportOCAF2::getSHUOColors(TDF_Label label,
|
||||
subname += App::DocumentObject::hiddenMarker();
|
||||
colors.emplace(subname,App::Color());
|
||||
} else {
|
||||
Quantity_Color aColor;
|
||||
Quantity_ColorRGBA aColor;
|
||||
if(aColorTool->GetColor(slabel, XCAFDoc_ColorSurf, aColor) ||
|
||||
aColorTool->GetColor(slabel, XCAFDoc_ColorGen, aColor))
|
||||
{
|
||||
colors.emplace(subname,App::Color(aColor.Red(),aColor.Green(),aColor.Blue()));
|
||||
colors.emplace(subname,convertColor(aColor));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -782,12 +810,9 @@ bool ImportOCAF2::createAssembly(App::Document *_doc,
|
||||
childInfo.vis.push_back(vis);
|
||||
childInfo.labels.push_back(childLabel);
|
||||
childInfo.plas.emplace_back(Part::TopoShape::convert(childShape.Location().Transformation()));
|
||||
Quantity_Color aColor;
|
||||
Quantity_ColorRGBA aColor;
|
||||
if (aColorTool->GetColor(childShape, XCAFDoc_ColorSurf, aColor)) {
|
||||
auto &color = childInfo.colors[childInfo.plas.size()-1];
|
||||
color.r = (float)aColor.Red();
|
||||
color.g = (float)aColor.Green();
|
||||
color.b = (float)aColor.Blue();
|
||||
childInfo.colors[childInfo.plas.size()-1] = convertColor(aColor);
|
||||
}
|
||||
}
|
||||
assert(visibilities.size() == children.size());
|
||||
@@ -1036,7 +1061,7 @@ void ExportOCAF2::setupObject(TDF_Label label, App::DocumentObject *obj,
|
||||
continue;
|
||||
}
|
||||
const App::Color& c = vv.second;
|
||||
Quantity_Color color(c.r,c.g,c.b,Quantity_TOC_RGB);
|
||||
Quantity_ColorRGBA color = convertColor(c);
|
||||
auto colorType = vv.first[0]=='F'?XCAFDoc_ColorSurf:XCAFDoc_ColorCurv;
|
||||
if(vv.first=="Face" || vv.first=="Edge") {
|
||||
aColorTool->SetColor(nodeLabel, color, colorType);
|
||||
@@ -1219,8 +1244,17 @@ TDF_Label ExportOCAF2::exportObject(App::DocumentObject* parentObj,
|
||||
// not call setupObject() on a non-located baseshape like above,
|
||||
// because OCCT does not respect shape style sharing when not
|
||||
// exporting assembly
|
||||
if(!keepPlacement)
|
||||
if(!keepPlacement || shape.getPlacement() == Base::Placement())
|
||||
shape.setShape(shape.getShape().Located(TopLoc_Location()));
|
||||
else {
|
||||
Base::Matrix4D mat = shape.getTransform();
|
||||
shape.setShape(shape.getShape().Located(TopLoc_Location()));
|
||||
// Transform with copy to conceal the transformation
|
||||
shape.transformShape(mat, true);
|
||||
// Even if the shape has no transformation, TopoShape still sets
|
||||
// a TopLoc_Location, so we need to clear it again.
|
||||
shape.setShape(shape.getShape().Located(TopLoc_Location()));
|
||||
}
|
||||
label = aShapeTool->AddShape(shape.getShape(),Standard_False, Standard_False);
|
||||
auto o = name?parentObj:obj;
|
||||
if(o!=linked)
|
||||
@@ -1277,7 +1311,7 @@ TDF_Label ExportOCAF2::exportObject(App::DocumentObject* parentObj,
|
||||
// Work around OCCT bug. If no color setting here, it will crash.
|
||||
// The culprit is at STEPCAFControl_Writer::1093 as shown below
|
||||
//
|
||||
// surfColor = Styles.EncodeColor(Quantity_Color(1,1,1,Quantity_TOC_RGB),DPDCs,ColRGBs);
|
||||
// surfColor = Styles.EncodeColor(Quantity_Color(1,1,1,OCC_COLOR_SPACE),DPDCs,ColRGBs);
|
||||
// PSA = Styles.MakeColorPSA ( item, surfColor, curvColor, isComponent );
|
||||
// if ( isComponent )
|
||||
// setDefaultInstanceColor( override, PSA);
|
||||
@@ -1287,13 +1321,13 @@ TDF_Label ExportOCAF2::exportObject(App::DocumentObject* parentObj,
|
||||
// setDefaultInstanceColor( override, PSA);
|
||||
//
|
||||
auto childShape = aShapeTool->GetShape(childLabel);
|
||||
Quantity_Color col;
|
||||
Quantity_ColorRGBA col;
|
||||
if(!aColorTool->GetInstanceColor(childShape,XCAFDoc_ColorGen,col) &&
|
||||
!aColorTool->GetInstanceColor(childShape,XCAFDoc_ColorSurf,col) &&
|
||||
!aColorTool->GetInstanceColor(childShape,XCAFDoc_ColorCurv,col))
|
||||
{
|
||||
auto &c = defaultColor;
|
||||
aColorTool->SetColor(childLabel, Quantity_Color(c.r,c.g,c.b,Quantity_TOC_RGB), XCAFDoc_ColorGen);
|
||||
aColorTool->SetColor(childLabel, convertColor(c), XCAFDoc_ColorGen);
|
||||
FC_WARN(labelName(childLabel) << " set default color");
|
||||
}
|
||||
aColorTool->SetVisibility(childLabel,Standard_False);
|
||||
|
||||
@@ -322,9 +322,10 @@ private:
|
||||
return;
|
||||
}
|
||||
// vp->MapFaceColor.setValue(false);
|
||||
if(colors.size() == 1)
|
||||
if(colors.size() == 1) {
|
||||
vp->ShapeColor.setValue(colors.front());
|
||||
else
|
||||
vp->Transparency.setValue(100 * colors.front().a);
|
||||
} else
|
||||
vp->DiffuseColor.setValues(colors);
|
||||
}
|
||||
virtual void applyEdgeColors(Part::Feature* part, const std::vector<App::Color>& colors) override {
|
||||
|
||||
@@ -76,6 +76,7 @@ PyMOD_INIT_FUNC(Mesh)
|
||||
Mesh::PropertyMeshKernel ::init();
|
||||
|
||||
Mesh::MeshObject ::init();
|
||||
Mesh::MeshSegment ::init();
|
||||
|
||||
Mesh::Feature ::init();
|
||||
Mesh::FeatureCustom ::init();
|
||||
|
||||
@@ -399,6 +399,8 @@ endif ()
|
||||
|
||||
add_library(Mesh SHARED ${Core_SRCS} ${WildMagic4_SRCS} ${Mesh_SRCS})
|
||||
target_link_libraries(Mesh ${Mesh_LIBS})
|
||||
set_target_properties(Mesh PROPERTIES CXX_STANDARD_REQUIRED ON)
|
||||
set_target_properties(Mesh PROPERTIES CXX_STANDARD 17)
|
||||
|
||||
|
||||
SET_BIN_DIR(Mesh Mesh /Mod/Mesh)
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <algorithm>
|
||||
#include <string_view>
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
+38
-13
@@ -62,6 +62,7 @@ using namespace Mesh;
|
||||
float MeshObject::Epsilon = 1.0e-5f;
|
||||
|
||||
TYPESYSTEM_SOURCE(Mesh::MeshObject, Data::ComplexGeoData)
|
||||
TYPESYSTEM_SOURCE(Mesh::MeshSegment, Data::Segment)
|
||||
|
||||
MeshObject::MeshObject()
|
||||
{
|
||||
@@ -93,7 +94,7 @@ MeshObject::~MeshObject()
|
||||
std::vector<const char*> MeshObject::getElementTypes() const
|
||||
{
|
||||
std::vector<const char*> temp;
|
||||
temp.push_back("Face"); // that's the mesh itself
|
||||
temp.push_back("Mesh");
|
||||
temp.push_back("Segment");
|
||||
|
||||
return temp;
|
||||
@@ -102,31 +103,47 @@ std::vector<const char*> MeshObject::getElementTypes() const
|
||||
unsigned long MeshObject::countSubElements(const char* Type) const
|
||||
{
|
||||
std::string element(Type);
|
||||
if (element == "Face")
|
||||
if (element == "Mesh")
|
||||
return 1;
|
||||
else if (element == "Segment")
|
||||
return countSegments();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Data::Segment* MeshObject::getSubElement(const char* Type, unsigned long /*n*/) const
|
||||
Data::Segment* MeshObject::getSubElement(const char* Type, unsigned long n) const
|
||||
{
|
||||
//TODO
|
||||
std::string element(Type);
|
||||
if (element == "Face")
|
||||
return nullptr;
|
||||
else if (element == "Segment")
|
||||
return nullptr;
|
||||
if (element == "Mesh" && n == 0) {
|
||||
MeshSegment* segm = new MeshSegment();
|
||||
segm->mesh = new MeshObject(*this);
|
||||
return segm;
|
||||
}
|
||||
else if (element == "Segment" && n < countSegments()) {
|
||||
MeshSegment* segm = new MeshSegment();
|
||||
segm->mesh = new MeshObject(*this);
|
||||
const Segment& faces = getSegment(n);
|
||||
segm->segment.reset(new Segment(static_cast<MeshObject*>(segm->mesh), faces.getIndices(), false));
|
||||
return segm;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MeshObject::getFacesFromSubelement(const Data::Segment* /*segm*/,
|
||||
std::vector<Base::Vector3d> &Points,
|
||||
std::vector<Base::Vector3d> &/*PointNormals*/,
|
||||
void MeshObject::getFacesFromSubElement(const Data::Segment* element,
|
||||
std::vector<Base::Vector3d> &points,
|
||||
std::vector<Base::Vector3d> &/*pointNormals*/,
|
||||
std::vector<Facet> &faces) const
|
||||
{
|
||||
//TODO
|
||||
this->getFaces(Points, faces, 0.0f);
|
||||
if (element && element->getTypeId() == MeshSegment::getClassTypeId()) {
|
||||
const MeshSegment* segm = static_cast<const MeshSegment*>(element);
|
||||
if (segm->segment) {
|
||||
Base::Reference<MeshObject> submesh(segm->mesh->meshFromSegment(segm->segment->getIndices()));
|
||||
submesh->getFaces(points, faces, 0.0f);
|
||||
}
|
||||
else {
|
||||
segm->mesh->getFaces(points, faces, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MeshObject::transformGeometry(const Base::Matrix4D &rclMat)
|
||||
@@ -161,6 +178,14 @@ Base::BoundBox3d MeshObject::getBoundBox()const
|
||||
return Bnd2;
|
||||
}
|
||||
|
||||
bool MeshObject::getCenterOfGravity(Base::Vector3d& center) const
|
||||
{
|
||||
MeshCore::MeshAlgorithm alg(_kernel);
|
||||
Base::Vector3f pnt = alg.GetGravityPoint();
|
||||
center = transformToOutside(pnt);
|
||||
return true;
|
||||
}
|
||||
|
||||
void MeshObject::copySegments(const MeshObject& mesh)
|
||||
{
|
||||
// After copying the segments the mesh pointers must be adjusted
|
||||
|
||||
+18
-2
@@ -60,6 +60,21 @@ class AbstractPolygonTriangulator;
|
||||
|
||||
namespace Mesh
|
||||
{
|
||||
|
||||
class MeshObject;
|
||||
class MeshExport MeshSegment : public Data::Segment
|
||||
{
|
||||
TYPESYSTEM_HEADER();
|
||||
|
||||
public:
|
||||
virtual std::string getName() const {
|
||||
return "MeshSegment";
|
||||
}
|
||||
|
||||
Base::Reference<MeshObject> mesh;
|
||||
std::unique_ptr<Mesh::Segment> segment;
|
||||
};
|
||||
|
||||
/**
|
||||
* The MeshObject class provides an interface for the underlying MeshKernel class and
|
||||
* most of its algorithm on it.
|
||||
@@ -97,7 +112,7 @@ public:
|
||||
/// get the subelement by type and number
|
||||
virtual Data::Segment* getSubElement(const char* Type, unsigned long) const;
|
||||
/** Get faces from segment */
|
||||
virtual void getFacesFromSubelement(
|
||||
virtual void getFacesFromSubElement(
|
||||
const Data::Segment*,
|
||||
std::vector<Base::Vector3d> &Points,
|
||||
std::vector<Base::Vector3d> &PointNormals,
|
||||
@@ -142,7 +157,8 @@ public:
|
||||
const MeshCore::MeshKernel& getKernel() const
|
||||
{ return _kernel; }
|
||||
|
||||
virtual Base::BoundBox3d getBoundBox()const;
|
||||
virtual Base::BoundBox3d getBoundBox() const;
|
||||
virtual bool getCenterOfGravity(Base::Vector3d& center) const;
|
||||
|
||||
/** @name I/O */
|
||||
//@{
|
||||
|
||||
@@ -184,7 +184,12 @@ lines = mesh.section(mesh2, [ConnectLines=True, MinDist=0.0001])
|
||||
</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="countSegments" Const="true">
|
||||
<Methode Name="addSegment">
|
||||
<Documentation>
|
||||
<UserDocu>Add a list of facet indices that describes a segment to the mesh</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="countSegments" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Get the number of segments which may also be 0</UserDocu>
|
||||
</Documentation>
|
||||
|
||||
@@ -845,6 +845,27 @@ PyObject* MeshPy::getPointNormals(PyObject *args)
|
||||
} PY_CATCH;
|
||||
}
|
||||
|
||||
PyObject* MeshPy::addSegment(PyObject *args)
|
||||
{
|
||||
PyObject* pylist;
|
||||
if (!PyArg_ParseTuple(args, "O", &pylist))
|
||||
return nullptr;
|
||||
|
||||
Py::Sequence list(pylist);
|
||||
std::vector<Mesh::FacetIndex> segment;
|
||||
unsigned long numFacets = getMeshObjectPtr()->countFacets();
|
||||
segment.reserve(list.size());
|
||||
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
|
||||
Py::Long value(*it);
|
||||
Mesh::FacetIndex index = static_cast<unsigned long>(value);
|
||||
if (index < numFacets)
|
||||
segment.push_back(index);
|
||||
}
|
||||
|
||||
getMeshObjectPtr()->addSegment(segment);
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
PyObject* MeshPy::countSegments(PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
# LGPL
|
||||
|
||||
import FreeCAD, os, sys, unittest, Mesh
|
||||
from FreeCAD import Base
|
||||
import time, tempfile, math
|
||||
# http://python-kurs.eu/threads.php
|
||||
try:
|
||||
@@ -46,6 +47,43 @@ class MeshTopoTestCases(unittest.TestCase):
|
||||
planarMeshObject = Mesh.Mesh(self.planarMesh)
|
||||
planarMeshObject.collapseFacets(range(18))
|
||||
|
||||
def testCorruptedFacet(self):
|
||||
v = FreeCAD.Vector
|
||||
mesh = Mesh.Mesh()
|
||||
mesh.addFacet(
|
||||
v(1.0e1, -1.0e1, 1.0e1),
|
||||
v(1.0e1, +1.0e1, 1.0e1),
|
||||
v(0.0e0, 0.0e0, 1.0e1))
|
||||
|
||||
mesh.addFacet(
|
||||
v(-1.0e1, -1.0e1, 1.0e1),
|
||||
v(-1.0e1, +1.0e1, 1.0e1),
|
||||
v(0e0, 0.0e0, 1.0e1))
|
||||
|
||||
mesh.addFacet(
|
||||
v(+1.0e1, +1.0e1, 1.0e1),
|
||||
v(-1.0e1, +1.0e1, 1.0e1),
|
||||
v(.0e0, 0.0e0, 1.0e1))
|
||||
|
||||
mesh.addFacet(
|
||||
v(+1.0e1, -1.0e1, 1.0e1),
|
||||
v(-1.0e1, -1.0e1, 1.0e1),
|
||||
v(.0e0, 0.0e0, 1.0e1))
|
||||
|
||||
mesh.addFacet(
|
||||
v(-1.0e1, +1.0e1, 1.0e1),
|
||||
v(+1.0e1, +1.0e1, 1.0e1),
|
||||
v(+1.0e1, +1.0e1, 1.0e1))
|
||||
|
||||
mesh.addFacet(
|
||||
v(+1.0e1, +1.0e1, 1.0e1),
|
||||
v(+1.0e1, 00.0e1, 1.0e1),
|
||||
v(+1.0e1, -1.0e1, 1.0e1))
|
||||
|
||||
self.assertEqual(mesh.CountFacets, 6)
|
||||
mesh.fixIndices()
|
||||
self.assertEqual(mesh.CountFacets, 5)
|
||||
|
||||
|
||||
class MeshSplitTestCases(unittest.TestCase):
|
||||
def setUp(self):
|
||||
@@ -363,3 +401,43 @@ class NastranReader(unittest.TestCase):
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
class MeshSubElement(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.mesh = Mesh.createBox(1.0, 1.0, 1.0)
|
||||
|
||||
def testCenterOfGravity(self):
|
||||
c = self.mesh.CenterOfGravity
|
||||
self.assertEqual(c, Base.Vector(0.0, 0.0, 0.0))
|
||||
|
||||
def testSubElements(self):
|
||||
types = self.mesh.getElementTypes()
|
||||
self.assertIn("Mesh", types)
|
||||
self.assertIn("Segment", types)
|
||||
|
||||
def testCountSubElements(self):
|
||||
self.assertEqual(self.mesh.countSubElements("Mesh"), 1)
|
||||
self.assertEqual(self.mesh.countSubElements("Segment"), 0)
|
||||
|
||||
def testFacesFromSubElement(self):
|
||||
element = self.mesh.getFacesFromSubElement("Mesh", 0)
|
||||
self.assertIsInstance(element, tuple)
|
||||
self.assertEqual(len(element), 2)
|
||||
self.assertEqual(len(element[0]), 8)
|
||||
self.assertEqual(len(element[1]), 12)
|
||||
|
||||
def testSegmentSubElement(self):
|
||||
self.mesh.addSegment([0, 2, 4, 6, 8])
|
||||
self.assertEqual(self.mesh.countSegments(), 1)
|
||||
self.assertEqual(self.mesh.countSubElements("Segment"), 1)
|
||||
element = self.mesh.getFacesFromSubElement("Segment", 0)
|
||||
self.assertIsInstance(element, tuple)
|
||||
self.assertEqual(len(element), 2)
|
||||
self.assertEqual(len(element[0]), 7)
|
||||
self.assertEqual(len(element[1]), 5)
|
||||
segment = self.mesh.meshFromSegment(self.mesh.getSegment(0))
|
||||
self.assertEqual(segment.CountPoints, 7)
|
||||
self.assertEqual(segment.CountFacets, 5)
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
@@ -569,7 +569,7 @@ int System::Write8be (FILE* pkFile, int iQuantity, const void* pvData)
|
||||
const char* System::GetPath (const char* acDirectory, const char* acFilename)
|
||||
{
|
||||
// #0000656: WildMagic4 doesn't build on 64-bit Mac OS
|
||||
#if defined(__APPLE__) && !defined(__x86_64__)
|
||||
#if defined(__APPLE__) && !defined(__aarch64__) && !defined(__x86_64__)
|
||||
// An application-relative path is needed for the applications to be able
|
||||
// to find the input data sets. Unfortunately, there is no exact way to
|
||||
// predict which directory the application is run from, since this depends
|
||||
|
||||
@@ -237,7 +237,7 @@
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>The path to the directory for transfering files to and from OpenSCAD</string>
|
||||
<string>The path to the directory for transferring files to and from OpenSCAD</string>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>transferdirectory</cstring>
|
||||
|
||||
@@ -134,6 +134,7 @@
|
||||
#include "PartFeature.h"
|
||||
#include "PartPyCXX.h"
|
||||
#include "modelRefine.h"
|
||||
#include "Tools.h"
|
||||
|
||||
#ifdef FCUseFreeType
|
||||
# include "FT2FC.h"
|
||||
@@ -804,33 +805,24 @@ private:
|
||||
auto theShape = static_cast<Part::TopoShapePy*>(shape)->getTopoShapePtr()->getShape();
|
||||
for (TopExp_Explorer ex(theShape, TopAbs_FACE); ex.More(); ex.Next()) {
|
||||
TopoDS_Face currentFace = TopoDS::Face(ex.Current());
|
||||
TopLoc_Location loc;
|
||||
Handle(Poly_Triangulation) facets = BRep_Tool::Triangulation(currentFace, loc);
|
||||
const TopAbs_Orientation anOrientation = currentFace.Orientation();
|
||||
bool flip = (anOrientation == TopAbs_REVERSED);
|
||||
if (!facets.IsNull()) {
|
||||
const TColgp_Array1OfPnt& nodes = facets->Nodes();
|
||||
const Poly_Array1OfTriangle& triangles = facets->Triangles();
|
||||
for (int i = 1; i <= triangles.Length(); i++) {
|
||||
|
||||
std::vector<gp_Pnt> points;
|
||||
std::vector<Poly_Triangle> facets;
|
||||
if (Tools::getTriangulation(currentFace, points, facets)) {
|
||||
for (const auto& it : facets) {
|
||||
Standard_Integer n1,n2,n3;
|
||||
triangles(i).Get(n1, n2, n3);
|
||||
gp_Pnt p1 = nodes(n1);
|
||||
gp_Pnt p2 = nodes(n2);
|
||||
gp_Pnt p3 = nodes(n3);
|
||||
p1.Transform(loc.Transformation());
|
||||
p2.Transform(loc.Transformation());
|
||||
p3.Transform(loc.Transformation());
|
||||
it.Get(n1, n2, n3);
|
||||
|
||||
gp_Pnt p1 = points[n1];
|
||||
gp_Pnt p2 = points[n2];
|
||||
gp_Pnt p3 = points[n3];
|
||||
|
||||
// TODO: verify if tolerance should be hard coded
|
||||
if (!p1.IsEqual(p2, 0.01) && !p2.IsEqual(p3, 0.01) && !p3.IsEqual(p1, 0.01)) {
|
||||
PyObject *t1 = PyTuple_Pack(3, PyFloat_FromDouble(p1.X()), PyFloat_FromDouble(p1.Y()), PyFloat_FromDouble(p1.Z()));
|
||||
PyObject *t2 = PyTuple_Pack(3, PyFloat_FromDouble(p2.X()), PyFloat_FromDouble(p2.Y()), PyFloat_FromDouble(p2.Z()));
|
||||
PyObject *t3 = PyTuple_Pack(3, PyFloat_FromDouble(p3.X()), PyFloat_FromDouble(p3.Y()), PyFloat_FromDouble(p3.Z()));
|
||||
if (flip) {
|
||||
list.append(Py::asObject(PyTuple_Pack(3, t2, t1, t3)));
|
||||
}
|
||||
else {
|
||||
list.append(Py::asObject(PyTuple_Pack(3, t1, t2, t3)));
|
||||
}
|
||||
list.append(Py::asObject(PyTuple_Pack(3, t1, t2, t3)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,10 +24,13 @@
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <GeomAdaptor_Curve.hxx>
|
||||
# include <GeomAdaptor_HCurve.hxx>
|
||||
# include <Geom2dAdaptor_Curve.hxx>
|
||||
# include <Geom2dAdaptor_HCurve.hxx>
|
||||
# include <Standard_Failure.hxx>
|
||||
# include <Standard_Version.hxx>
|
||||
# if OCC_VERSION_HEX < 0x070600
|
||||
# include <GeomAdaptor_HCurve.hxx>
|
||||
# include <Geom2dAdaptor_HCurve.hxx>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "GeomPlate/CurveConstraintPy.h"
|
||||
@@ -76,6 +79,16 @@ int CurveConstraintPy::PyInit(PyObject* args, PyObject* kwds)
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if OCC_VERSION_HEX >= 0x070600
|
||||
Handle(Adaptor3d_Curve) hCurve;
|
||||
if (curve->getTypeId().isDerivedFrom(GeomTrimmedCurve::getClassTypeId())) {
|
||||
GeomTrimmedCurve* trim = static_cast<GeomTrimmedCurve*>(curve);
|
||||
hCurve = new GeomAdaptor_Curve(handle, trim->getFirstParameter(), trim->getLastParameter());
|
||||
}
|
||||
else {
|
||||
hCurve = new GeomAdaptor_Curve(handle);
|
||||
}
|
||||
#else
|
||||
Handle(Adaptor3d_HCurve) hCurve;
|
||||
if (curve->getTypeId().isDerivedFrom(GeomTrimmedCurve::getClassTypeId())) {
|
||||
GeomTrimmedCurve* trim = static_cast<GeomTrimmedCurve*>(curve);
|
||||
@@ -86,6 +99,7 @@ int CurveConstraintPy::PyInit(PyObject* args, PyObject* kwds)
|
||||
GeomAdaptor_Curve adapt(handle);
|
||||
hCurve = new GeomAdaptor_HCurve(adapt);
|
||||
}
|
||||
#endif
|
||||
|
||||
ptr.reset(new GeomPlate_CurveConstraint(hCurve, order, nbPts, tolDist, tolAng, tolCurv));
|
||||
}
|
||||
@@ -212,11 +226,15 @@ PyObject* CurveConstraintPy::curve3d(PyObject *args)
|
||||
return nullptr;
|
||||
|
||||
try {
|
||||
Handle(Adaptor3d_HCurve) hAdapt = getGeomPlate_CurveConstraintPtr()->Curve3d();
|
||||
auto hAdapt = getGeomPlate_CurveConstraintPtr()->Curve3d();
|
||||
if (hAdapt.IsNull())
|
||||
Py_Return;
|
||||
|
||||
#if OCC_VERSION_HEX >= 0x070600
|
||||
const Adaptor3d_Curve& a3d = *hAdapt;
|
||||
#else
|
||||
const Adaptor3d_Curve& a3d = hAdapt->Curve();
|
||||
#endif
|
||||
std::unique_ptr<GeomCurve> ptr(Part::makeFromCurveAdaptor(a3d));
|
||||
return ptr->getPyObject();
|
||||
}
|
||||
@@ -282,6 +300,16 @@ PyObject* CurveConstraintPy::setProjectedCurve(PyObject *args)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if OCC_VERSION_HEX >= 0x070600
|
||||
Handle(Adaptor2d_Curve2d) hCurve;
|
||||
if (handle->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) {
|
||||
Handle(Geom2d_TrimmedCurve) aTC (Handle(Geom2d_TrimmedCurve)::DownCast (handle));
|
||||
hCurve = new Geom2dAdaptor_Curve(handle, aTC->FirstParameter(), aTC->LastParameter());
|
||||
}
|
||||
else {
|
||||
hCurve = new Geom2dAdaptor_Curve(handle);
|
||||
}
|
||||
#else
|
||||
Handle(Adaptor2d_HCurve2d) hCurve;
|
||||
if (handle->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) {
|
||||
Handle(Geom2d_TrimmedCurve) aTC (Handle(Geom2d_TrimmedCurve)::DownCast (handle));
|
||||
@@ -292,6 +320,7 @@ PyObject* CurveConstraintPy::setProjectedCurve(PyObject *args)
|
||||
Geom2dAdaptor_Curve adapt(handle);
|
||||
hCurve = new Geom2dAdaptor_HCurve(adapt);
|
||||
}
|
||||
#endif
|
||||
|
||||
getGeomPlate_CurveConstraintPtr()->SetProjectedCurve(hCurve, tolU, tolV);
|
||||
Py_Return;
|
||||
@@ -308,11 +337,15 @@ PyObject* CurveConstraintPy::projectedCurve(PyObject *args)
|
||||
return nullptr;
|
||||
|
||||
try {
|
||||
Handle(Adaptor2d_HCurve2d) hAdapt = getGeomPlate_CurveConstraintPtr()->ProjectedCurve();
|
||||
auto hAdapt = getGeomPlate_CurveConstraintPtr()->ProjectedCurve();
|
||||
if (hAdapt.IsNull())
|
||||
Py_Return;
|
||||
|
||||
#if OCC_VERSION_HEX >= 0x070600
|
||||
const Adaptor2d_Curve2d& a2d = *hAdapt;
|
||||
#else
|
||||
const Adaptor2d_Curve2d& a2d = hAdapt->Curve2d();
|
||||
#endif
|
||||
std::unique_ptr<Geom2dCurve> ptr(Part::makeFromCurveAdaptor2d(a2d));
|
||||
return ptr->getPyObject();
|
||||
}
|
||||
|
||||
@@ -51,7 +51,6 @@
|
||||
# include <Geom_RectangularTrimmedSurface.hxx>
|
||||
# include <Geom_SurfaceOfRevolution.hxx>
|
||||
# include <Geom_SurfaceOfLinearExtrusion.hxx>
|
||||
# include <GeomAdaptor_HCurve.hxx>
|
||||
# include <GeomAPI_Interpolate.hxx>
|
||||
# include <GeomConvert.hxx>
|
||||
# include <GeomConvert_CompCurveToBSplineCurve.hxx>
|
||||
@@ -101,6 +100,9 @@
|
||||
# include <GeomAPI_ExtremaCurveCurve.hxx>
|
||||
# include <ShapeConstruct_Curve.hxx>
|
||||
# include <LProp_NotDefined.hxx>
|
||||
# if OCC_VERSION_HEX < 0x070600
|
||||
# include <GeomAdaptor_HCurve.hxx>
|
||||
# endif
|
||||
|
||||
# include <ctime>
|
||||
# include <cmath>
|
||||
@@ -144,6 +146,9 @@
|
||||
|
||||
#include "Geometry.h"
|
||||
|
||||
#if OCC_VERSION_HEX >= 0x070600
|
||||
using GeomAdaptor_HCurve = GeomAdaptor_Curve;
|
||||
#endif
|
||||
|
||||
using namespace Part;
|
||||
|
||||
|
||||
@@ -22,6 +22,11 @@
|
||||
<UserDocu>Return the shape for the geometry.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="toShell" Const="true" Keyword="true">
|
||||
<Documentation>
|
||||
<UserDocu>Make a shell of the surface.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="getD0" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Returns the point of given parameter</UserDocu>
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <BRepBuilderAPI_MakeFace.hxx>
|
||||
# include <BRepBuilderAPI_MakeShell.hxx>
|
||||
# include <gp_Circ.hxx>
|
||||
# include <gp_Dir.hxx>
|
||||
# include <gp_Elips.hxx>
|
||||
@@ -74,6 +75,7 @@
|
||||
#include <Mod/Part/App/TopoShape.h>
|
||||
#include <Mod/Part/App/TopoShapePy.h>
|
||||
#include <Mod/Part/App/TopoShapeFacePy.h>
|
||||
#include <Mod/Part/App/TopoShapeShellPy.h>
|
||||
|
||||
namespace Part {
|
||||
const Py::Object makeTrimmedCurvePy(const Handle(Geom_Curve)& c, double f, double l)
|
||||
@@ -153,6 +155,52 @@ PyObject* GeometrySurfacePy::toShape(PyObject *args)
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject* GeometrySurfacePy::toShell(PyObject *args, PyObject* kwds)
|
||||
{
|
||||
PyObject* bound = nullptr;
|
||||
PyObject* segm = nullptr;
|
||||
static char *kwlist[] = {"Bounds", "Segment", nullptr};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!O!", kwlist,
|
||||
&PyTuple_Type, &bound, &PyBool_Type, &segm))
|
||||
return nullptr;
|
||||
|
||||
Handle(Geom_Geometry) g = getGeometryPtr()->handle();
|
||||
Handle(Geom_Surface) s = Handle(Geom_Surface)::DownCast(g);
|
||||
try {
|
||||
if (!s.IsNull()) {
|
||||
if (segm) {
|
||||
Standard_Boolean segment = PyObject_IsTrue(segm) ? Standard_True : Standard_False;
|
||||
BRepBuilderAPI_MakeShell mkBuilder(s, segment);
|
||||
TopoDS_Shape sh = mkBuilder.Shape();
|
||||
return new TopoShapeShellPy(new TopoShape(sh));
|
||||
}
|
||||
else {
|
||||
double u1,u2,v1,v2;
|
||||
s->Bounds(u1,u2,v1,v2);
|
||||
|
||||
if (bound) {
|
||||
Py::Tuple tuple(bound);
|
||||
u1 = double(Py::Float(tuple[0]));
|
||||
u2 = double(Py::Float(tuple[1]));
|
||||
v1 = double(Py::Float(tuple[2]));
|
||||
v2 = double(Py::Float(tuple[3]));
|
||||
}
|
||||
|
||||
BRepBuilderAPI_MakeShell mkBuilder(s, u1, u2, v1, v2);
|
||||
TopoDS_Shape sh = mkBuilder.Shape();
|
||||
return new TopoShapeShellPy(new TopoShape(sh));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Standard_Failure& e) {
|
||||
PyErr_SetString(PartExceptionOCCError, e.GetMessageString());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PyErr_SetString(PartExceptionOCCError, "Geometry is not a surface");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PyObject* GeometrySurfacePy::getD0(PyObject *args)
|
||||
{
|
||||
Handle(Geom_Geometry) g = getGeometryPtr()->handle();
|
||||
|
||||
@@ -216,6 +216,7 @@
|
||||
#include <BRepBuilderAPI_MakeFace.hxx>
|
||||
#include <BRepBuilderAPI_MakeWire.hxx>
|
||||
#include <BRepBuilderAPI_MakePolygon.hxx>
|
||||
#include <BRepBuilderAPI_MakeShell.hxx>
|
||||
#include <BRepBuilderAPI_MakeSolid.hxx>
|
||||
#include <BRepBuilderAPI_MakeVertex.hxx>
|
||||
#include <BRepBuilderAPI_Sewing.hxx>
|
||||
|
||||
@@ -25,9 +25,7 @@
|
||||
#ifndef _PreComp_
|
||||
# include <BRepFill.hxx>
|
||||
# include <BRepAdaptor_Curve.hxx>
|
||||
# include <BRepAdaptor_HCurve.hxx>
|
||||
# include <BRepAdaptor_CompCurve.hxx>
|
||||
# include <BRepAdaptor_HCompCurve.hxx>
|
||||
# include <BRepLib_MakeWire.hxx>
|
||||
# include <Geom_BSplineSurface.hxx>
|
||||
# include <TopoDS.hxx>
|
||||
@@ -43,7 +41,7 @@
|
||||
# include <TopExp_Explorer.hxx>
|
||||
# include <TopoDS.hxx>
|
||||
# include <Precision.hxx>
|
||||
# include <Adaptor3d_HCurve.hxx>
|
||||
# include <memory>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -170,22 +168,18 @@ App::DocumentObjectExecReturn *RuledSurface::execute(void)
|
||||
|
||||
if (Orientation.getValue() == 0) {
|
||||
// Automatic
|
||||
Handle(Adaptor3d_HCurve) a1;
|
||||
Handle(Adaptor3d_HCurve) a2;
|
||||
std::unique_ptr<Adaptor3d_Curve> a1;
|
||||
std::unique_ptr<Adaptor3d_Curve> a2;
|
||||
if (!isWire) {
|
||||
BRepAdaptor_Curve adapt1(TopoDS::Edge(S1));
|
||||
BRepAdaptor_Curve adapt2(TopoDS::Edge(S2));
|
||||
a1 = new BRepAdaptor_HCurve(adapt1);
|
||||
a2 = new BRepAdaptor_HCurve(adapt2);
|
||||
a1 = std::make_unique<BRepAdaptor_Curve>(TopoDS::Edge(S1));
|
||||
a2 = std::make_unique<BRepAdaptor_Curve>(TopoDS::Edge(S2));
|
||||
}
|
||||
else {
|
||||
BRepAdaptor_CompCurve adapt1(TopoDS::Wire(S1));
|
||||
BRepAdaptor_CompCurve adapt2(TopoDS::Wire(S2));
|
||||
a1 = new BRepAdaptor_HCompCurve(adapt1);
|
||||
a2 = new BRepAdaptor_HCompCurve(adapt2);
|
||||
a1 = std::make_unique<BRepAdaptor_CompCurve>(TopoDS::Wire(S1));
|
||||
a2 = std::make_unique<BRepAdaptor_CompCurve>(TopoDS::Wire(S2));
|
||||
}
|
||||
|
||||
if (!a1.IsNull() && !a2.IsNull()) {
|
||||
if (a1 && a2) {
|
||||
// get end points of 1st curve
|
||||
Standard_Real first, last;
|
||||
first = a1->FirstParameter();
|
||||
|
||||
@@ -94,6 +94,7 @@
|
||||
#include "OpenCascadeAll.h"
|
||||
#include <math_Gauss.hxx>
|
||||
#include <math_Matrix.hxx>
|
||||
#include <Poly_Connect.hxx>
|
||||
|
||||
#elif defined(FC_OS_WIN32)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
+402
-2
@@ -25,25 +25,35 @@
|
||||
# include <cassert>
|
||||
# include <gp_Pln.hxx>
|
||||
# include <gp_Lin.hxx>
|
||||
# include <Adaptor3d_HCurveOnSurface.hxx>
|
||||
# include <BRep_Tool.hxx>
|
||||
# include <Geom_BSplineSurface.hxx>
|
||||
# include <Geom_Plane.hxx>
|
||||
# include <GeomAdaptor_HCurve.hxx>
|
||||
# include <GeomAPI_IntSS.hxx>
|
||||
# include <GeomAPI_ProjectPointOnSurf.hxx>
|
||||
# include <Geom_Line.hxx>
|
||||
# include <Geom_Point.hxx>
|
||||
# include <GeomAdaptor_Curve.hxx>
|
||||
# include <GeomLib.hxx>
|
||||
# include <GeomPlate_BuildPlateSurface.hxx>
|
||||
# include <GeomPlate_CurveConstraint.hxx>
|
||||
# include <GeomPlate_MakeApprox.hxx>
|
||||
# include <GeomPlate_PlateG0Criterion.hxx>
|
||||
# include <GeomPlate_PointConstraint.hxx>
|
||||
# include <Poly_Connect.hxx>
|
||||
# include <Poly_Triangulation.hxx>
|
||||
# include <Precision.hxx>
|
||||
# include <Standard_Mutex.hxx>
|
||||
# include <Standard_TypeMismatch.hxx>
|
||||
# include <Standard_Version.hxx>
|
||||
# include <TColStd_ListOfTransient.hxx>
|
||||
# include <TColStd_ListIteratorOfListOfTransient.hxx>
|
||||
# include <TColgp_SequenceOfXY.hxx>
|
||||
# include <TColgp_SequenceOfXYZ.hxx>
|
||||
# include <TopoDS.hxx>
|
||||
# if OCC_VERSION_HEX < 0x070600
|
||||
# include <Adaptor3d_HCurveOnSurface.hxx>
|
||||
# include <GeomAdaptor_HCurve.hxx>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <Base/Vector3D.h>
|
||||
@@ -138,6 +148,20 @@ Part::Tools::makeSurface(const TColStd_ListOfTransient &theBoundaries,
|
||||
assert (0);
|
||||
Standard_ConstructionError::Raise ("Tools::makeSurface()");
|
||||
}
|
||||
#if OCC_VERSION_HEX >= 0x070600
|
||||
else if (aCur->IsKind (STANDARD_TYPE (Adaptor3d_CurveOnSurface))) {
|
||||
//G1 constraint
|
||||
Handle(Adaptor3d_CurveOnSurface) aHCOS (Handle(Adaptor3d_CurveOnSurface)::DownCast (aCur));
|
||||
Handle (GeomPlate_CurveConstraint) aConst = new GeomPlate_CurveConstraint (aHCOS, 1 /*GeomAbs_G1*/,aNbPnts, aTol3d, anAngTol, aCurvTol);
|
||||
aPlateBuilder.Add (aConst);
|
||||
}
|
||||
else if (aCur->IsKind (STANDARD_TYPE (GeomAdaptor_Curve))) {
|
||||
//G0 constraint
|
||||
Handle(GeomAdaptor_Curve) aHC (Handle(GeomAdaptor_Curve)::DownCast (aCur));
|
||||
Handle (GeomPlate_CurveConstraint) aConst = new GeomPlate_CurveConstraint (aHC, 0 /*GeomAbs_G0*/, aNbPnts, aTol3d);
|
||||
aPlateBuilder.Add (aConst);
|
||||
}
|
||||
#else
|
||||
else if (aCur->IsKind (STANDARD_TYPE (Adaptor3d_HCurveOnSurface))) {
|
||||
//G1 constraint
|
||||
Handle(Adaptor3d_HCurveOnSurface) aHCOS (Handle(Adaptor3d_HCurveOnSurface)::DownCast (aCur));
|
||||
@@ -150,6 +174,7 @@ Part::Tools::makeSurface(const TColStd_ListOfTransient &theBoundaries,
|
||||
Handle (GeomPlate_CurveConstraint) aConst = new GeomPlate_CurveConstraint (aHC, 0 /*GeomAbs_G0*/, aNbPnts, aTol3d);
|
||||
aPlateBuilder.Add (aConst);
|
||||
}
|
||||
#endif
|
||||
else if (aCur->IsKind (STANDARD_TYPE (Geom_Point))) {
|
||||
//Point constraint
|
||||
Handle(Geom_Point) aGP (Handle(Geom_Point)::DownCast (aCur));
|
||||
@@ -190,3 +215,378 @@ Part::Tools::makeSurface(const TColStd_ListOfTransient &theBoundaries,
|
||||
|
||||
return aRes;
|
||||
}
|
||||
|
||||
bool Part::Tools::getTriangulation(const TopoDS_Face& face, std::vector<gp_Pnt>& points, std::vector<Poly_Triangle>& facets)
|
||||
{
|
||||
TopLoc_Location loc;
|
||||
Handle(Poly_Triangulation) hTria = BRep_Tool::Triangulation(face, loc);
|
||||
if (hTria.IsNull())
|
||||
return false;
|
||||
|
||||
// getting the transformation of the face
|
||||
gp_Trsf transf;
|
||||
bool identity = true;
|
||||
if (!loc.IsIdentity()) {
|
||||
identity = false;
|
||||
transf = loc.Transformation();
|
||||
}
|
||||
|
||||
// check orientation
|
||||
TopAbs_Orientation orient = face.Orientation();
|
||||
|
||||
Standard_Integer nbNodes = hTria->NbNodes();
|
||||
Standard_Integer nbTriangles = hTria->NbTriangles();
|
||||
#if OCC_VERSION_HEX < 0x070600
|
||||
const TColgp_Array1OfPnt& nodes = hTria->Nodes();
|
||||
const Poly_Array1OfTriangle& triangles = hTria->Triangles();
|
||||
#endif
|
||||
|
||||
points.reserve(nbNodes);
|
||||
facets.reserve(nbTriangles);
|
||||
|
||||
// cycling through the poly mesh
|
||||
//
|
||||
for (int i = 1; i <= nbNodes; i++) {
|
||||
#if OCC_VERSION_HEX < 0x070600
|
||||
gp_Pnt p = nodes(i);
|
||||
#else
|
||||
gp_Pnt p = hTria->Node(i);
|
||||
#endif
|
||||
|
||||
// transform the vertices to the location of the face
|
||||
if (!identity) {
|
||||
p.Transform(transf);
|
||||
}
|
||||
|
||||
points.push_back(p);
|
||||
}
|
||||
|
||||
for (int i = 1; i <= nbTriangles; i++) {
|
||||
// Get the triangle
|
||||
Standard_Integer n1,n2,n3;
|
||||
#if OCC_VERSION_HEX < 0x070600
|
||||
triangles(i).Get(n1, n2, n3);
|
||||
#else
|
||||
hTria->Triangle(i).Get(n1, n2, n3);
|
||||
#endif
|
||||
--n1; --n2; --n3;
|
||||
|
||||
// change orientation of the triangles
|
||||
if (orient != TopAbs_FORWARD) {
|
||||
std::swap(n1, n2);
|
||||
}
|
||||
|
||||
facets.emplace_back(n1, n2, n3);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Part::Tools::getPolygonOnTriangulation(const TopoDS_Edge& edge, const TopoDS_Face& face, std::vector<gp_Pnt>& points)
|
||||
{
|
||||
TopLoc_Location loc;
|
||||
Handle(Poly_Triangulation) hTria = BRep_Tool::Triangulation(face, loc);
|
||||
if (hTria.IsNull())
|
||||
return false;
|
||||
|
||||
// this holds the indices of the edge's triangulation to the actual points
|
||||
Handle(Poly_PolygonOnTriangulation) hPoly = BRep_Tool::PolygonOnTriangulation(edge, hTria, loc);
|
||||
if (hPoly.IsNull())
|
||||
return false;
|
||||
|
||||
// getting the transformation of the edge
|
||||
gp_Trsf transf;
|
||||
bool identity = true;
|
||||
if (!loc.IsIdentity()) {
|
||||
identity = false;
|
||||
transf = loc.Transformation();
|
||||
}
|
||||
|
||||
// getting size and create the array
|
||||
Standard_Integer nbNodes = hPoly->NbNodes();
|
||||
points.reserve(nbNodes);
|
||||
const TColStd_Array1OfInteger& indices = hPoly->Nodes();
|
||||
#if OCC_VERSION_HEX < 0x070600
|
||||
const TColgp_Array1OfPnt& Nodes = hTria->Nodes();
|
||||
#endif
|
||||
|
||||
// go through the index array
|
||||
for (Standard_Integer i = indices.Lower(); i <= indices.Upper(); i++) {
|
||||
#if OCC_VERSION_HEX < 0x070600
|
||||
gp_Pnt p = Nodes(indices(i));
|
||||
#else
|
||||
gp_Pnt p = hTria->Node(indices(i));
|
||||
#endif
|
||||
if (!identity) {
|
||||
p.Transform(transf);
|
||||
}
|
||||
|
||||
points.push_back(p);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Part::Tools::getPolygon3D(const TopoDS_Edge& edge, std::vector<gp_Pnt>& points)
|
||||
{
|
||||
TopLoc_Location loc;
|
||||
Handle(Poly_Polygon3D) hPoly = BRep_Tool::Polygon3D(edge, loc);
|
||||
if (hPoly.IsNull())
|
||||
return false;
|
||||
|
||||
// getting the transformation of the edge
|
||||
gp_Trsf transf;
|
||||
bool identity = true;
|
||||
if (!loc.IsIdentity()) {
|
||||
identity = false;
|
||||
transf = loc.Transformation();
|
||||
}
|
||||
|
||||
// getting size and create the array
|
||||
Standard_Integer nbNodes = hPoly->NbNodes();
|
||||
points.reserve(nbNodes);
|
||||
const TColgp_Array1OfPnt& nodes = hPoly->Nodes();
|
||||
|
||||
for (int i = 1; i <= nbNodes; i++) {
|
||||
gp_Pnt p = nodes(i);
|
||||
|
||||
// transform the vertices to the location of the face
|
||||
if (!identity) {
|
||||
p.Transform(transf);
|
||||
}
|
||||
|
||||
points.push_back(p);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Part::Tools::getPointNormals(const std::vector<gp_Pnt>& points, const std::vector<Poly_Triangle>& facets, std::vector<gp_Vec>& vertexnormals)
|
||||
{
|
||||
vertexnormals.resize(points.size());
|
||||
|
||||
for (const auto& it : facets) {
|
||||
// Get the triangle
|
||||
Standard_Integer n1,n2,n3;
|
||||
it.Get(n1,n2,n3);
|
||||
|
||||
// Calculate triangle normal
|
||||
gp_Vec v1(points[n1].XYZ());
|
||||
gp_Vec v2(points[n2].XYZ());
|
||||
gp_Vec v3(points[n3].XYZ());
|
||||
gp_Vec n = (v2 - v1) ^ (v3 - v1);
|
||||
|
||||
// add the triangle normal to the vertex normal for all points of this triangle
|
||||
vertexnormals[n1] += n;
|
||||
vertexnormals[n2] += n;
|
||||
vertexnormals[n3] += n;
|
||||
}
|
||||
|
||||
for (auto& it : vertexnormals)
|
||||
it.Normalize();
|
||||
}
|
||||
|
||||
void Part::Tools::getPointNormals(const std::vector<gp_Pnt>& points, const TopoDS_Face& face, std::vector<gp_Vec>& vertexnormals)
|
||||
{
|
||||
if (points.size() != vertexnormals.size())
|
||||
return;
|
||||
|
||||
Handle(Geom_Surface) hSurface = BRep_Tool::Surface(face);
|
||||
if (hSurface.IsNull())
|
||||
return;
|
||||
|
||||
// normalize all vertex normals
|
||||
for (std::size_t i = 0; i < points.size(); i++) {
|
||||
try {
|
||||
GeomAPI_ProjectPointOnSurf ProPntSrf(points[i], hSurface);
|
||||
Standard_Real u, v;
|
||||
ProPntSrf.Parameters(1, u, v);
|
||||
|
||||
GeomLProp_SLProps propOfFace(hSurface, u, v, 2, gp::Resolution());
|
||||
|
||||
gp_Dir normal = propOfFace.Normal();
|
||||
gp_Vec temp = normal;
|
||||
if (temp * vertexnormals[i] < 0.0)
|
||||
temp = -temp;
|
||||
vertexnormals[i] = temp;
|
||||
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
|
||||
vertexnormals[i].Normalize();
|
||||
}
|
||||
}
|
||||
|
||||
void Part::Tools::getPointNormals(const TopoDS_Face& theFace, Handle(Poly_Triangulation) aPolyTri, TColgp_Array1OfDir& theNormals)
|
||||
{
|
||||
#if OCC_VERSION_HEX < 0x070600
|
||||
const TColgp_Array1OfPnt& aNodes = aPolyTri->Nodes();
|
||||
|
||||
if(aPolyTri->HasNormals())
|
||||
{
|
||||
// normals pre-computed in triangulation structure
|
||||
const TShort_Array1OfShortReal& aNormals = aPolyTri->Normals();
|
||||
const Standard_ShortReal* aNormArr = &(aNormals.Value(aNormals.Lower()));
|
||||
|
||||
for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
|
||||
{
|
||||
const Standard_Integer anId = 3 * (aNodeIter - aNodes.Lower());
|
||||
const gp_Dir aNorm(aNormArr[anId + 0],
|
||||
aNormArr[anId + 1],
|
||||
aNormArr[anId + 2]);
|
||||
theNormals(aNodeIter) = aNorm;
|
||||
}
|
||||
|
||||
if(theFace.Orientation() == TopAbs_REVERSED)
|
||||
{
|
||||
for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
|
||||
{
|
||||
theNormals.ChangeValue(aNodeIter).Reverse();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// take in face the surface location
|
||||
Poly_Connect thePolyConnect(aPolyTri);
|
||||
const TopoDS_Face aZeroFace = TopoDS::Face(theFace.Located(TopLoc_Location()));
|
||||
Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aZeroFace);
|
||||
const Standard_Real aTol = Precision::Confusion();
|
||||
Handle(TShort_HArray1OfShortReal) aNormals = new TShort_HArray1OfShortReal(1, aPolyTri->NbNodes() * 3);
|
||||
const Poly_Array1OfTriangle& aTriangles = aPolyTri->Triangles();
|
||||
const TColgp_Array1OfPnt2d* aNodesUV = aPolyTri->HasUVNodes() && !aSurf.IsNull()
|
||||
? &aPolyTri->UVNodes()
|
||||
: nullptr;
|
||||
Standard_Integer aTri[3];
|
||||
|
||||
for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
|
||||
{
|
||||
// try to retrieve normal from real surface first, when UV coordinates are available
|
||||
if (!aNodesUV || GeomLib::NormEstim(aSurf, aNodesUV->Value(aNodeIter), aTol, theNormals(aNodeIter)) > 1)
|
||||
{
|
||||
// compute flat normals
|
||||
gp_XYZ eqPlan(0.0, 0.0, 0.0);
|
||||
|
||||
for(thePolyConnect.Initialize(aNodeIter); thePolyConnect.More(); thePolyConnect.Next())
|
||||
{
|
||||
aTriangles(thePolyConnect.Value()).Get(aTri[0], aTri[1], aTri[2]);
|
||||
const gp_XYZ v1(aNodes(aTri[1]).Coord() - aNodes(aTri[0]).Coord());
|
||||
const gp_XYZ v2(aNodes(aTri[2]).Coord() - aNodes(aTri[1]).Coord());
|
||||
const gp_XYZ vv = v1 ^ v2;
|
||||
const Standard_Real aMod = vv.Modulus();
|
||||
|
||||
if(aMod >= aTol)
|
||||
{
|
||||
eqPlan += vv / aMod;
|
||||
}
|
||||
}
|
||||
|
||||
const Standard_Real aModMax = eqPlan.Modulus();
|
||||
theNormals(aNodeIter) = (aModMax > aTol) ? gp_Dir(eqPlan) : gp::DZ();
|
||||
}
|
||||
|
||||
const Standard_Integer anId = (aNodeIter - aNodes.Lower()) * 3;
|
||||
aNormals->SetValue(anId + 1, (Standard_ShortReal)theNormals(aNodeIter).X());
|
||||
aNormals->SetValue(anId + 2, (Standard_ShortReal)theNormals(aNodeIter).Y());
|
||||
aNormals->SetValue(anId + 3, (Standard_ShortReal)theNormals(aNodeIter).Z());
|
||||
}
|
||||
|
||||
aPolyTri->SetNormals(aNormals);
|
||||
|
||||
if(theFace.Orientation() == TopAbs_REVERSED)
|
||||
{
|
||||
for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
|
||||
{
|
||||
theNormals.ChangeValue(aNodeIter).Reverse();
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
Standard_Integer numNodes = aPolyTri->NbNodes();
|
||||
|
||||
if(aPolyTri->HasNormals())
|
||||
{
|
||||
for(Standard_Integer aNodeIter = 1; aNodeIter <= numNodes; ++aNodeIter)
|
||||
{
|
||||
theNormals(aNodeIter) = aPolyTri->Normal(aNodeIter);
|
||||
}
|
||||
|
||||
if(theFace.Orientation() == TopAbs_REVERSED)
|
||||
{
|
||||
for(Standard_Integer aNodeIter = 1; aNodeIter <= numNodes; ++aNodeIter)
|
||||
{
|
||||
theNormals.ChangeValue(aNodeIter).Reverse();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// take in face the surface location
|
||||
Poly_Connect thePolyConnect(aPolyTri);
|
||||
const TopoDS_Face aZeroFace = TopoDS::Face(theFace.Located(TopLoc_Location()));
|
||||
Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aZeroFace);
|
||||
const Standard_Real aTol = Precision::Confusion();
|
||||
Standard_Boolean hasNodesUV = aPolyTri->HasUVNodes() && !aSurf.IsNull();
|
||||
Standard_Integer aTri[3];
|
||||
|
||||
aPolyTri->AddNormals();
|
||||
for(Standard_Integer aNodeIter = 1; aNodeIter <= numNodes; ++aNodeIter)
|
||||
{
|
||||
// try to retrieve normal from real surface first, when UV coordinates are available
|
||||
if (!hasNodesUV || GeomLib::NormEstim(aSurf, aPolyTri->UVNode(aNodeIter), aTol, theNormals(aNodeIter)) > 1)
|
||||
{
|
||||
// compute flat normals
|
||||
gp_XYZ eqPlan(0.0, 0.0, 0.0);
|
||||
|
||||
for(thePolyConnect.Initialize(aNodeIter); thePolyConnect.More(); thePolyConnect.Next())
|
||||
{
|
||||
aPolyTri->Triangle(thePolyConnect.Value()).Get(aTri[0], aTri[1], aTri[2]);
|
||||
const gp_XYZ v1(aPolyTri->Node(aTri[1]).Coord() - aPolyTri->Node(aTri[0]).Coord());
|
||||
const gp_XYZ v2(aPolyTri->Node(aTri[2]).Coord() - aPolyTri->Node(aTri[1]).Coord());
|
||||
const gp_XYZ vv = v1 ^ v2;
|
||||
const Standard_Real aMod = vv.Modulus();
|
||||
|
||||
if(aMod >= aTol)
|
||||
{
|
||||
eqPlan += vv / aMod;
|
||||
}
|
||||
}
|
||||
|
||||
const Standard_Real aModMax = eqPlan.Modulus();
|
||||
theNormals(aNodeIter) = (aModMax > aTol) ? gp_Dir(eqPlan) : gp::DZ();
|
||||
}
|
||||
|
||||
aPolyTri->SetNormal(aNodeIter, theNormals(aNodeIter));
|
||||
}
|
||||
|
||||
if(theFace.Orientation() == TopAbs_REVERSED)
|
||||
{
|
||||
for(Standard_Integer aNodeIter = 1; aNodeIter <= numNodes; ++aNodeIter)
|
||||
{
|
||||
theNormals.ChangeValue(aNodeIter).Reverse();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Part::Tools::getPointNormals(const TopoDS_Face& face, Handle(Poly_Triangulation) aPoly, std::vector<gp_Vec>& normals)
|
||||
{
|
||||
TColgp_Array1OfDir dirs (1, aPoly->NbNodes());
|
||||
getPointNormals(face, aPoly, dirs);
|
||||
normals.reserve(aPoly->NbNodes());
|
||||
|
||||
for (int i = dirs.Lower(); i <= dirs.Upper(); ++i) {
|
||||
normals.emplace_back(dirs(i).XYZ());
|
||||
}
|
||||
}
|
||||
|
||||
void Part::Tools::applyTransformationOnNormals(const TopLoc_Location& loc, std::vector<gp_Vec>& normals)
|
||||
{
|
||||
if (!loc.IsIdentity()) {
|
||||
gp_Trsf myTransf = loc.Transformation();
|
||||
|
||||
for (auto& it : normals) {
|
||||
it.Transform(myTransf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,14 @@
|
||||
#include <gp_Dir.hxx>
|
||||
#include <gp_XYZ.hxx>
|
||||
#include <Geom_Surface.hxx>
|
||||
#include <Poly_Triangle.hxx>
|
||||
#include <Poly_Triangulation.hxx>
|
||||
#include <TColStd_ListOfTransient.hxx>
|
||||
#include <TColgp_Array1OfDir.hxx>
|
||||
#include <TopLoc_Location.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <vector>
|
||||
|
||||
class gp_Lin;
|
||||
class gp_Pln;
|
||||
@@ -104,7 +111,72 @@ public:
|
||||
const Standard_Integer theNbPnts,
|
||||
const Standard_Integer theNbIter,
|
||||
const Standard_Integer theMaxDeg);
|
||||
|
||||
/*!
|
||||
* @brief getTriangulation
|
||||
* The indexes of the triangles are adjusted to the points vector.
|
||||
* @param face
|
||||
* @param points
|
||||
* @param facets
|
||||
* @return true if a triangulation exists or false otherwise
|
||||
*/
|
||||
static bool getTriangulation(const TopoDS_Face& face, std::vector<gp_Pnt>& points, std::vector<Poly_Triangle>& facets);
|
||||
/*!
|
||||
* \brief getPolygonOnTriangulation
|
||||
* Get the polygon of edge.
|
||||
* \note \a edge must belong to face.
|
||||
* \param edge
|
||||
* \param face
|
||||
* \param points
|
||||
* \return true if a triangulation exists or false otherwise
|
||||
*/
|
||||
static bool getPolygonOnTriangulation(const TopoDS_Edge& edge, const TopoDS_Face& face, std::vector<gp_Pnt>& points);
|
||||
/*!
|
||||
* \brief getPolygon3D
|
||||
* \param edge
|
||||
* \param points
|
||||
* \return true if a polygon exists or false otherwise
|
||||
*/
|
||||
static bool getPolygon3D(const TopoDS_Edge& edge, std::vector<gp_Pnt>& points);
|
||||
/*!
|
||||
* \brief getPointNormals
|
||||
* Calculate the point normals of the given triangulation.
|
||||
* \param points
|
||||
* \param facets
|
||||
* \param normals
|
||||
*/
|
||||
static void getPointNormals(const std::vector<gp_Pnt>& points, const std::vector<Poly_Triangle>& facets, std::vector<gp_Vec>& vertexnormals);
|
||||
/*!
|
||||
* \brief getPointNormals
|
||||
* Computes the more accurate surface normals for the points. If the calculation for a point fails then the precomputed
|
||||
* point normal of the triangulation is used.
|
||||
* \param points
|
||||
* \param face
|
||||
* \param vertexnormals
|
||||
*/
|
||||
static void getPointNormals(const std::vector<gp_Pnt>& points, const TopoDS_Face& face, std::vector<gp_Vec>& vertexnormals);
|
||||
/*!
|
||||
* \brief getPointNormals
|
||||
* Computes the exact surface normals for the points by using the UV coordinates of the mesh vertexes.
|
||||
* \param face
|
||||
* \param aPoly
|
||||
* \param vertexnormals
|
||||
*/
|
||||
static void getPointNormals(const TopoDS_Face& face, Handle(Poly_Triangulation) aPoly, TColgp_Array1OfDir& normals);
|
||||
/*!
|
||||
* \brief getPointNormals
|
||||
* Computes the exact surface normals for the points by using the UV coordinates of the mesh vertexes.
|
||||
* \param face
|
||||
* \param aPoly
|
||||
* \param vertexnormals
|
||||
*/
|
||||
static void getPointNormals(const TopoDS_Face& face, Handle(Poly_Triangulation) aPoly, std::vector<gp_Vec>& normals);
|
||||
/*!
|
||||
* \brief applyTransformationOnNormals
|
||||
* Apply the transformation to the vectors
|
||||
* \param loc
|
||||
* \param normals
|
||||
*/
|
||||
static void applyTransformationOnNormals(const TopLoc_Location& loc, std::vector<gp_Vec>& normals);
|
||||
};
|
||||
|
||||
} //namespace Part
|
||||
|
||||
+84
-201
@@ -38,8 +38,6 @@
|
||||
# include <BRep_Tool.hxx>
|
||||
# include <BRepAdaptor_Curve.hxx>
|
||||
# include <BRepAdaptor_CompCurve.hxx>
|
||||
# include <BRepAdaptor_HCurve.hxx>
|
||||
# include <BRepAdaptor_HCompCurve.hxx>
|
||||
# include <BRepAdaptor_Surface.hxx>
|
||||
# include <BRepAlgoAPI_Common.hxx>
|
||||
# include <BRepAlgoAPI_Cut.hxx>
|
||||
@@ -186,6 +184,12 @@
|
||||
#if OCC_VERSION_HEX >= 0x070300
|
||||
# include <BRepAlgoAPI_Defeaturing.hxx>
|
||||
#endif
|
||||
|
||||
#if OCC_VERSION_HEX < 0x070600
|
||||
# include <BRepAdaptor_HCurve.hxx>
|
||||
# include <BRepAdaptor_HCompCurve.hxx>
|
||||
#endif
|
||||
|
||||
#endif // _PreComp_
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
@@ -1097,65 +1101,27 @@ void TopoShape::exportFaceSet(double dev, double ca,
|
||||
for (ex.Init(this->_Shape, TopAbs_FACE); ex.More(); ex.Next(), index++) {
|
||||
// get the shape and mesh it
|
||||
const TopoDS_Face& aFace = TopoDS::Face(ex.Current());
|
||||
Standard_Integer nbNodesInFace,nbTriInFace;
|
||||
std::vector<gp_Pnt> points;
|
||||
std::vector<Poly_Triangle> facets;
|
||||
if (!Tools::getTriangulation(aFace, points, facets))
|
||||
continue;
|
||||
|
||||
std::vector<Base::Vector3f> vertices;
|
||||
std::vector<int> indices;
|
||||
vertices.resize(points.size());
|
||||
indices.resize(4 * facets.size());
|
||||
|
||||
// doing the meshing and checking the result
|
||||
TopLoc_Location aLoc;
|
||||
Handle(Poly_Triangulation) aPoly = BRep_Tool::Triangulation(aFace,aLoc);
|
||||
if (aPoly.IsNull()) continue;
|
||||
|
||||
// getting the transformation of the shape/face
|
||||
gp_Trsf myTransf;
|
||||
Standard_Boolean identity = true;
|
||||
if (!aLoc.IsIdentity()) {
|
||||
identity = false;
|
||||
myTransf = aLoc.Transformation();
|
||||
for (std::size_t i = 0; i < points.size(); i++) {
|
||||
vertices[i] = Base::convertTo<Base::Vector3f>(points[i]);
|
||||
}
|
||||
|
||||
// getting size and create the array
|
||||
nbNodesInFace = aPoly->NbNodes();
|
||||
nbTriInFace = aPoly->NbTriangles();
|
||||
vertices.resize(nbNodesInFace);
|
||||
indices.resize(4*nbTriInFace);
|
||||
|
||||
// check orientation
|
||||
TopAbs_Orientation orient = aFace.Orientation();
|
||||
|
||||
// cycling through the poly mesh
|
||||
const Poly_Array1OfTriangle& Triangles = aPoly->Triangles();
|
||||
const TColgp_Array1OfPnt& Nodes = aPoly->Nodes();
|
||||
for (int i=1;i<=nbTriInFace;i++) {
|
||||
// Get the triangle
|
||||
Standard_Integer N1,N2,N3;
|
||||
Triangles(i).Get(N1,N2,N3);
|
||||
|
||||
// change orientation of the triangles
|
||||
if (orient != TopAbs_FORWARD) {
|
||||
Standard_Integer tmp = N1;
|
||||
N1 = N2;
|
||||
N2 = tmp;
|
||||
}
|
||||
|
||||
gp_Pnt V1 = Nodes(N1);
|
||||
gp_Pnt V2 = Nodes(N2);
|
||||
gp_Pnt V3 = Nodes(N3);
|
||||
|
||||
// transform the vertices to the place of the face
|
||||
if (!identity) {
|
||||
V1.Transform(myTransf);
|
||||
V2.Transform(myTransf);
|
||||
V3.Transform(myTransf);
|
||||
}
|
||||
|
||||
vertices[N1-1].Set((float)(V1.X()),(float)(V1.Y()),(float)(V1.Z()));
|
||||
vertices[N2-1].Set((float)(V2.X()),(float)(V2.Y()),(float)(V2.Z()));
|
||||
vertices[N3-1].Set((float)(V3.X()),(float)(V3.Y()),(float)(V3.Z()));
|
||||
|
||||
int j = i - 1;
|
||||
N1--; N2--; N3--;
|
||||
indices[4*j] = N1; indices[4*j+1] = N2; indices[4*j+2] = N3; indices[4*j+3] = -1;
|
||||
for (std::size_t i = 0; i < facets.size(); i++) {
|
||||
Standard_Integer n1,n2,n3;
|
||||
facets[i].Get(n1, n2, n3);
|
||||
indices[4 * i ] = n1;
|
||||
indices[4 * i + 1] = n2;
|
||||
indices[4 * i + 2] = n3;
|
||||
indices[4 * i + 3] = -1;
|
||||
}
|
||||
|
||||
builder.beginSeparator();
|
||||
@@ -1170,7 +1136,7 @@ void TopoShape::exportFaceSet(double dev, double ca,
|
||||
builder.endPoints();
|
||||
builder.addIndexedFaceSet(indices);
|
||||
builder.endSeparator();
|
||||
} // end of face loop
|
||||
}
|
||||
}
|
||||
|
||||
void TopoShape::exportLineSet(std::ostream& str) const
|
||||
@@ -1183,72 +1149,27 @@ void TopoShape::exportLineSet(std::ostream& str) const
|
||||
// build up map edge->face
|
||||
TopTools_IndexedDataMapOfShapeListOfShape edge2Face;
|
||||
TopExp::MapShapesAndAncestors(this->_Shape, TopAbs_EDGE, TopAbs_FACE, edge2Face);
|
||||
for (int i=0; i<M.Extent(); i++)
|
||||
{
|
||||
|
||||
for (int i=0; i<M.Extent(); i++) {
|
||||
const TopoDS_Edge& aEdge = TopoDS::Edge(M(i+1));
|
||||
gp_Trsf myTransf;
|
||||
TopLoc_Location aLoc;
|
||||
std::vector<gp_Pnt> points;
|
||||
|
||||
// try to triangulate the edge
|
||||
Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(aEdge, aLoc);
|
||||
|
||||
std::vector<Base::Vector3f> vertices;
|
||||
Standard_Integer nbNodesInFace;
|
||||
|
||||
// triangulation succeeded?
|
||||
if (!aPoly.IsNull()) {
|
||||
if (!aLoc.IsIdentity()) {
|
||||
myTransf = aLoc.Transformation();
|
||||
}
|
||||
nbNodesInFace = aPoly->NbNodes();
|
||||
vertices.resize(nbNodesInFace);
|
||||
|
||||
const TColgp_Array1OfPnt& Nodes = aPoly->Nodes();
|
||||
|
||||
gp_Pnt V;
|
||||
for (Standard_Integer i=0;i < nbNodesInFace;i++) {
|
||||
V = Nodes(i+1);
|
||||
V.Transform(myTransf);
|
||||
vertices[i].Set((float)(V.X()),(float)(V.Y()),(float)(V.Z()));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!Tools::getPolygon3D(aEdge, points)) {
|
||||
// the edge has not its own triangulation, but then a face the edge is attached to
|
||||
// must provide this triangulation
|
||||
|
||||
// Look for one face in our map (it doesn't care which one we take)
|
||||
const TopoDS_Face& aFace = TopoDS::Face(edge2Face.FindFromKey(aEdge).First());
|
||||
|
||||
// take the face's triangulation instead
|
||||
Handle(Poly_Triangulation) aPolyTria = BRep_Tool::Triangulation(aFace,aLoc);
|
||||
if (!aLoc.IsIdentity()) {
|
||||
myTransf = aLoc.Transformation();
|
||||
}
|
||||
|
||||
if (aPolyTria.IsNull()) break;
|
||||
|
||||
// this holds the indices of the edge's triangulation to the actual points
|
||||
Handle(Poly_PolygonOnTriangulation) aPoly = BRep_Tool::PolygonOnTriangulation(aEdge, aPolyTria, aLoc);
|
||||
if (aPoly.IsNull())
|
||||
continue; // polygon does not exist
|
||||
|
||||
// getting size and create the array
|
||||
nbNodesInFace = aPoly->NbNodes();
|
||||
vertices.resize(nbNodesInFace);
|
||||
|
||||
const TColStd_Array1OfInteger& indices = aPoly->Nodes();
|
||||
const TColgp_Array1OfPnt& Nodes = aPolyTria->Nodes();
|
||||
|
||||
gp_Pnt V;
|
||||
int pos = 0;
|
||||
// go through the index array
|
||||
for (Standard_Integer i=indices.Lower();i <= indices.Upper();i++) {
|
||||
V = Nodes(indices(i));
|
||||
V.Transform(myTransf);
|
||||
vertices[pos++].Set((float)(V.X()),(float)(V.Y()),(float)(V.Z()));
|
||||
}
|
||||
if (!Tools::getPolygonOnTriangulation(aEdge, aFace, points))
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<Base::Vector3f> vertices;
|
||||
vertices.reserve(points.size());
|
||||
std::for_each(points.begin(), points.end(), [&vertices](const gp_Pnt& p) {
|
||||
vertices.push_back(Base::convertTo<Base::Vector3f>(p));
|
||||
});
|
||||
|
||||
builder.addLineSet(vertices, 2, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
@@ -2216,12 +2137,20 @@ TopoDS_Shape TopoShape::makeTube(double radius, double tol, int cont, int maxdeg
|
||||
if (this->_Shape.IsNull())
|
||||
Standard_Failure::Raise("Cannot sweep along empty spine");
|
||||
|
||||
#if OCC_VERSION_HEX >= 0x070600
|
||||
Handle(Adaptor3d_Curve) myPath;
|
||||
if (this->_Shape.ShapeType() == TopAbs_EDGE) {
|
||||
const TopoDS_Edge& path_edge = TopoDS::Edge(this->_Shape);
|
||||
myPath = new BRepAdaptor_Curve(path_edge);
|
||||
}
|
||||
#else
|
||||
Handle(Adaptor3d_HCurve) myPath;
|
||||
if (this->_Shape.ShapeType() == TopAbs_EDGE) {
|
||||
const TopoDS_Edge& path_edge = TopoDS::Edge(this->_Shape);
|
||||
BRepAdaptor_Curve path_adapt(path_edge);
|
||||
myPath = new BRepAdaptor_HCurve(path_adapt);
|
||||
}
|
||||
#endif
|
||||
//else if (this->_Shape.ShapeType() == TopAbs_WIRE) {
|
||||
// const TopoDS_Wire& path_wire = TopoDS::Wire(this->_Shape);
|
||||
// BRepAdaptor_CompCurve path_adapt(path_wire);
|
||||
@@ -3443,46 +3372,40 @@ void TopoShape::getDomains(std::vector<Domain>& domains) const
|
||||
for (TopExp_Explorer xp(this->_Shape, TopAbs_FACE); xp.More(); xp.Next()) {
|
||||
TopoDS_Face face = TopoDS::Face(xp.Current());
|
||||
|
||||
TopLoc_Location loc;
|
||||
Handle(Poly_Triangulation) theTriangulation = BRep_Tool::Triangulation(face, loc);
|
||||
if (theTriangulation.IsNull()) {
|
||||
std::vector<gp_Pnt> points;
|
||||
std::vector<Poly_Triangle> facets;
|
||||
if (!Tools::getTriangulation(face, points, facets)) {
|
||||
// For a face that cannot be meshed append an empty domain.
|
||||
// It's important for some algorithms (e.g. color mapping) that the numbers of
|
||||
// faces and domains match
|
||||
Domain domain;
|
||||
domains.push_back(domain);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
Domain domain;
|
||||
// copy the points
|
||||
domain.points.reserve(points.size());
|
||||
for (const auto& it : points) {
|
||||
Standard_Real X, Y, Z;
|
||||
it.Coord (X, Y, Z);
|
||||
domain.points.emplace_back(X, Y, Z);
|
||||
}
|
||||
|
||||
Domain domain;
|
||||
// copy the points
|
||||
const TColgp_Array1OfPnt& points = theTriangulation->Nodes();
|
||||
domain.points.reserve(points.Length());
|
||||
for (int i = 1; i <= points.Length(); i++) {
|
||||
gp_Pnt p = points(i);
|
||||
p.Transform(loc.Transformation());
|
||||
Standard_Real X, Y, Z;
|
||||
p.Coord (X, Y, Z);
|
||||
domain.points.emplace_back(X, Y, Z);
|
||||
// copy the triangles
|
||||
domain.facets.reserve(facets.size());
|
||||
for (const auto& it : facets) {
|
||||
Standard_Integer N1, N2, N3;
|
||||
it.Get(N1, N2, N3);
|
||||
|
||||
Facet tria;
|
||||
tria.I1 = N1;
|
||||
tria.I2 = N2;
|
||||
tria.I3 = N3;
|
||||
domain.facets.push_back(tria);
|
||||
}
|
||||
|
||||
domains.push_back(domain);
|
||||
}
|
||||
|
||||
// copy the triangles
|
||||
const TopAbs_Orientation anOrientation = face.Orientation();
|
||||
bool flip = (anOrientation == TopAbs_REVERSED);
|
||||
const Poly_Array1OfTriangle& faces = theTriangulation->Triangles();
|
||||
domain.facets.reserve(faces.Length());
|
||||
for (int i = 1; i <= faces.Length(); i++) {
|
||||
Standard_Integer N1, N2, N3;
|
||||
faces(i).Get(N1, N2, N3);
|
||||
|
||||
Facet tria;
|
||||
tria.I1 = N1-1; tria.I2 = N2-1; tria.I3 = N3-1;
|
||||
if (flip)
|
||||
std::swap(tria.I1, tria.I2);
|
||||
domain.facets.push_back(tria);
|
||||
}
|
||||
|
||||
domains.push_back(domain);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3845,7 +3768,7 @@ void TopoShape::getPoints(std::vector<Base::Vector3d> &Points,
|
||||
Normals.clear();
|
||||
}
|
||||
|
||||
void TopoShape::getLinesFromSubelement(const Data::Segment* element,
|
||||
void TopoShape::getLinesFromSubElement(const Data::Segment* element,
|
||||
std::vector<Base::Vector3d> &vertices,
|
||||
std::vector<Line> &lines) const
|
||||
{
|
||||
@@ -3866,72 +3789,32 @@ void TopoShape::getLinesFromSubelement(const Data::Segment* element,
|
||||
for(TopExp_Explorer exp(shape,TopAbs_EDGE);exp.More();exp.Next()) {
|
||||
|
||||
TopoDS_Edge aEdge = TopoDS::Edge(exp.Current());
|
||||
TopLoc_Location aLoc;
|
||||
Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(aEdge, aLoc);
|
||||
std::vector<gp_Pnt> points;
|
||||
|
||||
gp_Trsf myTransf;
|
||||
Standard_Integer nbNodesInFace;
|
||||
|
||||
auto line_start = vertices.size();
|
||||
|
||||
// triangulation succeeded?
|
||||
if (!aPoly.IsNull()) {
|
||||
if (!aLoc.IsIdentity()) {
|
||||
myTransf = aLoc.Transformation();
|
||||
}
|
||||
nbNodesInFace = aPoly->NbNodes();
|
||||
|
||||
const TColgp_Array1OfPnt& Nodes = aPoly->Nodes();
|
||||
|
||||
gp_Pnt V;
|
||||
for (Standard_Integer i=0;i < nbNodesInFace;i++) {
|
||||
V = Nodes(i+1);
|
||||
V.Transform(myTransf);
|
||||
vertices.emplace_back(V.X(),V.Y(),V.Z());
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!Tools::getPolygon3D(aEdge, points)) {
|
||||
// the edge has not its own triangulation, but then a face the edge is attached to
|
||||
// must provide this triangulation
|
||||
|
||||
// Look for one face in our map (it doesn't care which one we take)
|
||||
int index = edge2Face.FindIndex(aEdge);
|
||||
if(!index)
|
||||
if (index < 1)
|
||||
continue;
|
||||
const auto &faces = edge2Face.FindFromIndex(index);
|
||||
if(!faces.Extent())
|
||||
if (faces.Extent() == 0)
|
||||
continue;
|
||||
const TopoDS_Face& aFace = TopoDS::Face(faces.First());
|
||||
|
||||
// take the face's triangulation instead
|
||||
Handle(Poly_Triangulation) aPolyTria = BRep_Tool::Triangulation(aFace,aLoc);
|
||||
if (!aLoc.IsIdentity()) {
|
||||
myTransf = aLoc.Transformation();
|
||||
}
|
||||
|
||||
if (aPolyTria.IsNull()) break;
|
||||
|
||||
// this holds the indices of the edge's triangulation to the actual points
|
||||
Handle(Poly_PolygonOnTriangulation) aPoly = BRep_Tool::PolygonOnTriangulation(aEdge, aPolyTria, aLoc);
|
||||
if (aPoly.IsNull())
|
||||
continue; // polygon does not exist
|
||||
|
||||
// getting size and create the array
|
||||
nbNodesInFace = aPoly->NbNodes();
|
||||
|
||||
const TColStd_Array1OfInteger& indices = aPoly->Nodes();
|
||||
const TColgp_Array1OfPnt& Nodes = aPolyTria->Nodes();
|
||||
|
||||
gp_Pnt V;
|
||||
// go through the index array
|
||||
for (Standard_Integer i=indices.Lower();i <= indices.Upper();i++) {
|
||||
V = Nodes(indices(i));
|
||||
V.Transform(myTransf);
|
||||
vertices.emplace_back(V.X(),V.Y(),V.Z());
|
||||
}
|
||||
if (!Part::Tools::getPolygonOnTriangulation(aEdge, aFace, points))
|
||||
continue;
|
||||
}
|
||||
|
||||
if(line_start+1 < vertices.size()) {
|
||||
auto line_start = vertices.size();
|
||||
vertices.reserve(vertices.size() + points.size());
|
||||
std::for_each(points.begin(), points.end(), [&vertices](const gp_Pnt& p) {
|
||||
vertices.push_back(Base::convertTo<Base::Vector3d>(p));
|
||||
});
|
||||
|
||||
if (line_start+1 < vertices.size()) {
|
||||
lines.emplace_back();
|
||||
lines.back().I1 = line_start;
|
||||
lines.back().I2 = vertices.size()-1;
|
||||
@@ -3940,7 +3823,7 @@ void TopoShape::getLinesFromSubelement(const Data::Segment* element,
|
||||
}
|
||||
}
|
||||
|
||||
void TopoShape::getFacesFromSubelement(const Data::Segment* element,
|
||||
void TopoShape::getFacesFromSubElement(const Data::Segment* element,
|
||||
std::vector<Base::Vector3d> &points,
|
||||
std::vector<Base::Vector3d> &pointNormals,
|
||||
std::vector<Facet> &faces) const
|
||||
|
||||
@@ -135,12 +135,12 @@ public:
|
||||
/// get the subelement by type and number
|
||||
virtual Data::Segment* getSubElement(const char* Type, unsigned long) const;
|
||||
/** Get lines from segment */
|
||||
virtual void getLinesFromSubelement(
|
||||
virtual void getLinesFromSubElement(
|
||||
const Data::Segment*,
|
||||
std::vector<Base::Vector3d> &Points,
|
||||
std::vector<Line> &lines) const;
|
||||
/** Get faces from segment */
|
||||
virtual void getFacesFromSubelement(
|
||||
virtual void getFacesFromSubElement(
|
||||
const Data::Segment*,
|
||||
std::vector<Base::Vector3d> &Points,
|
||||
std::vector<Base::Vector3d> &PointNormals,
|
||||
|
||||
@@ -493,6 +493,15 @@ PyObject* TopoShapeFacePy::getUVNodes(PyObject *args)
|
||||
return Py::new_reference_to(list);
|
||||
}
|
||||
|
||||
#if OCC_VERSION_HEX >= 0x070600
|
||||
for (int i=1; i<=mesh->NbNodes(); i++) {
|
||||
gp_Pnt2d pt2d = mesh->UVNode(i);
|
||||
Py::Tuple uv(2);
|
||||
uv.setItem(0, Py::Float(pt2d.X()));
|
||||
uv.setItem(1, Py::Float(pt2d.Y()));
|
||||
list.append(uv);
|
||||
}
|
||||
#else
|
||||
const TColgp_Array1OfPnt2d& aNodesUV = mesh->UVNodes();
|
||||
for (int i=aNodesUV.Lower(); i<=aNodesUV.Upper(); i++) {
|
||||
gp_Pnt2d pt2d = aNodesUV(i);
|
||||
@@ -501,6 +510,7 @@ PyObject* TopoShapeFacePy::getUVNodes(PyObject *args)
|
||||
uv.setItem(1, Py::Float(pt2d.Y()));
|
||||
list.append(uv);
|
||||
}
|
||||
#endif
|
||||
|
||||
return Py::new_reference_to(list);
|
||||
}
|
||||
|
||||
@@ -344,9 +344,9 @@ PyObject* TopoShapeWirePy::approximate(PyObject *args, PyObject *kwds)
|
||||
return 0;
|
||||
try {
|
||||
BRepAdaptor_CompCurve adapt(TopoDS::Wire(getTopoShapePtr()->getShape()));
|
||||
Handle(Adaptor3d_HCurve) hcurve = adapt.Trim(adapt.FirstParameter(),
|
||||
adapt.LastParameter(),
|
||||
tol2d);
|
||||
auto hcurve = adapt.Trim(adapt.FirstParameter(),
|
||||
adapt.LastParameter(),
|
||||
tol2d);
|
||||
Approx_Curve3d approx(hcurve, tol3d, GeomAbs_C0, maxseg, maxdeg);
|
||||
if (approx.IsDone()) {
|
||||
return new BSplineCurvePy(new GeomBSplineCurve(approx.Curve()));
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#include "ShapeFromMesh.h"
|
||||
#include "ui_ShapeFromMesh.h"
|
||||
#include <App/Application.h>
|
||||
#include <Base/UnitsApi.h>
|
||||
#include <App/DocumentObserver.h>
|
||||
#include <Gui/CommandT.h>
|
||||
#include <Gui/Selection.h>
|
||||
@@ -46,8 +46,7 @@ ShapeFromMesh::ShapeFromMesh(QWidget* parent, Qt::WindowFlags fl)
|
||||
|
||||
double STD_OCC_TOLERANCE = 1e-6;
|
||||
|
||||
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Units");
|
||||
int decimals = hGrp->GetInt("Decimals");
|
||||
int decimals = Base::UnitsApi::getDecimals();
|
||||
double tolerance_from_decimals = pow(10., -decimals);
|
||||
|
||||
double minimal_tolerance = tolerance_from_decimals < STD_OCC_TOLERANCE ? STD_OCC_TOLERANCE : tolerance_from_decimals;
|
||||
@@ -81,7 +80,7 @@ void ShapeFromMesh::perform()
|
||||
std::string mesh = (*it)->getNameInDocument();
|
||||
std::string name = doc->getUniqueObjectName(mesh.c_str());
|
||||
|
||||
Gui::cmdAppDocument(doc, std::ostringstream() << "addObject(\"Part::Feature\", \"" << name << "\")");
|
||||
Gui::cmdAppDocumentArgs(doc, "addObject('%s', '%s')", "Part::Feature", name);
|
||||
std::string partObj = App::DocumentObjectT(doc, name).getObjectPython();
|
||||
std::string meshObj = App::DocumentObjectT(doc, mesh).getObjectPython();
|
||||
|
||||
|
||||
@@ -711,8 +711,10 @@ int TaskCheckGeometryResults::goBOPSingleCheck(const TopoDS_Shape& shapeIn, Resu
|
||||
#if OCC_VERSION_HEX >= 0x060900
|
||||
#if OCC_VERSION_HEX < 0x070500
|
||||
BOPCheck.SetProgressIndicator(theProgress);
|
||||
#else
|
||||
#elif OCC_VERSION_HEX < 0x070600
|
||||
BOPCheck.SetProgressIndicator(theScope);
|
||||
#else
|
||||
Q_UNUSED(theScope)
|
||||
#endif // 0x070500
|
||||
#else
|
||||
Q_UNUSED(theProgress);
|
||||
@@ -740,7 +742,7 @@ int TaskCheckGeometryResults::goBOPSingleCheck(const TopoDS_Shape& shapeIn, Resu
|
||||
Base::TimeInfo start_time;
|
||||
#endif
|
||||
|
||||
BOPCheck.Perform();
|
||||
BOPCheck.Perform();
|
||||
|
||||
#ifdef FC_DEBUG
|
||||
float bopAlgoTime = Base::TimeInfo::diffTimeF(start_time,Base::TimeInfo());
|
||||
|
||||
@@ -125,6 +125,7 @@
|
||||
|
||||
#include <Mod/Part/App/PartFeature.h>
|
||||
#include <Mod/Part/App/PrimitiveFeature.h>
|
||||
#include <Mod/Part/App/Tools.h>
|
||||
|
||||
FC_LOG_LEVEL_INIT("Part", true, true)
|
||||
|
||||
@@ -133,94 +134,6 @@ using namespace PartGui;
|
||||
PROPERTY_SOURCE(PartGui::ViewProviderPartExt, Gui::ViewProviderGeometryObject)
|
||||
|
||||
|
||||
void ViewProviderPartExt::getNormals(const TopoDS_Face& theFace,
|
||||
const Handle(Poly_Triangulation)& aPolyTri,
|
||||
TColgp_Array1OfDir& theNormals)
|
||||
{
|
||||
const TColgp_Array1OfPnt& aNodes = aPolyTri->Nodes();
|
||||
|
||||
if(aPolyTri->HasNormals())
|
||||
{
|
||||
// normals pre-computed in triangulation structure
|
||||
const TShort_Array1OfShortReal& aNormals = aPolyTri->Normals();
|
||||
const Standard_ShortReal* aNormArr = &(aNormals.Value(aNormals.Lower()));
|
||||
|
||||
for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
|
||||
{
|
||||
const Standard_Integer anId = 3 * (aNodeIter - aNodes.Lower());
|
||||
const gp_Dir aNorm(aNormArr[anId + 0],
|
||||
aNormArr[anId + 1],
|
||||
aNormArr[anId + 2]);
|
||||
theNormals(aNodeIter) = aNorm;
|
||||
}
|
||||
|
||||
if(theFace.Orientation() == TopAbs_REVERSED)
|
||||
{
|
||||
for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
|
||||
{
|
||||
theNormals.ChangeValue(aNodeIter).Reverse();
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// take in face the surface location
|
||||
Poly_Connect thePolyConnect(aPolyTri);
|
||||
const TopoDS_Face aZeroFace = TopoDS::Face(theFace.Located(TopLoc_Location()));
|
||||
Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aZeroFace);
|
||||
const Standard_Real aTol = Precision::Confusion();
|
||||
Handle(TShort_HArray1OfShortReal) aNormals = new TShort_HArray1OfShortReal(1, aPolyTri->NbNodes() * 3);
|
||||
const Poly_Array1OfTriangle& aTriangles = aPolyTri->Triangles();
|
||||
const TColgp_Array1OfPnt2d* aNodesUV = aPolyTri->HasUVNodes() && !aSurf.IsNull()
|
||||
? &aPolyTri->UVNodes()
|
||||
: NULL;
|
||||
Standard_Integer aTri[3];
|
||||
|
||||
for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
|
||||
{
|
||||
// try to retrieve normal from real surface first, when UV coordinates are available
|
||||
if(aNodesUV == NULL
|
||||
|| GeomLib::NormEstim(aSurf, aNodesUV->Value(aNodeIter), aTol, theNormals(aNodeIter)) > 1)
|
||||
{
|
||||
// compute flat normals
|
||||
gp_XYZ eqPlan(0.0, 0.0, 0.0);
|
||||
|
||||
for(thePolyConnect.Initialize(aNodeIter); thePolyConnect.More(); thePolyConnect.Next())
|
||||
{
|
||||
aTriangles(thePolyConnect.Value()).Get(aTri[0], aTri[1], aTri[2]);
|
||||
const gp_XYZ v1(aNodes(aTri[1]).Coord() - aNodes(aTri[0]).Coord());
|
||||
const gp_XYZ v2(aNodes(aTri[2]).Coord() - aNodes(aTri[1]).Coord());
|
||||
const gp_XYZ vv = v1 ^ v2;
|
||||
const Standard_Real aMod = vv.Modulus();
|
||||
|
||||
if(aMod >= aTol)
|
||||
{
|
||||
eqPlan += vv / aMod;
|
||||
}
|
||||
}
|
||||
|
||||
const Standard_Real aModMax = eqPlan.Modulus();
|
||||
theNormals(aNodeIter) = (aModMax > aTol) ? gp_Dir(eqPlan) : gp::DZ();
|
||||
}
|
||||
|
||||
const Standard_Integer anId = (aNodeIter - aNodes.Lower()) * 3;
|
||||
aNormals->SetValue(anId + 1, (Standard_ShortReal)theNormals(aNodeIter).X());
|
||||
aNormals->SetValue(anId + 2, (Standard_ShortReal)theNormals(aNodeIter).Y());
|
||||
aNormals->SetValue(anId + 3, (Standard_ShortReal)theNormals(aNodeIter).Z());
|
||||
}
|
||||
|
||||
aPolyTri->SetNormals(aNormals);
|
||||
|
||||
if(theFace.Orientation() == TopAbs_REVERSED)
|
||||
{
|
||||
for(Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
|
||||
{
|
||||
theNormals.ChangeValue(aNodeIter).Reverse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
// Construction/Destruction
|
||||
|
||||
@@ -443,24 +356,19 @@ void ViewProviderPartExt::onChanged(const App::Property* prop)
|
||||
else if (prop == &ShapeMaterial || prop == &ShapeColor) {
|
||||
pcFaceBind->value = SoMaterialBinding::OVERALL;
|
||||
ViewProviderGeometryObject::onChanged(prop);
|
||||
DiffuseColor.setValue(ShapeColor.getValue());
|
||||
App::Color c = ShapeColor.getValue();
|
||||
c.a = Transparency.getValue()/100.0f;
|
||||
DiffuseColor.setValue(c);
|
||||
}
|
||||
else if (prop == &Transparency) {
|
||||
const App::Material& Mat = ShapeMaterial.getValue();
|
||||
long value = (long)(100*Mat.transparency);
|
||||
if (value != Transparency.getValue()) {
|
||||
float trans = Transparency.getValue()/100.0f;
|
||||
if (pcFaceBind->value.getValue() == SoMaterialBinding::PER_PART) {
|
||||
int cnt = pcShapeMaterial->diffuseColor.getNum();
|
||||
pcShapeMaterial->transparency.setNum(cnt);
|
||||
float *t = pcShapeMaterial->transparency.startEditing();
|
||||
for (int i=0; i<cnt; i++)
|
||||
t[i] = trans;
|
||||
pcShapeMaterial->transparency.finishEditing();
|
||||
}
|
||||
else {
|
||||
pcShapeMaterial->transparency = trans;
|
||||
}
|
||||
auto colors = DiffuseColor.getValues();
|
||||
for (auto &c : colors)
|
||||
c.a = trans;
|
||||
DiffuseColor.setValues(colors);
|
||||
|
||||
App::PropertyContainer* parent = ShapeMaterial.getContainer();
|
||||
ShapeMaterial.setContainer(0);
|
||||
@@ -729,7 +637,7 @@ void ViewProviderPartExt::setHighlightedFaces(const std::vector<App::Color>& col
|
||||
else if (colors.size() == 1) {
|
||||
pcFaceBind->value = SoMaterialBinding::OVERALL;
|
||||
pcShapeMaterial->diffuseColor.setValue(colors[0].r, colors[0].g, colors[0].b);
|
||||
//pcShapeMaterial->transparency = colors[0].a; do not get transparency from DiffuseColor in this case
|
||||
pcShapeMaterial->transparency = Transparency.getValue()/100.f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -795,6 +703,7 @@ std::map<std::string,App::Color> ViewProviderPartExt::getElementColors(const cha
|
||||
}
|
||||
if(size && singleColor) {
|
||||
color = DiffuseColor[0];
|
||||
color.a = Transparency.getValue()/100.0f;
|
||||
ret.clear();
|
||||
}
|
||||
ret["Face"] = color;
|
||||
@@ -1170,16 +1079,25 @@ void ViewProviderPartExt::updateVisual()
|
||||
|
||||
|
||||
// cycling through the poly mesh
|
||||
#if OCC_VERSION_HEX < 0x070600
|
||||
const Poly_Array1OfTriangle& Triangles = mesh->Triangles();
|
||||
const TColgp_Array1OfPnt& Nodes = mesh->Nodes();
|
||||
TColgp_Array1OfDir Normals (Nodes.Lower(), Nodes.Upper());
|
||||
#else
|
||||
int numNodes = mesh->NbNodes();
|
||||
TColgp_Array1OfDir Normals (1, numNodes);
|
||||
#endif
|
||||
if (NormalsFromUV)
|
||||
getNormals(actFace, mesh, Normals);
|
||||
Part::Tools::getPointNormals(actFace, mesh, Normals);
|
||||
|
||||
for (int g=1;g<=nbTriInFace;g++) {
|
||||
// Get the triangle
|
||||
Standard_Integer N1,N2,N3;
|
||||
#if OCC_VERSION_HEX < 0x070600
|
||||
Triangles(g).Get(N1,N2,N3);
|
||||
#else
|
||||
mesh->Triangle(g).Get(N1,N2,N3);
|
||||
#endif
|
||||
|
||||
// change orientation of the triangle if the face is reversed
|
||||
if ( orient != TopAbs_FORWARD ) {
|
||||
@@ -1189,7 +1107,11 @@ void ViewProviderPartExt::updateVisual()
|
||||
}
|
||||
|
||||
// get the 3 points of this triangle
|
||||
#if OCC_VERSION_HEX < 0x070600
|
||||
gp_Pnt V1(Nodes(N1)), V2(Nodes(N2)), V3(Nodes(N3));
|
||||
#else
|
||||
gp_Pnt V1(mesh->Node(N1)), V2(mesh->Node(N2)), V3(mesh->Node(N3));
|
||||
#endif
|
||||
|
||||
// get the 3 normals of this triangle
|
||||
gp_Vec NV1, NV2, NV3;
|
||||
@@ -1266,7 +1188,11 @@ void ViewProviderPartExt::updateVisual()
|
||||
// rare cases where some points are only referenced by the polygon
|
||||
// but not by any triangle. Thus, we must apply the coordinates to
|
||||
// make sure that everything is properly set.
|
||||
#if OCC_VERSION_HEX < 0x070600
|
||||
gp_Pnt p(Nodes(nodeIndex));
|
||||
#else
|
||||
gp_Pnt p(mesh->Node(nodeIndex));
|
||||
#endif
|
||||
if (!identity)
|
||||
p.Transform(myTransf);
|
||||
verts[index].setValue((float)(p.X()),(float)(p.Y()),(float)(p.Z()));
|
||||
|
||||
@@ -158,8 +158,6 @@ protected:
|
||||
virtual void onChanged(const App::Property* prop) override;
|
||||
bool loadParameter();
|
||||
void updateVisual();
|
||||
void getNormals(const TopoDS_Face& theFace, const Handle(Poly_Triangulation)& aPolyTri,
|
||||
TColgp_Array1OfDir& theNormals);
|
||||
|
||||
// nodes for the data representation
|
||||
SoMaterialBinding * pcFaceBind;
|
||||
|
||||
@@ -43,6 +43,7 @@ SOFTWARE.
|
||||
#include <memory> // unique_ptr
|
||||
#include <numeric> // accumulate
|
||||
#include <string> // string, stoi, to_string
|
||||
#include <string_view> // string_view
|
||||
#include <utility> // declval, forward, move, pair, swap
|
||||
#include <vector> // vector
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include <App/Part.h>
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/Command.h>
|
||||
#include <Gui/CommandT.h>
|
||||
#include <Gui/Control.h>
|
||||
#include <Gui/Selection.h>
|
||||
#include <Gui/MainWindow.h>
|
||||
@@ -1257,7 +1258,10 @@ void CmdPartDesignPad::activated(int iMsg)
|
||||
|
||||
Part::Part2DObject* sketch = dynamic_cast<Part::Part2DObject*>(profile);
|
||||
|
||||
FCMD_OBJ_CMD(Feat, "ReferenceAxis = (" << getObjectCmd(sketch) << ",['N_Axis'])");
|
||||
if (sketch) {
|
||||
std::ostringstream str;
|
||||
Gui::cmdAppObject(Feat, str << "ReferenceAxis = (" << getObjectCmd(sketch) << ",['N_Axis'])");
|
||||
}
|
||||
|
||||
finishProfileBased(cmd, sketch, Feat);
|
||||
cmd->adjustCameraPosition();
|
||||
|
||||
@@ -775,7 +775,10 @@ void TaskPadParameters::getReferenceAxis(App::DocumentObject*& obj, std::vector<
|
||||
int num = ui->directionCB->currentIndex();
|
||||
const App::PropertyLinkSub& lnk = *(axesInList[num]);
|
||||
if (lnk.getValue() == 0) {
|
||||
throw Base::RuntimeError("Still in reference selection mode; reference wasn't selected yet");
|
||||
// Note: Is is possible that a face of an object is directly padded without defining a profile shape
|
||||
obj = nullptr;
|
||||
sub.clear();
|
||||
//throw Base::RuntimeError("Still in reference selection mode; reference wasn't selected yet");
|
||||
}
|
||||
else {
|
||||
PartDesign::ProfileBased* pcDirection = static_cast<PartDesign::ProfileBased*>(vp->getObject());
|
||||
|
||||
@@ -40,7 +40,8 @@
|
||||
#endif
|
||||
|
||||
#include "ViewProviderAddSub.h"
|
||||
#include "Mod/Part/Gui/SoBrepFaceSet.h"
|
||||
#include <Mod/Part/Gui/SoBrepFaceSet.h>
|
||||
#include <Mod/Part/App/Tools.h>
|
||||
#include <Mod/PartDesign/App/FeatureAddSub.h>
|
||||
#include <Gui/TaskView/TaskDialog.h>
|
||||
#include <Gui/Control.h>
|
||||
@@ -115,9 +116,6 @@ void ViewProviderAddSub::updateAddSubShapeIndicator() {
|
||||
return;
|
||||
}
|
||||
|
||||
int numTriangles=0,numNodes=0,numNorms=0,numFaces=0;
|
||||
std::set<int> faceEdges;
|
||||
|
||||
try {
|
||||
// calculating the deflection value
|
||||
Bnd_Box bounds;
|
||||
@@ -125,16 +123,14 @@ void ViewProviderAddSub::updateAddSubShapeIndicator() {
|
||||
bounds.SetGap(0.0);
|
||||
Standard_Real xMin, yMin, zMin, xMax, yMax, zMax;
|
||||
bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax);
|
||||
Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 *
|
||||
Deviation.getValue();
|
||||
Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 * Deviation.getValue();
|
||||
|
||||
// create or use the mesh on the data structure
|
||||
#if OCC_VERSION_HEX >= 0x060600
|
||||
Standard_Real AngDeflectionRads = AngularDeflection.getValue() / 180.0 * M_PI;
|
||||
BRepMesh_IncrementalMesh(cShape,deflection,Standard_False,
|
||||
AngDeflectionRads,Standard_True);
|
||||
BRepMesh_IncrementalMesh(cShape, deflection, Standard_False, AngDeflectionRads, Standard_True);
|
||||
#else
|
||||
BRepMesh_IncrementalMesh(cShape,deflection);
|
||||
BRepMesh_IncrementalMesh(cShape, deflection);
|
||||
#endif
|
||||
// We must reset the location here because the transformation data
|
||||
// are set in the placement property
|
||||
@@ -142,6 +138,7 @@ void ViewProviderAddSub::updateAddSubShapeIndicator() {
|
||||
cShape.Location(aLoc);
|
||||
|
||||
// count triangles and nodes in the mesh
|
||||
int numTriangles=0,numNodes=0,numNorms=0,numFaces=0;
|
||||
TopExp_Explorer Ex;
|
||||
for (Ex.Init(cShape,TopAbs_FACE);Ex.More();Ex.Next()) {
|
||||
Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(TopoDS::Face(Ex.Current()), aLoc);
|
||||
@@ -159,11 +156,12 @@ void ViewProviderAddSub::updateAddSubShapeIndicator() {
|
||||
previewNorm ->vector .setNum(numNorms);
|
||||
previewFaceSet ->coordIndex .setNum(numTriangles*4);
|
||||
previewFaceSet ->partIndex .setNum(numFaces);
|
||||
|
||||
// get the raw memory for fast fill up
|
||||
SbVec3f* verts = previewCoords ->point .startEditing();
|
||||
SbVec3f* previewNorms = previewNorm ->vector .startEditing();
|
||||
int32_t* index = previewFaceSet ->coordIndex .startEditing();
|
||||
int32_t* parts = previewFaceSet ->partIndex .startEditing();
|
||||
SbVec3f* verts = previewCoords ->point .startEditing();
|
||||
SbVec3f* previewNorms = previewNorm ->vector .startEditing();
|
||||
int32_t* index = previewFaceSet ->coordIndex .startEditing();
|
||||
int32_t* parts = previewFaceSet ->partIndex .startEditing();
|
||||
|
||||
// preset the previewNormal vector with null vector
|
||||
for (int i=0;i < numNorms;i++)
|
||||
@@ -171,76 +169,46 @@ void ViewProviderAddSub::updateAddSubShapeIndicator() {
|
||||
|
||||
int ii = 0,faceNodeOffset=0,faceTriaOffset=0;
|
||||
for (Ex.Init(cShape, TopAbs_FACE); Ex.More(); Ex.Next(),ii++) {
|
||||
TopLoc_Location aLoc;
|
||||
const TopoDS_Face &actFace = TopoDS::Face(Ex.Current());
|
||||
// get the mesh of the shape
|
||||
Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(actFace,aLoc);
|
||||
if (mesh.IsNull()) continue;
|
||||
|
||||
// getting the transformation of the shape/face
|
||||
gp_Trsf myTransf;
|
||||
Standard_Boolean identity = true;
|
||||
if (!aLoc.IsIdentity()) {
|
||||
identity = false;
|
||||
myTransf = aLoc.Transformation();
|
||||
}
|
||||
TopLoc_Location loc;
|
||||
Handle(Poly_Triangulation) mesh = BRep_Tool::Triangulation(actFace, loc);
|
||||
if (mesh.IsNull())
|
||||
continue;
|
||||
|
||||
// get triangulation
|
||||
std::vector<gp_Pnt> points;
|
||||
std::vector<Poly_Triangle> facets;
|
||||
Part::Tools::getTriangulation(actFace, points, facets);
|
||||
|
||||
// get normal per vertex
|
||||
std::vector<gp_Vec> vertexnormals;
|
||||
Part::Tools::getPointNormals(actFace, mesh, vertexnormals);
|
||||
Part::Tools::applyTransformationOnNormals(loc, vertexnormals);
|
||||
|
||||
// getting size of node and triangle array of this face
|
||||
int nbNodesInFace = mesh->NbNodes();
|
||||
int nbTriInFace = mesh->NbTriangles();
|
||||
// check orientation
|
||||
TopAbs_Orientation orient = actFace.Orientation();
|
||||
std::size_t nbNodesInFace = points.size();
|
||||
std::size_t nbTriInFace = facets.size();
|
||||
|
||||
for (std::size_t i = 0; i < points.size(); i++) {
|
||||
verts[faceNodeOffset+i] = SbVec3f(points[i].X(), points[i].Y(), points[i].Z());
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < vertexnormals.size(); i++) {
|
||||
previewNorms[faceNodeOffset+i] = SbVec3f(vertexnormals[i].X(), vertexnormals[i].Y(), vertexnormals[i].Z());
|
||||
}
|
||||
|
||||
// cycling through the poly mesh
|
||||
const Poly_Array1OfTriangle& Triangles = mesh->Triangles();
|
||||
const TColgp_Array1OfPnt& Nodes = mesh->Nodes();
|
||||
TColgp_Array1OfDir Normals (Nodes.Lower(), Nodes.Upper());
|
||||
getNormals(actFace, mesh, Normals);
|
||||
|
||||
for (int g=1;g<=nbTriInFace;g++) {
|
||||
for (std::size_t g=0; g < nbTriInFace; g++) {
|
||||
// Get the triangle
|
||||
Standard_Integer N1,N2,N3;
|
||||
Triangles(g).Get(N1,N2,N3);
|
||||
|
||||
// change orientation of the triangle if the face is reversed
|
||||
if ( orient != TopAbs_FORWARD ) {
|
||||
Standard_Integer tmp = N1;
|
||||
N1 = N2;
|
||||
N2 = tmp;
|
||||
}
|
||||
|
||||
// get the 3 points of this triangle
|
||||
gp_Pnt V1(Nodes(N1)), V2(Nodes(N2)), V3(Nodes(N3));
|
||||
|
||||
// get the 3 previewNormals of this triangle
|
||||
gp_Dir NV1(Normals(N1)), NV2(Normals(N2)), NV3(Normals(N3));
|
||||
|
||||
// transform the vertices and previewNormals to the place of the face
|
||||
if(!identity) {
|
||||
V1.Transform(myTransf);
|
||||
V2.Transform(myTransf);
|
||||
V3.Transform(myTransf);
|
||||
NV1.Transform(myTransf);
|
||||
NV2.Transform(myTransf);
|
||||
NV3.Transform(myTransf);
|
||||
}
|
||||
|
||||
// add the previewNormals for all points of this triangle
|
||||
previewNorms[faceNodeOffset+N1-1] += SbVec3f(NV1.X(),NV1.Y(),NV1.Z());
|
||||
previewNorms[faceNodeOffset+N2-1] += SbVec3f(NV2.X(),NV2.Y(),NV2.Z());
|
||||
previewNorms[faceNodeOffset+N3-1] += SbVec3f(NV3.X(),NV3.Y(),NV3.Z());
|
||||
|
||||
// set the vertices
|
||||
verts[faceNodeOffset+N1-1].setValue((float)(V1.X()),(float)(V1.Y()),(float)(V1.Z()));
|
||||
verts[faceNodeOffset+N2-1].setValue((float)(V2.X()),(float)(V2.Y()),(float)(V2.Z()));
|
||||
verts[faceNodeOffset+N3-1].setValue((float)(V3.X()),(float)(V3.Y()),(float)(V3.Z()));
|
||||
facets[g].Get(N1,N2,N3);
|
||||
|
||||
// set the index vector with the 3 point indexes and the end delimiter
|
||||
index[faceTriaOffset*4+4*(g-1)] = faceNodeOffset+N1-1;
|
||||
index[faceTriaOffset*4+4*(g-1)+1] = faceNodeOffset+N2-1;
|
||||
index[faceTriaOffset*4+4*(g-1)+2] = faceNodeOffset+N3-1;
|
||||
index[faceTriaOffset*4+4*(g-1)+3] = SO_END_FACE_INDEX;
|
||||
index[faceTriaOffset*4+4*g] = faceNodeOffset+N1;
|
||||
index[faceTriaOffset*4+4*g+1] = faceNodeOffset+N2;
|
||||
index[faceTriaOffset*4+4*g+2] = faceNodeOffset+N3;
|
||||
index[faceTriaOffset*4+4*g+3] = SO_END_FACE_INDEX;
|
||||
}
|
||||
|
||||
parts[ii] = nbTriInFace; // new part
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/Command.h>
|
||||
#include <Mod/Part/App/TopoShape.h>
|
||||
#include <Mod/Part/App/Tools.h>
|
||||
#include <Mod/PartDesign/App/FeatureTransformed.h>
|
||||
#include <Mod/PartDesign/App/FeatureAddSub.h>
|
||||
#include <Mod/PartDesign/App/FeatureMultiTransform.h>
|
||||
@@ -198,162 +199,131 @@ void ViewProviderTransformed::recomputeFeature(bool recompute)
|
||||
}
|
||||
|
||||
// Display the rejected transformations in red
|
||||
|
||||
if (rejected > 0) {
|
||||
try {
|
||||
// calculating the deflection value
|
||||
Standard_Real xMin, yMin, zMin, xMax, yMax, zMax;
|
||||
{
|
||||
Bnd_Box bounds;
|
||||
BRepBndLib::Add(cShape, bounds);
|
||||
bounds.SetGap(0.0);
|
||||
bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax);
|
||||
}
|
||||
Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 * Deviation.getValue();
|
||||
|
||||
// create or use the mesh on the data structure
|
||||
// Note: This DOES have an effect on cShape
|
||||
#if OCC_VERSION_HEX >= 0x060600
|
||||
Standard_Real AngDeflectionRads = AngularDeflection.getValue() / 180.0 * M_PI;
|
||||
BRepMesh_IncrementalMesh(cShape,deflection,Standard_False,
|
||||
AngDeflectionRads,Standard_True);
|
||||
#else
|
||||
BRepMesh_IncrementalMesh(cShape,deflection);
|
||||
#endif
|
||||
// We must reset the location here because the transformation data
|
||||
// are set in the placement property
|
||||
TopLoc_Location aLoc;
|
||||
cShape.Location(aLoc);
|
||||
|
||||
// count triangles and nodes in the mesh
|
||||
int nbrTriangles=0, nbrNodes=0;
|
||||
TopExp_Explorer Ex;
|
||||
for (Ex.Init(cShape,TopAbs_FACE);Ex.More();Ex.Next()) {
|
||||
Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(TopoDS::Face(Ex.Current()), aLoc);
|
||||
// Note: we must also count empty faces
|
||||
if (!mesh.IsNull()) {
|
||||
nbrTriangles += mesh->NbTriangles();
|
||||
nbrNodes += mesh->NbNodes();
|
||||
}
|
||||
}
|
||||
|
||||
// create memory for the nodes and indexes
|
||||
SoCoordinate3* rejectedCoords = new SoCoordinate3();
|
||||
rejectedCoords ->point .setNum(nbrNodes);
|
||||
SoNormal* rejectedNorms = new SoNormal();
|
||||
rejectedNorms ->vector .setNum(nbrNodes);
|
||||
SoIndexedFaceSet* rejectedFaceSet = new SoIndexedFaceSet();
|
||||
rejectedFaceSet ->coordIndex .setNum(nbrTriangles*4);
|
||||
|
||||
// get the raw memory for fast fill up
|
||||
SbVec3f* verts = rejectedCoords ->point .startEditing();
|
||||
SbVec3f* norms = rejectedNorms ->vector .startEditing();
|
||||
int32_t* index = rejectedFaceSet ->coordIndex .startEditing();
|
||||
|
||||
// preset the normal vector with null vector
|
||||
for (int i=0; i < nbrNodes; i++)
|
||||
norms[i]= SbVec3f(0.0,0.0,0.0);
|
||||
|
||||
int ii = 0,FaceNodeOffset=0,FaceTriaOffset=0;
|
||||
for (Ex.Init(cShape, TopAbs_FACE); Ex.More(); Ex.Next(),ii++) {
|
||||
TopLoc_Location aLoc;
|
||||
const TopoDS_Face &actFace = TopoDS::Face(Ex.Current());
|
||||
// get the mesh of the shape
|
||||
Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(actFace,aLoc);
|
||||
if (mesh.IsNull()) continue;
|
||||
|
||||
// getting the transformation of the shape/face
|
||||
gp_Trsf myTransf;
|
||||
Standard_Boolean identity = true;
|
||||
if (!aLoc.IsIdentity()) {
|
||||
identity = false;
|
||||
myTransf = aLoc.Transformation();
|
||||
}
|
||||
|
||||
// getting size of node and triangle array of this face
|
||||
int nbNodesInFace = mesh->NbNodes();
|
||||
int nbTriInFace = mesh->NbTriangles();
|
||||
// check orientation
|
||||
TopAbs_Orientation orient = actFace.Orientation();
|
||||
|
||||
// cycling through the poly mesh
|
||||
const Poly_Array1OfTriangle& Triangles = mesh->Triangles();
|
||||
const TColgp_Array1OfPnt& Nodes = mesh->Nodes();
|
||||
for (int g=1; g <= nbTriInFace; g++) {
|
||||
// Get the triangle
|
||||
Standard_Integer N1,N2,N3;
|
||||
Triangles(g).Get(N1,N2,N3);
|
||||
|
||||
// change orientation of the triangle if the face is reversed
|
||||
if ( orient != TopAbs_FORWARD ) {
|
||||
Standard_Integer tmp = N1;
|
||||
N1 = N2;
|
||||
N2 = tmp;
|
||||
}
|
||||
|
||||
// get the 3 points of this triangle
|
||||
gp_Pnt V1(Nodes(N1)), V2(Nodes(N2)), V3(Nodes(N3));
|
||||
|
||||
// transform the vertices to the place of the face
|
||||
if (!identity) {
|
||||
V1.Transform(myTransf);
|
||||
V2.Transform(myTransf);
|
||||
V3.Transform(myTransf);
|
||||
}
|
||||
|
||||
// calculating per vertex normals
|
||||
// Calculate triangle normal
|
||||
gp_Vec v1(V1.X(),V1.Y(),V1.Z()),v2(V2.X(),V2.Y(),V2.Z()),v3(V3.X(),V3.Y(),V3.Z());
|
||||
gp_Vec Normal = (v2-v1)^(v3-v1);
|
||||
|
||||
// add the triangle normal to the vertex normal for all points of this triangle
|
||||
norms[FaceNodeOffset+N1-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z());
|
||||
norms[FaceNodeOffset+N2-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z());
|
||||
norms[FaceNodeOffset+N3-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z());
|
||||
|
||||
// set the vertices
|
||||
verts[FaceNodeOffset+N1-1].setValue((float)(V1.X()),(float)(V1.Y()),(float)(V1.Z()));
|
||||
verts[FaceNodeOffset+N2-1].setValue((float)(V2.X()),(float)(V2.Y()),(float)(V2.Z()));
|
||||
verts[FaceNodeOffset+N3-1].setValue((float)(V3.X()),(float)(V3.Y()),(float)(V3.Z()));
|
||||
|
||||
// set the index vector with the 3 point indexes and the end delimiter
|
||||
index[FaceTriaOffset*4+4*(g-1)] = FaceNodeOffset+N1-1;
|
||||
index[FaceTriaOffset*4+4*(g-1)+1] = FaceNodeOffset+N2-1;
|
||||
index[FaceTriaOffset*4+4*(g-1)+2] = FaceNodeOffset+N3-1;
|
||||
index[FaceTriaOffset*4+4*(g-1)+3] = SO_END_FACE_INDEX;
|
||||
}
|
||||
|
||||
// counting up the per Face offsets
|
||||
FaceNodeOffset += nbNodesInFace;
|
||||
FaceTriaOffset += nbTriInFace;
|
||||
|
||||
|
||||
// normalize all normals
|
||||
for (int i=0; i < nbrNodes; i++)
|
||||
norms[i].normalize();
|
||||
|
||||
// end the editing of the nodes
|
||||
rejectedCoords ->point .finishEditing();
|
||||
rejectedNorms ->vector .finishEditing();
|
||||
rejectedFaceSet ->coordIndex .finishEditing();
|
||||
|
||||
// fill in the transformation matrices
|
||||
SoMultipleCopy* rejectedTrfms = new SoMultipleCopy();
|
||||
|
||||
|
||||
rejectedTrfms->matrix.finishEditing();
|
||||
rejectedTrfms->addChild(rejectedFaceSet);
|
||||
SoSeparator* sep = new SoSeparator();
|
||||
sep->addChild(rejectedCoords);
|
||||
sep->addChild(rejectedNorms);
|
||||
sep->addChild(rejectedTrfms);
|
||||
pcRejectedRoot->addChild(sep);
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
Base::Console().Error("Cannot compute Inventor representation for the rejected transformations of shape of %s.\n",
|
||||
pcTransformed->getNameInDocument());
|
||||
}
|
||||
showRejectedShape(cShape);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewProviderTransformed::showRejectedShape(TopoDS_Shape shape)
|
||||
{
|
||||
try {
|
||||
// calculating the deflection value
|
||||
Standard_Real xMin, yMin, zMin, xMax, yMax, zMax;
|
||||
{
|
||||
Bnd_Box bounds;
|
||||
BRepBndLib::Add(shape, bounds);
|
||||
bounds.SetGap(0.0);
|
||||
bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax);
|
||||
}
|
||||
Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 * Deviation.getValue();
|
||||
|
||||
// create or use the mesh on the data structure
|
||||
// Note: This DOES have an effect on shape
|
||||
#if OCC_VERSION_HEX >= 0x060600
|
||||
Standard_Real AngDeflectionRads = AngularDeflection.getValue() / 180.0 * M_PI;
|
||||
BRepMesh_IncrementalMesh(shape, deflection, Standard_False, AngDeflectionRads, Standard_True);
|
||||
#else
|
||||
BRepMesh_IncrementalMesh(shape, deflection);
|
||||
#endif
|
||||
// We must reset the location here because the transformation data
|
||||
// are set in the placement property
|
||||
TopLoc_Location aLoc;
|
||||
shape.Location(aLoc);
|
||||
|
||||
// count triangles and nodes in the mesh
|
||||
int nbrTriangles=0, nbrNodes=0;
|
||||
TopExp_Explorer Ex;
|
||||
for (Ex.Init(shape, TopAbs_FACE); Ex.More(); Ex.Next()) {
|
||||
Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(TopoDS::Face(Ex.Current()), aLoc);
|
||||
// Note: we must also count empty faces
|
||||
if (!mesh.IsNull()) {
|
||||
nbrTriangles += mesh->NbTriangles();
|
||||
nbrNodes += mesh->NbNodes();
|
||||
}
|
||||
}
|
||||
|
||||
// create memory for the nodes and indexes
|
||||
SoCoordinate3* rejectedCoords = new SoCoordinate3();
|
||||
rejectedCoords ->point .setNum(nbrNodes);
|
||||
SoNormal* rejectedNorms = new SoNormal();
|
||||
rejectedNorms ->vector .setNum(nbrNodes);
|
||||
SoIndexedFaceSet* rejectedFaceSet = new SoIndexedFaceSet();
|
||||
rejectedFaceSet ->coordIndex .setNum(nbrTriangles*4);
|
||||
|
||||
// get the raw memory for fast fill up
|
||||
SbVec3f* verts = rejectedCoords ->point .startEditing();
|
||||
SbVec3f* norms = rejectedNorms ->vector .startEditing();
|
||||
int32_t* index = rejectedFaceSet ->coordIndex .startEditing();
|
||||
|
||||
// preset the normal vector with null vector
|
||||
for (int i=0; i < nbrNodes; i++)
|
||||
norms[i]= SbVec3f(0.0,0.0,0.0);
|
||||
|
||||
int FaceNodeOffset=0,FaceTriaOffset=0;
|
||||
for (Ex.Init(shape, TopAbs_FACE); Ex.More(); Ex.Next()) {
|
||||
const TopoDS_Face &actFace = TopoDS::Face(Ex.Current());
|
||||
|
||||
// get triangulation
|
||||
std::vector<gp_Pnt> points;
|
||||
std::vector<Poly_Triangle> facets;
|
||||
if (!Part::Tools::getTriangulation(actFace, points, facets))
|
||||
continue;
|
||||
|
||||
// get normal per vertex
|
||||
std::vector<gp_Vec> vertexnormals;
|
||||
Part::Tools::getPointNormals(points, facets, vertexnormals);
|
||||
|
||||
// getting size of node and triangle array of this face
|
||||
std::size_t nbNodesInFace = points.size();
|
||||
std::size_t nbTriInFace = facets.size();
|
||||
|
||||
for (std::size_t i = 0; i < points.size(); i++) {
|
||||
verts[FaceNodeOffset+i] = SbVec3f(points[i].X(), points[i].Y(), points[i].Z());
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < vertexnormals.size(); i++) {
|
||||
norms[FaceNodeOffset+i] = SbVec3f(vertexnormals[i].X(), vertexnormals[i].Y(), vertexnormals[i].Z());
|
||||
}
|
||||
|
||||
// cycling through the poly mesh
|
||||
for (std::size_t g=0; g < nbTriInFace; g++) {
|
||||
// Get the triangle
|
||||
Standard_Integer N1,N2,N3;
|
||||
facets[g].Get(N1,N2,N3);
|
||||
|
||||
// set the index vector with the 3 point indexes and the end delimiter
|
||||
index[FaceTriaOffset*4+4*g] = FaceNodeOffset+N1;
|
||||
index[FaceTriaOffset*4+4*g+1] = FaceNodeOffset+N2;
|
||||
index[FaceTriaOffset*4+4*g+2] = FaceNodeOffset+N3;
|
||||
index[FaceTriaOffset*4+4*g+3] = SO_END_FACE_INDEX;
|
||||
}
|
||||
|
||||
// counting up the per Face offsets
|
||||
FaceNodeOffset += nbNodesInFace;
|
||||
FaceTriaOffset += nbTriInFace;
|
||||
|
||||
// normalize all normals
|
||||
for (int i=0; i < nbrNodes; i++)
|
||||
norms[i].normalize();
|
||||
|
||||
// end the editing of the nodes
|
||||
rejectedCoords ->point .finishEditing();
|
||||
rejectedNorms ->vector .finishEditing();
|
||||
rejectedFaceSet ->coordIndex .finishEditing();
|
||||
|
||||
// fill in the transformation matrices
|
||||
SoMultipleCopy* rejectedTrfms = new SoMultipleCopy();
|
||||
rejectedTrfms->matrix.finishEditing();
|
||||
rejectedTrfms->addChild(rejectedFaceSet);
|
||||
SoSeparator* sep = new SoSeparator();
|
||||
sep->addChild(rejectedCoords);
|
||||
sep->addChild(rejectedNorms);
|
||||
sep->addChild(rejectedTrfms);
|
||||
pcRejectedRoot->addChild(sep);
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
Base::Console().Error("Cannot compute Inventor representation for the rejected transformations of shape of %s.\n",
|
||||
getObject()->getNameInDocument());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,9 @@ protected:
|
||||
public:
|
||||
void recomputeFeature(bool recompute=true);
|
||||
QString getMessage() const {return diagMessage;}
|
||||
|
||||
private:
|
||||
void showRejectedShape(TopoDS_Shape shape);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -49,10 +49,7 @@
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <gp_Lin.hxx>
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <BRepAdaptor_CompCurve.hxx>
|
||||
#include <BRepAdaptor_HCompCurve.hxx>
|
||||
#include <Approx_Curve3d.hxx>
|
||||
#include <BRepAdaptor_HCurve.hxx>
|
||||
#include <BRepAdaptor_Curve.hxx>
|
||||
|
||||
#include "CommandPy.h"
|
||||
#include "PathPy.h"
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <Base/Exception.h>
|
||||
#include <Base/Matrix.h>
|
||||
#include <Base/Tools.h>
|
||||
#include <Base/UnitsApi.h>
|
||||
#include <App/Application.h>
|
||||
#include <App/Document.h>
|
||||
#include <Gui/Application.h>
|
||||
@@ -197,10 +198,16 @@ CmdPointsConvert::CmdPointsConvert()
|
||||
void CmdPointsConvert::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
double STD_OCC_TOLERANCE = 1e-6;
|
||||
|
||||
int decimals = Base::UnitsApi::getDecimals();
|
||||
double tolerance_from_decimals = pow(10., -decimals);
|
||||
|
||||
double minimal_tolerance = tolerance_from_decimals < STD_OCC_TOLERANCE ? STD_OCC_TOLERANCE : tolerance_from_decimals;
|
||||
|
||||
bool ok;
|
||||
double tol = QInputDialog::getDouble(Gui::getMainWindow(), QObject::tr("Distance"),
|
||||
QObject::tr("Enter maximum distance:"), 0.1, 0.05, 10.0, 2, &ok, Qt::MSWindowsFixedSizeDialogHint);
|
||||
QObject::tr("Enter maximum distance:"), 0.1, minimal_tolerance, 10.0, decimals, &ok, Qt::MSWindowsFixedSizeDialogHint);
|
||||
if (!ok)
|
||||
return;
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
|
||||
#include "PovTools.h"
|
||||
#include "LuxTools.h"
|
||||
#include <Mod/Part/App/Tools.h>
|
||||
|
||||
using Base::Console;
|
||||
|
||||
@@ -95,35 +96,34 @@ void LuxTools::writeShape(std::ostream &out, const char *PartName, const TopoDS_
|
||||
// get the shape and mesh it
|
||||
const TopoDS_Face& aFace = TopoDS::Face(ex.Current());
|
||||
|
||||
// this block mesh the face and transfers it in a C array of vertices and face indexes
|
||||
Standard_Integer nbNodesInFace,nbTriInFace;
|
||||
gp_Vec* vertices=0;
|
||||
gp_Vec* vertexnormals=0;
|
||||
long* cons=0;
|
||||
std::vector<gp_Pnt> points;
|
||||
std::vector<gp_Vec> vertexnormals;
|
||||
std::vector<Poly_Triangle> facets;
|
||||
if (!Part::Tools::getTriangulation(aFace, points, facets)) {
|
||||
break;
|
||||
}
|
||||
|
||||
PovTools::transferToArray(aFace,&vertices,&vertexnormals,&cons,nbNodesInFace,nbTriInFace);
|
||||
Part::Tools::getPointNormals(points, facets, vertexnormals);
|
||||
Part::Tools::getPointNormals(points, aFace, vertexnormals);
|
||||
|
||||
if (!vertices) break;
|
||||
// writing vertices
|
||||
for (int i=0; i < nbNodesInFace; i++) {
|
||||
P << vertices[i].X() << " " << vertices[i].Y() << " " << vertices[i].Z() << " ";
|
||||
for (std::size_t i=0; i < points.size(); i++) {
|
||||
P << points[i].X() << " " << points[i].Y() << " " << points[i].Z() << " ";
|
||||
}
|
||||
|
||||
// writing per vertex normals
|
||||
for (int j=0; j < nbNodesInFace; j++) {
|
||||
for (std::size_t j=0; j < vertexnormals.size(); j++) {
|
||||
N << vertexnormals[j].X() << " " << vertexnormals[j].Y() << " " << vertexnormals[j].Z() << " ";
|
||||
}
|
||||
|
||||
// writing triangle indices
|
||||
for (int k=0; k < nbTriInFace; k++) {
|
||||
triindices << cons[3*k]+vi << " " << cons[3*k+2]+vi << " " << cons[3*k+1]+vi << " ";
|
||||
for (std::size_t k=0; k < facets.size(); k++) {
|
||||
Standard_Integer n1, n2, n3;
|
||||
facets[k].Get(n1, n2, n3);
|
||||
triindices << n1 + vi << " " << n3 + vi << " " << n2 + vi << " ";
|
||||
}
|
||||
|
||||
vi = vi + nbNodesInFace;
|
||||
|
||||
delete [] vertexnormals;
|
||||
delete [] vertices;
|
||||
delete [] cons;
|
||||
vi = vi + points.size();
|
||||
|
||||
seq.next();
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
|
||||
|
||||
#include "PovTools.h"
|
||||
#include <Mod/Part/App/Tools.h>
|
||||
|
||||
using Base::Console;
|
||||
|
||||
@@ -158,7 +159,7 @@ void PovTools::writeData(const char *FileName, const char *PartName,
|
||||
std::vector<Base::Vector3d> normals;
|
||||
std::vector<Data::ComplexGeoData::Facet> facets;
|
||||
Data::Segment* segm = data->getSubElement("Face", i);
|
||||
data->getFacesFromSubelement(segm, points, normals, facets);
|
||||
data->getFacesFromSubElement(segm, points, normals, facets);
|
||||
delete segm;
|
||||
|
||||
// writing per face header
|
||||
@@ -242,53 +243,53 @@ void PovTools::writeShape(std::ostream &out, const char *PartName,
|
||||
// get the shape and mesh it
|
||||
const TopoDS_Face& aFace = TopoDS::Face(ex.Current());
|
||||
|
||||
// this block mesh the face and transfers it in a C array of vertices and face indexes
|
||||
Standard_Integer nbNodesInFace,nbTriInFace;
|
||||
gp_Vec* vertices=0;
|
||||
gp_Vec* vertexnormals=0;
|
||||
long* cons=0;
|
||||
std::vector<gp_Pnt> points;
|
||||
std::vector<gp_Vec> vertexnormals;
|
||||
std::vector<Poly_Triangle> facets;
|
||||
if (!Part::Tools::getTriangulation(aFace, points, facets)) {
|
||||
break;
|
||||
}
|
||||
Part::Tools::getPointNormals(points, facets, vertexnormals);
|
||||
Part::Tools::getPointNormals(points, aFace, vertexnormals);
|
||||
|
||||
transferToArray(aFace,&vertices,&vertexnormals,&cons,nbNodesInFace,nbTriInFace);
|
||||
|
||||
if (!vertices) break;
|
||||
// writing per face header
|
||||
out << "// face number" << l << " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl
|
||||
<< "#declare " << PartName << l << " = mesh2{" << endl
|
||||
<< " vertex_vectors {" << endl
|
||||
<< " " << nbNodesInFace << "," << endl;
|
||||
<< " " << points.size() << "," << endl;
|
||||
// writing vertices
|
||||
for (int i=0; i < nbNodesInFace; i++) {
|
||||
out << " <" << vertices[i].X() << ","
|
||||
<< vertices[i].Z() << ","
|
||||
<< vertices[i].Y() << ">,"
|
||||
<< endl;
|
||||
for (std::size_t i=0; i < points.size(); i++) {
|
||||
out << " <"
|
||||
<< points[i].X() << ","
|
||||
<< points[i].Z() << ","
|
||||
<< points[i].Y() << ">,"
|
||||
<< endl;
|
||||
}
|
||||
out << " }" << endl
|
||||
// writing per vertex normals
|
||||
<< " normal_vectors {" << endl
|
||||
<< " " << nbNodesInFace << "," << endl;
|
||||
for (int j=0; j < nbNodesInFace; j++) {
|
||||
out << " <" << vertexnormals[j].X() << ","
|
||||
<< vertexnormals[j].Z() << ","
|
||||
<< vertexnormals[j].Y() << ">,"
|
||||
<< endl;
|
||||
<< " " << vertexnormals.size() << "," << endl;
|
||||
for (std::size_t j=0; j < vertexnormals.size(); j++) {
|
||||
out << " <"
|
||||
<< vertexnormals[j].X() << ","
|
||||
<< vertexnormals[j].Z() << ","
|
||||
<< vertexnormals[j].Y() << ">,"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
out << " }" << endl
|
||||
// writing triangle indices
|
||||
<< " face_indices {" << endl
|
||||
<< " " << nbTriInFace << "," << endl;
|
||||
for (int k=0; k < nbTriInFace; k++) {
|
||||
out << " <" << cons[3*k] << ","<< cons[3*k+2] << ","<< cons[3*k+1] << ">," << endl;
|
||||
<< " " << facets.size() << "," << endl;
|
||||
for (std::size_t k=0; k < facets.size(); k++) {
|
||||
Standard_Integer n1, n2, n3;
|
||||
facets[k].Get(n1, n2, n3);
|
||||
out << " <" << n1 << ","<< n3 << "," << n2 << ">," << endl;
|
||||
}
|
||||
// end of face
|
||||
out << " }" << endl
|
||||
<< "} // end of Face"<< l << endl << endl;
|
||||
|
||||
delete [] vertexnormals;
|
||||
delete [] vertices;
|
||||
delete [] cons;
|
||||
|
||||
seq.next();
|
||||
|
||||
} // end of face loop
|
||||
@@ -323,36 +324,32 @@ void PovTools::writeShapeCSV(const char *FileName,
|
||||
Base::SequencerLauncher seq("Writing file", l);
|
||||
|
||||
// write the file
|
||||
l = 1;
|
||||
for (ex.Init(Shape, TopAbs_FACE); ex.More(); ex.Next(),l++) {
|
||||
for (ex.Init(Shape, TopAbs_FACE); ex.More(); ex.Next()) {
|
||||
|
||||
// get the shape and mesh it
|
||||
const TopoDS_Face& aFace = TopoDS::Face(ex.Current());
|
||||
|
||||
// this block mesh the face and transfers it in a C array of vertices and face indexes
|
||||
Standard_Integer nbNodesInFace,nbTriInFace;
|
||||
gp_Vec* vertices=0;
|
||||
gp_Vec* vertexnormals=0;
|
||||
long* cons=0;
|
||||
|
||||
transferToArray(aFace,&vertices,&vertexnormals,&cons,nbNodesInFace,nbTriInFace);
|
||||
|
||||
if (!vertices) break;
|
||||
// writing per face header
|
||||
// writing vertices
|
||||
for (int i=0; i < nbNodesInFace; i++) {
|
||||
fout << vertices[i].X() << cSeperator
|
||||
<< vertices[i].Z() << cSeperator
|
||||
<< vertices[i].Y() << cSeperator
|
||||
<< vertexnormals[i].X() * fLength <<cSeperator
|
||||
<< vertexnormals[i].Z() * fLength <<cSeperator
|
||||
<< vertexnormals[i].Y() * fLength <<cSeperator
|
||||
<< endl;
|
||||
std::vector<gp_Pnt> points;
|
||||
std::vector<gp_Vec> vertexnormals;
|
||||
std::vector<Poly_Triangle> facets;
|
||||
if (!Part::Tools::getTriangulation(aFace, points, facets)) {
|
||||
break;
|
||||
}
|
||||
|
||||
delete [] vertexnormals;
|
||||
delete [] vertices;
|
||||
delete [] cons;
|
||||
Part::Tools::getPointNormals(points, facets, vertexnormals);
|
||||
Part::Tools::getPointNormals(points, aFace, vertexnormals);
|
||||
|
||||
// writing per face header
|
||||
// writing vertices
|
||||
for (std::size_t i=0; i < points.size(); i++) {
|
||||
fout << points[i].X() << cSeperator
|
||||
<< points[i].Z() << cSeperator
|
||||
<< points[i].Y() << cSeperator
|
||||
<< vertexnormals[i].X() * fLength << cSeperator
|
||||
<< vertexnormals[i].Z() * fLength << cSeperator
|
||||
<< vertexnormals[i].Y() * fLength << cSeperator
|
||||
<< endl;
|
||||
}
|
||||
|
||||
seq.next();
|
||||
|
||||
@@ -360,130 +357,3 @@ void PovTools::writeShapeCSV(const char *FileName,
|
||||
|
||||
fout.close();
|
||||
}
|
||||
|
||||
void PovTools::transferToArray(const TopoDS_Face& aFace,gp_Vec** vertices,gp_Vec** vertexnormals, long** cons,int &nbNodesInFace,int &nbTriInFace )
|
||||
{
|
||||
TopLoc_Location aLoc;
|
||||
|
||||
// doing the meshing and checking the result
|
||||
//BRepMesh_IncrementalMesh MESH(aFace,fDeflection);
|
||||
Handle(Poly_Triangulation) aPoly = BRep_Tool::Triangulation(aFace,aLoc);
|
||||
if (aPoly.IsNull()) {
|
||||
Base::Console().Log("Empty face triangulation\n");
|
||||
nbNodesInFace =0;
|
||||
nbTriInFace = 0;
|
||||
vertices = 0l;
|
||||
cons = 0l;
|
||||
return;
|
||||
}
|
||||
|
||||
// getting the transformation of the shape/face
|
||||
gp_Trsf myTransf;
|
||||
Standard_Boolean identity = true;
|
||||
if (!aLoc.IsIdentity()) {
|
||||
identity = false;
|
||||
myTransf = aLoc.Transformation();
|
||||
}
|
||||
|
||||
Standard_Integer i;
|
||||
// getting size and create the array
|
||||
nbNodesInFace = aPoly->NbNodes();
|
||||
nbTriInFace = aPoly->NbTriangles();
|
||||
*vertices = new gp_Vec[nbNodesInFace];
|
||||
*vertexnormals = new gp_Vec[nbNodesInFace];
|
||||
for (i=0; i < nbNodesInFace; i++) {
|
||||
(*vertexnormals)[i]= gp_Vec(0.0,0.0,0.0);
|
||||
}
|
||||
|
||||
*cons = new long[3*(nbTriInFace)+1];
|
||||
|
||||
// check orientation
|
||||
TopAbs_Orientation orient = aFace.Orientation();
|
||||
|
||||
// cycling through the poly mesh
|
||||
const Poly_Array1OfTriangle& Triangles = aPoly->Triangles();
|
||||
const TColgp_Array1OfPnt& Nodes = aPoly->Nodes();
|
||||
for (i=1; i<=nbTriInFace; i++) {
|
||||
// Get the triangle
|
||||
Standard_Integer N1,N2,N3;
|
||||
Triangles(i).Get(N1,N2,N3);
|
||||
|
||||
// change orientation of the triangles
|
||||
if ( orient != TopAbs_FORWARD )
|
||||
{
|
||||
Standard_Integer tmp = N1;
|
||||
N1 = N2;
|
||||
N2 = tmp;
|
||||
}
|
||||
|
||||
gp_Pnt V1 = Nodes(N1);
|
||||
gp_Pnt V2 = Nodes(N2);
|
||||
gp_Pnt V3 = Nodes(N3);
|
||||
|
||||
// transform the vertices to the place of the face
|
||||
if (!identity) {
|
||||
V1.Transform(myTransf);
|
||||
V2.Transform(myTransf);
|
||||
V3.Transform(myTransf);
|
||||
}
|
||||
|
||||
// Calculate triangle normal
|
||||
gp_Vec v1(V1.X(),V1.Y(),V1.Z()),v2(V2.X(),V2.Y(),V2.Z()),v3(V3.X(),V3.Y(),V3.Z());
|
||||
gp_Vec Normal = (v2-v1)^(v3-v1);
|
||||
|
||||
//Standard_Real Area = 0.5 * Normal.Magnitude();
|
||||
|
||||
// add the triangle normal to the vertex normal for all points of this triangle
|
||||
(*vertexnormals)[N1-1] += gp_Vec(Normal.X(),Normal.Y(),Normal.Z());
|
||||
(*vertexnormals)[N2-1] += gp_Vec(Normal.X(),Normal.Y(),Normal.Z());
|
||||
(*vertexnormals)[N3-1] += gp_Vec(Normal.X(),Normal.Y(),Normal.Z());
|
||||
|
||||
(*vertices)[N1-1].SetX((float)(V1.X()));
|
||||
(*vertices)[N1-1].SetY((float)(V1.Y()));
|
||||
(*vertices)[N1-1].SetZ((float)(V1.Z()));
|
||||
(*vertices)[N2-1].SetX((float)(V2.X()));
|
||||
(*vertices)[N2-1].SetY((float)(V2.Y()));
|
||||
(*vertices)[N2-1].SetZ((float)(V2.Z()));
|
||||
(*vertices)[N3-1].SetX((float)(V3.X()));
|
||||
(*vertices)[N3-1].SetY((float)(V3.Y()));
|
||||
(*vertices)[N3-1].SetZ((float)(V3.Z()));
|
||||
|
||||
int j = i - 1;
|
||||
N1--;
|
||||
N2--;
|
||||
N3--;
|
||||
(*cons)[3*j] = N1;
|
||||
(*cons)[3*j+1] = N2;
|
||||
(*cons)[3*j+2] = N3;
|
||||
}
|
||||
|
||||
// normalize all vertex normals
|
||||
for (i=0; i < nbNodesInFace; i++) {
|
||||
|
||||
gp_Dir clNormal;
|
||||
|
||||
try {
|
||||
Handle(Geom_Surface) Surface = BRep_Tool::Surface(aFace);
|
||||
|
||||
gp_Pnt vertex((*vertices)[i].XYZ());
|
||||
// gp_Pnt vertex((*vertices)[i][0], (*vertices)[i][1], (*vertices)[i][2]);
|
||||
GeomAPI_ProjectPointOnSurf ProPntSrf(vertex, Surface);
|
||||
Standard_Real fU, fV;
|
||||
ProPntSrf.Parameters(1, fU, fV);
|
||||
|
||||
GeomLProp_SLProps clPropOfFace(Surface, fU, fV, 2, gp::Resolution());
|
||||
|
||||
clNormal = clPropOfFace.Normal();
|
||||
gp_Vec temp = clNormal;
|
||||
//Base::Console().Log("unterschied:%.2f",temp.dot((*vertexnormals)[i]));
|
||||
if ( temp * (*vertexnormals)[i] < 0 )
|
||||
temp = -temp;
|
||||
(*vertexnormals)[i] = temp;
|
||||
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
|
||||
(*vertexnormals)[i].Normalize();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,9 +110,6 @@ public:
|
||||
const TopoDS_Shape& Shape,
|
||||
float fMeshDeviation,
|
||||
float fLength);
|
||||
|
||||
|
||||
static void transferToArray(const TopoDS_Face& aFace,gp_Vec** vertices,gp_Vec** vertexnormals, long** cons,int &nbNodesInFace,int &nbTriInFace );
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ set(SketcherGui_UIC_SRCS
|
||||
SketchRectangularArrayDialog.ui
|
||||
SketcherRegularPolygonDialog.ui
|
||||
ConstraintMultiFilterDialog.ui
|
||||
ConstraintSettingsDialog.ui
|
||||
)
|
||||
|
||||
if(BUILD_QT5)
|
||||
@@ -120,6 +121,8 @@ SET(SketcherGui_SRCS
|
||||
SketcherRegularPolygonDialog.cpp
|
||||
ConstraintMultiFilterDialog.h
|
||||
ConstraintMultiFilterDialog.cpp
|
||||
ConstraintSettingsDialog.h
|
||||
ConstraintSettingsDialog.cpp
|
||||
TaskDlgEditSketch.cpp
|
||||
TaskDlgEditSketch.h
|
||||
ViewProviderPython.cpp
|
||||
|
||||
@@ -337,6 +337,7 @@ void CmdSketcherSelectConstraints::activated(int iMsg)
|
||||
|
||||
getSelection().clearSelection();
|
||||
|
||||
std::vector<std::string> constraintSubNames;
|
||||
// go through the selected subelements
|
||||
for (std::vector<std::string>::const_iterator it=SubNames.begin(); it != SubNames.end(); ++it) {
|
||||
// only handle edges
|
||||
@@ -349,13 +350,15 @@ void CmdSketcherSelectConstraints::activated(int iMsg)
|
||||
it != vals.end(); ++it,++i)
|
||||
{
|
||||
if ((*it)->First == GeoId || (*it)->Second == GeoId || (*it)->Third == GeoId) {
|
||||
Gui::Selection().addSelection(doc_name.c_str(),
|
||||
obj_name.c_str(),
|
||||
Sketcher::PropertyConstraintList::getConstraintName(i).c_str());
|
||||
constraintSubNames.push_back(Sketcher::PropertyConstraintList::getConstraintName(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!constraintSubNames.empty())
|
||||
Gui::Selection().addSelections(doc_name.c_str(), obj_name.c_str(), constraintSubNames);
|
||||
|
||||
}
|
||||
|
||||
bool CmdSketcherSelectConstraints::isActive(void)
|
||||
@@ -533,17 +536,20 @@ void CmdSketcherSelectRedundantConstraints::activated(int iMsg)
|
||||
getSelection().clearSelection();
|
||||
|
||||
// push the constraints
|
||||
std::vector<std::string> constraintSubNames;
|
||||
|
||||
int i = 0;
|
||||
for (std::vector< Sketcher::Constraint * >::const_iterator it= vals.begin();it != vals.end(); ++it,++i) {
|
||||
for(std::vector< int >::const_iterator itc= solverredundant.begin();itc != solverredundant.end(); ++itc) {
|
||||
if ((*itc) - 1 == i) {
|
||||
Gui::Selection().addSelection(doc_name.c_str(),
|
||||
obj_name.c_str(),
|
||||
Sketcher::PropertyConstraintList::getConstraintName(i).c_str());
|
||||
constraintSubNames.push_back(Sketcher::PropertyConstraintList::getConstraintName(i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!constraintSubNames.empty())
|
||||
Gui::Selection().addSelections(doc_name.c_str(), obj_name.c_str(), constraintSubNames);
|
||||
}
|
||||
|
||||
bool CmdSketcherSelectRedundantConstraints::isActive(void)
|
||||
@@ -587,17 +593,19 @@ void CmdSketcherSelectMalformedConstraints::activated(int iMsg)
|
||||
getSelection().clearSelection();
|
||||
|
||||
// push the constraints
|
||||
std::vector<std::string> constraintSubNames;
|
||||
int i = 0;
|
||||
for (std::vector< Sketcher::Constraint * >::const_iterator it= vals.begin();it != vals.end(); ++it,++i) {
|
||||
for(std::vector< int >::const_iterator itc= solvermalformed.begin();itc != solvermalformed.end(); ++itc) {
|
||||
if ((*itc) - 1 == i) {
|
||||
Gui::Selection().addSelection(doc_name.c_str(),
|
||||
obj_name.c_str(),
|
||||
Sketcher::PropertyConstraintList::getConstraintName(i).c_str());
|
||||
constraintSubNames.push_back(Sketcher::PropertyConstraintList::getConstraintName(i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!constraintSubNames.empty())
|
||||
Gui::Selection().addSelections(doc_name.c_str(), obj_name.c_str(), constraintSubNames);
|
||||
}
|
||||
|
||||
bool CmdSketcherSelectMalformedConstraints::isActive(void)
|
||||
@@ -641,17 +649,19 @@ void CmdSketcherSelectPartiallyRedundantConstraints::activated(int iMsg)
|
||||
getSelection().clearSelection();
|
||||
|
||||
// push the constraints
|
||||
std::vector<std::string> constraintSubNames;
|
||||
int i = 0;
|
||||
for (std::vector< Sketcher::Constraint * >::const_iterator it= vals.begin();it != vals.end(); ++it,++i) {
|
||||
for(std::vector< int >::const_iterator itc= solverpartiallyredundant.begin();itc != solverpartiallyredundant.end(); ++itc) {
|
||||
if ((*itc) - 1 == i) {
|
||||
Gui::Selection().addSelection(doc_name.c_str(),
|
||||
obj_name.c_str(),
|
||||
Sketcher::PropertyConstraintList::getConstraintName(i).c_str());
|
||||
constraintSubNames.push_back(Sketcher::PropertyConstraintList::getConstraintName(i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!constraintSubNames.empty())
|
||||
Gui::Selection().addSelections(doc_name.c_str(), obj_name.c_str(), constraintSubNames);
|
||||
}
|
||||
|
||||
bool CmdSketcherSelectPartiallyRedundantConstraints::isActive(void)
|
||||
@@ -693,17 +703,19 @@ void CmdSketcherSelectConflictingConstraints::activated(int iMsg)
|
||||
getSelection().clearSelection();
|
||||
|
||||
// push the constraints
|
||||
std::vector<std::string> constraintSubNames;
|
||||
int i = 0;
|
||||
for (std::vector< Sketcher::Constraint * >::const_iterator it= vals.begin();it != vals.end(); ++it,++i) {
|
||||
for (std::vector< int >::const_iterator itc= solverconflicting.begin();itc != solverconflicting.end(); ++itc) {
|
||||
if ((*itc) - 1 == i) {
|
||||
Gui::Selection().addSelection(doc_name.c_str(),
|
||||
obj_name.c_str(),
|
||||
Sketcher::PropertyConstraintList::getConstraintName(i).c_str());
|
||||
constraintSubNames.push_back(Sketcher::PropertyConstraintList::getConstraintName(i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!constraintSubNames.empty())
|
||||
Gui::Selection().addSelections(doc_name.c_str(), obj_name.c_str(), constraintSubNames);
|
||||
}
|
||||
|
||||
bool CmdSketcherSelectConflictingConstraints::isActive(void)
|
||||
@@ -747,8 +759,7 @@ void CmdSketcherSelectElementsAssociatedWithConstraints::activated(int iMsg)
|
||||
std::string obj_name = Obj->getNameInDocument();
|
||||
std::stringstream ss;
|
||||
|
||||
int selected = 0;
|
||||
|
||||
std::vector<std::string> elementSubNames;
|
||||
// go through the selected subelements
|
||||
for (std::vector<std::string>::const_iterator it=SubNames.begin(); it != SubNames.end(); ++it) {
|
||||
// only handle constraints
|
||||
@@ -772,9 +783,7 @@ void CmdSketcherSelectElementsAssociatedWithConstraints::activated(int iMsg)
|
||||
ss << "Vertex" << vertex + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str());
|
||||
selected++;
|
||||
elementSubNames.push_back(ss.str());
|
||||
}
|
||||
|
||||
if(vals[ConstrId]->Second!=Constraint::GeoUndef){
|
||||
@@ -794,8 +803,7 @@ void CmdSketcherSelectElementsAssociatedWithConstraints::activated(int iMsg)
|
||||
break;
|
||||
}
|
||||
|
||||
Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str());
|
||||
selected++;
|
||||
elementSubNames.push_back(ss.str());
|
||||
}
|
||||
|
||||
if(vals[ConstrId]->Third!=Constraint::GeoUndef){
|
||||
@@ -815,17 +823,20 @@ void CmdSketcherSelectElementsAssociatedWithConstraints::activated(int iMsg)
|
||||
break;
|
||||
}
|
||||
|
||||
Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str());
|
||||
selected++;
|
||||
elementSubNames.push_back(ss.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (selected == 0) {
|
||||
if (elementSubNames.empty()) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("No constraint selected"),
|
||||
QObject::tr("At least one constraint must be selected"));
|
||||
}
|
||||
else {
|
||||
Gui::Selection().addSelections(doc_name.c_str(), obj_name.c_str(), elementSubNames);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool CmdSketcherSelectElementsAssociatedWithConstraints::isActive(void)
|
||||
@@ -866,22 +877,24 @@ void CmdSketcherSelectElementsWithDoFs::activated(int iMsg)
|
||||
|
||||
auto geos = Obj->getInternalGeometry();
|
||||
|
||||
auto testselectvertex = [&Obj, &ss, &doc_name, &obj_name](int geoId, PointPos pos) {
|
||||
std::vector<std::string> elementSubNames;
|
||||
|
||||
auto testselectvertex = [&Obj, &ss, &elementSubNames](int geoId, PointPos pos) {
|
||||
ss.str(std::string());
|
||||
|
||||
int vertex = Obj->getVertexIndexGeoPos(geoId, pos);
|
||||
if (vertex > -1) {
|
||||
ss << "Vertex" << vertex + 1;
|
||||
|
||||
Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str());
|
||||
elementSubNames.push_back(ss.str());
|
||||
}
|
||||
};
|
||||
|
||||
auto testselectedge = [&ss, &doc_name, &obj_name](int geoId) {
|
||||
auto testselectedge = [&ss, &elementSubNames](int geoId) {
|
||||
ss.str(std::string());
|
||||
|
||||
ss << "Edge" << geoId + 1;
|
||||
Gui::Selection().addSelection(doc_name.c_str(), obj_name.c_str(), ss.str().c_str());
|
||||
elementSubNames.push_back(ss.str());
|
||||
};
|
||||
|
||||
int geoid = 0;
|
||||
@@ -911,6 +924,10 @@ void CmdSketcherSelectElementsWithDoFs::activated(int iMsg)
|
||||
geoid++;
|
||||
}
|
||||
|
||||
if (!elementSubNames.empty()) {
|
||||
Gui::Selection().addSelections(doc_name.c_str(), obj_name.c_str(), elementSubNames);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool CmdSketcherSelectElementsWithDoFs::isActive(void)
|
||||
|
||||
@@ -36,19 +36,19 @@ namespace ConstraintFilter {
|
||||
Datums = 2,
|
||||
Named = 3,
|
||||
NonDriving = 4,
|
||||
Horizontal = 5,
|
||||
Vertical = 6,
|
||||
Coincident = 7,
|
||||
PointOnObject = 8,
|
||||
Coincident = 5,
|
||||
PointOnObject = 6,
|
||||
Vertical = 7,
|
||||
Horizontal = 8,
|
||||
Parallel = 9,
|
||||
Perpendicular = 10,
|
||||
Tangent = 11,
|
||||
Equality = 12,
|
||||
Symmetric = 13,
|
||||
Block = 14,
|
||||
Distance = 15,
|
||||
HorizontalDistance = 16,
|
||||
VerticalDistance = 17,
|
||||
HorizontalDistance = 15,
|
||||
VerticalDistance = 16,
|
||||
Distance = 17,
|
||||
Radius = 18,
|
||||
Weight = 19,
|
||||
Diameter = 20,
|
||||
@@ -60,6 +60,8 @@ namespace ConstraintFilter {
|
||||
|
||||
enum SpecialFilterValue {
|
||||
Multiple = 24,
|
||||
Selection = 25,
|
||||
AssociatedConstraints = 26,
|
||||
NumSpecialFilterValue
|
||||
};
|
||||
|
||||
@@ -73,22 +75,22 @@ namespace ConstraintFilter {
|
||||
1 << FilterValue::Geometric | 1 << FilterValue::Horizontal | 1 << FilterValue::Vertical | 1 << FilterValue::Coincident |
|
||||
1 << FilterValue::PointOnObject | 1 << FilterValue::Parallel | 1 << FilterValue::Perpendicular | 1 << FilterValue::Tangent |
|
||||
1 << FilterValue::Equality | 1 << FilterValue::Symmetric | 1 << FilterValue::Block | 1 << FilterValue::InternalAlignment, // Geometric = All others not being datums (1)
|
||||
1 << FilterValue::Datums | 1 << FilterValue::NonDriving | 1 << FilterValue::Distance | 1 << FilterValue::HorizontalDistance | 1 << FilterValue::VerticalDistance | 1 << FilterValue::Radius | 1 << FilterValue::Weight | 1 << FilterValue::Diameter | 1 << FilterValue::Angle | 1 << FilterValue::SnellsLaw, // Datum = all others not being geometric (2)
|
||||
1 << FilterValue::Datums | 1 << FilterValue::Distance | 1 << FilterValue::HorizontalDistance | 1 << FilterValue::VerticalDistance | 1 << FilterValue::Radius | 1 << FilterValue::Weight | 1 << FilterValue::Diameter | 1 << FilterValue::Angle | 1 << FilterValue::SnellsLaw, // Datum = all others not being geometric (2)
|
||||
1 << FilterValue::Named, // Named = Just this (3)
|
||||
1 << FilterValue::NonDriving, // NonDriving = Just this (4)
|
||||
1 << FilterValue::Horizontal, // Horizontal = Just this (5)
|
||||
1 << FilterValue::Vertical, // Vertical = Just this (6)
|
||||
1 << FilterValue::Coincident, // Coincident = Just this (7)
|
||||
1 << FilterValue::PointOnObject, // PointOnObject = Just this (8)
|
||||
1 << FilterValue::Coincident, // Coincident = Just this (5)
|
||||
1 << FilterValue::PointOnObject, // PointOnObject = Just this (6)
|
||||
1 << FilterValue::Vertical, // Vertical = Just this (7)
|
||||
1 << FilterValue::Horizontal, // Horizontal = Just this (8)
|
||||
1 << FilterValue::Parallel, // Parallel = Just this (9)
|
||||
1 << FilterValue::Perpendicular, // Perpendicular = Just this (10)
|
||||
1 << FilterValue::Tangent, // Tangent = Just this (11)
|
||||
1 << FilterValue::Equality, // Equality = Just this (12)
|
||||
1 << FilterValue::Symmetric, // Symmetric = Just this (13)
|
||||
1 << FilterValue::Block, // Block = Just this (14)
|
||||
1 << FilterValue::Distance, // Distance = Just this (15)
|
||||
1 << FilterValue::HorizontalDistance, // HorizontalDistance = Just this (16)
|
||||
1 << FilterValue::VerticalDistance, // VerticalDistance = Just this (17)
|
||||
1 << FilterValue::HorizontalDistance, // HorizontalDistance = Just this (15)
|
||||
1 << FilterValue::VerticalDistance, // VerticalDistance = Just this (16)
|
||||
1 << FilterValue::Distance, // Distance = Just this (17)
|
||||
1 << FilterValue::Radius, // Radius = Just this (18)
|
||||
1 << FilterValue::Weight, // Weight = Just this (19)
|
||||
1 << FilterValue::Diameter, // Diameter = Just this (20)
|
||||
|
||||
@@ -93,15 +93,43 @@ void ConstraintMultiFilterDialog::on_listMultiFilter_itemChanged(QListWidgetItem
|
||||
{
|
||||
int filterindex = ui->listMultiFilter->row(item);
|
||||
|
||||
auto aggregate = filterAggregates[filterindex];
|
||||
auto itemAggregate = filterAggregates[filterindex];
|
||||
|
||||
ui->listMultiFilter->blockSignals(true);
|
||||
if(item->checkState() == Qt::Checked) {
|
||||
for(int i = 0; i < ui->listMultiFilter->count(); i++) {
|
||||
if(aggregate[i])
|
||||
ui->listMultiFilter->item(i)->setCheckState(Qt::Checked);
|
||||
|
||||
for(int i = 0; i < ui->listMultiFilter->count(); i++) {
|
||||
// any filter comprised on the filter of the activated item, gets the same check state
|
||||
if(itemAggregate[i])
|
||||
ui->listMultiFilter->item(i)->setCheckState(item->checkState());
|
||||
|
||||
// if unchecking, in addition uncheck any group comprising the unchecked item
|
||||
if(item->checkState() == Qt::Unchecked) {
|
||||
if(filterAggregates[i][filterindex])
|
||||
ui->listMultiFilter->item(i)->setCheckState(Qt::Unchecked);
|
||||
}
|
||||
}
|
||||
|
||||
// Now that all filters are correctly updated to match dependencies,
|
||||
// if checking, in addition check any group comprising all items that are checked, and check it if all checked.
|
||||
if(item->checkState() == Qt::Checked) {
|
||||
for(int i = 0; i < ui->listMultiFilter->count(); i++) {
|
||||
if(filterAggregates[i][filterindex]) { // only for groups comprising the changed filter
|
||||
bool mustBeChecked = true;
|
||||
|
||||
for(int j = 0; j < FilterValue::NumFilterValue; j++) {
|
||||
if (i == j)
|
||||
continue;
|
||||
|
||||
if (filterAggregates[i][j]) // if it is in group
|
||||
mustBeChecked = mustBeChecked && ui->listMultiFilter->item(j)->checkState() == Qt::Checked;
|
||||
}
|
||||
|
||||
if(mustBeChecked)
|
||||
ui->listMultiFilter->item(i)->setCheckState(Qt::Checked);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui->listMultiFilter->blockSignals(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,22 +9,16 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>325</width>
|
||||
<width>274</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>700</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Multiple filter selection</string>
|
||||
</property>
|
||||
@@ -39,16 +33,13 @@
|
||||
<item>
|
||||
<widget class="QListWidget" name="listMultiFilter">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>500</height>
|
||||
</size>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
@@ -78,17 +69,7 @@
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Non-Driving</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Horizontal</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Vertical</string>
|
||||
<string>Reference</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
@@ -101,6 +82,16 @@
|
||||
<string>Point on Object</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Vertical</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Horizontal</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Parallel</string>
|
||||
@@ -131,11 +122,6 @@
|
||||
<string>Block</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Distance</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Horizontal Distance</string>
|
||||
@@ -146,6 +132,11 @@
|
||||
<string>Vertical Distance</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Distance</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Radius</string>
|
||||
@@ -217,19 +208,6 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item alignment="Qt::AlignHCenter">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2021 Abdullah Tahiri <abdullah.tahiri.yo@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 <QPixmap>
|
||||
# include <QDialog>
|
||||
#endif
|
||||
|
||||
#include <Gui/BitmapFactory.h>
|
||||
#include <Gui/MainWindow.h>
|
||||
#include <Base/Tools.h>
|
||||
#include <Base/UnitsApi.h>
|
||||
#include <Gui/PrefWidgets.h>
|
||||
|
||||
#include "ui_ConstraintSettingsDialog.h"
|
||||
#include "ConstraintSettingsDialog.h"
|
||||
|
||||
using namespace SketcherGui;
|
||||
|
||||
ConstraintSettingsDialog::ConstraintSettingsDialog(void)
|
||||
: QDialog(Gui::getMainWindow()), ui(new Ui_ConstraintSettingsDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
{ // in case any signal is connected before this
|
||||
QSignalBlocker block(this);
|
||||
loadSettings();
|
||||
snapshotInitialSettings();
|
||||
}
|
||||
|
||||
QObject::connect(
|
||||
ui->filterInternalAlignment, SIGNAL(stateChanged(int)),
|
||||
this , SLOT (on_filterInternalAlignment_stateChanged(int))
|
||||
);
|
||||
QObject::connect(
|
||||
ui->extendedInformation, SIGNAL(stateChanged(int)),
|
||||
this , SLOT (on_extendedInformation_stateChanged(int))
|
||||
);
|
||||
QObject::connect(
|
||||
ui->visualisationTrackingFilter, SIGNAL(stateChanged(int)),
|
||||
this , SLOT (on_visualisationTrackingFilter_stateChanged(int))
|
||||
);
|
||||
}
|
||||
|
||||
void ConstraintSettingsDialog::saveSettings()
|
||||
{
|
||||
ui->extendedInformation->onSave();
|
||||
ui->filterInternalAlignment->onSave();
|
||||
ui->visualisationTrackingFilter->onSave();
|
||||
}
|
||||
|
||||
void ConstraintSettingsDialog::loadSettings()
|
||||
{
|
||||
ui->extendedInformation->onRestore();
|
||||
ui->filterInternalAlignment->onRestore();
|
||||
ui->visualisationTrackingFilter->onRestore();
|
||||
}
|
||||
|
||||
void ConstraintSettingsDialog::snapshotInitialSettings()
|
||||
{
|
||||
auto isChecked = [] (auto prefwidget) {return prefwidget->checkState() == Qt::Checked;};
|
||||
|
||||
extendedInformation = isChecked(ui->extendedInformation);
|
||||
filterInternalAlignment = isChecked(ui->filterInternalAlignment);
|
||||
visualisationTrackingFilter = isChecked(ui->visualisationTrackingFilter);
|
||||
}
|
||||
|
||||
void ConstraintSettingsDialog::restoreInitialSettings()
|
||||
{
|
||||
auto restoreCheck = [] (auto prefwidget, bool initialvalue) {
|
||||
if( initialvalue != (prefwidget->checkState() == Qt::Checked)) // if the state really changed
|
||||
initialvalue ? prefwidget->setCheckState(Qt::Checked) : prefwidget->setCheckState(Qt::Unchecked);
|
||||
};
|
||||
|
||||
restoreCheck(ui->extendedInformation, extendedInformation);
|
||||
restoreCheck(ui->filterInternalAlignment, filterInternalAlignment);
|
||||
restoreCheck(ui->visualisationTrackingFilter, visualisationTrackingFilter);
|
||||
}
|
||||
|
||||
void ConstraintSettingsDialog::accept()
|
||||
{
|
||||
saveSettings();
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void ConstraintSettingsDialog::reject()
|
||||
{
|
||||
restoreInitialSettings();
|
||||
saveSettings();
|
||||
QDialog::reject();
|
||||
}
|
||||
|
||||
void ConstraintSettingsDialog::on_filterInternalAlignment_stateChanged(int state)
|
||||
{
|
||||
ui->filterInternalAlignment->onSave();
|
||||
Q_EMIT emit_filterInternalAlignment_stateChanged(state);
|
||||
}
|
||||
|
||||
void ConstraintSettingsDialog::on_visualisationTrackingFilter_stateChanged(int state)
|
||||
{
|
||||
ui->visualisationTrackingFilter->onSave();
|
||||
Q_EMIT emit_visualisationTrackingFilter_stateChanged(state);
|
||||
}
|
||||
|
||||
void ConstraintSettingsDialog::on_extendedInformation_stateChanged(int state)
|
||||
{
|
||||
ui->extendedInformation->onSave();
|
||||
Q_EMIT emit_extendedInformation_stateChanged(state);
|
||||
}
|
||||
|
||||
ConstraintSettingsDialog::~ConstraintSettingsDialog()
|
||||
{
|
||||
}
|
||||
|
||||
#include "moc_ConstraintSettingsDialog.cpp"
|
||||
@@ -0,0 +1,70 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2021 Abdullah Tahiri <abdullah.tahiri.yo@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 SKETCHERGUI_ConstraintSettingsDialog_H
|
||||
#define SKETCHERGUI_ConstraintSettingsDialog_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "ConstraintFilters.h"
|
||||
|
||||
namespace SketcherGui {
|
||||
|
||||
using namespace ConstraintFilter;
|
||||
|
||||
class Ui_ConstraintSettingsDialog;
|
||||
class ConstraintSettingsDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ConstraintSettingsDialog(void);
|
||||
~ConstraintSettingsDialog();
|
||||
|
||||
Q_SIGNALS:
|
||||
void emit_filterInternalAlignment_stateChanged(int);
|
||||
void emit_extendedInformation_stateChanged(int);
|
||||
void emit_visualisationTrackingFilter_stateChanged(int);
|
||||
|
||||
public Q_SLOTS:
|
||||
void accept();
|
||||
void reject();
|
||||
void on_filterInternalAlignment_stateChanged(int state);
|
||||
void on_extendedInformation_stateChanged(int state);
|
||||
void on_visualisationTrackingFilter_stateChanged(int state);
|
||||
|
||||
private:
|
||||
void saveSettings();
|
||||
void loadSettings();
|
||||
void snapshotInitialSettings();
|
||||
void restoreInitialSettings();
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui_ConstraintSettingsDialog> ui;
|
||||
bool extendedInformation;
|
||||
bool filterInternalAlignment;
|
||||
bool visualisationTrackingFilter;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // SKETCHERGUI_ConstraintSettingsDialog_H
|
||||
@@ -0,0 +1,195 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SketcherGui::ConstraintSettingsDialog</class>
|
||||
<widget class="QWidget" name="SketcherGui::ConstraintSettingsDialog">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::WindowModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>275</width>
|
||||
<height>215</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Constraint widget settings</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>List control</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="1" column="0">
|
||||
<widget class="Gui::PrefCheckBox" name="filterInternalAlignment">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Internal alignments will be hidden</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Hide internal alignment</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>HideInternalAlignment</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Sketcher</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="Gui::PrefCheckBox" name="extendedInformation">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Extended information will be added to the list</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Extended information</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>ExtendedConstraintInformation</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Sketcher</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>3D view control</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="0" column="0">
|
||||
<widget class="Gui::PrefCheckBox" name="visualisationTrackingFilter">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Constraint visualisation tracks filter selection so that filtered out constraints are hidden</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show only filtered constraints</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>VisualisationTrackingFilter</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Sketcher</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item alignment="Qt::AlignHCenter">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Gui::PrefCheckBox</class>
|
||||
<extends>QCheckBox</extends>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>SketcherGui::ConstraintSettingsDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>SketcherGui::ConstraintSettingsDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -238,6 +238,9 @@
|
||||
<file>icons/tools/Sketcher_SelectVerticalAxis.svg</file>
|
||||
<file>icons/tools/Sketcher_Symmetry.svg</file>
|
||||
</qresource>
|
||||
<qresource>
|
||||
<file>icons/dialogs/Sketcher_Settings.svg</file>
|
||||
</qresource>
|
||||
<qresource>
|
||||
<file>translations/Sketcher_af.qm</file>
|
||||
<file>translations/Sketcher_ar.qm</file>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user