Skip to content

Model and entities

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

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.

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.

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.

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.

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().

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²`);

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.