# Shape3D

A 3D geometric primitive, e.g., Line, LineSegment, Polyline, Plane, Rectangle, Circle, Box, Sphere, Cylinder, Cone, etc. The pose (position and orientation) of most shapes is controlled by a 3D Transform. Such shapes have a defined default pose, often centered around the origin, from which the pose transform is used to move and rotate the shape into the desired pose in 3D space. When creating a shape, the pose transform is not allowed to change the size of the shape (the size is set by specific parameters), that is, the pose transform must be of rigid, rotation or translation type. Shapes can be transformed using more general transformations, however the type of transformations allowed is specific to each shape and limited to make sure the shape stays within its class. For example, a non-uniform scaling will turn a circle into an ellipse and is thus not allowed. The Shape3D object is represented in mathematical analytical form. Operations such as finding intersection points, distances and transforming the geometric primitive are for this reason efficiently computed.

Shape3D.clone(inputShape)
  Argument:

    - inputShape (`Shape3D`)

  Return type:

    `Shape3D`

  Create an independent copy of the shape. If the input is a vector of shapes, the output is a vector of shapes.

Shape3D.contains(shape3d, point)
  Arguments:

    - shape3d (`Shape3D`)

    - point (`Point`)

  Return type:

    `boolean`

  Returns true if the supplied 3D point is within the shape. Returns false for all shapes with zero volume. If more than one shape is provided true is returned if the point is inside any of the shapes. If more than one point is provided a vector is returned with one value for each input point.

Shape3D.countInside(shape3d, points)
  Arguments:

    - shape3d (`Shape3D`)

    - points (`Point`)

  Return type:

    `int`

  Counts the number of points that fall within the shape.

Shape3D.createBox(sizeX, sizeY, sizeZ, poseTransform)
  Arguments:

    - sizeX (`float`)

    - sizeY (`float`)

    - sizeZ (`float`)

    - poseTransform (`Transform`)

  Return type:

    `Shape3D`

  Create box(es) in 3D space. Unless transformed, the box is centered on the origin.

Shape3D.createCircle(radius, poseTransform)
  Arguments:

    - radius (`float`)

    - poseTransform (`Transform`)

  Return type:

    `Shape3D`

  Create 2D circle(s) embedded in 3D space. Unless transformed, the circle is created in the xy-plane, centered on the origin.

Shape3D.createCone(radius, heightZ, poseTransform)
  Arguments:

    - radius (`float`)

    - heightZ (`float`)

    - poseTransform (`Transform`)

  Return type:

    `Shape3D`

  Create cone(s) in 3D space. Unless transformed, the z-axis is the symmetry axis of the cone, the base circle is centered on the origin and the apex is at the point (0, 0, heightZ).

Shape3D.createCylinder(radius, heightZ, poseTransform)
  Arguments:

    - radius (`float`)

    - heightZ (`float`)

    - poseTransform (`Transform`)

  Return type:

    `Shape3D`

  Create cylinder(s) in 3D space. Unless transformed, the cylinder is centered on the origin with the z-axis as symmetry line.

Shape3D.createEllipse(radiusX, radiusY, poseTransform)
  Arguments:

    - radiusX (`float`)

    - radiusY (`float`)

    - poseTransform (`Transform`)

  Return type:

    `Shape3D`

  Create 2D ellipse(s) embedded in 3D space. Unless transformed, the ellipse is created in the xy-plane, centered on the origin.

Shape3D.createEllipticCylinder(radiusX, radiusY, heightZ, poseTransform)
  Arguments:

    - radiusX (`float`)

    - radiusY (`float`)

    - heightZ (`float`)

    - poseTransform (`Transform`)

  Return type:

    `Shape3D`

  Create elliptic cylinder(s) in 3D space. Unless transformed, the elliptic cylinder is centered on the origin centered on the z-axis.

Shape3D.createLine(point1, point2)
  Arguments:

    - point1 (`Point`)

    - point2 (`Point`)

  Return type:

    `Shape3D`

  Create line(s) in 3D, passing through the two given 3D points.

