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: object

An 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: object

A 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: object

An 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 ComponentDefinition this 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: object

A polyline curve grouping a sequence of edges (SUCurve).

Curves are stored as a contiguous range of edge IDs. When is_polygon is True the 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

True when 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: object

A 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 Curve if this edge belongs to a polyline, otherwise None.

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:

True when the hidden bit is set.

Return type:

bool

property is_smooth: bool

Return True when SketchUp marks this edge smooth.

Returns:

True when the smooth bit is set.

Return type:

bool

property is_soft: bool

Return True when SketchUp marks this edge soft.

Returns:

True when the soft bit is set.

Return type:

bool

class skppy.data_structure.entities.EdgeUse[source]

Bases: object

One 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 True the edge is traversed from its end vertex toward its start vertex.

edge_id

ID of the referenced Edge.

Type:

int

reversed

True if 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: object

Container 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 * pi creates 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 Vertex objects, Vector3D objects, 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 PreparedMesh from 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 Material object. 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: object

A 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: object

Per-face texture projection transform parsed from the SKP TLV (tag 0x2715).

transform is a 3x3 row-major affine matrix stored as 9 float64 values. 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 through projection_direction; modern files observed so far do not need it.

See docs/format/uv_projection.md for 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 None when the transform is singular.

Return type:

numpy.ndarray or None

is_singular() bool[source]

Return whether the stored UV transform cannot be inverted.

Returns:

True when the transform has no stable inverse.

Return type:

bool

class skppy.data_structure.entities.Group[source]

Bases: object

A 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: object

An 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: object

An 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. None when 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: object

Exact texture control point stored for a face projection.

texture_position is in raw texture-space inches and model_position is 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: object

A 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