Skip to content

Commit

Permalink
added(display): In addition to pixels, dashed lines can now also be d…
Browse files Browse the repository at this point in the history
…efined and displayed in meter units.

Signed-off-by: Tim Deubler <tim.deubler@here.com>
  • Loading branch information
TerminalTim committed Nov 6, 2023
1 parent 2b737a4 commit ee7c7c5
Show file tree
Hide file tree
Showing 6 changed files with 207 additions and 172 deletions.
306 changes: 158 additions & 148 deletions packages/core/src/styles/LineStyle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,166 +22,176 @@ import {Color, StyleValueFunction, StyleZoomRange} from './LayerStyle';
* Interface for configuring the visual appearance of Lines.
*/
export interface LineStyle {
/**
* Specifies the type of style to render.
*/
type: 'Line';
/**
* Specifies the type of style to render.
*/
type: 'Line';

zIndex: number;
zIndex: number;

/**
* Indicates drawing order across multiple layers.
* Styles using zLayer with a high value are rendered on top of zLayers with a low value.
* If no zLayer is defined the zLayer depends on the display layer order.
* The first (lowest) layer has a zLayer value of 1.
*
* @example \{...zLayer: 2, zIndex: 5\} will be rendered on top of \{...zLayer: 1, zIndex: 10\}
*/
zLayer?: number | StyleValueFunction<number>;
/**
* Indicates drawing order across multiple layers.
* Styles using zLayer with a high value are rendered on top of zLayers with a low value.
* If no zLayer is defined the zLayer depends on the display layer order.
* The first (lowest) layer has a zLayer value of 1.
*
* @example \{...zLayer: 2, zIndex: 5\} will be rendered on top of \{...zLayer: 1, zIndex: 10\}
*/
zLayer?: number | StyleValueFunction<number>;

/**
* Defines the opacity of the style.
* The value must be between 0.0 (fully transparent) and 1.0 (fully opaque).
* It is valid for all style types.
* @defaultValue 1
*/
opacity?: number | StyleValueFunction<number> | StyleZoomRange<number>;
/**
* Defines the opacity of the style.
* The value must be between 0.0 (fully transparent) and 1.0 (fully opaque).
* It is valid for all style types.
* @defaultValue 1
*/
opacity?: number | StyleValueFunction<number> | StyleZoomRange<number>;

/**
* Sets the stroke color of the Line.
*
* @see {@link Color} for a detailed list of possible supported formats.
*/
stroke?: Color | StyleValueFunction<Color> | StyleZoomRange<Color>;
/**
* Sets the stroke color of the Line.
*
* @see {@link Color} for a detailed list of possible supported formats.
*/
stroke?: Color | StyleValueFunction<Color> | StyleZoomRange<Color>;

/**
* Sets the width of the line.
* The unit of strokeWidth is defined in pixels.
* For Polygons that are using {@link extrude}, the maximum possible strokeWidth is 1.0 pixel.
* For Styles of type Line the strokeWidth can also be defined in meters by using a string: "$\{width\}m".
*
* @example
* ```typescript
* // define a Line that has a with of 1 meter
* {
* zIndex: 0,
* type: "Line",
* stroke: "blue",
* strokeWidth: "1m"
* }
* // define a Line that has a with of 16 pixel
* {
* zIndex: 0,
* type: "Line",
* stroke: "green",
* strokeWidth: "16
* }
* ```
*/
strokeWidth: number | string | StyleValueFunction<number | number> | StyleZoomRange<string | number>;
/**
* Sets the width of the line.
* The unit of strokeWidth is defined in pixels.
* For Polygons that are using {@link extrude}, the maximum possible strokeWidth is 1.0 pixel.
* For Styles of type Line the strokeWidth can also be defined in meters by using a string: "$\{width\}m".
*
* @example
* ```typescript
* // define a Line that has a with of 1 meter
* {
* zIndex: 0,
* type: "Line",
* stroke: "blue",
* strokeWidth: "1m"
* }
* // define a Line that has a with of 16 pixel
* {
* zIndex: 0,
* type: "Line",
* stroke: "green",
* strokeWidth: "16
* }
* ```
*/
strokeWidth: number | string | StyleValueFunction<number | number> | StyleZoomRange<string | number>;

/**
* This controls the shape of the ends of lines. there are three possible values for strokeLinecap:
* - "butt" closes the line off with a straight edge that's normal (at 90 degrees) to the direction of the stroke and crosses its end.
* - "square" has essentially the same appearance, but stretches the stroke slightly beyond the actual path. The distance that the stroke goes beyond the path is half the strokeWidth.
* - "round" produces a rounded effect on the end of the stroke. The radius of this curve is also controlled by the strokeWidth.
* This attribute is valid for Line styles only.
*
* If "strokeLinecap" is used in combination with "altitude", only "butt" is supported for "strokeLinecap".
*/
strokeLinecap?: string | StyleValueFunction<string> | StyleZoomRange<string>;
/**
* This controls the shape of the ends of lines. there are three possible values for strokeLinecap:
* - "butt" closes the line off with a straight edge that's normal (at 90 degrees) to the direction of the stroke and crosses its end.
* - "square" has essentially the same appearance, but stretches the stroke slightly beyond the actual path. The distance that the stroke goes beyond the path is half the strokeWidth.
* - "round" produces a rounded effect on the end of the stroke. The radius of this curve is also controlled by the strokeWidth.
* This attribute is valid for Line styles only.
*
* If "strokeLinecap" is used in combination with "altitude", only "butt" is supported for "strokeLinecap".
*/
strokeLinecap?: string | StyleValueFunction<string> | StyleZoomRange<string>;

/**
* The joint where the two segments in a line meet is controlled by the strokeLinejoin attribute, There are three possible values for this attribute:
* - "miter" extends the line slightly beyond its normal width to create a square corner where only one angle is used.
* - "round" creates a rounded line segment.
* - "bevel" creates a new angle to aid in the transition between the two segments.
* This attribute is valid for Line styles only.
*
* If "strokeLinejoin" is used in combination with "altitude", the use of "round" is not supported.
*/
strokeLinejoin?: string | StyleValueFunction<string> | StyleZoomRange<string>;
/**
* The joint where the two segments in a line meet is controlled by the strokeLinejoin attribute, There are three possible values for this attribute:
* - "miter" extends the line slightly beyond its normal width to create a square corner where only one angle is used.
* - "round" creates a rounded line segment.
* - "bevel" creates a new angle to aid in the transition between the two segments.
* This attribute is valid for Line styles only.
*
* If "strokeLinejoin" is used in combination with "altitude", the use of "round" is not supported.
*/
strokeLinejoin?: string | StyleValueFunction<string> | StyleZoomRange<string>;

/**
* The strokeDasharray attribute controls the pattern of dashes and gaps used to stroke paths.
* It's an array of <length> that specify the lengths of alternating dashes and gaps. If an odd number of values is provided,
* then the list of values is repeated to yield an even number of values. Thus, 5,3,2 is equivalent to 5,3,2,5,3,2.
* This attribute is valid for Line styles only.
*/
strokeDasharray?: number[] | StyleValueFunction<number[]> | StyleZoomRange<number[]> | 'none';
/**
* The strokeDasharray attribute controls the pattern of dashes and gaps used to stroke paths.
* It's an array of <length> that specify the lengths of alternating dashes and gaps. If an odd number of values is provided,
* then the list of values is repeated to yield an even number of values. Thus, 5,3,2 is equivalent to 5,3,2,5,3,2.
* The size of dashes and gaps can be defined in pixel or meter.
* The default unit for dash and gap size is pixel.
* To define the size in meters, a string containing the "dash"/"gap" size and ending with "m" must be used.
*
* @example
* // dash and gap size is defined in pixel.
* strokeDasharray: [20,10]
* // dash and gap size is defined in meter.
* strokeDasharray: ["20m","10m"]
* // dash -> 10 meter, gap -> 10 pixel.
* strokeDasharray: ["20m",10] || ["20m","10px"]
*/
strokeDasharray?: (number | string)[] | StyleValueFunction<(number | string)[]> | StyleZoomRange<(number | string)[]> | 'none';

/**
* Specifies the URL of the image to be rendered at the positions of the dashes.
* If strokeDashimage is defined, only the first dash and gap definition of the {@link strokeDasharry} pattern is used.
* The dashimage will be colored with the color defined in {@link stroke}.
*/
strokeDashimage?: string
/**
* Specifies the URL of the image to be rendered at the positions of the dashes.
* If strokeDashimage is defined, only the first dash and gap definition of the {@link strokeDasharry} pattern is used.
* The dashimage will be colored with the color defined in {@link stroke}.
*/
strokeDashimage?: string;

/**
* Define the starting position of a segment of the entire line in %.
* A Segment allows to display and style parts of the entire line individually.
* The value must be between 0 and 1.
* The Default is 0.
*
* @example
* from: 0.0 // -\> 0%, the segment has the same starting point as the entire line
* from: 0.5 // -\> 50%, the segment starts in the middle of the entire line
*/
from?: number | StyleValueFunction<number> | StyleZoomRange<number>;
/**
* Define the starting position of a segment of the entire line in %.
* A Segment allows to display and style parts of the entire line individually.
* The value must be between 0 and 1.
* The Default is 0.
*
* @example
* from: 0.0 // -\> 0%, the segment has the same starting point as the entire line
* from: 0.5 // -\> 50%, the segment starts in the middle of the entire line
*/
from?: number | StyleValueFunction<number> | StyleZoomRange<number>;

/**
* Define the end position of a segment of the entire line in %.
* A Segment allows to display and style parts of the entire line individually.
* The value must be between 0 and 1.
* The Default is 1.
*
* @example
* to: 0.5 // -\> 50%, the segment ends in the middle of the entire line
* to: 1.0 // -\> 100%, the segment has the same end point as the entire line
*/
to?: number | StyleValueFunction<number> | StyleZoomRange<number>;
/**
* Define the end position of a segment of the entire line in %.
* A Segment allows to display and style parts of the entire line individually.
* The value must be between 0 and 1.
* The Default is 1.
*
* @example
* to: 0.5 // -\> 50%, the segment ends in the middle of the entire line
* to: 1.0 // -\> 100%, the segment has the same end point as the entire line
*/
to?: number | StyleValueFunction<number> | StyleZoomRange<number>;

/**
* Offset a line to the left or right side in pixel or meter.
* A positive values offsets to the right side, a negative value offsets to the left.
* The side is defined relative to the direction of the line geometry.
* The default unit is pixels.
* To define the offset in meters a string that contains the offset value and ends with "m" must be used.
* Applies to Line style only.
* @example
* ```typescript
* // offset line by 8px
* { type: "Line", zIndex: 0, stroke:'blue', strokeWidth: 4, offset: 8}
*
* // offset line by 2m
* { type: "Line", zIndex: 0, stroke:'blue', strokeWidth: 4, offset: "2m"}
* ```
*/
offset?: number | string | StyleValueFunction<number | string> | StyleZoomRange<number | string>;
/**
* Offset a line to the left or right side in pixel or meter.
* A positive values offsets to the right side, a negative value offsets to the left.
* The side is defined relative to the direction of the line geometry.
* The default unit is pixels.
* To define the offset in meters a string that contains the offset value and ends with "m" must be used.
* Applies to Line style only.
* @example
* ```typescript
* // offset line by 8px
* { type: "Line", zIndex: 0, stroke:'blue', strokeWidth: 4, offset: 8}
*
* // offset line by 2m
* { type: "Line", zIndex: 0, stroke:'blue', strokeWidth: 4, offset: "2m"}
* ```
*/
offset?: number | string | StyleValueFunction<number | string> | StyleZoomRange<number | string>;

/**
* The altitude of the line in meters.
* The altitude defines the distance in the vertical direction between the ground plane at 0 meters and the geometry/style.
* If altitude is set to true, the altitude from the feature's geometry coordinates will be used automatically.
* If a number is set for altitude, the altitude of the feature's geometry is ignored and the value of "altitude" is used instead.
* The height must be defined in meters.
*
* @defaultValue false
*
* @experimental
*/
altitude?: number | boolean | StyleValueFunction<number | boolean> | StyleZoomRange<number | boolean>
/**
* The altitude of the line in meters.
* The altitude defines the distance in the vertical direction between the ground plane at 0 meters and the geometry/style.
* If altitude is set to true, the altitude from the feature's geometry coordinates will be used automatically.
* If a number is set for altitude, the altitude of the feature's geometry is ignored and the value of "altitude" is used instead.
* The height must be defined in meters.
*
* @defaultValue false
*
* @experimental
*/
altitude?: number | boolean | StyleValueFunction<number | boolean> | StyleZoomRange<number | boolean>;

/**
* Scales the size of a style based on the feature's altitude.
* If it's enabled (true), features closer to the camera will be drawn larger than those farther away.
* When off (false), the size of the style is always the same size, regardless of its actual altitude, as if it were placed on the ground (altitude 0).
* This attribute applies to styles of type "Rect", "Image", "Text", "Circle", "Line", "Box", or "Sphere" whose size ({@link width}, {@link radius}, {@link strokeWidth}) that are using "map" {@link alignment} only.
* If the size attribute is defined in meters, scaleByAltitude is enabled by default, for pixels it is disabled.
*
* @defaultValue false (pixels), true (meters)
*
* @experimental
*/
scaleByAltitude?: boolean | StyleValueFunction<boolean> | StyleZoomRange<boolean>
/**
* Scales the size of a style based on the feature's altitude.
* If it's enabled (true), features closer to the camera will be drawn larger than those farther away.
* When off (false), the size of the style is always the same size, regardless of its actual altitude, as if it were placed on the ground (altitude 0).
* This attribute applies to styles of type "Rect", "Image", "Text", "Circle", "Line", "Box", or "Sphere" whose size ({@link width}, {@link radius}, {@link strokeWidth}) that are using "map" {@link alignment} only.
* If the size attribute is defined in meters, scaleByAltitude is enabled by default, for pixels it is disabled.
*
* @defaultValue false (pixels), true (meters)
*
* @experimental
*/
scaleByAltitude?: boolean | StyleValueFunction<boolean> | StyleZoomRange<boolean>;
}
18 changes: 13 additions & 5 deletions packages/display/src/displays/webgl/buffer/FeatureFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ type DrawGroup = {
strokeWidth: number;
strokeLinecap: string;
strokeLinejoin: string;
strokeDasharray: number[];
strokeDasharray: {pattern:number[], units:string[]};
strokeDashimage: string;
width: number;
height: number;
Expand Down Expand Up @@ -540,13 +540,21 @@ export class FeatureFactory {
strokeLinejoin;
strokeDasharray = getValue('strokeDasharray', style, feature, level);

if (Array.isArray(strokeDasharray)) {
if (!strokeDasharray.length || !strokeDasharray[0]) {
strokeDasharray = UNDEF;
}

if (Array.isArray(strokeDasharray) && strokeDasharray[0] ) {
groupId += strokeDasharray;

let pattern = [];
let units = [];

for (let i=0; i< strokeDasharray.length; i++) {
const [size, unit] = parseSizeValue(strokeDasharray[i]);
pattern[i] = size;
units[i] = unit;
}

strokeDasharray = {pattern, units};

strokeDashimage = getValue('strokeDashimage', style, feature, level);

if (strokeDashimage) {
Expand Down
Loading

0 comments on commit ee7c7c5

Please sign in to comment.