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!
looo
Posts: 2905
Joined: Mon Nov 11, 2013 5:29 pm

Re: surface flattening

Postby looo » Wed Sep 06, 2017 9:24 pm

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...
please help with my conda-packaging efforts: https://liberapay.com/looooo/
looo
Posts: 2905
Joined: Mon Nov 11, 2013 5:29 pm

Re: surface flattening

Postby looo » Thu Sep 07, 2017 10:19 am

uv-mesh is setup :D
uv-mesh.png
uv-mesh.png (85.89 KiB) Viewed 757 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.
please help with my conda-packaging efforts: https://liberapay.com/looooo/
looo
Posts: 2905
Joined: Mon Nov 11, 2013 5:29 pm

Re: surface flattening

Postby looo » Thu Sep 07, 2017 10:58 am

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)
please help with my conda-packaging efforts: https://liberapay.com/looooo/
wmayer
Site Admin
Posts: 14887
Joined: Thu Feb 19, 2009 10:32 am

Re: surface flattening

Postby wmayer » Thu Sep 07, 2017 11:17 am

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.
looo
Posts: 2905
Joined: Mon Nov 11, 2013 5:29 pm

Re: surface flattening

Postby looo » 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++;
    }
please help with my conda-packaging efforts: https://liberapay.com/looooo/
User avatar
tanderson69
Posts: 1500
Joined: Thu Feb 18, 2010 1:07 am

Re: surface flattening

Postby tanderson69 » Thu Sep 07, 2017 3:21 pm

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++;
    }
looo
Posts: 2905
Joined: Mon Nov 11, 2013 5:29 pm

Re: surface flattening

Postby looo » Thu Sep 07, 2017 4:57 pm

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 705 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.
please help with my conda-packaging efforts: https://liberapay.com/looooo/
wmayer
Site Admin
Posts: 14887
Joined: Thu Feb 19, 2009 10:32 am

Re: surface flattening

Postby wmayer » Thu Sep 07, 2017 8:22 pm

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
looo
Posts: 2905
Joined: Mon Nov 11, 2013 5:29 pm

Re: surface flattening

Postby looo » Fri Sep 08, 2017 6:43 am

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
please help with my conda-packaging efforts: https://liberapay.com/looooo/
wmayer
Site Admin
Posts: 14887
Joined: Thu Feb 19, 2009 10:32 am

Re: surface flattening

Postby wmayer » Fri Sep 08, 2017 8:36 am

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.