MeshFlattening: add function to unwrap face
This commit is contained in:
@@ -587,6 +587,20 @@ endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
if(FREECAD_USE_PCL)
|
||||
find_package(PCL REQUIRED COMPONENTS common kdtree features surface io filters segmentation sample_consensus)
|
||||
endif(FREECAD_USE_PCL)
|
||||
|
||||
# -------------------------------- PyBind11 -----------------------------
|
||||
EXECUTE_PROCESS(COMMAND ${PYTHON_EXECUTABLE} -c
|
||||
"import pybind11; print(bool(pybind11))"
|
||||
OUTPUT_VARIABLE PYBIND11_FOUND OUTPUT_STRIP_TRAILING_WHITESPACE )
|
||||
|
||||
EXECUTE_PROCESS(COMMAND ${PYTHON_EXECUTABLE} -c
|
||||
"import pybind11; print(pybind11.get_include())"
|
||||
OUTPUT_VARIABLE PYBIND11_INCLUDE_DIR OUTPUT_STRIP_TRAILING_WHITESPACE )
|
||||
|
||||
if (PYBIND11_FOUND)
|
||||
message(STATUS "successfully found pybind11")
|
||||
message(STATUS "pybind11 include dir is: " ${PYBIND11_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
# -------------------------------- Boost --------------------------------
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const
|
||||
<< "Mesh_Merge" << "Mesh_PolySelect" << "Mesh_PolyCut"
|
||||
<< "Mesh_PolySplit" << "Mesh_PolySegm" << "Mesh_PolyTrim" << "Separator"
|
||||
<< "Mesh_TrimByPlane" << "Mesh_SectionByPlane" << "Mesh_Segmentation"
|
||||
<< "Mesh_VertexCurvature" << "CreateFlatMesh";
|
||||
<< "Mesh_VertexCurvature" << "CreateFlatMesh" << "CreateFlatFace";
|
||||
return root;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,8 +39,12 @@ class MeshWorkbench (Workbench):
|
||||
def Initialize(self):
|
||||
import Mesh
|
||||
import MeshGui
|
||||
import MeshFlatteningCommand
|
||||
|
||||
try:
|
||||
import flatmesh
|
||||
import MeshFlatteningCommand
|
||||
except ImportError as e:
|
||||
import FreeCAD
|
||||
FreeCAD.Console.PrintLog((str(e)))
|
||||
def GetClassName(self):
|
||||
return "MeshGui::Workbench"
|
||||
|
||||
|
||||
@@ -81,24 +81,25 @@ SET_PYTHON_PREFIX_SUFFIX(MeshPart)
|
||||
INSTALL(TARGETS MeshPart DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
|
||||
|
||||
|
||||
################################ flat mesh ###############################
|
||||
SET(FLATMESH_SRCS
|
||||
MeshFlatteningPy.cpp
|
||||
MeshFlattening.cpp
|
||||
MeshFlattening.h
|
||||
MeshFlatteningNurbs.h
|
||||
MeshFlatteningNurbs.cpp
|
||||
MeshFlatteningLscmRelax.h
|
||||
MeshFlatteningLscmRelax.cpp
|
||||
)
|
||||
if (PYBIND11_FOUND)
|
||||
################################ flat mesh ###############################
|
||||
SET(FLATMESH_SRCS
|
||||
MeshFlatteningPy.cpp
|
||||
MeshFlattening.cpp
|
||||
MeshFlattening.h
|
||||
MeshFlatteningNurbs.h
|
||||
MeshFlatteningNurbs.cpp
|
||||
MeshFlatteningLscmRelax.h
|
||||
MeshFlatteningLscmRelax.cpp
|
||||
)
|
||||
|
||||
|
||||
|
||||
add_library(flatmesh SHARED ${FLATMESH_SRCS})
|
||||
SET_PYTHON_PREFIX_SUFFIX(flatmesh)
|
||||
target_link_libraries(flatmesh ${PYTHON_LIBRARIES} ${MeshPart_LIBS})
|
||||
add_library(flatmesh SHARED ${FLATMESH_SRCS})
|
||||
SET_PYTHON_PREFIX_SUFFIX(flatmesh)
|
||||
target_link_libraries(flatmesh ${PYTHON_LIBRARIES} ${MeshPart_LIBS})
|
||||
|
||||
SET_BIN_DIR(flatmesh flatmesh /Mod/MeshPart)
|
||||
install(TARGETS flatmesh DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
############################################################################
|
||||
SET_BIN_DIR(flatmesh flatmesh /Mod/MeshPart)
|
||||
install(TARGETS flatmesh DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
############################################################################
|
||||
endif()
|
||||
|
||||
@@ -169,13 +169,13 @@ FaceUnwrapper::FaceUnwrapper(const TopoDS_Face& face)
|
||||
}
|
||||
}
|
||||
|
||||
void FaceUnwrapper::findFlatNodes()
|
||||
void FaceUnwrapper::findFlatNodes(int steps, double val)
|
||||
{
|
||||
std::vector<long> fixed_pins; //TODO: INPUT
|
||||
LscmRelax mesh_flattener(this->xyz_nodes.transpose(), this->tris.transpose(), fixed_pins);
|
||||
mesh_flattener.lscm();
|
||||
for (int j=0; j<9; j++)
|
||||
mesh_flattener.relax(0.9);
|
||||
for (int j=0; j<steps; j++)
|
||||
mesh_flattener.relax(0.95);
|
||||
this->ze_nodes = mesh_flattener.flat_vertices.transpose();
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ class FaceUnwrapper{
|
||||
public:
|
||||
FaceUnwrapper(const TopoDS_Face & face);
|
||||
FaceUnwrapper(ColMat<double, 3> xyz_nodes, ColMat<long, 3> tris);
|
||||
void findFlatNodes();
|
||||
void findFlatNodes(int steps, double val);
|
||||
ColMat<double, 3> interpolateFlatFace(const TopoDS_Face& face);
|
||||
std::vector<ColMat<double, 3>> getFlatBoundaryNodes();
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "MeshFlatteningLscmRelax.h"
|
||||
#include <Eigen/IterativeLinearSolvers>
|
||||
#include<Eigen/SparseCholesky>
|
||||
#include <Eigen/SVD>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
@@ -278,10 +279,9 @@ void LscmRelax::relax(double weight)
|
||||
// rhs += K_g * Eigen::VectorXd::Ones(K_g.rows());
|
||||
|
||||
// solve linear system (privately store the value for guess in next step)
|
||||
Eigen::ConjugateGradient<spMat, Eigen::Lower> solver;
|
||||
solver.setTolerance(0.0000001);
|
||||
Eigen::SimplicialLDLT<spMat, Eigen::Lower> solver;
|
||||
solver.compute(K_g);
|
||||
this->sol = solver.solveWithGuess(-rhs, this->sol);
|
||||
this->sol = solver.solve(-rhs);
|
||||
this->set_shift(this->sol.head(this->vertices.cols() * 2) * weight);
|
||||
this->set_q_l_m();
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ public:
|
||||
ColMat<double, 1> rhs;
|
||||
Eigen::MatrixXd MATRIX;
|
||||
|
||||
double nue=0.0;
|
||||
double nue=0.9;
|
||||
double elasticity=1.;
|
||||
|
||||
void lscm();
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <iostream>
|
||||
#include "math.h"
|
||||
|
||||
|
||||
namespace nurbs{
|
||||
|
||||
double divide(double a, double b)
|
||||
@@ -35,6 +36,28 @@ double divide(double a, double b)
|
||||
return a / b;
|
||||
}
|
||||
|
||||
Eigen::VectorXd NurbsBase1D::getKnotSequence(double u_min, double u_max, int u_deg, int num_u_poles)
|
||||
{
|
||||
// boarder poles are on the surface
|
||||
std::vector<double> u_knots;
|
||||
for (int i=0; i < u_deg; i++)
|
||||
u_knots.push_back(u_min);
|
||||
for (int i=0; i < num_u_poles; i++)
|
||||
u_knots.push_back(u_min + (u_max - u_min) * i / (num_u_poles - 1));
|
||||
for (int i=0; i < u_deg; i++)
|
||||
u_knots.push_back(u_max);
|
||||
return Eigen::Map<Eigen::VectorXd>(u_knots.data(), u_knots.size());
|
||||
}
|
||||
|
||||
Eigen::VectorXd NurbsBase1D::getWeightList(Eigen::VectorXd knots, int u_deg)
|
||||
{
|
||||
Eigen::VectorXd weights;
|
||||
weights.resize(knots.rows() - u_deg - 1);
|
||||
weights.setOnes();
|
||||
return weights;
|
||||
}
|
||||
|
||||
|
||||
// DE BOOR ALGORITHM FROM OPENGLIDER
|
||||
std::function<double(double)> get_basis(int degree, int i, Eigen::VectorXd knots)
|
||||
// Return a basis_function for the given degree """
|
||||
@@ -180,7 +203,7 @@ void add_triplets(Eigen::VectorXd values, double row, std::vector<trip> &triplet
|
||||
spMat NurbsBase2D::getInfluenceMatrix(Eigen::Matrix<double, Eigen::Dynamic, 2> U)
|
||||
{
|
||||
std::vector<trip> triplets;
|
||||
for (int row_index; row_index < U.rows(); row_index++)
|
||||
for (unsigned int row_index = 0; row_index < U.rows(); row_index++)
|
||||
add_triplets(this->getInfluenceVector(U.row(row_index)), row_index, triplets);
|
||||
spMat mat(U.rows(), this->u_functions.size() * this->v_functions.size());
|
||||
mat.setFromTriplets(triplets.begin(), triplets.end());
|
||||
@@ -288,7 +311,7 @@ Eigen::VectorXd NurbsBase2D::getDvVector(Eigen::Vector2d u)
|
||||
spMat NurbsBase2D::getDuMatrix(Eigen::Matrix<double, Eigen::Dynamic, 2> U)
|
||||
{
|
||||
std::vector<trip> triplets;
|
||||
for (int row_index; row_index < U.rows(); row_index++)
|
||||
for (unsigned int row_index = 0; row_index < U.rows(); row_index++)
|
||||
add_triplets(this->getDuVector(U.row(row_index)), row_index, triplets);
|
||||
spMat mat(U.rows(), this->u_functions.size() * this->v_functions.size());
|
||||
mat.setFromTriplets(triplets.begin(), triplets.end());
|
||||
@@ -298,13 +321,66 @@ spMat NurbsBase2D::getDuMatrix(Eigen::Matrix<double, Eigen::Dynamic, 2> U)
|
||||
spMat NurbsBase2D::getDvMatrix(Eigen::Matrix<double, Eigen::Dynamic, 2> U)
|
||||
{
|
||||
std::vector<trip> triplets;
|
||||
for (int row_index; row_index < U.rows(); row_index++)
|
||||
for (unsigned int row_index = 0; row_index < U.rows(); row_index++)
|
||||
add_triplets(this->getDvVector(U.row(row_index)), row_index, triplets);
|
||||
spMat mat(U.rows(), this->u_functions.size() * this->v_functions.size());
|
||||
mat.setFromTriplets(triplets.begin(), triplets.end());
|
||||
return mat;
|
||||
}
|
||||
|
||||
|
||||
std::tuple<NurbsBase2D, Eigen::MatrixXd> NurbsBase2D::interpolateUBS(
|
||||
Eigen::Matrix<double, Eigen::Dynamic, 3> poles,
|
||||
int degree_u,
|
||||
int degree_v,
|
||||
int num_u_poles,
|
||||
int num_v_poles,
|
||||
int num_u_points,
|
||||
int num_v_points)
|
||||
{
|
||||
double u_min = this->u_knots(0);
|
||||
double u_max = this->u_knots(this->u_knots.size() - 1);
|
||||
double v_min = this->v_knots(0);
|
||||
double v_max = this->v_knots(this->v_knots.size() - 1);
|
||||
Eigen::VectorXd weights, u_knots, v_knots;
|
||||
u_knots = NurbsBase1D::getKnotSequence(u_min, u_max, degree_u, num_u_poles);
|
||||
v_knots = NurbsBase1D::getKnotSequence(v_min, v_max, degree_v, num_v_poles);
|
||||
|
||||
weights.resize((u_knots.rows() - degree_u - 1) * (v_knots.rows() - degree_v - 1));
|
||||
weights.setOnes();
|
||||
NurbsBase2D new_base(u_knots, v_knots, weights, degree_u, degree_v);
|
||||
Eigen::Matrix<double, Eigen::Dynamic, 2> uv_points = this->getUVMesh(num_u_points, num_v_points);
|
||||
Eigen::Matrix<double, Eigen::Dynamic, 3> xyz_points = this->getInfluenceMatrix(uv_points) * poles;
|
||||
spMat A = new_base.getInfluenceMatrix(uv_points);
|
||||
Eigen::LeastSquaresConjugateGradient<spMat > solver;
|
||||
solver.compute(A);
|
||||
Eigen::Matrix<double, Eigen::Dynamic, 3> new_poles = solver.solve(xyz_points);
|
||||
return std::tuple<NurbsBase2D, Eigen::MatrixXd >(new_base, new_poles);
|
||||
}
|
||||
|
||||
Eigen::Matrix<double, Eigen::Dynamic, 2> NurbsBase2D::getUVMesh(int num_u_points, int num_v_points)
|
||||
{
|
||||
double u_min = this->u_knots(0);
|
||||
double u_max = this->u_knots(this->u_knots.size() - 1);
|
||||
double v_min = this->v_knots(0);
|
||||
double v_max = this->v_knots(this->v_knots.size() - 1);
|
||||
Eigen::Matrix<double, Eigen::Dynamic, 2> uv_points;
|
||||
uv_points.resize(num_u_points * num_v_points, 2);
|
||||
int i = 0;
|
||||
for (int u = 0; u < num_u_points; u++)
|
||||
{
|
||||
for (int v = 0; v < num_v_points; v++)
|
||||
{
|
||||
uv_points(i, 0) = u_min + (u_max - u_min) * u / (num_u_points - 1);
|
||||
uv_points(i, 1) = v_min + (v_max - v_min) * v / (num_v_points - 1);
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
||||
return uv_points;
|
||||
}
|
||||
|
||||
|
||||
NurbsBase1D::NurbsBase1D(Eigen::VectorXd u_knots, Eigen::VectorXd weights, int degree_u)
|
||||
{
|
||||
this->u_knots = u_knots;
|
||||
@@ -336,7 +412,7 @@ Eigen::VectorXd NurbsBase1D::getInfluenceVector(double u)
|
||||
spMat NurbsBase1D::getInfluenceMatrix(Eigen::VectorXd u)
|
||||
{
|
||||
std::vector<trip> triplets;
|
||||
for (int row_index; row_index < u.size(); row_index++)
|
||||
for (unsigned int row_index = 0; row_index < u.size(); row_index++)
|
||||
add_triplets(this->getInfluenceVector(u[row_index]), row_index, triplets);
|
||||
spMat mat(u.size(), this->u_functions.size());
|
||||
mat.setFromTriplets(triplets.begin(), triplets.end());
|
||||
@@ -393,11 +469,44 @@ Eigen::VectorXd NurbsBase1D::getDuVector(double u)
|
||||
spMat NurbsBase1D::getDuMatrix(Eigen::VectorXd U)
|
||||
{
|
||||
std::vector<trip> triplets;
|
||||
for (int row_index; row_index < U.size(); row_index++)
|
||||
for (unsigned int row_index = 0; row_index < U.size(); row_index++)
|
||||
add_triplets(this->getDuVector(U[row_index]), row_index, triplets);
|
||||
spMat mat(U.size(), this->u_functions.size());
|
||||
mat.setFromTriplets(triplets.begin(), triplets.end());
|
||||
return mat;
|
||||
}
|
||||
|
||||
std::tuple<NurbsBase1D, Eigen::Matrix<double, Eigen::Dynamic, 3>> NurbsBase1D::interpolateUBS(
|
||||
Eigen::Matrix<double,
|
||||
Eigen::Dynamic, 3> poles,
|
||||
int degree,
|
||||
int num_poles,
|
||||
int num_points)
|
||||
{
|
||||
double u_min = this->u_knots(0);
|
||||
double u_max = this->u_knots(this->u_knots.size() - 1);
|
||||
Eigen::VectorXd u_knots, weights;
|
||||
u_knots = NurbsBase1D::getKnotSequence(u_min, u_max, degree, num_poles);
|
||||
weights = NurbsBase1D::getWeightList(u_knots, degree);
|
||||
NurbsBase1D new_base(u_knots, weights, degree);
|
||||
Eigen::Matrix<double, Eigen::Dynamic, 1> u_points = this->getUMesh(num_points);
|
||||
Eigen::Matrix<double, Eigen::Dynamic, 3> xyz_points;
|
||||
xyz_points = this->getInfluenceMatrix(u_points) * poles;
|
||||
spMat A = new_base.getInfluenceMatrix(u_points);
|
||||
Eigen::LeastSquaresConjugateGradient<spMat > solver;
|
||||
solver.compute(A);
|
||||
Eigen::Matrix<double, Eigen::Dynamic, 3> new_poles = solver.solve(xyz_points);
|
||||
return std::tuple<NurbsBase1D, Eigen::Matrix<double, Eigen::Dynamic, 3> >(new_base, new_poles);
|
||||
}
|
||||
|
||||
Eigen::VectorXd NurbsBase1D::getUMesh(int num_u_points)
|
||||
{
|
||||
double u_min = this->u_knots(0);
|
||||
double u_max = this->u_knots(this->u_knots.size() - 1);
|
||||
Eigen::Matrix<double, Eigen::Dynamic, 1> u_points;
|
||||
u_points.setLinSpaced(num_u_points, u_min, u_max);
|
||||
return u_points;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <Eigen/Geometry>
|
||||
#include <Eigen/IterativeLinearSolvers>
|
||||
#include <Eigen/SparseCore>
|
||||
#include <tuple>
|
||||
|
||||
namespace nurbs{
|
||||
|
||||
@@ -67,13 +68,24 @@ struct NurbsBase2D
|
||||
|
||||
Eigen::VectorXd getDvVector(Eigen::Vector2d u);
|
||||
spMat getDvMatrix(Eigen::Matrix<double, Eigen::Dynamic, 2> U);
|
||||
|
||||
Eigen::Matrix<double, Eigen::Dynamic, 2> getUVMesh(int num_u_points, int num_v_points);
|
||||
|
||||
std::tuple<NurbsBase2D, Eigen::MatrixXd> interpolateUBS(
|
||||
Eigen::Matrix<double, Eigen::Dynamic, 3> poles,
|
||||
int degree_u,
|
||||
int degree_v,
|
||||
int num_u_poles,
|
||||
int num_v_poles,
|
||||
int num_u_points,
|
||||
int num_v_points);
|
||||
};
|
||||
|
||||
struct NurbsBase1D
|
||||
{
|
||||
NurbsBase1D(){;};
|
||||
NurbsBase1D(Eigen::VectorXd u_knots, Eigen::VectorXd weights, int degree_u=3);
|
||||
int degree_u = degree_u;
|
||||
int degree_u;
|
||||
Eigen::VectorXd u_knots;
|
||||
Eigen::VectorXd weights;
|
||||
std::vector<std::function<double(double)>> u_functions;
|
||||
@@ -88,6 +100,17 @@ struct NurbsBase1D
|
||||
|
||||
Eigen::VectorXd getDuVector(double u);
|
||||
spMat getDuMatrix(Eigen::VectorXd u);
|
||||
|
||||
static Eigen::VectorXd getKnotSequence(double u_min, double u_max, int deg, int num_poles);
|
||||
static Eigen::VectorXd getWeightList(Eigen::VectorXd knots, int u_deg);
|
||||
|
||||
Eigen::VectorXd getUMesh(int num_u_points);
|
||||
|
||||
std::tuple<NurbsBase1D, Eigen::Matrix<double, Eigen::Dynamic, 3>> interpolateUBS(
|
||||
Eigen::Matrix<double, Eigen::Dynamic, 3> poles,
|
||||
int degree,
|
||||
int num_u_poles,
|
||||
int num_u_points);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#include <Mod/Part/App/TopoShapeFacePy.h>
|
||||
#include <Mod/Part/App/TopoShapeEdgePy.h>
|
||||
|
||||
#include <Eigen/Core>
|
||||
#include <Eigen/Geometry>
|
||||
@@ -44,39 +45,62 @@
|
||||
#include "MeshFlatteningNurbs.h"
|
||||
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <ShapeFix_Edge.hxx>
|
||||
|
||||
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
// void FaceUnwrapper_constructor(FaceUnwrapper& instance, Part::TopoShapeFacePy Face)
|
||||
FaceUnwrapper* FaceUnwrapper_constructor(py::object face)
|
||||
const TopoDS_Face& getTopoDSFace(py::object* face)
|
||||
{
|
||||
if (PyObject_TypeCheck(face.ptr(), &(Part::TopoShapeFacePy::Type)))
|
||||
if (PyObject_TypeCheck(face->ptr(), &(Part::TopoShapeFacePy::Type)))
|
||||
{
|
||||
const Part::TopoShapeFacePy* f = static_cast<Part::TopoShapeFacePy*>(face.ptr());
|
||||
const Part::TopoShapeFacePy* f = static_cast<Part::TopoShapeFacePy*>(face->ptr());
|
||||
const TopoDS_Face& myFace = TopoDS::Face(f->getTopoShapePtr()->getShape());
|
||||
return new FaceUnwrapper(myFace);
|
||||
return myFace;
|
||||
}
|
||||
else
|
||||
throw std::invalid_argument("FaceUnwrapper should be initialized with Part.Face");
|
||||
throw std::invalid_argument("must be a face");
|
||||
}
|
||||
|
||||
ColMat<double, 3> interpolateFlatFacePy(FaceUnwrapper& instance, py::object face)
|
||||
const TopoDS_Edge& getTopoDSEdge(py::object* edge)
|
||||
{
|
||||
std::cout << face.ptr()->ob_type->tp_name << std::endl;
|
||||
std::cout << Part::TopoShapeFacePy::Type.tp_name << std::endl;
|
||||
if (PyObject_TypeCheck(face.ptr(), &(Part::TopoShapeFacePy::Type)))
|
||||
if (PyObject_TypeCheck(edge->ptr(), &(Part::TopoShapeEdgePy::Type)))
|
||||
{
|
||||
const Part::TopoShapeFacePy* f = static_cast<Part::TopoShapeFacePy*>(face.ptr());
|
||||
const TopoDS_Face& myFace = TopoDS::Face(f->getTopoShapePtr()->getShape());
|
||||
return instance.interpolateFlatFace(myFace);
|
||||
const Part::TopoShapeEdgePy* e = static_cast<Part::TopoShapeEdgePy*>(edge->ptr());
|
||||
const TopoDS_Edge& myEdge = TopoDS::Edge(e->getTopoShapePtr()->getShape());
|
||||
return myEdge;
|
||||
}
|
||||
else
|
||||
throw std::invalid_argument("FaceUnwrapper.interpolateNurbs should be initialized with Part.Face");
|
||||
throw std::invalid_argument("must be an edge");
|
||||
}
|
||||
|
||||
Py::Object makeEdge(const TopoDS_Edge& edge)
|
||||
{
|
||||
return Py::asObject(new Part::TopoShapeEdgePy(new Part::TopoShape(edge)));
|
||||
}
|
||||
|
||||
py::object makeFace(const TopoDS_Face& face)
|
||||
{
|
||||
return py::cast(new Part::TopoShapeFacePy(new Part::TopoShape(face)));
|
||||
}
|
||||
|
||||
|
||||
FaceUnwrapper* FaceUnwrapper_constructor(py::object* face)
|
||||
{
|
||||
const TopoDS_Face& myFace = getTopoDSFace(face);
|
||||
return new FaceUnwrapper(myFace);
|
||||
}
|
||||
|
||||
ColMat<double, 3> interpolateFlatFacePy(FaceUnwrapper& instance, py::object* face)
|
||||
{
|
||||
const TopoDS_Face& myFace = getTopoDSFace(face);
|
||||
return instance.interpolateFlatFace(myFace);
|
||||
}
|
||||
|
||||
|
||||
PYBIND11_MODULE(flatmesh, m)
|
||||
{
|
||||
m.doc() = "functions to unwrapp faces/ meshes";
|
||||
@@ -96,21 +120,34 @@ PYBIND11_MODULE(flatmesh, m)
|
||||
|
||||
py::class_<nurbs::NurbsBase2D>(m, "NurbsBase2D")
|
||||
.def(py::init<Eigen::VectorXd, Eigen::VectorXd, Eigen::VectorXd, int, int>())
|
||||
.def_readonly("u_knots", &nurbs::NurbsBase2D::u_knots)
|
||||
.def_readonly("weights", &nurbs::NurbsBase2D::weights)
|
||||
.def_readonly("degree_u", &nurbs::NurbsBase2D::degree_u)
|
||||
.def_readonly("v_knots", &nurbs::NurbsBase2D::u_knots)
|
||||
.def_readonly("degree_v", &nurbs::NurbsBase2D::degree_u)
|
||||
.def("getUVMesh", &nurbs::NurbsBase2D::getUVMesh)
|
||||
.def("computeFirstDerivatives", &nurbs::NurbsBase2D::computeFirstDerivatives)
|
||||
.def("getInfluenceVector", &nurbs::NurbsBase2D::getInfluenceVector)
|
||||
.def("getInfluenceMatrix", &nurbs::NurbsBase2D::getInfluenceMatrix)
|
||||
.def("getDuVector", &nurbs::NurbsBase2D::getDuVector)
|
||||
.def("getDuMatrix", &nurbs::NurbsBase2D::getDuMatrix)
|
||||
.def("getDvVector", &nurbs::NurbsBase2D::getDvVector)
|
||||
.def("getDvMatrix", &nurbs::NurbsBase2D::getDvMatrix);
|
||||
.def("getDvMatrix", &nurbs::NurbsBase2D::getDvMatrix)
|
||||
.def("interpolateUBS", &nurbs::NurbsBase2D::interpolateUBS);
|
||||
|
||||
py::class_<nurbs::NurbsBase1D>(m, "NurbsBase1D")
|
||||
.def(py::init<Eigen::VectorXd, Eigen::VectorXd, int>())
|
||||
.def_readonly("u_knots", &nurbs::NurbsBase1D::u_knots)
|
||||
.def_readonly("weights", &nurbs::NurbsBase1D::weights)
|
||||
.def_readonly("degree_u", &nurbs::NurbsBase1D::degree_u)
|
||||
.def("getUMesh", &nurbs::NurbsBase1D::getUMesh)
|
||||
.def("computeFirstDerivatives", &nurbs::NurbsBase1D::computeFirstDerivatives)
|
||||
.def("getInfluenceVector", &nurbs::NurbsBase1D::getInfluenceVector)
|
||||
.def("getInfluenceMatrix", &nurbs::NurbsBase1D::getInfluenceMatrix)
|
||||
.def("getDuVector", &nurbs::NurbsBase1D::getDuVector)
|
||||
.def("getDuMatrix", &nurbs::NurbsBase1D::getDuMatrix);
|
||||
.def("getDuMatrix", &nurbs::NurbsBase1D::getDuMatrix)
|
||||
.def_static("getKnotSequence", &nurbs::NurbsBase1D::getKnotSequence)
|
||||
.def_static("getWeightList", &nurbs::NurbsBase1D::getWeightList);
|
||||
|
||||
py::class_<FaceUnwrapper>(m, "FaceUnwrapper")
|
||||
.def(py::init(&FaceUnwrapper_constructor))
|
||||
@@ -124,4 +161,5 @@ PYBIND11_MODULE(flatmesh, m)
|
||||
.def_readonly("ze_nodes", &FaceUnwrapper::ze_nodes)
|
||||
.def_readonly("ze_poles", &FaceUnwrapper::ze_poles)
|
||||
.def_readonly("A", &FaceUnwrapper::A);
|
||||
|
||||
};
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import FreeCADGui as gui
|
||||
import Mesh
|
||||
import FreeCAD as App
|
||||
import FreeCADGui as gui
|
||||
import FreeCADGui as Gui
|
||||
import Part
|
||||
import numpy as np
|
||||
from pivy import graphics as g
|
||||
from pivy import coin
|
||||
|
||||
class BaseCommand(object):
|
||||
def __init__(self):
|
||||
@@ -12,6 +15,7 @@ class BaseCommand(object):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
class CreateFlatMesh(BaseCommand):
|
||||
"""create flat wires from a meshed face"""
|
||||
@@ -22,15 +26,14 @@ class CreateFlatMesh(BaseCommand):
|
||||
def Activated(self):
|
||||
import numpy as np
|
||||
import flatmesh
|
||||
import Part
|
||||
obj = gui.Selection.getSelection()[0] # obj must be a Mesh (Mesh-Design->Meshes->Create-Mesh)
|
||||
mesh = Mesh.Mesh(obj.Mesh) # copy of the mesh to set new vertices later on
|
||||
obj = Gui.Selection.getSelection()[0] # obj must be a Mesh (Mesh-Design->Meshes->Create-Mesh)
|
||||
points = np.array([[i.x, i.y, i.z] for i in obj.Mesh.Points])
|
||||
faces = np.array([list(i) for i in obj.Mesh.Topology[1]])
|
||||
print(faces)
|
||||
flattener = flatmesh.FaceUnwrapper(points, faces)
|
||||
flattener.findFlatNodes()
|
||||
flattener.findFlatNodes(5, 0.99)
|
||||
boundaries = flattener.getFlatBoundaryNodes()
|
||||
print(flattener.ze_nodes)
|
||||
print(boundaries)
|
||||
wires = []
|
||||
for edge in boundaries:
|
||||
pi = Part.makePolygon([App.Vector(*node) for node in edge])
|
||||
@@ -38,9 +41,10 @@ class CreateFlatMesh(BaseCommand):
|
||||
|
||||
def IsActive(self):
|
||||
assert(super(CreateFlatMesh, self).IsActive())
|
||||
assert(isinstance(gui.Selection.getSelection()[0].Mesh, Mesh.Mesh))
|
||||
assert(isinstance(Gui.Selection.getSelection()[0].Mesh, Mesh.Mesh))
|
||||
return True
|
||||
|
||||
|
||||
class CreateFlatFace(BaseCommand):
|
||||
"""create a flat face from a single face
|
||||
only full faces are supported right now"""
|
||||
@@ -48,11 +52,34 @@ class CreateFlatFace(BaseCommand):
|
||||
def GetResources(self):
|
||||
return {'MenuText': 'Unwrap Face', 'ToolTip': 'find a flat representation of a mesh'}
|
||||
|
||||
def Activated(self):
|
||||
import numpy as np
|
||||
import flatmesh
|
||||
face = Gui.Selection.getSelectionEx()[0].SubObjects[0]
|
||||
shape = face.toNurbs()
|
||||
face = shape.Faces[0]
|
||||
nurbs = face.Surface
|
||||
nurbs.setUNotPeriodic()
|
||||
nurbs.setVNotPeriodic()
|
||||
bs = nurbs.toBSpline(1, "C0", "C0", 3, 3, 10)
|
||||
face = bs.toShape()
|
||||
face.tessellate(0.01)
|
||||
flattener = flatmesh.FaceUnwrapper(face)
|
||||
flattener.findFlatNodes(5, 0.99)
|
||||
poles = flattener.interpolateFlatFace(face)
|
||||
num_u_poles = len(bs.getPoles())
|
||||
num_v_poles = len(bs.getPoles()[0])
|
||||
i = 0
|
||||
for u in range(num_u_poles):
|
||||
for v in range(num_v_poles):
|
||||
bs.setPole(u + 1, v + 1, App.Vector(poles[i]))
|
||||
i += 1
|
||||
Part.show(bs.toShape())
|
||||
|
||||
def IsActive(self):
|
||||
assert(super(CreateFlatMesh, self).IsActive())
|
||||
assert(isinstance(gui.Selection.getSelection()[0], Part.Face))
|
||||
assert(super(CreateFlatFace, self).IsActive())
|
||||
assert(isinstance(Gui.Selection.getSelectionEx()[0].SubObjects[0], Part.Face))
|
||||
return True
|
||||
|
||||
|
||||
|
||||
gui.addCommand('CreateFlatMesh', CreateFlatMesh())
|
||||
Gui.addCommand('CreateFlatMesh', CreateFlatMesh())
|
||||
Gui.addCommand('CreateFlatFace', CreateFlatFace())
|
||||
|
||||
Reference in New Issue
Block a user