# Oops...

This website is made for modern browsers. You are seeing this, because your browser is missing a feature or two. Please install the latest update or switch to a modern browser. See you soon.

# Curve and surface parameters

This how-to guide handles curve and surface parameters, which are an essential part for algorithmic modeling in Grasshopper. Both are used to define a position on the geometric shape. Curves have one dimension and thus one parameter is needed to specify a point on the curve. Surfaces have two dimensions and thus two coordinates specify a point.

## Curve parameters

A curve has one dimension, though it can inhabit a two- or three-dimensional space. To specify a point on a curve, we can describe its position by the distance that one has to travel along, from the curve’s start until reaching the point. Though the curve parameter does not have to equal the actually travelled length (as describe later), it starts at the lower bound of the curve’s domain and ascends until it reaches the upper bound.

### Curve Domains

Let’s assume a simple curve: a circle with the radius of 2. The domain of the circle can be displayed with a Domain Domain (Domain)
Params  >  Primitive  >  Domain
Contains a collection of numeric domains
component and is always 0 To 2.0 * Pi, despite the radius and length. Every infinitesimal interval of the curve can be allocated within the curve’s domain. In other words, a number within the curve’s domain can be remapped to a position on the curve.

However, there is a pitfall with curves and their domains: When the type of a shape changes, for example from a Circle to a Circular Curve, the domain might change as well. For example, when we use the component Curve Domain Curve Domain (CrvDom)
Curve  >  Analysis  >  Curve Domain
Measure and set the curve domain
Inputs
Curve (C)Curve to measure/modify
Domain (D)Optional domain, if omitted the curve will not be modified.
Outputs
Curve (C)Curve with new domain.
Domain (D)Domain of original curve.
, the circles are internally converted to curves and we get the curve’s domain instead of the circle’s domain; for our circle, the upper bound of 2 * Pi is replaced with the curve’s length, here 4 * Pi. The component Curve Domain will transform the Circle into a Circular Curve and then return the domain of the curve and not the circle.

The domain of a curve does not have to start at 0, any real number is possible. For example, if we Shatter Shatter (Shatter)
Curve  >  Division  >  Shatter
Shatter a curve into segments.
Inputs
Curve (C)Curve to trim
Parameters (t)Parameters to split at
Outputs
Segments (S)Shattered remains
a circle into two curves, we get two consecutive domains.
To Shatter Shatter (Shatter)
Curve  >  Division  >  Shatter
Shatter a curve into segments.
Inputs
Curve (C)Curve to trim
Parameters (t)Parameters to split at
Outputs
Segments (S)Shattered remains
a circle into two parts, we have to set two parameters, otherwise we get a circular curve with an identical start and end point.
To Shatter Shatter (Shatter)
Curve  >  Division  >  Shatter
Shatter a curve into segments.
Inputs
Curve (C)Curve to trim
Parameters (t)Parameters to split at
Outputs
Segments (S)Shattered remains
a circle into two parts, we have to set two parameters, otherwise we get a circular curve with an identical start and end point.

### Working with curve parameters

From the foregoing, we can recap that every value within a curve’s domain represents a point on that curve. We can find a point and the curve’s properties at that position with the component Evaluate Curve Evaluate Curve (Eval)
Curve  >  Analysis  >  Evaluate Curve
Evaluate a curve at the specified parameter.
Inputs
Curve (C)Curve to evaluate
Parameter (t)Parameter on curve domain to evaluate
Outputs
Point (P)Point on the curve at {t}
Tangent (T)Tangent vector at {t}
Angle (A)Angle (in Radians) of incoming vs. outgoing curve at {t}
. To continue with our circle, we can set the curve parameter t to 2 * Pi to evaluate the midpoint of the domain (the component converts the circle to a curve and thus the domain changes to 4 * Pi).

To solve the above more parametric and to react to changes of the curve’s domain, we can calculate a representative value in the curve’s domain with Remap Numbers Remap Numbers (ReMap)
Maths  >  Domain  >  Remap Numbers
Remap numbers into a new numeric domain
Inputs
Value (V)Value to remap
Source (S)Source domain
Target (T)Target domain
Outputs
Mapped (R)Remapped number
Clipped (C)Remapped and clipped number
: At input V (value) we use a Number Slider Number Slider
Params  >  Input  >  Number Slider
Numeric slider for single values
from 0 to 1 and at input S we set the source domain to 0 To 1. Before we connect our circle, we need to convert it to a Circular Curve with Curve Curve (Crv)
Params  >  Geometry  >  Curve
Contains a collection of generic curves
to get the correct domain. We can then wire the curve directly to input T and it will become our target domain. Changing the Number Slider lets us now address every position on the curve.

Grasshopper offers several components to retrieve curve parameters, for example by intersection events or by curve analysis. Other components need a curve parameter as input to perform a certain function at that position of the curve. Examples of components that have curve parameters as input or output.

### Reparameterize curves

In the examples above, dealing with curve domains was cumbersome and needed special attention. But we can make our lives easier: domains can be reparameterized. This means, a domain is rewritten, or remapped, to the normalized domain 0 To 1. Thus, independent of the curve or type of curve, we always get the same domain.

