View Source Tucan.Geometry (tucan v0.4.1)

An API for drawing common geometrical shapes.

Tucan.Geometry offers an interface for rendering typical geometric forms, such as lines, circles, and polygons. Unlike the general Tucan API, these functions require only the parameters defining the respective geometric shapes, rather than a dataset and data fields.

You can overlay tucan plots with geometrical shapes through the Tucan.layers/2 function.

Examples

Tucan.layers([
  Tucan.Geometry.circle({3, 3}, 4, line_color: "red", stroke_width: 3),
  Tucan.Geometry.rectangle({-2, 10}, {7, -3}, line_color: "green"),
  Tucan.Geometry.rectangle({-3.5, 0.1}, {8.1, -4.2},
    fill_color: "pink",
    fill_opacity: 0.3
  ),
  Tucan.Geometry.polyline([{1, 1}, {2, 7}, {5, 3}],
    closed: true,
    fill_color: "green",
    fill_opacity: 0.3
  )
])
|> Tucan.Scale.set_xy_domain(-5, 11)
|> Tucan.set_size(400, 400)
|> Tucan.set_title("Tucan.Geometry examples")
{"$schema":"https://vega.github.io/schema/vega-lite/v5.json","height":400,"layer":[{"data":{"sequence":{"as":"theta","start":0,"step":0.1,"stop":361}},"encoding":{"order":{"field":"theta"},"x":{"field":"x","scale":{"domain":[-5,11]},"type":"quantitative"},"y":{"field":"y","scale":{"domain":[-5,11]},"type":"quantitative"}},"mark":{"color":"red","fillOpacity":1,"strokeOpacity":1,"strokeWidth":3,"type":"line"},"transform":[{"as":"x","calculate":"3 + cos(datum.theta*PI/180) * 4"},{"as":"y","calculate":"3 + sin(datum.theta*PI/180) * 4"}]},{"data":{"values":[{"order":0,"x":-2,"y":-3},{"order":1,"x":-2,"y":10},{"order":2,"x":7,"y":10},{"order":3,"x":7,"y":-3},{"order":4,"x":-2,"y":-3}]},"encoding":{"order":{"field":"order"},"x":{"field":"x","scale":{"domain":[-5,11]},"type":"quantitative"},"y":{"field":"y","scale":{"domain":[-5,11]},"type":"quantitative"}},"mark":{"color":"green","fillOpacity":1,"strokeOpacity":1,"strokeWidth":1,"type":"line"}},{"data":{"values":[{"order":0,"x":-3.5,"y":-4.2},{"order":1,"x":-3.5,"y":0.1},{"order":2,"x":8.1,"y":0.1},{"order":3,"x":8.1,"y":-4.2},{"order":4,"x":-3.5,"y":-4.2}]},"encoding":{"order":{"field":"order"},"x":{"field":"x","scale":{"domain":[-5,11]},"type":"quantitative"},"y":{"field":"y","scale":{"domain":[-5,11]},"type":"quantitative"}},"mark":{"fill":"pink","fillOpacity":0.3,"strokeOpacity":1,"strokeWidth":1,"type":"line"}},{"data":{"values":[{"order":0,"x":1,"y":1},{"order":1,"x":2,"y":7},{"order":2,"x":5,"y":3},{"order":3,"x":1,"y":1}]},"encoding":{"order":{"field":"order"},"x":{"field":"x","scale":{"domain":[-5,11]},"type":"quantitative"},"y":{"field":"y","scale":{"domain":[-5,11]},"type":"quantitative"}},"mark":{"fill":"green","fillOpacity":0.3,"strokeOpacity":1,"strokeWidth":1,"type":"line"}}],"title":{"text":"Tucan.Geometry examples"},"width":400}

Summary

Types

A cartesian point in the form {x, y}

Functions

Draws a circle with the given center and radius.

Draws an ellipse with the given center, x_radius, y_radius, and rotation_angle.

Draws a polyline defined by the given vertices.

Draws a rectangle defined by the given upper_left and bottom_right points.

