Skip to content

Commit eefb794

Browse files
implement label overwrites for occt dimensions, which allow expression evaluations.
1 parent ef0178b commit eefb794

File tree

2 files changed

+86
-4
lines changed

2 files changed

+86
-4
lines changed

packages/dev/occt/lib/api/inputs/occ-inputs.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7041,7 +7041,7 @@ export namespace OCCT {
70417041
direction: Base.Vector3 = [0, 1, 0];
70427042
}
70437043
export class SimpleLinearLengthDimensionDto {
7044-
constructor(start?: Base.Point3, end?: Base.Point3, direction?: Base.Vector3, offsetFromPoints?: number, crossingSize?: number, labelSuffix?: string, labelSize?: number, labelOffset?: number, labelRotation?: number, arrowType?: dimensionEndTypeEnum, arrowSize?: number, arrowAngle?: number, arrowsFlipped?: boolean, labelFlipHorizontal?: boolean, labelFlipVertical?: boolean) {
7044+
constructor(start?: Base.Point3, end?: Base.Point3, direction?: Base.Vector3, offsetFromPoints?: number, crossingSize?: number, labelSuffix?: string, labelSize?: number, labelOffset?: number, labelRotation?: number, arrowType?: dimensionEndTypeEnum, arrowSize?: number, arrowAngle?: number, arrowsFlipped?: boolean, labelFlipHorizontal?: boolean, labelFlipVertical?: boolean, labelOverwrite?: string) {
70457045
if (start !== undefined) { this.start = start; }
70467046
if (end !== undefined) { this.end = end; }
70477047
if (direction !== undefined) { this.direction = direction; }
@@ -7057,6 +7057,7 @@ export namespace OCCT {
70577057
if (arrowsFlipped !== undefined) { this.arrowsFlipped = arrowsFlipped; }
70587058
if (labelFlipHorizontal !== undefined) { this.labelFlipHorizontal = labelFlipHorizontal; }
70597059
if (labelFlipVertical !== undefined) { this.labelFlipVertical = labelFlipVertical; }
7060+
if (labelOverwrite !== undefined) { this.labelOverwrite = labelOverwrite; }
70607061
}
70617062
/**
70627063
* The start point for dimension
@@ -7162,9 +7163,15 @@ export namespace OCCT {
71627163
* @default false
71637164
*/
71647165
labelFlipVertical? = false;
7166+
/**
7167+
* Override label text with custom expression (supports 'val' for computed value, e.g., '100*val', 'Length: val mm')
7168+
* @default 1*val
7169+
* @optional true
7170+
*/
7171+
labelOverwrite? = "1*val";
71657172
}
71667173
export class SimpleAngularDimensionDto {
7167-
constructor(direction1?: Base.Point3, direction2?: Base.Point3, center?: Base.Point3, radius?: number, offsetFromCenter?: number, crossingSize?: number, radians?: boolean, labelSuffix?: string, labelSize?: number, labelOffset?: number, endType?: dimensionEndTypeEnum, arrowSize?: number, arrowAngle?: number, arrowsFlipped?: boolean, labelRotation?: number, labelFlipHorizontal?: boolean, labelFlipVertical?: boolean) {
7174+
constructor(direction1?: Base.Point3, direction2?: Base.Point3, center?: Base.Point3, radius?: number, offsetFromCenter?: number, crossingSize?: number, radians?: boolean, labelSuffix?: string, labelSize?: number, labelOffset?: number, endType?: dimensionEndTypeEnum, arrowSize?: number, arrowAngle?: number, arrowsFlipped?: boolean, labelRotation?: number, labelFlipHorizontal?: boolean, labelFlipVertical?: boolean, labelOverwrite?: string) {
71687175
if (direction1 !== undefined) { this.direction1 = direction1; }
71697176
if (direction2 !== undefined) { this.direction2 = direction2; }
71707177
if (center !== undefined) { this.center = center; }
@@ -7182,6 +7189,7 @@ export namespace OCCT {
71827189
if (labelRotation !== undefined) { this.labelRotation = labelRotation; }
71837190
if (labelFlipHorizontal !== undefined) { this.labelFlipHorizontal = labelFlipHorizontal; }
71847191
if (labelFlipVertical !== undefined) { this.labelFlipVertical = labelFlipVertical; }
7192+
if (labelOverwrite !== undefined) { this.labelOverwrite = labelOverwrite; }
71857193
}
71867194

71877195
/**
@@ -7301,6 +7309,12 @@ export namespace OCCT {
73017309
* @default false
73027310
*/
73037311
labelFlipVertical? = false;
7312+
/**
7313+
* Override label text with custom expression (supports 'val' for computed value, e.g., '100*val', 'Angle: val deg')
7314+
* @default 1*val
7315+
* @optional true
7316+
*/
7317+
labelOverwrite? = "1*val";
73047318
}
73057319
export class PinWithLabelDto {
73067320
constructor(startPoint?: Base.Point3, endPoint?: Base.Point3, direction?: Base.Vector3, offsetFromStart?: number, label?: string, labelOffset?: number, labelSize?: number, endType?: dimensionEndTypeEnum, arrowSize?: number, arrowAngle?: number, arrowsFlipped?: boolean, labelRotation?: number, labelFlipHorizontal?: boolean, labelFlipVertical?: boolean) {

packages/dev/occt/lib/services/base/dimensions.service.ts

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,60 @@ export class DimensionsService {
2222
private readonly wiresService: WiresService
2323
) { }
2424

25+
/**
26+
* Evaluates a mathematical expression or template string with a given value
27+
* @param expression The expression to evaluate (can contain 'val' placeholder)
28+
* @param value The numeric value to substitute for 'val'
29+
* @param decimalPlaces Number of decimal places to format the result
30+
* @returns The evaluated expression as a formatted string
31+
*/
32+
private evaluateExpression(expression: string, value: number, decimalPlaces: number): string {
33+
try {
34+
// Replace 'val' with the actual value in the expression
35+
const evaluatedExpression = expression.replace(/val/g, value.toString());
36+
37+
// Simple math expression evaluation (supports +, -, *, /, parentheses)
38+
// Only allow safe mathematical operations
39+
const safeExpression = evaluatedExpression.replace(/[^0-9+\-*/.() ]/g, "");
40+
if (safeExpression !== evaluatedExpression) {
41+
// If expression contains non-math characters, treat it as a template
42+
// For template strings, we still want to format numbers with decimal places
43+
const formattedValue = value.toFixed(decimalPlaces);
44+
return expression.replace(/val/g, formattedValue);
45+
}
46+
47+
// Evaluate mathematical expression and apply decimal places
48+
const result = Function("\"use strict\"; return (" + safeExpression + ")")();
49+
return result.toFixed(decimalPlaces);
50+
} catch (error) {
51+
// If evaluation fails, return the original value formatted
52+
return value.toFixed(decimalPlaces);
53+
}
54+
}
55+
56+
/**
57+
* Formats dimension label text with optional expression evaluation
58+
* @param value The numeric value to display
59+
* @param labelOverwrite Optional expression to evaluate instead of raw value
60+
* @param decimalPlaces Number of decimal places for formatting
61+
* @param labelSuffix Suffix to append to the text
62+
* @returns Formatted dimension label text
63+
*/
64+
private formatDimensionLabel(
65+
value: number,
66+
labelOverwrite: string | undefined,
67+
decimalPlaces: number,
68+
labelSuffix: string
69+
): string {
70+
let result: string;
71+
if (labelOverwrite) {
72+
result = this.evaluateExpression(labelOverwrite, value, decimalPlaces);
73+
} else {
74+
result = value.toFixed(decimalPlaces);
75+
}
76+
return result + " " + labelSuffix;
77+
}
78+
2579
private createArrow(inputs: {
2680
tipPoint: Inputs.Base.Point3,
2781
direction: Inputs.Base.Vector3,
@@ -141,8 +195,15 @@ export class DimensionsService {
141195
endPoint: inputs.end,
142196
});
143197

198+
const labelText = this.formatDimensionLabel(
199+
length,
200+
inputs.labelOverwrite,
201+
inputs.decimalPlaces,
202+
inputs.labelSuffix
203+
);
204+
144205
const txtOpt = new Inputs.OCCT.TextWiresDto();
145-
txtOpt.text = length.toFixed(inputs.decimalPlaces) + " " + inputs.labelSuffix;
206+
txtOpt.text = labelText;
146207
txtOpt.xOffset = 0;
147208
txtOpt.yOffset = 0;
148209
txtOpt.height = inputs.labelSize;
@@ -324,8 +385,15 @@ export class DimensionsService {
324385
angle = this.base.math.degToRad({ number: angle });
325386
}
326387

388+
const labelText = this.formatDimensionLabel(
389+
angle,
390+
inputs.labelOverwrite,
391+
inputs.decimalPlaces,
392+
inputs.labelSuffix
393+
);
394+
327395
const txtOpt = new Inputs.OCCT.TextWiresDto();
328-
txtOpt.text = angle.toFixed(inputs.decimalPlaces) + " " + inputs.labelSuffix;
396+
txtOpt.text = labelText;
329397
txtOpt.xOffset = 0;
330398
txtOpt.yOffset = 0;
331399
txtOpt.height = inputs.labelSize;

0 commit comments

Comments
 (0)