PreserveStructure morphing surfaces

Hello,

I’m deforming surfaces using morph. I need the same number of points in each deformation, so I use preserveStructure param and it works fine when the morph points has been shortly moved. However, when I do more complex deformations, the structure surface changes. Is it normal?

Thanks in advance.

Hi Jona,

We are going to need more details if were are going to be helpful. Do you have sample source code and geometry? How can I repeat what you are seeing?

– Dale

Hi Dale,

I have simplified the problem all I can. Actually I’m morphing iteratively and randomly a simple nurbs sphere, until the surface suddenly turns into a polysurface changing it internal structure. Of course, the preserve structure flag is true.

This is the code:

GeometryBase geom;

//-------------------------------------------------------------------------------------

    private bool ApplyMorph()
    {
             try
             {
                  if ( geom == null ) geom = refObj.Geometry( );
                  if ( !typeof( Brep ).IsInstanceOfType( geom ) && !typeof( Surface ).IsInstanceOfType( geom ) ) return false;
        
                  TMorphingSurfaceFromCage morph = new TMorphingSurfaceFromCage( );
                  morph.PreserveStructure = true;
                  morph.Morph( geom );
                  RhinoDoc.ActiveDoc.Objects.Replace( refObj, geom as Brep );
        	      return true;
        	}
        	catch ( Exception ex )
        	{
        #if (DEBUG)
        				MessageBox.Show( ex.ToString( ) );
        #endif
        	     return false;
           }
    }

//-------------------------------------------------------------------------------------

    public override Point3d MorphPoint( Point3d point )
    {
        try
        {
              System.Random random = new Random( System.DateTime.Now.Millisecond );
              point.X += ( ( random.NextDouble( ) * 2 ) - 1 ) * point.X * 0.2;
              point.Y += ( ( random.NextDouble( ) * 2 ) - 1 ) * point.Y * 0.2;
              point.Z += ( ( random.NextDouble( ) * 2 ) - 1 ) * point.Z * 0.2;
              return point;
        }
        catch ( Exception ex )
        {
        #if (DEBUG)
                        MessageBox.Show( ex.ToString( ) );
        #endif
               return point;
         }
    }

Thanks

Hi Jona,

Thanks for this. But what I really need is some code I can run and a model I can run the code against. Otherwise, I’m going to spend a lot of time trying to type up something that may or may not repeat the problem you are reporting.

Feel free to email me directly if needed.

Thanks,

– Dale

Hi Dale,

I have created a simple project and video to show you my problem.

I create a simple nurbs sphere and, after some random deformations it usually changes it structure. Sometimes it becomes a polysurface, and sometimes it continues to be a surface but duplicates the control points of the joint. Anyway, we end with a hole in the sphere, and more control points than we started with. All of this, of course, with the Preserve structure flag as true.

This seems to be a problem related to closed surfaces.

Deformer Test.zip (2.8 MB)

Thanks.

Hi Jona,

For this specific example, NURBS surface created by defining a sphere and then getting its NURB form will have fully multiple knots. Full multiplicity knot in the middle of the knot list means there is a place on the NURBS surface that can be bent into a sharp kink. When you add surfaces to Rhino that have kinks, they are automatically split. This is why your spherical surface is turning into a polysurface.

To get around this particular problem, you can rebuild the NURBS surface. Rebuilding will remove the fully multiple knots.

For example:

surface = new Sphere(new Point3d(), 20).ToNurbsSurface(); surface = surface.Rebuild(3, 3, 10, 10);

Now, morphing will not result in your surface being split into a polysurface.

Hope this helps.

– Dale

Hi Dale,

I understand now that the morph function can receive the same control points more than one time, so I have to apply exactly the same deformation to each of them, if I want to mantain it structure.

In my algortihm (not the example I passed before), I move the morph points depending on its location, I mean, two control points with the same coordinates, have the same weight, and apply the same movement to them, so I should never have this problem, but sometimes the geometry turns into a polysurface.

I have seen that Rhino makes something similar with the deformation cage tool as seen in the video http://upload.inescop.es/www/?a=d&i=3169344363

I’m thinking now, that maybe the problem could be related to precission or rounding values.

What do you think Dale?

Unless your geometry is far from the world origin, precision and/or rounding should not be a problem.

I have found a script function http://docs.mcneel.com/rhino/6/help/en-us/commands/creasesplitting.htm, that modifies the “GeneralSettings->SplitCreasedSurfaces” registry value.

With this value I can force surfaces with kinks to not split into polysurfaces, that is exactly what I want.

The problem is I have not found anyway in the api to modify this parameter. Is there any option available or I have to manually change this in the registry? If not, could this be added in the future?

Thanks,

One of the doc.Objects.AddBrep methods has a splitKinkySurfaces parameter that you can specify.

Thanks, I’ve solved my problem with splitKinkySurfaces parameter. But I was working with “replace” after having morph objects, and I had to change all “replace” to “addBep” method (doing this, the Guid of my Brep changes). May be you would have to consider introduce splitKinkySurfaces parameter to “replace” method.

You might just call something like the following before calling “replace”.

public static bool BrepSplitKinkyFaces(Brep brep)
{
  var rc = false;
  if (null != brep && brep.IsValid)
  {
    var face_count = brep.Faces.Count;
    var edge_count = brep.Edges.Count;
    if (brep.Faces.SplitKinkyFaces(RhinoMath.DefaultAngleTolerance, true))
    {
      if (face_count != brep.Faces.Count || edge_count != brep.Edges.Count)
        rc = true;
    }
  }
  return rc;
}