Types

@type point() :: {number(), number()}

A cartesian point in the form {x, y}

Functions

Link to this function

circle(center, radius, opts \\ [])

View Source
@spec circle(center :: point(), radius :: number(), opts :: keyword()) :: VegaLite.t()

Draws a circle with the given center and radius.

Options

Styling Options

  • :fill_color (String.t/0) - The fill color of the marks. This will override the color encoding if set.
  • :fill_opacity (number/0) - The fill opacity of the plotted elements. The default value is 1.
  • :line_color (String.t/0) - The color of the line
  • :opacity (number/0) - The overall opacity of the mark
  • :stroke_dash (list of pos_integer/0) - An array of alternating stroke, space lengths in pixels for creating dashed or dotted lines.
  • :stroke_opacity (number/0) - The opacity of the stroke. The default value is 1.
  • :stroke_width (pos_integer/0) - The stroke width in pixels The default value is 1.

Examples

Tucan.layers([
  Tucan.Geometry.circle({3, 2}, 5),
  Tucan.Geometry.circle({-1, 6}, 2, line_color: "red"),
  Tucan.Geometry.circle({0, 1}, 4, line_color: "green", stroke_width: 5)
])
|> Tucan.Scale.set_x_domain(-5, 10)
|> Tucan.Scale.set_y_domain(-5, 10)
{"$schema":"https://vega.github.io/schema/vega-lite/v5.json","layer":[{"data":{"sequence":{"as":"theta","start":0,"step":0.1,"stop":361}},"encoding":{"order":{"field":"theta"},"x":{"field":"x","scale":{"domain":[-5,10]},"type":"quantitative"},"y":{"field":"y","scale":{"domain":[-5,10]},"type":"quantitative"}},"mark":{"fillOpacity":1,"strokeOpacity":1,"strokeWidth":1,"type":"line"},"transform":[{"as":"x","calculate":"3 + cos(datum.theta*PI/180) * 5"},{"as":"y","calculate":"2 + sin(datum.theta*PI/180) * 5"}]},{"data":{"sequence":{"as":"theta","start":0,"step":0.1,"stop":361}},"encoding":{"order":{"field":"theta"},"x":{"field":"x","scale":{"domain":[-5,10]},"type":"quantitative"},"y":{"field":"y","scale":{"domain":[-5,10]},"type":"quantitative"}},"mark":{"color":"red","fillOpacity":1,"strokeOpacity":1,"strokeWidth":1,"type":"line"},"transform":[{"as":"x","calculate":"-1 + cos(datum.theta*PI/180) * 2"},{"as":"y","calculate":"6 + sin(datum.theta*PI/180) * 2"}]},{"data":{"sequence":{"as":"theta","start":0,"step":0.1,"stop":361}},"encoding":{"order":{"field":"theta"},"x":{"field":"x","scale":{"domain":[-5,10]},"type":"quantitative"},"y":{"field":"y","scale":{"domain":[-5,10]},"type":"quantitative"}},"mark":{"color":"green","fillOpacity":1,"strokeOpacity":1,"strokeWidth":5,"type":"line"},"transform":[{"as":"x","calculate":"0 + cos(datum.theta*PI/180) * 4"},{"as":"y","calculate":"1 + sin(datum.theta*PI/180) * 4"}]}]}

You can also draw filled circles by setting the :fill_color option. Opacity of the fill color and the stroke color can be configured by :opacity or independently by :fill_opacity and :stroke_opacity.

