# Simple Line Decoration
Line decoration is entity that can change shape of line. This example demonstrates existing line decorations.
import { Point } from "@int/geotoolkit/util/Point.ts";
import { LineDecoration } from "@int/geotoolkit/attributes/LineDecoration.ts";
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { Line } from "@int/geotoolkit/scene/shapes/Line.ts";
import { KnownColors } from "@int/geotoolkit/util/ColorUtil.ts";
import { Patterns } from "@int/geotoolkit/attributes/LineStyle.ts";
import { Group } from "@int/geotoolkit/scene/Group.ts";
import { Dimension } from "@int/geotoolkit/util/Dimension.ts";
import { FontPainter } from "@int/geotoolkit/scene/shapes/painters/FontPainter.ts";
export const createScene = (canvas) => {
const lineDecoration = [
LineDecoration.Solid,
LineDecoration.Wavy,
LineDecoration.Double,
LineDecoration.DoubleWavy,
LineDecoration.getPainter(new FontPainter("src/assets/fonts/", "Roboto Condensed Light Italic", "/"), new Dimension(10, 10))
];
const lines = [];
for (let i = 1; i < lineDecoration.length; i++) {
lines.push(new Line({
"from": new Point(50, i * 50),
"to": new Point(300, (i + 1) * 50),
"linestyle": {
"color": KnownColors.Blue,
"width": 2,
"pattern": Patterns.Solid
},
"linedecoration": lineDecoration[i]
}));
}
return new Plot({
"canvaselement": canvas,
"root": new Group().addChild(lines)
});
};
createScene(document.querySelector('[ref="plot"]'));
# Custom Line Decoration
This is example how to create and register custom line decoration.
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __decorateClass = (decorators, target, key, kind) => {
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
for (var i = decorators.length - 1, decorator; i >= 0; i--)
if (decorator = decorators[i])
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
if (kind && result)
__defProp(target, key, result);
return result;
};
import { LineRenderingContext } from "@int/geotoolkit/attributes/LineRenderingContext.ts";
import { Point } from "@int/geotoolkit/util/Point.ts";
import { MathUtil } from "@int/geotoolkit/util/MathUtil.ts";
import { Transformation } from "@int/geotoolkit/util/Transformation.ts";
import { Path } from "@int/geotoolkit/scene/shapes/Path.ts";
import { ILineDecoration } from "@int/geotoolkit/attributes/ILineDecoration.ts";
import { Implements, Obfuscate } from "@int/geotoolkit/decorators.ts";
import { LineDecoration } from "@int/geotoolkit/attributes/LineDecoration.ts";
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { Line } from "@int/geotoolkit/scene/shapes/Line.ts";
import { KnownColors } from "@int/geotoolkit/util/ColorUtil.ts";
import { Patterns } from "@int/geotoolkit/attributes/LineStyle.ts";
import { Group } from "@int/geotoolkit/scene/Group.ts";
const LINE_WIDTH = 10;
let CustomRenderingState = class extends LineRenderingContext {
constructor(context) {
super(context);
this._lineStyle = null;
this._context = context;
}
setLineStyle(lineStyle, area) {
this._context.setLineStyle(lineStyle, area);
this._lineStyle = lineStyle;
return this;
}
drawLine(x1, y1, x2, y2) {
const transformation = this._context.getTransformation();
const p1 = transformation.transformXY(x1, y1).clone();
const p2 = transformation.transformXY(x2, y2).clone();
const distance = Point.getDistance(p1, p2);
let angle = 0;
const px1 = p1.x, py = p1.y;
let px2;
if (MathUtil.equals(p1.y, p2.y)) {
px2 = p2.x;
} else if (MathUtil.equals(p1.x, p2.x)) {
angle = (p2.y < p1.y ? -1 : 1) * Math.PI / 2;
px2 = px1 + distance;
} else {
angle = Math.asin(Math.abs(p1.y - p2.y) / distance);
if (p2.y < p1.y) {
if (p2.x < p1.x) {
angle = -(Math.PI - angle);
} else {
angle = -angle;
}
} else if (p2.x < p1.x) {
angle = angle + Math.PI / 2;
}
px2 = px1 + distance;
}
this._context.setTransformation(new Transformation());
const path = new Path({
"linestyle": this._lineStyle
});
let currentY = -LINE_WIDTH * 0.5;
path.moveTo(px1, py + currentY);
for (let i = px1 + LINE_WIDTH; i <= px2; i += LINE_WIDTH) {
currentY = -currentY;
path.lineTo(i, py + currentY);
}
const reminder = (px2 - px1) % LINE_WIDTH;
if (reminder > 0) {
path.lineTo(px2, py + (currentY > 0 ? currentY - reminder : currentY + reminder) / LINE_WIDTH);
}
path.rotate(angle, p1.x, p1.y);
path.render(this._context);
path.dispose();
this._context.setTransformation(transformation);
}
};
CustomRenderingState = __decorateClass([
Obfuscate()
], CustomRenderingState);
let CustomLine = class {
getName() {
return "custom";
}
getLineWidth(lineStyle) {
return LINE_WIDTH;
}
createLineRenderingContext(context) {
return new CustomRenderingState(context);
}
};
CustomLine = __decorateClass([
Obfuscate(),
Implements(ILineDecoration)
], CustomLine);
LineDecoration.registerLineDecoration("custom", new CustomLine());
export const createScene = (canvas) => {
const lineDecoration = LineDecoration.getLineDecoration("custom");
const line = new Line({
"from": new Point(50, 50),
"to": new Point(300, 300),
"linestyle": {
"color": KnownColors.Blue,
"width": 2,
"pattern": Patterns.Solid
},
"linedecoration": lineDecoration
});
return new Plot({
"canvaselement": canvas,
"root": new Group().addChild(line)
});
};
createScene(document.querySelector('[ref="plot"]'));