Shape3D.createLineSegment(point1, point2)
  Arguments:

    - point1 (`Point`)

    - point2 (`Point`)

  Return type:

    `Shape3D`

  Create line segment(s) in 3D between the two given 3D points.

Shape3D.createPlane(nx, ny, nz, distance)
  Arguments:

    - nx (`float`)

    - ny (`float`)

    - nz (`float`)

    - distance (`float`)

  Return type:

    `Shape3D`

  Create plane(s) in 3D. A plane is defined by its normal vector (vector perpendicular to the plane) and a distance from the world origin (Hesse normal form). For example, an XY-aligned plane at Z = 5 is constructed using Shape3D.createPlane(0, 0, 1, 5). The distance is signed and measured from the origin along the normal. A plane where the normal points from the plane towards the origin has a negative distance.

Shape3D.createPlaneFromPoints(point1, point2, point3)
  Arguments:

    - point1 (`Point`)

    - point2 (`Point`)

    - point3 (`Point`)

  Return type:

    `Shape3D`

  Create plane(s) in 3D containing the three given 3D points. The three points must span a plane, i.e., they must not be distributed along a line.

Shape3D.createPolygon(points)
  Argument:

    - points (`Point`)

  Return type:

    `Shape3D`

  Create a 2D closed polygon embedded in 3D space. If the points are not in a plane, the points are projected onto the best fitting plane. At least three points are required.

Shape3D.createPolyline(points)
  Argument:

    - points (`Point`)

  Return type:

    `Shape3D`

  Create a full 3D polyline. Corners can be placed freely in 3D, however, a closed surface for a general 3D polyline would be ambiguous and thus this shape can not be closed. Use the 3D polygon for closed shapes.

Shape3D.createRectangle(sizeX, sizeY, poseTransform)
  Arguments:

    - sizeX (`float`)

    - sizeY (`float`)

    - poseTransform (`Transform`)

  Return type:

    `Shape3D`

  Create 2D rectangle(s) embedded in 3D space. Unless transformed, the rectangle is created in the xy-plane, centered on the origin.

Shape3D.createSphere(radius, poseTransform)
  Arguments:

    - radius (`float`)

    - poseTransform (`Transform`)

  Return type:

    `Shape3D`

  Create sphere(s) in 3D space. Unless transformed, the sphere is centered on the origin.

Shape3D.cropLine(line, box)
  Arguments:

    - line (`Shape3D`)

    - box (`Shape3D`)

  Return type:

    `Shape3D`

  Returns the part of line(s) within box(es) as new line segment(s). If the line does not intersect the box, nil is returned.

Shape3D.fitLine(points, mode, marginType, margin, iterations)
  Arguments:

    - points (`Point`)

    - mode (`enum`)

    - marginType (`enum`)

    - margin (`float`)

    - iterations (`int`)

  Return type:

    `Shape3D`

  Fit a 3D line to a set of 3D-points. Different fitting and outlier handling modes are available.

  Fitting mode may be any of: LEASTSQUARES - Ordinary least squares, fast but not robust against outliers. RANSAC - Outlier rejection by random sampling and consensus. The trade-off between speed and robustness can be adjusted using an iteration parameter. TRIMMED - Two stages of least squares fitting with outlier rejection between the stages. Performance is in general in between RANSAC and least squares with respect to robustness and speed.

  For RANSAC and trimmed modes, outliers are specified with a margin parameter in one of the following ways: ABSOLUTE - Absolute outlier margin, points with a distance larger than the specified distance from the line are treated as outliers. RANK - Defines the fraction of points to treat as inlier points. For example, a rank margin of 0.7 means that the best 70% of all points are included and the rest are ignored as outliers. If there are additional points close to the margin, those will also be included such that the final inlier fraction may be higher.