Tucan.layers([
  Tucan.Geometry.circle({3, 2}, 5, stroke_width: 3, stroke_opacity: 0.4),
  Tucan.Geometry.circle({-1, 6}, 2, line_color: "red", fill_color: "pink", opacity: 0.3),
  Tucan.Geometry.circle({0, 1}, 4,
    line_color: "green",
    stroke_width: 5,
    fill_color: "green",
    fill_opacity: 0.2
  )
])
|> Tucan.Scale.set_x_domain(-5, 10)
|> Tucan.Scale.set_y_domain(-5, 10)
{"$schema":"https://vega.github.io/schema/vega-lite/v5.json","layer":[{"data":{"sequence":{"as":"theta","start":0,"step":0.1,"stop":361}},"encoding":{"order":{"field":"theta"},"x":{"field":"x","scale":{"domain":[-5,10]},"type":"quantitative"},"y":{"field":"y","scale":{"domain":[-5,10]},"type":"quantitative"}},"mark":{"fillOpacity":1,"strokeOpacity":0.4,"strokeWidth":3,"type":"line"},"transform":[{"as":"x","calculate":"3 + cos(datum.theta*PI/180) * 5"},{"as":"y","calculate":"2 + sin(datum.theta*PI/180) * 5"}]},{"data":{"sequence":{"as":"theta","start":0,"step":0.1,"stop":361}},"encoding":{"order":{"field":"theta"},"x":{"field":"x","scale":{"domain":[-5,10]},"type":"quantitative"},"y":{"field":"y","scale":{"domain":[-5,10]},"type":"quantitative"}},"mark":{"color":"red","fill":"pink","fillOpacity":1,"opacity":0.3,"strokeOpacity":1,"strokeWidth":1,"type":"line"},"transform":[{"as":"x","calculate":"-1 + cos(datum.theta*PI/180) * 2"},{"as":"y","calculate":"6 + sin(datum.theta*PI/180) * 2"}]},{"data":{"sequence":{"as":"theta","start":0,"step":0.1,"stop":361}},"encoding":{"order":{"field":"theta"},"x":{"field":"x","scale":{"domain":[-5,10]},"type":"quantitative"},"y":{"field":"y","scale":{"domain":[-5,10]},"type":"quantitative"}},"mark":{"color":"green","fill":"green","fillOpacity":0.2,"strokeOpacity":1,"strokeWidth":5,"type":"line"},"transform":[{"as":"x","calculate":"0 + cos(datum.theta*PI/180) * 4"},{"as":"y","calculate":"1 + sin(datum.theta*PI/180) * 4"}]}]}

Circles and plot dimensions

Notice that the plot must be square with identical scale domains across the two axes for the circle to appear circular. In a different case it will look like an ellipsis.

circle = Tucan.Geometry.circle({0, 0}, 1)

Tucan.hconcat([
  circle
  |> Tucan.set_size(150, 150)
  |> Tucan.set_title("Square frame"),
  circle
  |> Tucan.Scale.set_x_domain(-2, 2)
  |> Tucan.Scale.set_y_domain(-1, 1)
  |> Tucan.set_size(150, 150)
  |> Tucan.set_title("Different domains"),
  circle
  |> Tucan.set_size(200, 150)
  |> Tucan.set_title("Different frame dimensions")
])
{"$schema":"https://vega.github.io/schema/vega-lite/v5.json","hconcat":[{"data":{"sequence":{"as":"theta","start":0,"step":0.1,"stop":361}},"encoding":{"order":{"field":"theta"},"x":{"field":"x","type":"quantitative"},"y":{"field":"y","type":"quantitative"}},"height":150,"mark":{"fillOpacity":1,"strokeOpacity":1,"strokeWidth":1,"type":"line"},"title":{"text":"Square frame"},"transform":[{"as":"x","calculate":"0 + cos(datum.theta*PI/180) * 1"},{"as":"y","calculate":"0 + sin(datum.theta*PI/180) * 1"}],"width":150},{"data":{"sequence":{"as":"theta","start":0,"step":0.1,"stop":361}},"encoding":{"order":{"field":"theta"},"x":{"field":"x","scale":{"domain":[-2,2]},"type":"quantitative"},"y":{"field":"y","scale":{"domain":[-1,1]},"type":"quantitative"}},"height":150,"mark":{"fillOpacity":1,"strokeOpacity":1,"strokeWidth":1,"type":"line"},"title":{"text":"Different domains"},"transform":[{"as":"x","calculate":"0 + cos(datum.theta*PI/180) * 1"},{"as":"y","calculate":"0 + sin(datum.theta*PI/180) * 1"}],"width":150},{"data":{"sequence":{"as":"theta","start":0,"step":0.1,"stop":361}},"encoding":{"order":{"field":"theta"},"x":{"field":"x","type":"quantitative"},"y":{"field":"y","type":"quantitative"}},"height":150,"mark":{"fillOpacity":1,"strokeOpacity":1,"strokeWidth":1,"type":"line"},"title":{"text":"Different frame dimensions"},"transform":[{"as":"x","calculate":"0 + cos(datum.theta*PI/180) * 1"},{"as":"y","calculate":"0 + sin(datum.theta*PI/180) * 1"}],"width":200}]}
Link to this function

