I know it's possible to use `Curve2D`

to describe a 2D curve.

But how would one go about *drawing* that curve?

0 votes

I know it's possible to use `Curve2D`

to describe a 2D curve.

But how would one go about *drawing* that curve?

I've been researching this for about a week. ;)

You need to build add points to a `Curve2D`

object, then adjust the control points of the curve, and then finally draw the curve. So here's some simple, almost pseudo code:

```
var array_of_line_points # This already has the vectors which describe our line
for point in array_of_line_points:
# The "get_perpendicular_vector()" function returns a vector that's a copy of the point, yet has been slid along a line parallel to two neighboring points. The "distance" variable is how far the control point should be from the originating point.
var control_point1 = get_perpendicular_vector(point, distance)
var control_point2 = get_perpendicular_vector(point, -distance)
curve.add_point(point, control_point1, control_point2)
# ...In the draw function
func _draw():
draw_polyline(curve.get_baked_points(), red, 2.0)
```

I got inspiration for creating the curves this way from this webpage on spline interpolation.

I hope this helps!

+3 votes

Best answer

May as well promote my comment to an answer.

You need to add points to a `Curve2D`

object, then adjust the control points of the curve, and then finally draw the curve. So here's some simple, almost pseudo code:

```
var array_of_line_points # This already has the vectors which describe our line
for point in array_of_line_points:
# The "get_perpendicular_vector()" function returns a vector that's a copy of the point, yet has been slid along a line parallel to two neighboring points. The "distance" variable is how far the control point should be from the originating point.
var control_point1 = get_perpendicular_vector(point, distance)
var control_point2 = get_perpendicular_vector(point, -distance)
curve.add_point(point, control_point1, control_point2)
# ...In the draw function
func _draw():
draw_polyline(curve.get_baked_points(), red, 2.0)
```

I got the inspiration for this from Rob Spencer's page on Spline Interpolation. I'd like to make this more thorough (i.e. defining the `get_perpendicular_vector()`

function). But this is the best I can currently do.

0 votes

It's in the documentation:

http://docs.godotengine.org/en/3.0/tutorials/2d/custom_drawing_in_2d.html

```
func draw_circle_arc(center, radius, angle_from, angle_to, color):
var nb_points = 32
var points_arc = PoolVector2Array()
for i in range(nb_points+1):
var angle_point = deg2rad(angle_from + i * (angle_to-angle_from) / nb_points - 90)
points_arc.push_back(center + Vector2(cos(angle_point), sin(angle_point)) * radius)
for index_point in range(nb_points):
draw_line(points_arc[index_point], points_arc[index_point + 1], color)
```

+2 votes

Hey I just wrote this node called `SmoothPath`

based on Ertain's answer.

First you create straight lines in the editor then press the `Smooth`

button in the Inspector.

```
tool
class_name SmoothPath
extends Path2D
export(float) var spline_length = 100
export(bool) var _smooth setget smooth
export(bool) var _straighten setget straighten
func straighten(value):
if not value: return
for i in curve.get_point_count():
curve.set_point_in(i, Vector2())
curve.set_point_out(i, Vector2())
func smooth(value):
if not value: return
var point_count = curve.get_point_count()
for i in point_count:
var spline = _get_spline(i)
curve.set_point_in(i, -spline)
curve.set_point_out(i, spline)
func _get_spline(i):
var last_point = _get_point(i - 1)
var next_point = _get_point(i + 1)
var spline = last_point.direction_to(next_point) * spline_length
return spline
func _get_point(i):
var point_count = curve.get_point_count()
i = wrapi(i, 0, point_count - 1)
return curve.get_point_position(i)
func _draw():
var points = curve.get_baked_points()
if points:
draw_polyline(points, Color.black, 8, true)
```

Great job mate! I am also trying to visualize point*in and point*out handles by adding:

```
draw_circle(get_point_in(), 3, Color.white)
draw_circle(get_point_out(), 3, Color.white)
```

to the _draw() function. But it returns an error. Obviously, it needs to be done differently. I would highly appreciate if you have any idea how it can be done. I even tried this one below still without success:

```
for pc in curve.get_point_count():
var spline = _get_spline(pc)
var point_in = curve.get_point_in(-pc, _get_spline(pc))
var point_out = curve.get_point_out(pc, _get_spline(pc))
draw_circle(point_in, 3, Color.white)
draw_circle(point_out, 3, Color.white)
```

It returns: Too many arguments for get*point*in/out()

0 votes

Late to the game here, but here's a simple function that takes an array of vector2D (e.g. the points of a Line2D) and returns a Curve2D.

```
func array_to_curve(input : Array, dist : float):
#dist determines length of controls, set dist = 0 for no smoothing
var curve = Curve2D.new()
#calculate first point
var start_dir = input[0].direction_to(input[1])
curve.add_point(input[0], - start_dir * dist, start_dir * dist)
#calculate middle points
for i in range(1, input.size() - 1):
var dir = input[i-1].direction_to(input[i+1])
curve.add_point(input[i], -dir * dist, dir * dist)
#calculate last point
var end_dir = input[-1].direction_to(input[-2])
curve.add_point(input[-1], - end_dir * dist, end_dir * dist)
return curve
```

- All categories
- Engine 25,085