To do so, we can set a new domain D, here 0 To 1, with a Curve Domain Curve Domain (CrvDom)
Curve  >  Analysis  >  Curve Domain
Measure and set the curve domain
Inputs
Curve (C)Curve to measure/modify
Domain (D)Optional domain, if omitted the curve will not be modified.
Outputs
Curve (C)Curve with new domain.
Domain (D)Domain of original curve.
component. At output D we get the original domain of the curve. As shown in the image, all fed curves get the new domain.

Because the normalization of a curve’s domain is so useful, it can also be achieved with a shortcut: right-click the input grip of a curve and select Reparameterize. That an input is reparameterized is indicated by the little symbol. After reparameterizing a curve, the curve parameters t also relate to the normalized domain.

Picking up the example from above, in which we remapped a value to fit the curve’s domain, we can, after reparameterizing a curve’s domain, use a default Number Slider Number Slider
Params  >  Input  >  Number Slider
Numeric slider for single values
to evaluate any position on the curve.

### Curve parameters and lengths

In case of our circle, there was a relation between the curve parameter and the length; the midpoint (length factor 0.5) was at curve parameter Pi. However, this is often not the case. For example, the domain of polylines depends on the number of segments. The domain of a polyline is based on the number of segments.

Nurbs curves, as another example, set their domain in relation to the number of knots. Even after reparameterizing a curve’s domain, there is no relation between the curve parameter and the length of a curve’s segment. As shown in the image below, the midpoint of this curve is at t = 0.580508. The curve parameter 0.5 of a normalized curve does not always represent the middle of a curve.

After dividing this curve into segments according to equal subdomains of the curve’s domain, we see that the actual segments' lengths vary significantly. Sometimes, there is no relation between the curve parameter and the distance on the curve.

To conclude, we have to treat curve parameter and length factor as two different properties, which occasionally have the same value. When dealing with curve parameters, it’s usually better to work with the normalized format.

## Surface parameters

A surface has two dimensions and can inhabit a two- or three-dimensional space. To specify a point on the surface, we need two coordinates, which are commonly called u and v. These coordinates have to be within the domains of the surface. Because there are two dimensions, we have two domains. In Grasshopper, there is a special data type to host these domains, which is Domain² and each domain is named according to the coordinate.

To get the domain of a surface, we can use a Domain² Domain² (Domain²)
Params  >  Primitive  >  Domain²
Contains a collection of 2D number domains
container. In comparison to the Dimensions Dimensions (Dim)
Surface  >  Analysis  >  Dimensions
Get the approximate dimensions of a surface
Inputs
Surface (S)Surface to measure
Outputs
U dimension (U)Approximate dimension in U direction
V dimension (V)Approximate dimension in V direction
of a surface, we see a relation between the domains and the dimensions, but similar to curves, they are not necessarily coincident.

To find the uv-coordinates of a point on a surface, we can use Surface Closest Point Surface Closest Point (Srf CP)
Surface  >  Analysis  >  Surface Closest Point
Find the closest point on a surface.
Inputs
Point (P)Sample point
Surface (S)Base surface
Outputs
Point (P)Closest point
UV Point (uvP){uv} coordinates of closest point
Distance (D)Distance between sample point and surface
. Note though, that this component outputs the normalized coordinates.

Grasshopper offers several components that either output uv-coordinates by some kind of event or rule and components that use uv-coordinates as input to perform certain functions at those positions.

### Reparameterize surfaces

The concept of reparameterization, as described above, is also applicable and even more useful for surfaces. If we do not normalize the domains, we need to deconstruct the surface’s domains, find the coordinates of the position within these domains and combine them. Using a reparameterized surfaces shortens this to setting the position in a predefined domain space.

### Trimmed and untrimmed surfaces

When dealing with surfaces, there is also a pitfall: trimmed surfaces. A trimmed surface is a combination of an arbitrary shape and closed curves. Internally, Rhino and Grasshopper use the underlying, untrimmed shape and display what is inside the outer border; additional closed curves can be used to cut holes into the remaining surface. If possible, transformations are calculated for the arbitrary, untrimmed shape and the curves separately and then displayed again as the combined, trimmed surface.

The surface’s domains and its uv-coordinates relate to the untrimmed surface, not the trimmed one. This means that coordinates can actually be outside of the trimmed surface. To illustrate this, we create a trimmed surface with a hexagon and evaluate a position on that surface with an MD Slider MD Slider (MD Slider)
Params  >  Input  >  MD Slider
A multidimensional slider
. Then we use Point In Curve Point In Curve (InCurve)
Curve  >  Analysis  >  Point In Curve
Test a point for closed curve containment.
Inputs
Point (P)Point for region inclusion test
Curve (C)Boundary region (closed curves only)
Outputs
Relationship (R)Point/Region relationship (0 = outside, 1 = coincident, 2 = inside)
Point (P')Point projected on region plane.
to check whether the point is inside the hexagon. As we can see in the image, there are coordinates that are not within the trimmed surface (R = 0). Evaluating a point on a surface doesn’t necessarily mean that this point is inside the trimmed surface.

To retrieve the untrimmed surface from a trimmed one, we can use Untrim Untrim (Untrim)
Surface  >  Util  >  Untrim
Remove all trim curves from a surface.
Inputs
Surface (S)Base surface
Outputs
Surface (S)Untrimmed surface
.