ellipse(radius, x_radius, y_radius, rotation_angle, opts \\ [])

View Source
@spec ellipse(
  center :: point(),
  x_radius :: number(),
  y_radius :: number(),
  rotation_angle :: number(),
  opts :: keyword()
) :: VegaLite.t()

Draws an ellipse with the given center, x_radius, y_radius, and rotation_angle.

x_radius is expected to be a positive number corresponding to the major semi-axis length, y_radius a positive number corresponding to the minor semi-axis length and rotation_angle the ellipse's rotation angle with respect to the x-axis.

Options

Styling Options

  • :fill_color (String.t/0) - The fill color of the marks. This will override the color encoding if set.
  • :fill_opacity (number/0) - The fill opacity of the plotted elements. The default value is 1.
  • :line_color (String.t/0) - The color of the line
  • :opacity (number/0) - The overall opacity of the mark
  • :stroke_dash (list of pos_integer/0) - An array of alternating stroke, space lengths in pixels for creating dashed or dotted lines.
  • :stroke_opacity (number/0) - The opacity of the stroke. The default value is 1.
  • :stroke_width (pos_integer/0) - The stroke width in pixels The default value is 1.

Examples

Tucan.layers([
  Tucan.Geometry.ellipse({0, 0}, 5, 3, 0),
  Tucan.Geometry.ellipse({3, 4}, 5, 4, 45, line_color: "red"),
  Tucan.Geometry.ellipse({4, 1}, 7, 2, -30, line_color: "green", stroke_width: 2)
])
|> Tucan.Scale.set_x_domain(-5, 10)
|> Tucan.Scale.set_y_domain(-5, 10)
{"$schema":"https://vega.github.io/schema/vega-lite/v5.json","layer":[{"data":{"sequence":{"as":"theta","start":0,"step":0.1,"stop":361}},"encoding":{"order":{"field":"theta"},"x":{"field":"x","scale":{"domain":[-5,10]},"type":"quantitative"},"y":{"field":"y","scale":{"domain":[-5,10]},"type":"quantitative"}},"mark":{"fillOpacity":1,"strokeOpacity":1,"strokeWidth":1,"type":"line"},"transform":[{"as":"x","calculate":"0 + cos(datum.theta*PI/180) * cos(0*PI/180) * 5 -sin(datum.theta*PI/180) * sin(0*PI/180) * 3"},{"as":"y","calculate":"0 + cos(datum.theta*PI/180) * sin(0*PI/180) * 5 +sin(datum.theta*PI/180) * cos(0*PI/180) * 3"}]},{"data":{"sequence":{"as":"theta","start":0,"step":0.1,"stop":361}},"encoding":{"order":{"field":"theta"},"x":{"field":"x","scale":{"domain":[-5,10]},"type":"quantitative"},"y":{"field":"y","scale":{"domain":[-5,10]},"type":"quantitative"}},"mark":{"color":"red","fillOpacity":1,"strokeOpacity":1,"strokeWidth":1,"type":"line"},"transform":[{"as":"x","calculate":"3 + cos(datum.theta*PI/180) * cos(45*PI/180) * 5 -sin(datum.theta*PI/180) * sin(45*PI/180) * 4"},{"as":"y","calculate":"4 + cos(datum.theta*PI/180) * sin(45*PI/180) * 5 +sin(datum.theta*PI/180) * cos(45*PI/180) * 4"}]},{"data":{"sequence":{"as":"theta","start":0,"step":0.1,"stop":361}},"encoding":{"order":{"field":"theta"},"x":{"field":"x","scale":{"domain":[-5,10]},"type":"quantitative"},"y":{"field":"y","scale":{"domain":[-5,10]},"type":"quantitative"}},"mark":{"color":"green","fillOpacity":1,"strokeOpacity":1,"strokeWidth":2,"type":"line"},"transform":[{"as":"x","calculate":"4 + cos(datum.theta*PI/180) * cos(-30*PI/180) * 7 -sin(datum.theta*PI/180) * sin(-30*PI/180) * 2"},{"as":"y","calculate":"1 + cos(datum.theta*PI/180) * sin(-30*PI/180) * 7 +sin(datum.theta*PI/180) * cos(-30*PI/180) * 2"}]}]}
Link to this function