Shape3D.fitPlane(points, mode, marginType, margin, iterations)
  Arguments:

    - points (`Point`)

    - mode (`enum`)

    - marginType (`enum`)

    - margin (`float`)

    - iterations (`int`)

  Return type:

    `Shape3D`

  Fit a plane shape to a set of 3D-points. Different fitting and outlier handling modes are available.

  Fitting mode may be any of: LEASTSQUARES - Ordinary least squares, fast but not robust against outliers. RANSAC - Outlier rejection by random sampling and consensus. The trade-off between speed and robustness can be adjusted using an iteration parameter. TRIMMED - Two stages of least squares fitting with outlier rejection between the stages. Performance is in general in between RANSAC and least squares with respect to robustness and speed.

  For RANSAC and trimmed modes, outliers are specified with a margin parameter in one of the following ways: ABSOLUTE - Absolute outlier margin, points with a distance larger than the specified distance from the plane are treated as outliers. RANK - Defines the fraction of points to treat as inlier points. For example, a rank margin of 0.7 means that the best 70% of all points are included and the rest are ignored as outliers. If there are additional points close to the margin, those will also be included such that the final inlier fraction may be higher.

Shape3D.getArea(shape3d)
  Argument:

    - shape3d (`Shape3D`)

  Return type:

    `float`

  Returns the total surface area of the shape(s). For flat shapes, e.g., a rectangle, circle or ellipse in 3D space, only one side is counted.

Shape3D.getBoundingBox(shape3d)
  Argument:

    - shape3d (`Shape3D`)

  Return type:

    `Shape3D`

  Returns the smallest axis aligned box(es) that encloses the shape(s).

Shape3D.getBounds(shape)
  Argument:

    - shape (`Shape3D`)

  Return type:

    `float`

  Get the bounds of the shape as individual values.

Shape3D.getBoxParameters(box)
  Argument:

    - box (`Shape3D`)

  Return type:

    `float`

  Get the size and pose of the 3D box(es).

Shape3D.getCenterOfGravity(shape3d)
  Argument:

    - shape3d (`Shape3D`)

  Return type:

    `Point`

  Returns the center(s) of gravity of the shape(s). Returns nil for invalid shapes and for shapes with infinite size.

Shape3D.getCircleParameters(circle)
  Argument:

    - circle (`Shape3D`)

  Return type:

    `float`

  Get the radius and pose of the 3D circle(s).

Shape3D.getClosestSurfacePoint(shape3d, point)
  Arguments:

    - shape3d (`Shape3D`)

    - point (`Point`)

  Return type:

    `Point`

  Returns the point on the shape surface (or edge) closest to the probe point. If there are more than one shape provided the closest point on any shape surface is returned. If there are more than one point provided one point is returned for each input point.

Shape3D.getConeApex(shape)
  Argument:

    - shape (`Shape3D`)

  Return type:

    `Point`

  Returns the position(s) of the tip of the cone(s). Together with getCenterOfGravity, two points defining the direction of the cone can be found.

Shape3D.getConeParameters(cone)
  Argument:

    - cone (`Shape3D`)

  Return type:

    `float`

  Get the radius, height and pose of a cone.

Shape3D.getCylinderParameters(cylinder)
  Argument:

    - cylinder (`Shape3D`)

  Return type:

    `float`

  Get the radius, height and pose of a cylinder.

Shape3D.getEllipseParameters(ellipse)
  Argument:

    - ellipse (`Shape3D`)

  Return type:

    `float`

  Get the radii and pose transform of the 3D ellipse(s).

Shape3D.getEllipticCylinderParameters(ellipticCylinder)
  Argument:

    - ellipticCylinder (`Shape3D`)

  Return type:

    `float`

  Get the radii, height and pose of an elliptic cylinder.

Shape3D.getIntersectionAngle(shape1, shape2)
  Arguments:

    - shape1 (`Shape3D`)

    - shape2 (`Shape3D`)

  Return type:

    `float`

  Get the sharpest angle between two flat Shape3D shapes (circle, rectangle, ellipse in 3D space, etc.), 3D lines, 3D line segments or combination thereof. The shapes do not need to intersect. The angle is in the range 0 to pi/2 where zero indicates parallel planes or lines. Shapes lying in orthogonal planes result in the angle pi/2. Nil is returned if either argument is not a flat shape or a line.

