Module OManifold.Cross

Two-dimensional cross sections guaranteed to be without self-intersections, or overlaps between polygons (from construction onwards)

type t
type fill_rule = [
  1. | `EvenOdd
    (*

    only odd numbered sub-regions are filled

    *)
  2. | `NonZero
    (*

    non-zero sub-regions are filled

    *)
  3. | `Positive
    (*

    only sub-regions with winding counts > 0 are filled

    *)
  4. | `Negative
    (*

    only sub-regions with winding counts < 0 are filled

    *)
]

Filling rules used by the clipping algorithm for boolean operations. See Clipper2's docs for a detailed explanation of how they differ).

type join_type = [
  1. | `Square
    (*

    squaring applied uniformally at all joins where the internal join angle is less than 90 degrees. The squared edg will be at exactly the offset distance from the join vertex

    *)
  2. | `Round
    (*

    rounding is appliedto all joins that have convex external angles, and it maintains the exact offset distance from the join vertex

    *)
  3. | `Miter
    (*

    there's a necessary limit to mitered joins (to avoid narrow angled joins producing excessively long and narrow spikes)). The limit sets the maximum distance in multiples of the delta specified for the offsetting operation (default is 2., which is the minimum allowed).

    *)
]

Defines the treatment of corners when offsetting paths. Visual examples are available in the Clipper2 docs.

Constructors

val empty : unit -> t

empty ()

Create an empty cross-section containing no contours.

val of_path : ?fill_rule:fill_rule -> OCADml.Path2.t -> t

of_path ?fill_rule path

Create a 2d cross-section from a single outline path. A boolean union operation (with `Positive filling rule by default) is performed to ensure the resulting cross-section is free of self-intersections.

val of_paths : ?fill_rule:fill_rule -> OCADml.Path2.t list -> t

of_paths ?fill_rule paths

Create a 2d cross-section from a set of closed paths (zero or more complex polygons). A boolean union operation (with `Positive filling rule by default) is performed to combine overlapping polygons and ensure the resulting cross-section is free of intersections.

val of_poly2 : ?fill_rule:fill_rule -> OCADml.Poly2.t -> t

of_poly2 ?fill_rule poly

Create a 2d cross-section from an OCADml polygon. A boolean union operation (with `Positive filling rule by default) is performed to combine overlapping polygons and ensure the resulting cross-section is free of intersections.

val of_poly2s : ?fill_rule:fill_rule -> OCADml.Poly2.t list -> t

of_poly2 ?fill_rule poly

Create a 2d cross-section from a list of OCADml polygons. A boolean union operation (with `Positive filling rule by default) is performed to combine overlapping polygons and ensure the resulting cross-section is free of intersections.

Shapes

val circle : ?fn:int -> float -> t

circle ?fn r

Create a circular cross-section with radius r. fn can be provided to set the number of segments that it should be drawn with, otherwise it will be determined according to the globals governed by OManifold.Quality.

val square : ?center:bool -> OCADml.v2 -> t

square ?center dims

Create a square with the given XY dims. By default it is positioned in the first quadrant, touching the origin. Setting ~center:true will instead centre the shape on the origin. If any dimensions in size are negative, or if all are zero, an empty Manifold.t will be returned.

Booleans

val boolean : op:[ `Add | `Subtract | `Intersect ] -> t -> t -> t

boolean ~op a b

Compute the boolean operation op between the cross-sections a and b.