polyline(vertices, opts \\ [])

View Source
@spec polyline(vertices :: [point()], opts :: keyword()) :: VegaLite.t()

Draws a polyline defined by the given vertices.

The order of the vertices defines the order of the line segments that will be generated.

The polyline or polygon will be added as a new layer to the given plot vl.

Options

  • :closed (boolean/0) - Whether a last segment will be added between the last and first points. The default value is false.

Styling Options

  • :fill_color (String.t/0) - The fill color of the marks. This will override the color encoding if set.
  • :fill_opacity (number/0) - The fill opacity of the plotted elements. The default value is 1.
  • :line_color (String.t/0) - The color of the line
  • :opacity (number/0) - The overall opacity of the mark
  • :stroke_dash (list of pos_integer/0) - An array of alternating stroke, space lengths in pixels for creating dashed or dotted lines.
  • :stroke_opacity (number/0) - The opacity of the stroke. The default value is 1.
  • :stroke_width (pos_integer/0) - The stroke width in pixels The default value is 1.

Examples

Tucan.Geometry.polyline([{-1, 1}, {-2, 4}, {-1, 3}, {4, 7}, {8, 2}])
|> Tucan.Scale.set_x_domain(-3, 10)
|> Tucan.Scale.set_y_domain(-1, 9)
{"$schema":"https://vega.github.io/schema/vega-lite/v5.json","data":{"values":[{"order":0,"x":-1,"y":1},{"order":1,"x":-2,"y":4},{"order":2,"x":-1,"y":3},{"order":3,"x":4,"y":7},{"order":4,"x":8,"y":2}]},"encoding":{"order":{"field":"order"},"x":{"field":"x","scale":{"domain":[-3,10]},"type":"quantitative"},"y":{"field":"y","scale":{"domain":[-1,9]},"type":"quantitative"}},"mark":{"fillOpacity":1,"strokeOpacity":1,"strokeWidth":1,"type":"line"}}

If :closed is set to true a line segment is added between the last and first point.

Tucan.Geometry.polyline([{-1, 1}, {-2, 4}, {-1, 3}, {4, 7}, {8, 2}], closed: true)
|> Tucan.Scale.set_x_domain(-3, 10)
|> Tucan.Scale.set_y_domain(-1, 9)
{"$schema":"https://vega.github.io/schema/vega-lite/v5.json","data":{"values":[{"order":0,"x":-1,"y":1},{"order":1,"x":-2,"y":4},{"order":2,"x":-1,"y":3},{"order":3,"x":4,"y":7},{"order":4,"x":8,"y":2},{"order":5,"x":-1,"y":1}]},"encoding":{"order":{"field":"order"},"x":{"field":"x","scale":{"domain":[-3,10]},"type":"quantitative"},"y":{"field":"y","scale":{"domain":[-1,9]},"type":"quantitative"}},"mark":{"fillOpacity":1,"strokeOpacity":1,"strokeWidth":1,"type":"line"}}

You can change the appearance of the polyline/polygon.

