surface flattening

Have some feature requests, feedback, cool stuff to share, or want to know where FreeCAD is going? This is the place.
Forum rules
Be nice to others! Read the FreeCAD code of conduct!
User avatar
looo
Veteran
Posts: 3941
Joined: Mon Nov 11, 2013 5:29 pm

Re: surface flattening

Post by looo »

this way the constructor is happy:

Code: Select all

void FaceUnwrapper_constructor(FaceUnwrapper& instance, pybind11::object face)
{
    if (PyObject_TypeCheck(face.ptr(), &(Part::TopoShapeFacePy::Type)))
    {
        const Part::TopoShapeFacePy* f = static_cast<Part::TopoShapeFacePy*>(face.ptr());
        const TopoDS_Face& myFace = TopoDS::Face(f->getTopoShapePtr()->getShape());
        new (& instance) FaceUnwrapper(myFace);
    }
    else
    {
        throw std::invalid_argument("FaceUnwrapper should be initialized with Part.Face");
    }
}
The exception is translated into a python exception automatically. Hopefully this is acceptable...
User avatar
looo
Veteran
Posts: 3941
Joined: Mon Nov 11, 2013 5:29 pm

Re: surface flattening

Post by looo »

uv-mesh is setup :D
uv-mesh.png
uv-mesh.png (85.89 KiB) Viewed 2035 times
problems:
- I can't pass a face which has converted to nurbs (with method face.toNurbs()) because of:

Code: Select all

if (triangulation.IsNull())
      throw std::runtime_error("null triangulation in face construction");
- limitation: the faces must be open nurbs. if not there is no way to find a mapping between unwrapped (2d) and 3d face.
User avatar
looo
Veteran
Posts: 3941
Joined: Mon Nov 11, 2013 5:29 pm

Re: surface flattening

Post by looo »

me wrote:- I can't pass a face which has converted to nurbs (with method face.toNurbs())
maybe the reason is the garbage-collector?

while this works:

Code: Select all

import flatmesh

a = App.ActiveDocument.ActiveObject.Shape.Faces[0]
a = a.toNurbs()
g = a.Faces[0]
Part.show(g)
b = flatmesh.FaceUnwrapper(g)
this is not working:

Code: Select all

import flatmesh

a = App.ActiveDocument.ActiveObject.Shape.Faces[0]
a = a.toNurbs()
g = a.Faces[0]
b = flatmesh.FaceUnwrapper(g)
wmayer
Founder
Posts: 20309
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: surface flattening

Post by wmayer »

A shape that has never been visualized may not have a tessellation. In this case you have to invoke the tessellate method to create it.
User avatar
looo
Veteran
Posts: 3941
Joined: Mon Nov 11, 2013 5:29 pm

Re: surface flattening

Post by looo »

thanks, sounds logical.

Is there a smarter way to copy occ-arrays to eigen?

Code: Select all

    const Poly_Array1OfTriangle &_tris = triangulation->Triangles();
    this->tris.resize(triangulation->NbTriangles(), 3);
    i = 0;
    for (Poly_Triangle _tri: _tris)
    {
        int n1, n2, n3;
        _tri.Get(n1, n2, n3);
        this->tris.row(i) << n1-1, n2-1, n3-1;
        i++;
    }
User avatar
tanderson69
Veteran
Posts: 1626
Joined: Thu Feb 18, 2010 1:07 am

Re: surface flattening

Post by tanderson69 »

looo wrote: Thu Sep 07, 2017 1:09 pm thanks, sounds logical.

Is there a smarter way to copy occ-arrays to eigen?

Code: Select all

    const Poly_Array1OfTriangle &_tris = triangulation->Triangles();
    this->tris.resize(triangulation->NbTriangles(), 3);
    i = 0;
    for (Poly_Triangle _tri: _tris)
    {
        int n1, n2, n3;
        _tri.Get(n1, n2, n3);
        this->tris.row(i) << n1-1, n2-1, n3-1;
        i++;
    }
Smarter? Doesn't this work? There are different ways to do it, but I doubt it will make a difference. Looking at the doc for Poly_triangle, here is what I would do, but I don't think you will notice anything different. https://dev.opencascade.org/doc/refman/ ... angle.html

Code: Select all

    const Poly_Array1OfTriangle &_tris = triangulation->Triangles();
    this->tris.resize(triangulation->NbTriangles(), 3);
    i = 0;
    for (const auto &_tri: _tris) //this won't make a copy of the Poly_Triangle.
    {
        //now that '_tri' is const, the following 'operator()' calls will call the const version
        //eliminating 3 more integer copies.
        this->tris.row(i) << _tri(1) - 1, _tri(2) - 1, _tri(3) - 1;
        i++;
    }
