Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Curve In node #1817

Closed
zeffii opened this issue Oct 16, 2017 · 12 comments
Closed

Curve In node #1817

zeffii opened this issue Oct 16, 2017 · 12 comments

Comments

@zeffii
Copy link
Collaborator

zeffii commented Oct 16, 2017

Object In can already load Curve data, but strips all data except points.

As @Durman alludes to in this thread there's a weakness in what we offer regarding Curve Object data. I'd like to offer extra introspection into the spline data, there's a lot we can add. Some of this data can only be conveniently accessed via scripts at this point.

Bezier Curve
    - points
    - num points per subcurve (set this property)
    - radius at points ( interpolate according to `LINEAR`..etc )
Spline Curve
    - points
    - num points per subcurve (set this property)
    - radius at points ( interpolate according to `LINEAR`..etc )
optional 
    - edges 
         - inferred if no thickness :   connect between points, 
         - if thickneses then use obj.to_mesh
    - polygons output  (when thickness present this can use obj.to_mesh)

No ETA.

@Durman
Copy link
Collaborator

Durman commented Oct 16, 2017

I already have tried to receive radiuses of curve with script node.

if objs_in[0].data.splines[0].type == 'BEZIER':

    for i in objs_in[0].data.splines[0].bezier_points:
        bas_r.append(i.radius)
        bas_c.append(i.co)
else:
    for i in objs_in[0].data.splines[0].points:
        bas_r.append(i.radius)
        bas_c.append(i.co)

But i had problem with interpolation value of radius between intermediate points. I did not manage to receive exact distance between points by curve.

@zeffii
Copy link
Collaborator Author

zeffii commented Oct 16, 2017

yeah, i think the radii must be calculated by hand for interpolated points - i'm not aware of any convenience methods for this.. that's OK though.

@Durman
Copy link
Collaborator

Durman commented Oct 16, 2017

Interpolation of radiuses i did thus:
2017-10-16_18-57-47
Where D axis is distance between points, R axis is radiuses of points, C1,2 is points of curve, Pn is interpolation points.
Pny = dyC2 * dxPn / dxC2 + C1y
But i do not know how to find distance between points on curve.

@zeffii
Copy link
Collaborator Author

zeffii commented Oct 16, 2017

@Durman we can offer multiple radius interpolation approaches. I'll implement linear and maybe cubic. If you're interested you can look at the Blender source for the exact algorithms. I'm not ready to do this yet

@zeffii
Copy link
Collaborator Author

zeffii commented Oct 22, 2017

anyone want to write a function that interpolates radii?

num_segments = curve.render_resolution_u or curve.resolution_u

def interpolate_radii(spline, num_segments, interpolation_type='LINEAR'):
    radii = []
    if spline.use_cyclic_u:
        ...

    return radii

@zeffii
Copy link
Collaborator Author

zeffii commented Oct 22, 2017

https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.interp.html (linear only)

vals = [1.0, 2.0, 0.2, 1.0]

import sverchok

from sverchok.nodes.number.range_float import frange_count

A = vals[0], vals[1], 10
F = list(frange_count(*A))
print(F)

@zeffii
Copy link
Collaborator Author

zeffii commented Oct 22, 2017

something like this?

import sverchok
from sverchok.nodes.number.range_float import frange_count


def interpolate_radii(spline, segments, interpolation_type='LINEAR', spline_type='NURBS'):
    radii = []

    point_attr = {'NURBS': 'points', 'BEZIER': 'bezier_points'}.get(spline_type)
    points = [p.radius for p in getattr(spline, point_attr)]

    if spline.use_cyclic_u:
        points.append(points[0])

    for idx in range(len(points)-1):
        params = points[idx], points[idx+1], segments
        if len(points) == 2 or not (idx < (len(points)-2)):
            radii.extend(list(frange_count(*params)))
        else:
            radii.extend(list(frange_count(*params))[:-1])

    return radii


num_segments = curve.render_resolution_u or curve.resolution_u
radii = interpolate_radii(spline, num_segments, interpolation_type='LINEAR', spline_type='NURBS')
print(radii)

@zeffii
Copy link
Collaborator Author

zeffii commented Oct 27, 2017

looks like Linear and Catmul radii interpolation works.. and Biezer curve pickup too, but NURBS pickup should work too (Path)

@zeffii
Copy link
Collaborator Author

zeffii commented Oct 27, 2017

image

@zeffii
Copy link
Collaborator Author

zeffii commented Oct 27, 2017

see the curve-in branch for testing.
image

Note: the radius won't match if the Curve has a bevel depth. In that case you should add bevel_depth/2 to the radius i think.. or subtract it..whatever :)

@zeffii zeffii closed this as completed Oct 27, 2017
@Durman
Copy link
Collaborator

Durman commented Oct 28, 2017

Is it possible to do same resolution of radiuses as points?
resolution

@zeffii
Copy link
Collaborator Author

zeffii commented Oct 28, 2017

I think I will leave it at Object Level U resolution for the time being. Obviously resolution per Spline (which is what you are changing when modifying Active Spline's U resolution) would be valuable to have.

    for obj in objects:

            ## collect all data we can get from the subcurve(s)

            mtrx_out.append([list(m) for m in obj.matrix_world])
            verts, edges, faces, radii = [], [], [], []
            curve = obj.data
            resolution = curve.render_resolution_u or curve.resolution_u
            # ('POLY', 'BEZIER', 'BSPLINE', 'CARDINAL', 'NURBS')
            for spline in obj.data.splines:
                
                if spline.type == 'BEZIER':
                    verts_part, edges_part, radii = get_points_bezier(spline, calc_radii=calc_radii)
                elif spline.type == 'NURBS':
                    verts_part, edges_part, radii = get_points_nurbs(spline, resolution, calc_radii=calc_radii)
                else:
                    # maybe later?
                    continue

                # empty means we don't offset the index
                edges.extend(offset(edges_part, len(verts)) if verts else edges_part)
                verts.extend(verts_part)
                # faces.extend(faces_part)
                if _out['radii'].is_linked:
                    radii_part = interpolate_radii(spline, resolution, interpolation_type=self.selected_mode)
                    radii.extend(radii_part)

            ## pass all resulting subcurve data

            verts_out.append(verts)
            edges_out.append(edges)
            # faces_out.append(faces) 
            radii_out.append(radii)

@Durman Durman mentioned this issue Jan 10, 2018
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants