-
Notifications
You must be signed in to change notification settings - Fork 208
/
LineStyle.ts
193 lines (169 loc) · 7.07 KB
/
LineStyle.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
* @module Symbology
*/
import { Id64String } from "@itwin/core-bentley";
import { Transform, Vector3d, XYZProps, YawPitchRollAngles, YawPitchRollProps } from "@itwin/core-geometry";
/** @public */
export namespace LineStyle {
/** Modify the line style appearance without changing the line style definition.
* Applies to the style previously established by a [[GeometryAppearanceProps]] or current [[SubCategoryAppearance]].
* Most of the modifiers affect the line style stroke pattern, with the orientation and scales being the exception.
* @see [[GeometryStreamEntryProps]]
*/
export interface ModifierProps {
/** Optional scale to apply to all length values, 1.0 if undefined */
scale?: number;
/** Optional scale to apply to scalable dashes, 1.0 if undefined */
dashScale?: number;
/** Optional scale to apply to scalable gaps, 1.0 if undefined */
gapScale?: number;
/** Optional start width in meters to apply to dashes, no width if undefined */
startWidth?: number;
/** Optional end width in meters to apply to dashes, same as startWidth if undefined */
endWidth?: number;
/** Optional shift by distance in meters, 0.0 if undefined */
distPhase?: number;
/** Optional shift by fraction, 0.0 if undefined */
fractPhase?: number;
/** Optional flag to center stroke pattern and stretch ends, false if undefined */
centerPhase?: boolean;
/** Optional flag to enable or disable single segment mode */
segmentMode?: boolean;
/** Optional flag that denotes startWidth and endWidth represent physical widths that should not be affected by scale, false if undefined */
physicalWidth?: boolean;
/** Optional up vector for style (applicable to 3d only), 0.0,0.0,1.0 if undefined */
normal?: XYZProps;
/** Optional orientation for style (applicable to 3d only), 0.0,0.0,0.0 if undefined */
rotation?: YawPitchRollProps;
}
/** Optional modifiers to override line style definition */
export class Modifier implements ModifierProps {
public scale?: number;
public dashScale?: number;
public gapScale?: number;
public startWidth?: number;
public endWidth?: number;
public distPhase?: number;
public fractPhase?: number;
public centerPhase?: boolean;
public segmentMode?: boolean;
public physicalWidth?: boolean;
public normal?: Vector3d;
public rotation?: YawPitchRollAngles;
/** constructor for LineStyle.Modifier */
constructor(props: ModifierProps) {
this.scale = props.scale;
this.dashScale = props.dashScale;
this.gapScale = props.gapScale;
this.startWidth = props.startWidth;
this.endWidth = props.endWidth;
this.distPhase = props.distPhase;
this.fractPhase = props.fractPhase;
this.centerPhase = props.centerPhase;
this.segmentMode = props.segmentMode;
this.physicalWidth = props.physicalWidth;
this.normal = props.normal ? Vector3d.fromJSON(props.normal) : undefined;
this.rotation = props.rotation ? YawPitchRollAngles.fromJSON(props.rotation) : undefined;
}
/** Returns a deep copy of this object. */
public clone() {
return new Modifier(this);
}
/** Compare two LineStyle.Modifier for equivalence */
public equals(other: Modifier): boolean {
if (this === other) // same pointer
return true;
if (other.scale !== this.scale ||
other.dashScale !== this.dashScale ||
other.gapScale !== this.gapScale ||
other.startWidth !== this.startWidth ||
other.endWidth !== this.endWidth ||
other.distPhase !== this.distPhase ||
other.fractPhase !== this.fractPhase ||
other.centerPhase !== this.centerPhase ||
other.segmentMode !== this.segmentMode ||
other.physicalWidth !== this.physicalWidth)
return false;
if ((this.normal === undefined) !== (other.normal === undefined))
return false;
if (this.normal && !this.normal.isAlmostEqual(other.normal!))
return false;
if ((this.rotation === undefined) !== (other.rotation === undefined))
return false;
if (this.rotation && !this.rotation.isAlmostEqual(other.rotation!))
return false;
return true;
}
public applyTransform(transform: Transform): boolean {
if (transform.isIdentity)
return true;
if (this.normal) {
transform.matrix.multiplyVector(this.normal, this.normal);
const normalized = this.normal.normalize();
if (normalized)
this.normal.setFrom(normalized);
else
return false;
}
if (this.rotation) {
const newTransform = this.rotation.toMatrix3d().multiplyMatrixTransform(transform);
const scales = new Vector3d();
if (!newTransform.matrix.normalizeColumnsInPlace(scales))
return false;
const newRotation = YawPitchRollAngles.createFromMatrix3d(newTransform.matrix);
if (undefined === newRotation)
return false;
this.rotation.setFrom(newRotation);
}
let scaleFactor;
const scaleVector = Vector3d.create();
const scaleMatrix = transform.matrix;
scaleMatrix.normalizeRowsInPlace(scaleVector);
// Check for flatten transform, dividing scaleVector by 3 gives wrong scaleFactor
if (scaleVector.x !== 0.0 && scaleVector.y !== 0.0 && scaleVector.z !== 0.0)
scaleFactor = (scaleVector.x + scaleVector.y + scaleVector.z) / 3.0;
else
scaleFactor = (scaleVector.x + scaleVector.y + scaleVector.z) / 2.0;
if (1.0 === scaleFactor)
return true;
if (this.scale)
this.scale *= scaleFactor;
if (this.physicalWidth)
return true;
if (this.startWidth)
this.startWidth *= scaleFactor;
if (this.endWidth)
this.endWidth *= scaleFactor;
return true;
}
}
/** Line style id and optional modifiers to override line style definition */
export class Info {
public styleId: Id64String;
public styleMod?: Modifier; // Optional modifiers to override line style definition
/** Creates a LineStyle.Info object */
constructor(styleId: Id64String, styleMod?: Modifier) {
this.styleId = styleId;
this.styleMod = styleMod;
}
/** Returns a deep copy of this object. */
public clone(): Info {
return new Info(this.styleId, this.styleMod ? this.styleMod.clone() : undefined);
}
public equals(other: Info): boolean {
if (this === other)
return true;
if (this.styleId !== other.styleId)
return false;
if ((this.styleMod === undefined) !== (other.styleMod === undefined))
return false;
if (this.styleMod && !this.styleMod.equals(other.styleMod!))
return false;
return true;
}
}
}