User avatar
looo
Veteran
Posts: 3941
Joined: Mon Nov 11, 2013 5:29 pm

Re: surface flattening

Post by looo »

tanderson69 wrote:Smarter? Doesn't this work?
It works, but yours look better. :)

I am quite proud, that everything has worked like I have proposed. Even the A * p = v for the flat poles worked... But there is a problem. Using the same nurbs-base will lead to some not so good unwrapped faces.
same_nurbs_base.png
same_nurbs_base.png (21.27 KiB) Viewed 1983 times
I have already seen this when I computed the derivatives of a nurbs-circle. I expected them to be constant, but actually ds/du is not constant for a nurbs-circle. Or in other words, if a circle is divided into segments with same length, the difference of the u-value of these segments is not constant.
wmayer
Founder
Posts: 20309
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: surface flattening

Post by wmayer »

Example:

Code: Select all

circle=Part.Circle()
circle.Radius=50
nurbs=circle.toNurbs()
nurbs.getWeights() # different weights => rational B-Spline

step=(nurbs.LastParameter-nurbs.FirstParameter)/20
c=Part.Compound([])
for i in range(20):
  c.add(Part.Vertex(nurbs.value(i*step)))

App.ActiveDocument.addObject("Part::Feature","Circle").Shape=circle.toShape()
App.ActiveDocument.addObject("Part::Spline","Nurbs").Shape=nurbs.toShape()
# the arc length is clearly different
App.ActiveDocument.addObject("Part::Feature","Points").Shape=c


spline=circle.toBSpline() # a non-rational B-Spline
App.ActiveDocument.addObject("Part::Spline","Spline").Shape=spline.toShape()
c=Part.Compound([])
for i in range(20):
  c.add(Part.Vertex(spline.value(i*step)))

# the arc length seems to be constant
App.ActiveDocument.addObject("Part::Feature","Points").Shape=c

# all values are equal (within a tolerance)
for i in range(20):
  print (spline.length(i*step, (i+1)*step))


# the points don't have uniform distance
pts=[]
for i in range(21):
  pts.append(nurbs.value(i*step))

# approximate spline
b=Part.BSplineCurve()
b.approximate(Points=pts, ParamType="ChordLength")
App.ActiveDocument.addObject("Part::Spline","b").Shape=b.toShape()

# arc length is almost equal
for i in range(20):
  print (b.length(i/20.0, (i+1)/20.0))

# approximate spline
a=Part.BSplineCurve()
a.approximate(Points=pts, ParamType="Uniform")
App.ActiveDocument.addObject("Part::Spline","a").Shape=a.toShape()

# arc length is clearly different
for i in range(20):
  print (a.length(i/20.0, (i+1)/20.0))
For the splines you can display their control points in the context-menu. I guess that it depends on them if the arc lengths is uniform or not.

See also https://knowledge.autodesk.com/support/ ... s-htm.html
User avatar
looo
Veteran
Posts: 3941
Joined: Mon Nov 11, 2013 5:29 pm

Re: surface flattening

Post by looo »

thanks for the example. I always thought nurbs are the only splines which can model a circle exactly. But non rational B-Splines can do that too? But what Is it a nurbs without weights or a bspline which has non uniform knot vectors?

I had two ideas to solve the shown problem:

1. looking at pictures of rhino [1], it seems the degree of the flat faces is higher. So maybe there is a nurbs-base with a higher degree which can give an exact solution. I think it is possible to find such a nurbs-base which can exactly map some poles to the derivatives of the spline....

2. Another mapping could be introduced. This maps the uv-coordinate on exactly the same uv-boundary, but removes the varying derivatives.

[1]http://docs.mcneel.com/rhino/5/help/en- ... rf-001.png, http://www.rhino3.de/design/modeling/de ... e_Cone.jpg
wmayer
Founder
Posts: 20309
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: surface flattening

Post by wmayer »

thanks for the example. I always thought nurbs are the only splines which can model a circle exactly. But non rational B-Splines can do that too?
No, only real nurbs can model a circle exactly because you need control points with different weights. And this property of different weights is what makes a spline rational. With a non-rational B-Spline you can only approximate a circle which is actually obvious because the base curves are only polynomials.
But what Is it a nurbs without weights
Not without weights but with equal weights. A nurbs with equal weights is a non-rational B-Spline.
or a bspline which has non uniform knot vectors
The knot vector is irrelevant. You can slightly influence the shape of the curve but you can't make it rational or non-rational.
Post Reply