Skip to content

Commit 2bf9089

Browse files
committed
feat(core): extract CAD/CADPort annotations into flattened DAE variables
1 parent 40e7a2c commit 2bf9089

3 files changed

Lines changed: 67 additions & 7 deletions

File tree

packages/core/src/compiler/modelica/annotation.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,5 +172,21 @@ class Annotation
172172
String text;
173173
end Choice;
174174
175+
// CAD Integration
176+
177+
record CAD
178+
String uri "URI to the STEP or GLTF file";
179+
Real scale[3] = {1, 1, 1};
180+
Real position[3] = {0, 0, 0};
181+
Real rotation[4] = {0, 0, 0, 1} "Quaternion";
182+
end CAD;
183+
184+
record CADPort
185+
String feature "Name of the CAD feature (e.g., face, edge, vertex) to mate with";
186+
Real offsetScale[3] = {1, 1, 1};
187+
Real offsetPosition[3] = {0, 0, 0};
188+
Real offsetRotation[4] = {0, 0, 0, 1};
189+
end CADPort;
190+
175191
end Annotation;
176192
`;

packages/core/src/compiler/modelica/dae.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2094,6 +2094,8 @@ export abstract class ModelicaVariable extends ModelicaPrimaryExpression {
20942094
arrayDimensions: number[] | null;
20952095
/** Clock domain index (undefined = continuous time). */
20962096
clockDomain?: number | undefined;
2097+
/** Extracted CAD / 3D annotations (as raw string or JSON), e.g. "CAD(uri=\"...\")" */
2098+
cadAnnotationString: string | null;
20972099

20982100
constructor(
20992101
name: string,
@@ -2121,6 +2123,7 @@ export abstract class ModelicaVariable extends ModelicaPrimaryExpression {
21212123
this.arrayDimensions = null;
21222124
/** Clock domain index (undefined = continuous time). */
21232125
this.clockDomain = undefined;
2126+
this.cadAnnotationString = null;
21242127
}
21252128

21262129
override get hash(): string {
@@ -2158,7 +2161,8 @@ export class ModelicaBooleanVariable extends ModelicaVariable {
21582161
return this.attributes.get("start") ?? null;
21592162
}
21602163

2161-
override get toJSON(): string {
2164+
override get toJSON(): JSONValue {
2165+
if (this.cadAnnotationString) return { name: this.name, cad: this.cadAnnotationString };
21622166
return this.name;
21632167
}
21642168

@@ -2201,7 +2205,8 @@ export class ModelicaIntegerVariable extends ModelicaVariable {
22012205
return this.attributes.get("start") ?? null;
22022206
}
22032207

2204-
override get toJSON(): string {
2208+
override get toJSON(): JSONValue {
2209+
if (this.cadAnnotationString) return { name: this.name, cad: this.cadAnnotationString };
22052210
return this.name;
22062211
}
22072212

@@ -2256,7 +2261,8 @@ export class ModelicaRealVariable extends ModelicaVariable {
22562261
return this.attributes.get("stateSelect") ?? null;
22572262
}
22582263

2259-
override get toJSON(): string {
2264+
override get toJSON(): JSONValue {
2265+
if (this.cadAnnotationString) return { name: this.name, cad: this.cadAnnotationString };
22602266
return this.name;
22612267
}
22622268

@@ -2299,7 +2305,8 @@ export class ModelicaStringVariable extends ModelicaVariable {
22992305
return this.attributes.get("start") ?? null;
23002306
}
23012307

2302-
override get toJSON(): string {
2308+
override get toJSON(): JSONValue {
2309+
if (this.cadAnnotationString) return { name: this.name, cad: this.cadAnnotationString };
23032310
return this.name;
23042311
}
23052312

@@ -2322,7 +2329,8 @@ export class ModelicaExpressionVariable extends ModelicaVariable {
23222329
return visitor.visitExpressionVariable(this, argument);
23232330
}
23242331

2325-
override get toJSON(): string {
2332+
override get toJSON(): JSONValue {
2333+
if (this.cadAnnotationString) return { name: this.name, cad: this.cadAnnotationString };
23262334
return this.name;
23272335
}
23282336

@@ -2345,7 +2353,8 @@ export class ModelicaClockVariable extends ModelicaVariable {
23452353
return visitor.visitClockVariable(this, argument);
23462354
}
23472355

2348-
override get toJSON(): string {
2356+
override get toJSON(): JSONValue {
2357+
if (this.cadAnnotationString) return { name: this.name, cad: this.cadAnnotationString };
23492358
return this.name;
23502359
}
23512360

@@ -2414,7 +2423,8 @@ export class ModelicaEnumerationVariable extends ModelicaVariable {
24142423
return this.attributes.get("start") ?? null;
24152424
}
24162425

2417-
override get toJSON(): string {
2426+
override get toJSON(): JSONValue {
2427+
if (this.cadAnnotationString) return { name: this.name, cad: this.cadAnnotationString };
24182428
return this.name;
24192429
}
24202430

@@ -4270,6 +4280,7 @@ export class ModelicaDAEPrinter extends ModelicaDAEVisitor<never> {
42704280
variable.expression.accept(this);
42714281
}
42724282
if (variable.description) this.out.write(' "' + variable.description + '"');
4283+
if (variable.cadAnnotationString) this.out.write(" annotation(" + variable.cadAnnotationString + ")");
42734284
this.out.write(";\n");
42744285
}
42754286

packages/core/src/compiler/modelica/flattener.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,6 +1440,39 @@ export class ModelicaFlattener extends ModelicaModelVisitor<[string, ModelicaDAE
14401440
}
14411441

14421442
if (variable) {
1443+
// Extract CAD and CADPort annotations
1444+
const formatCADAnnotation = (modName: string, modArg: { modificationArguments: unknown[] }): string => {
1445+
const parts: string[] = [];
1446+
for (const arg of modArg.modificationArguments) {
1447+
if (arg instanceof ModelicaElementModification && arg.name) {
1448+
const expr = arg.expression;
1449+
if (expr instanceof ModelicaStringLiteral) parts.push(`${arg.name}="${expr.value}"`);
1450+
else if (expr instanceof ModelicaRealLiteral || expr instanceof ModelicaIntegerLiteral)
1451+
parts.push(`${arg.name}=${expr.value}`);
1452+
else if (expr instanceof ModelicaBooleanLiteral) parts.push(`${arg.name}=${expr.value ? "true" : "false"}`);
1453+
else if (expr instanceof ModelicaArray) {
1454+
const vals = expr.elements
1455+
.map((e) => (e instanceof ModelicaRealLiteral || e instanceof ModelicaIntegerLiteral ? e.value : 0))
1456+
.join(", ");
1457+
parts.push(`${arg.name}={${vals}}`);
1458+
}
1459+
}
1460+
}
1461+
return `${modName}(${parts.join(", ")})`;
1462+
};
1463+
1464+
if (node.annotations && Array.isArray(node.annotations)) {
1465+
const cadAnnotation = node.annotations.find((a) => a.name === "CAD");
1466+
if (cadAnnotation instanceof ModelicaClassInstance && cadAnnotation.modification) {
1467+
variable.cadAnnotationString = formatCADAnnotation("CAD", cadAnnotation.modification);
1468+
} else {
1469+
const cadPortAnnotation = node.annotations.find((a) => a.name === "CADPort");
1470+
if (cadPortAnnotation instanceof ModelicaClassInstance && cadPortAnnotation.modification) {
1471+
variable.cadAnnotationString = formatCADAnnotation("CADPort", cadPortAnnotation.modification);
1472+
}
1473+
}
1474+
}
1475+
14431476
// Set flow/stream prefix for connector variables
14441477
if (node.flowPrefix === ModelicaFlow.FLOW) variable.flowPrefix = "flow";
14451478
else if (node.flowPrefix === ModelicaFlow.STREAM) variable.flowPrefix = "stream";

0 commit comments

Comments
 (0)