skppy.data_structure.entities¶
Geometry, topology, components, and scoped entity builder methods.
An Entities object owns one independent ID scope. The model root and
every ComponentDefinition therefore have separate vertex, edge, face,
annotation, and placement collections. Faces reference loops, loops reference
directed edge uses, and edges reference vertices by ID.
Use the builder methods when creating geometry; they allocate consistent IDs and construct the required topology.
Example
import skppy
model = skppy.new_model()
floor = model.entities.add_face(
[(0, 0, 0), (120, 0, 0), (120, 96, 0), (0, 96, 0)]
)
print(floor.id, len(model.entities.edges)) # one boundary edge per corner
- class skppy.data_structure.entities.ArcCurve[source]
Bases:
objectAn arc-curve entity grouping a circular arc sequence of edges (SUArcCurve).
Arc curves represent circular arcs (including full circles). Legacy files expose mapped geometric parameters when their schema is known. The modern parser currently preserves its unresolved arc-specific payload verbatim and leaves those optional parameters absent.
- id
Unique arc-curve ID.
- Type:
int
- edge_ids
Ordered list of edge IDs approximating the arc.
- Type:
list of int
- center
3-D center position
(x, y, z)in SketchUp inches.- Type:
tuple of float or None
- normal
Axis normal unit vector.
- Type:
tuple of float or None
- radius
Arc radius in SketchUp inches.
- Type:
float or None
- start_angle
Start angle in radians.
- Type:
float or None
- end_angle
End angle in radians.
- Type:
float or None
- raw_arc_payload
Raw TAG_ARC_SPECIFIC_PAYLOAD bytes, preserved when geometric parameter extraction fails.
- Type:
bytes or None
- __init__(id: int = 0, edge_ids: List[int] = <factory>, center: Tuple[float, float, float] | None=None, normal: Tuple[float, float, float] | None=None, radius: float | None = None, start_angle: float | None = None, end_angle: float | None = None, raw_arc_payload: bytes | None = None) None
- class skppy.data_structure.entities.ComponentDefinition[source]
Bases:
objectA reusable named component definition (SUComponentDefinition).
Instances are placed via
Entities.add_instance().- id
Unique definition ID.
- Type:
int
- guid
16-byte GUID blob.
- Type:
bytes
- name
Definition name.
- Type:
str
- description
Optional description.
- Type:
str
- entities
Geometry contained in this definition.
- Type:
Entities
- loaded_from
Path from which the definition was loaded (0x1580).
- Type:
str
- timestamp
Timestamp of last modification (0x1581).
- Type:
int
- modified
Whether the definition has been modified (0x1582).
- Type:
bool
- definition_type
Definition type enum (0x1583).
- Type:
int
- packed_payload
Packed payload blob containing thumbnails (0x1585).
- Type:
bytes or None
- behavior_snap_mode
Snap mode for component behavior (0x1B59).
- Type:
int
- behavior_no_scale_mask
No-scale mask for component behavior (0x1B5A).
- Type:
int
- behavior_snap_enabled
Whether snap is enabled (0x1B5B).
- Type:
bool
- behavior_cuts_opening
Whether the component cuts openings (0x1B5C).
- Type:
bool
- behavior_always_face_camera
Whether the component always faces the camera (0x1B5D).
- Type:
bool
- behavior_shadows_face_sun
Whether shadows face the sun (0x1B5E).
- Type:
bool
- __init__(id: int = 0, guid: bytes = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', name: str = '', description: str = '', entities: Entities = <factory>, loaded_from: str = '', timestamp: int = 0, modified: bool = False, definition_type: int = 0, packed_payload: bytes | None = None, behavior_snap_mode: int = 0, behavior_no_scale_mask: int = 0, behavior_snap_enabled: bool = False, behavior_cuts_opening: bool = False, behavior_always_face_camera: bool = False, behavior_shadows_face_sun: bool = False) None
- class skppy.data_structure.entities.ComponentInstance[source]
Bases:
objectAn instance of a ComponentDefinition (SUComponentInstance).
- id
Unique instance ID within the Entities scope.
- Type:
int
- guid
16-byte GUID that identifies this instance across save/load cycles.
- Type:
bytes
- name
Optional instance name.
- Type:
str or None
- definition_id
ID of the
ComponentDefinitionthis instance references.- Type:
int
- transform
13-float SUTransformation (row-major 4x4 with perspective omitted).
- Type:
list of float
- material_id
Override material applied to all un-materialed faces in the definition, or
None.- Type:
int or None
- layer_id
Owning layer/tag ID.
- Type:
int or None
- __init__(id: int = 0, guid: bytes = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', name: str | None = None, definition_id: int = 0, transform: List[float] = <factory>, material_id: int | None = None, layer_id: int | None = None) None
- class skppy.data_structure.entities.Curve[source]
Bases:
objectA polyline curve grouping a sequence of edges (SUCurve).
Curves are stored as a contiguous range of edge IDs. When is_polygon is
Truethe edges form a closed polygon.- id
Unique curve ID.
- Type:
int
- edge_ids
Ordered list of edge IDs that form the polyline.
- Type:
list of int
- is_polygon
Truewhen the edges form a closed polygon.- Type:
bool
- __init__(id: int = 0, edge_ids: List[int] = <factory>, is_polygon: bool = False) None
- class skppy.data_structure.entities.Edge[source]
Bases:
objectA line segment between two vertices (SUEdge).
- id
Unique edge ID within the Entities scope.
- Type:
int
- start_vertex_id
ID of the start vertex.
- Type:
int
- end_vertex_id
ID of the end vertex.
- Type:
int
- flags
Bitmask of edge flags (e.g. smooth, soft, hidden).
- Type:
int
- curve_id
ID of the parent
Curveif this edge belongs to a polyline, otherwiseNone.- Type:
int or None
- layer_id
Owning layer/tag ID.
- Type:
int or None
- __init__(id: int, start_vertex_id: int, end_vertex_id: int, flags: int = 0, curve_id: int | None = None, layer_id: int | None = None) None
- property is_hidden: bool
Return True when SketchUp marks this edge hidden.
- Returns:
Truewhen the hidden bit is set.- Return type:
bool
- property is_smooth: bool
Return True when SketchUp marks this edge smooth.
- Returns:
Truewhen the smooth bit is set.- Return type:
bool
- property is_soft: bool
Return True when SketchUp marks this edge soft.
- Returns:
Truewhen the soft bit is set.- Return type:
bool
- class skppy.data_structure.entities.EdgeUse[source]
Bases:
objectOne directed edge reference within a face loop (SUEdgeUse).
An edge use records not just which edge is part of a loop, but also the traversal direction. When reversed is
Truethe edge is traversed from its end vertex toward its start vertex.- edge_id
ID of the referenced
Edge.- Type:
int
- reversed
Trueif the edge direction is opposite to the loop winding.- Type:
bool
- __init__(edge_id: int, reversed: bool) None
- class skppy.data_structure.entities.Entities[source]
Bases:
objectContainer for all geometry in a scope (root model or component definition).
Builder API¶
Create vertices, edges, and faces programmatically:
ents = Entities() face = ents.add_face([(0,0,0),(100,0,0),(100,100,0),(0,100,0)])
- vertices, edges, faces
Raw geometric primitives in this scope.
- Type:
list
- component_instances, groups, images
Entity references to component definitions.
- Type:
list
- curves, arc_curves
Edge grouping metadata.
- Type:
list
- guide_points, guide_lines, section_planes
Construction and section entities.
- Type:
list
- texts, linear_dimensions, radial_dimensions
Shared annotation entities, independent of the source SKP container.
- Type:
list
- relationships
Directed references between entities in this scope.
- Type:
list of EntityRelationship
- attribute_dictionaries_by_entity_id
Attribute dictionaries grouped by their owning entity ID.
- Type:
dict
- __init__(vertices: List[Vertex] = <factory>, edges: List[Edge] = <factory>, faces: List[Face] = <factory>, component_instances: List[ComponentInstance] = <factory>, groups: List[Group] = <factory>, images: List[Image] = <factory>, curves: List[Curve] = <factory>, arc_curves: List[ArcCurve] = <factory>, guide_points: List[GuidePoint] = <factory>, guide_lines: List[GuideLine] = <factory>, section_planes: List[SectionPlane] = <factory>, texts: List['Text'] = <factory>, linear_dimensions: List['LinearDimension'] = <factory>, radial_dimensions: List['RadialDimension'] = <factory>, relationships: List['EntityRelationship'] = <factory>, attribute_dictionaries_by_entity_id: Dict[int, List['AttributeDictionary']]=<factory>) None
- add_arc_curve(center: Vertex | Vector3D | Tuple[float, float, float], normal: Vertex | Vector3D | Tuple[float, float, float], radius: float, start_angle: float, end_angle: float, segments: int) ArcCurve[source]
Create a segmented circular arc and its owning arc-curve entity.
Angles are expressed in radians in the arc plane. A span of
2 * picreates a full circle with a duplicated closing vertex, matching SketchUp’s public API representation.
- add_arc_curve_from_edges(edge_ids: Sequence[int], center: Vertex | Vector3D | Tuple[float, float, float], normal: Vertex | Vector3D | Tuple[float, float, float], radius: float, start_angle: float, end_angle: float) ArcCurve[source]
Group existing segmented edges into a circular arc.
This is useful when an arc boundary is shared with faces, such as the four circular seams of a hollow cylinder.
- add_edge(v1: Vertex | int, v2: Vertex | int) Edge[source]
Create an edge between two vertices and add it to this container.
- Parameters:
v1 (Vertex or int) – First vertex (or its ID).
v2 (Vertex or int) – Second vertex (or its ID).
- Returns:
The newly created edge.
- Return type:
Edge
- add_face(points: Sequence[Vertex | Vector3D | Tuple[float, float, float]], material_id: int | None = None, back_material_id: int | None = None) Face[source]
Create a polygon face from an ordered list of corner points.
Vertices and edges are created automatically for each corner. Points may be
Vertexobjects,Vector3Dobjects, or plain(x, y, z)tuples. The face normal is computed using Newell’s method, and a plane equation is stored on the face.- Parameters:
points (list) – Ordered corner positions (minimum 3). Counter-clockwise winding when viewed from the front (outward normal) is the SketchUp convention.
material_id (int, optional) – ID of the front-face material.
back_material_id (int, optional) – ID of the back-face material.
- Returns:
The newly created face.
- Return type:
Face
- Raises:
ValueError – If fewer than three points are supplied.
- add_instance(definition: ComponentDefinition, transform: Transform | None = None, name: str | None = None) ComponentInstance[source]
Place a component definition into this scope as a component instance.
- Parameters:
definition (ComponentDefinition) – The definition to instantiate.
transform (Transform, optional) – Placement transform (position, rotation, scale). Defaults to the identity transform.
name (str, optional) – Display name for this instance.
- Return type:
ComponentInstance
- add_vertex(x: float, y: float, z: float) Vertex[source]
Create a new vertex at the given position and add it to this container.
- Parameters:
x (float) – Position in SketchUp inches.
y (float) – Position in SketchUp inches.
z (float) – Position in SketchUp inches.
- Returns:
The newly created vertex.
- Return type:
Vertex
- prepare_mesh(name: str, material_lookup: Dict[int, 'Material'], inherited_material_id: int | None = None, split_holes_to_ngons: bool = False, opening_positions_by_face_id: Dict[int, List[List[Tuple[float, float, float]]]] | None = None) PreparedMesh[source]
Build a
PreparedMeshfrom this entities scope.All geometry is resolved to plain Python tuples so the caller does not need to know about the SKP TLV format. Positions are in SketchUp inches (definition-local space; no world transform is applied here).
- Parameters:
name (str) – Display name for the resulting mesh (e.g. the definition name, or
"RootGeometry"for root-level geometry).material_lookup (dict) – Mapping from material ID (int) to a
Materialobject. Used to resolve material names and texture tile dimensions for UV computation.inherited_material_id (int, optional) – Effective material from a parent instance or group override, applied to faces that have no front or back material set.
split_holes_to_ngons (bool, optional) – When True, faces with exactly one inner loop are represented as two simple n-gons joined by generated bridge edges. Faces with multiple holes still fall back to triangulation.
opening_positions_by_face_id (dict, optional) – Additional face-hole contours inferred from glued cutting component instances, grouped by source face ID.
- Returns:
All faces from this scope resolved and ready for import.
- Return type:
PreparedMesh
- class skppy.data_structure.entities.Face[source]
Bases:
objectA planar polygon with an outer loop and optional inner loops (SUFace).
- id
Unique face ID within the Entities scope.
- Type:
int
- plane
Plane equation
(a, b, c, d).- Type:
tuple
- outer_loop
Boundary loop for the face exterior.
- Type:
Loop
- inner_loops
Hole loops, if any.
- Type:
list of Loop
- front_material_id, back_material_id
Material IDs assigned to each side.
- Type:
int or None
- front_uv, back_uv
Per-side texture projection data.
- Type:
FaceUVProjection or None
- layer_id
Owning layer/tag ID.
- Type:
int or None
- __init__(id: int, plane: Tuple[float, float, float, float], outer_loop: Loop, inner_loops: List[Loop], front_material_id: int | None = None, back_material_id: int | None = None, front_uv: FaceUVProjection | None = None, back_uv: FaceUVProjection | None = None, layer_id: int | None = None) None
- normal() Vector3D[source]
Return the face normal.
- Returns:
The
(a, b, c)component of the face plane.- Return type:
Vector3D
- resolve_material_mapping(inherited_material_id: int | None = None) Tuple[int | None, FaceUVProjection | None][source]
Resolve the single material and UV mapping used by mesh consumers.
A SketchUp face can have independent front and back appearances, while common polygon meshes expose one material and UV set. The shared policy is front-first: an explicit front material wins, an explicit back material is used only when the front is unpainted, and an inherited material is used only when neither side is painted.
A projection from the opposite side is reusable only when both sides reference the same material. Inherited materials may use either stored projection because neither face side owns an explicit material.
- Parameters:
inherited_material_id (int, optional) – Material supplied by a containing instance or group.
- Returns:
Effective material ID and applicable UV projection.
- Return type:
tuple
- triangulate(entities: Entities) List[Tuple[int, int, int]][source]
Fan-triangulate the outer loop.
- Parameters:
entities (Entities) – The parent entities container (used to resolve edge->vertex mappings).
- Returns:
List of vertex-ID triples forming triangles.
- Return type:
list of (int, int, int)
Notes
This is a simple fan triangulation from the first vertex. Inner loops (holes) are not handled – use
skppy.triangulation.triangulate_face_3d()for proper ear-clipping with hole support.
- class skppy.data_structure.entities.FaceUVProjection[source]
Bases:
objectPer-face texture projection transform parsed from the SKP TLV (tag 0x2715).
transformis a 3x3 row-major affine matrix stored as 9float64values. In observed modern files it maps raw texture-space coordinates to projected face coordinates using row-vector convention:[sx sy 1] = [u_raw v_raw 1] * transform
compute_uv()inverts this matrix, projects the 3-D vertex to the face’s 2-D coordinate pair, then divides by the material texture scale.origin(tag 0x2716) is retained for inspection. Legacy projected textures additionally expose their projection vector throughprojection_direction; modern files observed so far do not need it.See
docs/format/uv_projection.mdfor details.- transform
Nine doubles storing a row-major 3x3 affine UV matrix.
- Type:
list of float
- origin
Raw projection origin retained for diagnostics.
- Type:
tuple of float
- projection_direction
Legacy projection direction. When present, it defines the 2-D basis used before applying the texture matrix instead of the face normal.
- Type:
tuple of float or None
- pins
Exact texture coordinates for control points manipulated with the texture-positioning tool.
- Type:
list of UVPin
- __init__(transform: List[float] = <factory>, origin: Tuple[float, float, float]=(0.0, 0.0, 0.0), projection_direction: Tuple[float, float, float] | None=None, pins: List[UVPin] = <factory>) None
- compute_uv(px: float, py: float, pz: float, x_scale: float, y_scale: float, normal: Tuple[float, float, float] | None = None) Tuple[float, float][source]
Compute
(u, v)for a vertex at local position(px, py, pz).- Parameters:
px – Vertex position in SketchUp inches, definition-local space. Do not apply any world/instance transform before calling this.
py – Vertex position in SketchUp inches, definition-local space. Do not apply any world/instance transform before calling this.
pz – Vertex position in SketchUp inches, definition-local space. Do not apply any world/instance transform before calling this.
x_scale – Texture width in inches (
material.texture.width / 0.0254).y_scale – Texture height in inches (
material.texture.height / 0.0254).normal – Optional face normal used to project the vertex into SketchUp’s 2-D face-local basis before applying the texture transform.
- Returns:
(u, v)texture coordinates.- Return type:
tuple[float, float]
- compute_uvs(positions: List[Tuple[float, float, float]], x_scale: float, y_scale: float, normal: Tuple[float, float, float] | None = None) List[Tuple[float, float]][source]
Compute UV coordinates for multiple local SKP-inch positions.
This is the preferred path for importers because it inverts the stored affine matrix once and projects all corners with NumPy in one batch.
- Parameters:
positions (list of tuple of float) – Vertex positions in definition-local SketchUp inches.
x_scale (float) – Texture width in SketchUp inches.
y_scale (float) – Texture height in SketchUp inches.
normal (tuple of float, optional) – Face normal used for orientation-aware projection.
- Returns:
UV coordinates matching positions order.
- Return type:
list of tuple of float
- inverse_transform() ndarray | None[source]
Return the cached inverse of SketchUp’s UV affine matrix.
- Returns:
Inverse 3x3 matrix, or
Nonewhen the transform is singular.- Return type:
numpy.ndarray or None
- is_singular() bool[source]
Return whether the stored UV transform cannot be inverted.
- Returns:
Truewhen the transform has no stable inverse.- Return type:
bool
- class skppy.data_structure.entities.Group[source]
Bases:
objectA group, which is a special single-use ComponentInstance (SUGroup).
Groups are internally represented as a component definition with a single instance, but are semantically distinct in SketchUp.
- id
Unique group ID within the Entities scope.
- Type:
int
- guid
16-byte GUID.
- Type:
bytes
- name
Optional group name.
- Type:
str or None
- definition_id
ID of the internal
ComponentDefinition.- Type:
int
- transform
13-float SUTransformation.
- Type:
list of float
- material_id
Override material, or
None.- Type:
int or None
- layer_id
Owning layer/tag ID.
- Type:
int or None
- __init__(id: int = 0, guid: bytes = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', name: str | None = None, definition_id: int = 0, transform: List[float] = <factory>, material_id: int | None = None, layer_id: int | None = None) None
- class skppy.data_structure.entities.Image[source]
Bases:
objectAn image entity placed in 3-D space (SUImage).
Images are standalone raster images placed in the model at a specific position and orientation.
- id
Unique image ID within the Entities scope.
- Type:
int
- guid
16-byte GUID.
- Type:
bytes
- name
Optional image name.
- Type:
str or None
- definition_id
ID of the internal
ComponentDefinition.- Type:
int
- transform
13-float SUTransformation.
- Type:
list of float
- material_id
Override material, or
None.- Type:
int or None
- layer_id
Owning layer/tag ID.
- Type:
int or None
- __init__(id: int = 0, guid: bytes = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', name: str | None = None, definition_id: int = 0, transform: List[float] = <factory>, material_id: int | None = None, layer_id: int | None = None) None
- class skppy.data_structure.entities.Loop[source]
Bases:
objectAn ordered, closed sequence of edge uses (SULoop).
A loop defines the boundary of a face. The outer loop winds counter-clockwise when viewed from the front face normal; inner loops (holes) wind clockwise.
- edge_uses
Ordered edge references that form the closed loop.
- Type:
list of EdgeUse
- is_outer
Whether SketchUp marks this as the face’s outer boundary.
- Type:
bool
- is_convex
Legacy convexity cache.
Nonewhen the source format omits it.- Type:
bool or None
- __init__(edge_uses: List[EdgeUse] = <factory>, is_outer: bool = False, is_convex: bool | None = None) None
- vertex_ids(edge_map: Dict[int, Tuple[int, int]]) List[int][source]
Resolve edge uses to an ordered list of vertex IDs.
- Parameters:
edge_map (dict) – Mapping of
edge_id -> (start_vertex_id, end_vertex_id).- Returns:
Vertex IDs in loop traversal order. Edges missing from edge_map are silently skipped.
- Return type:
list of int
- class skppy.data_structure.entities.UVPin[source]
Bases:
objectExact texture control point stored for a face projection.
texture_positionis in raw texture-space inches andmodel_positionis the corresponding point in the face’s projected 2-D coordinate system. The physical texture scale converts the former to the normalized UV coordinates used by renderers.- __init__(texture_position: Vector2D = <factory>, model_position: Vector2D = <factory>) None
- class skppy.data_structure.entities.Vertex[source]
Bases:
objectA 3-D point in an Entities scope (SUVertex).
Vertices are the lowest-level geometry primitive. Edges and faces reference vertices by their integer id.
- id
Unique vertex ID within the Entities scope.
- Type:
int
- position
Position in SketchUp inches.
- Type:
Vector3D
- __init__(id: int, position: Vector3D) None