val batch_boolean : op:[ `Add | `Subtract | `Intersect ] -> t list -> t

batch_boolean ~op cs

Compute the boolean operation op on the list of cross-sections cs. In the case of ~op:`Subtract, the tail is differenced from the head.

val add : t -> t -> t

add a b

Union (logical or) the cross-sections a and b.

val union : t list -> t

union ts

Union (logical or) the list of cross-sections ts.

val sub : t -> t -> t

sub a b

Subtract (logical and not) the cross-section b from the cross-section a.

val difference : t -> t list -> t

difference t d

Subtract (logical and not) the list of cross-sections d from the cross-section t.

val intersect : t -> t -> t

intersect a b

Compute the intersection (logical and) of the cross-sections a and b.

val intersection : t list -> t

intersection ts

Compute the intersection (logical and) of the cross-sections ts. Only the area which is common or shared by all shapes are retained. If ts is empty, an empty cross-section t will result.

val rect_clip : t -> OCADml.Box2.t -> t

rect_clip t rect

Compute the intersection between the cross-section t and an axis-aligned bounding box rect. This operation has much higher performance (O(n) vs O(n3) than the general purpose intersection algorithm used for sets of cross-sections.

Topology

val compose : t list -> t

compose ts

Create a cross-section from a list of cross-sections ts (see union). Unlike Manifold.compose, it isn't necessary that the input shapes are non-overlapping as a clipping operation is performed here.

val decompose : t -> t list

decompose t

Break the cross-section t into a list of topologically disconnected cross-sections, each containing one outline contour with zero or more holes.

Transformations

val translate : OCADml.v2 -> t -> t

translate p t

Move t along the vector p.

val xtrans : float -> t -> t

xtrans x t

Move t by the distance x along the x-axis.

val ytrans : float -> t -> t

ytrans y t

Move t by the distance y along the y-axis.

val rotate : ?about:OCADml.v2 -> float -> t -> t

rotate ?about r t

Rotate the cross-section t around the z-axis through the origin (or the point about if provided) by r (in radians).

val zrot : ?about:OCADml.v2 -> float -> t -> t

zrot ?about r t

Rotate the cross-section t around the z-axis through the origin (or the point about if provided) by r (in radians).

val mirror : OCADml.v2 -> t -> t

mirror ax t

Mirror the cross-seciton t over the arbitrary axis described by the unit form of the vector ax. If the length of ax is zero, an empty cross-section is returned.

val affine : OCADml.Affine2.t -> t -> t

affine m t

Transform the cross-section t with the affine transformation matrix m.

val scale : OCADml.v2 -> t -> t

scale factors t

Scales t by the given factors in xy.

val xscale : float -> t -> t

xscale s t

Scales t by the factor s in the x-dimension.

val yscale : float -> t -> t

yscale s t

Scales t by the factor s in the y-dimension.

val warp : (OCADml.v2 -> OCADml.v2) -> t -> t

warp f t

Map over the vertices of the cross-section t with the function f, followed by a union operation ensuring that the result is free of intersections.

Path simplification and offsetting

val simplify : ?eps:float -> t -> t

simplify ?eps t

Remove vertices from the contours in t that are less than the specified distance eps from an imaginary line that passes through its two adjacent vertices. Near duplicate vertices and collinear points will be removed at lower epsilons, with elimination of line segments becoming increasingly aggressive with larger epsilons.

It is recommended to apply this function following offset, in order to clean up any spurious tiny line segments introduced that do not improve quality in any meaningful way. This is particularly important if further offseting operations are to be performed, which would compound the issue.

val offset : ?join_type:join_type -> ?miter_limit:float -> ?arc_tolerance:float -> delta:float -> t -> t

offset ?join_type ?miter_limit ?arc_tolerance ~delta t

Inflate the contours in the cross-section t by the delta, handling corners according to join_type (default = `Square). Positive delta will cause the expansion of outlining contours to expand, and retraction of inner (hole) contours. Negative deltas will have the opposite effect.

  • miter_limit sets maximum distance in multiples of delta that vertices can be offset from their original positions with before squaring is applied, when the join type is `Miter (default is 2., which is the minimum allowed). See the Clipper2 MiterLimit page for a visual example.
  • arc_tolerance sets the maximum acceptable imperfection for curves drawn (approximated with line segments) for `Round joins (not relevant for other join_types). By default the allowable imprecision is scaled in inverse proportion to the offset delta.

Geometry

val bounds : t -> OCADml.Box2.t

bounds t

Compute the axis-aligned bounding rectangle of all of the cross-section t's vertices.

val area : t -> float

area t

Compute the total area covered by complex polygons making up the cross-section t.

val num_vert : t -> int

num_vert t

The number of vertices in the cross-section t.

val num_contour : t -> int

num_contour t

The number of contours in the cross-section t.

val is_empty : t -> bool

is_empty t

Does the cross-section t contain zero contours?

Conversion

val to_paths : t -> OCADml.Path2.t list

to_paths t

Extract the contours (closed paths) from t, describing zero or more complex polygons. If a list describing a single complex polygon with the its outline at the head, and inner/hole paths in the tail, one should first apply decompose.