Shape3D.getIntersectionLine(shape1, shape2)
  Arguments:

    - shape1 (`Shape3D`)

    - shape2 (`Shape3D`)

  Return type:

    `Shape3D`

  Returns the intersection line of two planes.

Shape3D.getIntersectionPoints(shape1, shape2)
  Arguments:

    - shape1 (`Shape3D`)

    - shape2 (`Shape3D`)

  Return type:

    `Point`

  Returns the intersection points of two shapes. One of the shapes must be a line or a line segment.

Shape3D.getLineParameters(line)
  Argument:

    - line (`Shape3D`)

  Return type:

    `Point`

  Get two 3D points on the line(s). Note that these two points may not be the same points used for creating a line using the createLine() function as the line representation is normalized internally.

Shape3D.getLineSegmentParameters(lineSegment)
  Argument:

    - lineSegment (`Shape3D`)

  Return type:

    `Point`

  Get the 3D end points of the line segment(s).

Shape3D.getPlaneDistance(shape, referencePlane)
  Arguments:

    - shape (`Shape3D`)

    - referencePlane (`Shape3D`)

  Return type:

    `float`

  Returns the minimum and maximum distance(s) from all points on the shape(s) to the reference plane(s). Distances are measured orthogonal to the reference plane(s). The query shape should have finite size.

Shape3D.getPlaneParameters(plane)
  Argument:

    - plane (`Shape3D`)

  Return type:

    `float`

  Get the parameters of the plane(s) (normal vector plus distance). The distance is signed and measured from the origin along the normal. A plane where the normal points from the plane towards the origin has a negative distance.

Shape3D.getPlanePoints(shape, points2d)
  Arguments:

    - shape (`Shape`)

    - points2d (`Point`)

  Return type:

    `Point`

  Returns the point(s) on the plane at the given x,y-coordinate(s).

Shape3D.getPolygonParameters(polygon)
  Argument:

    - polygon (`Shape3D`)

  Return type:

    `Point`

  Get the points defining the polygon.

Shape3D.getPolylineParameters(polyline)
  Argument:

    - polyline (`Shape3D`)

  Return type:

    `Point`

  Get the points defining the polyline.

Shape3D.getRectangleParameters(rectangle)
  Argument:

    - rectangle (`Shape3D`)

  Return type:

    `float`

  Get the size and pose of the 3D rectangle(s).

Shape3D.getSphereParameters(sphere)
  Argument:

    - sphere (`Shape3D`)

  Return type:

    `float`

  Get the radius and position of the sphere.

Shape3D.getType(shape3d)
  Argument:

    - shape3d (`Shape3D`)

  Return type:

    `enum`

  Get the shape(s) type(s).

Shape3D.getVolume(shape3d)
  Argument:

    - shape3d (`Shape3D`)

  Return type:

    `float`

  Returns the volume of the shape(s).

Shape3D.isClosed(shape3d)
  Argument:

    - shape3d (`Shape3D`)

  Return type:

    `boolean`

  Returns true if the shape(s) has/have no endpoints and encloses an area.

Shape3D.isZeroVolume(shape3d)
  Argument:

    - shape3d (`Shape3D`)

  Return type:

    `boolean`

  Returns true if the shape(s) type in general has no volume, such as for 2D shapes in 3D space.

Shape3D.projectZ(shape)
  Argument:

    - shape (`Shape3D`)

  Return type:

    `Shape`

  Projects one or more Shape3D orthogonally onto the plane described by z = 0. Returns the result as one or more Shape2D together with the minimum and maximum z-values encountered. Lines, line segments, circles, ellipses, boxes, rectangles, spheres, polygons and polylines are supported.

