Model and entities
The model
Section titled “The model”modlumi.activeModel is the Model the script
runs against. From it you reach everything else:
| Property | Contents |
|---|---|
model.entities |
Elements at the model root |
model.activeEntities |
Elements of the context being edited, such as an open group |
model.selection |
The current selection |
model.definitions |
All group and component definitions |
model.materials |
All materials |
model.activeView |
A view for image export |
Entities
Section titled “Entities”Everything stored in the model is an Entity.
Iterating an Entities collection yields its
elements: edges, faces, groups, component instances and guides. Every entity
has a type property naming its class, so a switch can tell them apart:
const model = modlumi.activeModel;for (const entity of model.entities) { switch (entity.type) { case "Edge": console.log("Edge", entity.length, "m"); break; case "Face": console.log("Face", entity.area, "m²"); break; case "Group": case "ComponentInstance": console.log("Placement", entity.name || entity.definition.name); break; }}instanceof works too, for example entity instanceof modlumi.Face. To get
all elements of one type, use ofType:
const faces = modlumi.activeModel.entities.ofType("Face");console.log(`${faces.length} faces`);Collections have a length, can be iterated, and support at(index),
which counts from the end for negative indices, and toArray(). Iteration
works on a snapshot, so editing the model inside the loop doesn’t change what
the loop visits. Vertices aren’t elements; get them from entities.vertices
or from an edge’s start and end.
Each model entity is represented by one object, so ===, Set and Map
work as identity. Every entity also has an entityId that stays the same
across undo and redo. An edit can delete an entity, for example when a face
is replaced. Check isDeleted or isValid before using an entity you kept
from earlier.
Faces, loops and edges
Section titled “Faces, loops and edges”A Face is bounded by loops: one outerLoop and
one loop per hole. Each Loop lists its edges in
order. The EdgeUse objects in edgeUses
also tell you which way the loop runs along each edge:
for (const face of modlumi.activeModel.entities.ofType("Face")) { const corners = face.outerLoop.edgeUses.map((use) => use.start.position); console.log(`Face with ${corners.length} corners and ${face.loops.length - 1} holes`);}Edges drawn by a curve tool belong to a Curve,
or to an ArcCurve with a center and radius
for arcs and circles. edge.curve returns it, or null.
Groups and components
Section titled “Groups and components”A Group or
ComponentInstance places a
ComponentDefinition in its parent
with a transformation. The definition’s entities use their own local
coordinates. Multiply by the transformation to get coordinates in the parent:
/** * @param {modlumi.Entities} entities * @param {modlumi.Transformation} toWorld */function walk(entities, toWorld, depth = 0) { const indent = " ".repeat(depth); for (const entity of entities) { if (entity.type === "Group" || entity.type === "ComponentInstance") { console.log(indent + (entity.name || entity.definition.name)); walk(entity.definition.entities, toWorld.multiply(entity.transformation), depth + 1); } else if (entity.type === "Edge") { const start = toWorld.multiply(entity.start.position); console.log(`${indent}edge from ${start}`); } }}
walk(modlumi.activeModel.entities, new modlumi.Transformation());Measurements such as edge.length and face.area are in the entity’s own
context; they don’t include the placements above it.
All instances of a component share one definition, so editing the
definition’s entities changes every instance. Renaming a definition renames
it for all instances, while instance.name names only that placement. Groups
have a name of their own too.
Guides
Section titled “Guides”A Guide is a construction point or an infinite
construction line, like the ones the Measure tool places. Guides
don’t form faces. isPoint tells them apart; a guide line has a position
on the line and a direction.
Visibility
Section titled “Visibility”Edges, faces, groups and component instances have hidden and visible
properties for their own hidden flag. Changing them requires an operation:
const model = modlumi.activeModel;model.operation("Hide selected", () => { for (const entity of model.selection) { entity.hidden = true; }});Hiding a group hides everything in it without changing its definition. To
check whether an element is actually visible, including hidden groups above
it, pass its path from the model root to
model.isDrawingElementVisible().
Selection
Section titled “Selection”model.selection is the selection in the
window. Changing it doesn’t need an operation and isn’t part of undo. You
can only select drawing elements in the active editing context:
const model = modlumi.activeModel;model.selection.clear();for (const face of model.activeEntities.ofType("Face")) { if (face.area > 1.0) { model.selection.add(face); }}console.log(`Selected ${model.selection.length} faces larger than 1 m²`);Materials
Section titled “Materials”Material objects have a name and a
color with r, g, b and a components from 0 to 1. Faces have a front
material and a backMaterial; edges, groups and instances have a
material. Each is null when nothing is applied. Scripts can’t create or
edit materials yet.