Speckle provides a rich set of geometry types that work across all platforms. All geometry objects inherit from Base and implement common interfaces for properties like units, area, and length.
Copy
from specklepy.objects.geometry import Point, Line, Mesh, Polylinefrom specklepy.objects import Base# All geometry are Base objectspoint = Point(x=1.0, y=2.0, z=3.0)print(isinstance(point, Base)) # Trueprint(point.speckle_type) # "Objects.Geometry.Point"
from specklepy.objects.geometry import Polyline, Pointdef polyline_from_points(points): """Create a Polyline from a list of Point objects.""" coords = [] for point in points: coords.extend([point.x, point.y, point.z]) polyline = Polyline(value=coords) if points: polyline.units = points[0].units return polyline# Use itpoints = [ Point(x=0, y=0, z=0), Point(x=5, y=0, z=0), Point(x=5, y=5, z=0), Point(x=0, y=5, z=0),]polyline = polyline_from_points(points)
Mesh face format: Each face starts with vertex count, followed by vertex indices.
[3, 0, 1, 2] = triangle with vertices 0, 1, 2.
[4, 0, 1, 2, 3] = quad with vertices 0, 1, 2, 3.
from specklepy.objects.geometry import Meshimport mathdef create_cylinder(radius, height, segments=16): """Create a cylindrical mesh.""" vertices = [] faces = [] # Bottom circle vertices for i in range(segments): angle = (i / segments) * 2 * math.pi x = radius * math.cos(angle) y = radius * math.sin(angle) vertices.extend([x, y, 0]) # Top circle vertices for i in range(segments): angle = (i / segments) * 2 * math.pi x = radius * math.cos(angle) y = radius * math.sin(angle) vertices.extend([x, y, height]) # Side faces (quads) for i in range(segments): next_i = (i + 1) % segments faces.extend([ 4, # Quad i, # Bottom current next_i, # Bottom next next_i + segments, # Top next i + segments, # Top current ]) mesh = Mesh(vertices=vertices, faces=faces) mesh.units = "m" mesh.name = "Cylinder" return mesh# Use itcylinder = create_cylinder(radius=5, height=10, segments=32)print(f"Cylinder has {cylinder.vertices_count} vertices")
Complex objects often have a displayValue - simplified geometry for visualization:
Copy
from specklepy.objects import Basefrom specklepy.objects.geometry import Mesh# A parametric objectcolumn = Base()column.speckle_type = "Objects.Structural.Column"column.height = 3.0column.profile = "HE300A"# Add display geometrycolumn.displayValue = Mesh( vertices=[...], # Mesh representing the column faces=[...])column.displayValue.units = "m"# Viewers will show the mesh even if they don't understand "Structural.Column"
Always provide displayValue for custom objects - it ensures they’re visible in Speckle viewers even without native support.
from specklepy.objects.geometry import Polyline, Pointdef simplify_polyline(polyline, tolerance=0.1): """Remove points that don't significantly change direction.""" points = polyline.get_points() if len(points) <= 2: return polyline # Can't simplify further simplified = [points[0]] # Always keep first point for i in range(1, len(points) - 1): prev = simplified[-1] curr = points[i] next_pt = points[i + 1] # Calculate distance from current point to line between prev and next # If distance > tolerance, keep the point # (Simplified distance calculation) dist = abs( (next_pt.x - prev.x) * (prev.y - curr.y) - (prev.x - curr.x) * (next_pt.y - prev.y) ) / prev.distance_to(next_pt) if dist > tolerance: simplified.append(curr) simplified.append(points[-1]) # Always keep last point # Build new polyline coords = [] for p in simplified: coords.extend([p.x, p.y, p.z]) result = Polyline(value=coords) result.units = polyline.units return result