Shape3D.rotateX(shape, rotationAngle, rotationCenter)
  Arguments:

    - shape (`Shape3D`)

    - rotationAngle (`float`)

    - rotationCenter (`Point`)

  Return type:

    `Shape3D`

  Rotate the shape(s) around an axis parallel to the world x-axis. The rotation center is optional. If not provided, the nominal center of the shape is used. For most shapes, this is the same point as the center of gravity. For cones, the nominal center is the center of the base circle. For lines and planes, the nominal center is the point in the shape closest to the origin.

Shape3D.rotateY(shape, rotationAngle, rotationCenter)
  Arguments:

    - shape (`Shape3D`)

    - rotationAngle (`float`)

    - rotationCenter (`Point`)

  Return type:

    `Shape3D`

  Rotate the shape(s) around an axis parallel to the world y-axis. The rotation center is optional. If not provided, the nominal center of the shape is used. For most shapes, this is the same point as the center of gravity. For cones, the nominal center is the center of the base circle. For lines and planes, the nominal center is the point in the shape closest to the origin.

Shape3D.rotateZ(shape, rotationAngle, rotationCenter)
  Arguments:

    - shape (`Shape3D`)

    - rotationAngle (`float`)

    - rotationCenter (`Point`)

  Return type:

    `Shape3D`

  Rotate the shape(s) around an axis parallel to the world z-axis. The rotation center is optional. If not provided, the nominal center of the shape is used. For most shapes, this is the same point as the center of gravity. For cones, the nominal center is the center of the base circle. For lines and planes, the nominal center is the point in the shape closest to the origin.

Shape3D.toLine(shape3d)
  Argument:

    - shape3d (`Shape3D`)

  Return type:

    `Shape3D`

  Extends line segment(s) to the the infinite line type.

Shape3D.toPixelRegion(shape, referenceImage, fill)
  Arguments:

    - shape (`Shape3D`)

    - referenceImage (`Image`)

    - fill (`boolean`)

  Return type:

    `Image.PixelRegion`

  Projects the convex hull of a Shape3D (except polyLine) onto the plane z = 0 (in world coordinates) and creates the corresponding pixel region. The minimum and maximum world coordinate extent of the convex hull in the z-direction are returned. The reference image defines the pixel coordinate system to be used for the PixelRegion.

Shape3D.toPlane(shape3d)
  Argument:

    - shape3d (`Shape3D`)

  Return type:

    `Shape3D`

  Returns the plane(s) with a flat shape span, such as rectangles, circles and polygons. Not defined for a line type shape.

Shape3D.toPolygon(shape, epsilon, maxPoints)
  Arguments:

    - shape (`Shape3D`)

    - epsilon (`float`)

    - maxPoints (`int`)

  Return type:

    `Shape3D`

  Approximates flat closed shape(s) in 3D as polygon(s).

Shape3D.toString(shape3d)
  Argument:

    - shape3d (`Shape3D`)

  Return type:

    `string`

  Get a user-friendly string description of the 3D shape.

Shape3D.transform(shape3d, transform)
  Arguments:

    - shape3d (`Shape3D`)

    - transform (`Transform`)

  Return type:

    `Shape3D`

  Transforms a single shape or a vector of shapes according to the supplied transform. The transform must not change the type of the geometric primitive, e.g., it is not possible to transform a sphere using an affine transform as the result may not be a sphere anymore. The pose transform of shapes are kept as non-mirroring rigid transforms, made to always generate a right-handed orthonormal local coordinate system. Transforming a shape with a similarity transform will decompose the transform and apply the scaling component directly to the size of the shape. Similarly, a transform containing a mirroring component will be reformulated to get the mirroring aligned with a symmetry plane of the shape, where it has no effect on the shape and will be removed. Thus the shape will be correctly transformed, however fetching the pose transform of a shape may not return the transform used to transform the shape.

Shape3D.translate(shape3d, translationX, translationY, translationZ)
  Arguments:

    - shape3d (`Shape3D`)

    - translationX (`float`)

    - translationY (`float`)

    - translationZ (`float`)

  Return type:

    `Shape3D`

  Translate the shape(s), i.e., shift it along the x,y,z directions.