points = [{-1, 1}, {-2, 4}, {-1, 3}, {4, 7}, {8, 2}]

Tucan.Geometry.polyline(points,
  closed: true,
  fill_color: "red",
  line_color: "green",
  fill_opacity: 0.3,
  stroke_width: 3,
  stroke_dash: [5, 3]
)
|> Tucan.Scale.set_x_domain(-3, 10)
|> Tucan.Scale.set_y_domain(-1, 9)
{"$schema":"https://vega.github.io/schema/vega-lite/v5.json","data":{"values":[{"order":0,"x":-1,"y":1},{"order":1,"x":-2,"y":4},{"order":2,"x":-1,"y":3},{"order":3,"x":4,"y":7},{"order":4,"x":8,"y":2},{"order":5,"x":-1,"y":1}]},"encoding":{"order":{"field":"order"},"x":{"field":"x","scale":{"domain":[-3,10]},"type":"quantitative"},"y":{"field":"y","scale":{"domain":[-1,9]},"type":"quantitative"}},"mark":{"color":"green","fill":"red","fillOpacity":0.3,"strokeDash":[5,3],"strokeOpacity":1,"strokeWidth":3,"type":"line"}}
Link to this function

rectangle(upper_left, bottom_right, opts \\ [])

View Source
@spec rectangle(upper_left :: point(), bottom_right :: point(), opts :: keyword()) ::
  VegaLite.t()

Draws a rectangle defined by the given upper_left and bottom_right points.

Options

See polyline/2

Examples

Tucan.layers([
  Tucan.Geometry.rectangle({1, 5}, {5, 1},
    line_color: "black",
    stroke_width: 2,
    stroke_dash: [5, 5]
  ),
  Tucan.Geometry.rectangle({-2, 10}, {7, -3}, line_color: "green"),
  Tucan.Geometry.rectangle({-3.5, 0.1}, {8.1, -4.2}, fill_color: "pink", fill_opacity: 0.3)
])
|> Tucan.Scale.set_xy_domain(-5, 11)
|> Tucan.set_size(400, 300)
{"$schema":"https://vega.github.io/schema/vega-lite/v5.json","height":300,"layer":[{"data":{"values":[{"order":0,"x":1,"y":1},{"order":1,"x":1,"y":5},{"order":2,"x":5,"y":5},{"order":3,"x":5,"y":1},{"order":4,"x":1,"y":1}]},"encoding":{"order":{"field":"order"},"x":{"field":"x","scale":{"domain":[-5,11]},"type":"quantitative"},"y":{"field":"y","scale":{"domain":[-5,11]},"type":"quantitative"}},"mark":{"color":"black","fillOpacity":1,"strokeDash":[5,5],"strokeOpacity":1,"strokeWidth":2,"type":"line"}},{"data":{"values":[{"order":0,"x":-2,"y":-3},{"order":1,"x":-2,"y":10},{"order":2,"x":7,"y":10},{"order":3,"x":7,"y":-3},{"order":4,"x":-2,"y":-3}]},"encoding":{"order":{"field":"order"},"x":{"field":"x","scale":{"domain":[-5,11]},"type":"quantitative"},"y":{"field":"y","scale":{"domain":[-5,11]},"type":"quantitative"}},"mark":{"color":"green","fillOpacity":1,"strokeOpacity":1,"strokeWidth":1,"type":"line"}},{"data":{"values":[{"order":0,"x":-3.5,"y":-4.2},{"order":1,"x":-3.5,"y":0.1},{"order":2,"x":8.1,"y":0.1},{"order":3,"x":8.1,"y":-4.2},{"order":4,"x":-3.5,"y":-4.2}]},"encoding":{"order":{"field":"order"},"x":{"field":"x","scale":{"domain":[-5,11]},"type":"quantitative"},"y":{"field":"y","scale":{"domain":[-5,11]},"type":"quantitative"}},"mark":{"fill":"pink","fillOpacity":0.3,"strokeOpacity":1,"strokeWidth":1,"type":"line"}}],"width":400}