UNPKG

gd-canvas

Version:

This set of libraries was generated with [Angular CLI](https://github.com/angular/angular-cli) version 9.1.0 and no dependencies accept gd-tree (it has jquery and jstree) and gd-graph (it has jquery and chart.js).

1,083 lines (1,078 loc) 255 kB
import { EventEmitter, ɵɵdefineInjectable, ɵsetClassMetadata, Injectable, ɵɵdefineComponent, Component, ɵɵdirectiveInject, ElementRef, KeyValueDiffers, ɵɵviewQuery, ɵɵqueryRefresh, ɵɵloadQuery, ɵɵelementStart, ɵɵlistener, ɵɵelement, ɵɵelementEnd, ɵɵadvance, ɵɵproperty, ViewChild, Input, ɵɵdefineNgModule, ɵɵdefineInjector, ɵɵsetNgModuleScope, NgModule } from '@angular/core'; import { CustomTypes, CustomActions, CustomObject, GDCanvasCustomTypesModule } from 'gd-canvas-custom-types'; import { Point, Rect, Vector, Line, Size, IDGenerator, GDCommonTools, State as State$1, GDCommonService, GDCommonModule } from 'gd-common'; import { GDTooltipComponent, GDTooltipModule } from 'gd-tooltip'; import { CommonModule } from '@angular/common'; import { GDWindowModule } from 'gd-window'; class GDCanvasService { constructor() { this.showContextmenu$ = new EventEmitter(); this.focusedMove$ = new EventEmitter(); this.redrawRefChildren$ = new EventEmitter(); this.selectedChanged$ = new EventEmitter(); this.canvasIsReady$ = new EventEmitter(); this.canvasInfo$ = new EventEmitter(); this.customLayerRequest$ = new EventEmitter(); this.shapeChangedParent$ = new EventEmitter(); } SelectedChanged(arg) { this.selectedChanged$.emit(arg); } ShowContextmenu(arg) { this.showContextmenu$.emit(arg); } CustomLayerRequest(arg) { this.customLayerRequest$.emit(arg); } CanvasIsReady(arg) { this.canvasIsReady$.emit(arg); } CanvasInfo(info) { this.canvasInfo$.emit(info); } FocusedMove(offset) { this.focusedMove$.emit(offset); } RedrawRefChildren() { this.redrawRefChildren$.emit(); } ShapeChangedParent(shape) { this.shapeChangedParent$.emit(shape); } } GDCanvasService.ɵfac = function GDCanvasService_Factory(t) { return new (t || GDCanvasService)(); }; GDCanvasService.ɵprov = ɵɵdefineInjectable({ token: GDCanvasService, factory: GDCanvasService.ɵfac, providedIn: 'root' }); /*@__PURE__*/ (function () { ɵsetClassMetadata(GDCanvasService, [{ type: Injectable, args: [{ providedIn: 'root' }] }], function () { return []; }, null); })(); var GondolaTypes; (function (GondolaTypes) { GondolaTypes[GondolaTypes["regular"] = 1] = "regular"; GondolaTypes[GondolaTypes["wall"] = 2] = "wall"; })(GondolaTypes || (GondolaTypes = {})); class ShapeWithDistance { constructor(s, d) { this.shape = s; this.distance = d; } } var DefaultActions; (function (DefaultActions) { DefaultActions[DefaultActions["none"] = 0] = "none"; DefaultActions[DefaultActions["move"] = 1] = "move"; DefaultActions[DefaultActions["moveActivePoint"] = 2] = "moveActivePoint"; DefaultActions[DefaultActions["moveActiveLine"] = 3] = "moveActiveLine"; DefaultActions[DefaultActions["rotate"] = 4] = "rotate"; DefaultActions[DefaultActions["resize"] = 5] = "resize"; DefaultActions[DefaultActions["select"] = 6] = "select"; DefaultActions[DefaultActions["selectShapesInOrder"] = 7] = "selectShapesInOrder"; DefaultActions[DefaultActions["selectShapes"] = 8] = "selectShapes"; DefaultActions[DefaultActions["pan"] = 9] = "pan"; DefaultActions[DefaultActions["scale"] = 10] = "scale"; DefaultActions[DefaultActions["dnd"] = 11] = "dnd"; // addRegularGondola = 12, // addWallGondola = 13, DefaultActions[DefaultActions["addShape"] = 14] = "addShape"; DefaultActions[DefaultActions["addPolygon"] = 15] = "addPolygon"; // addArea = 16 DefaultActions[DefaultActions["edit"] = 17] = "edit"; DefaultActions[DefaultActions["deletePolylinePoint"] = 18] = "deletePolylinePoint"; DefaultActions[DefaultActions["addPolylinePoint"] = 19] = "addPolylinePoint"; })(DefaultActions || (DefaultActions = {})); var State; (function (State) { State[State["unchanged"] = 0] = "unchanged"; State[State["added"] = 1] = "added"; State[State["changed"] = 2] = "changed"; State[State["deleted"] = 3] = "deleted"; })(State || (State = {})); var DefaultTypes; (function (DefaultTypes) { // add to the end DefaultTypes[DefaultTypes["none"] = 0] = "none"; DefaultTypes[DefaultTypes["drawing"] = 1] = "drawing"; DefaultTypes[DefaultTypes["fixture"] = 2] = "fixture"; DefaultTypes[DefaultTypes["fixtureContainer"] = 3] = "fixtureContainer"; DefaultTypes[DefaultTypes["fixtureProduct"] = 4] = "fixtureProduct"; //gondola = 5, DefaultTypes[DefaultTypes["container"] = 6] = "container"; DefaultTypes[DefaultTypes["polygon"] = 7] = "polygon"; DefaultTypes[DefaultTypes["shape"] = 8] = "shape"; DefaultTypes[DefaultTypes["text"] = 9] = "text"; DefaultTypes[DefaultTypes["segment"] = 10] = "segment"; DefaultTypes[DefaultTypes["polyline"] = 11] = "polyline"; DefaultTypes[DefaultTypes["arc"] = 12] = "arc"; DefaultTypes[DefaultTypes["dimension"] = 13] = "dimension"; DefaultTypes[DefaultTypes["callout"] = 14] = "callout"; // shapeContainer = 15, DefaultTypes[DefaultTypes["reference"] = 16] = "reference"; DefaultTypes[DefaultTypes["block"] = 17] = "block"; DefaultTypes[DefaultTypes["gondolaWall"] = 18] = "gondolaWall"; })(DefaultTypes || (DefaultTypes = {})); class ShapeOver { } var ShapeTypes; (function (ShapeTypes) { ShapeTypes[ShapeTypes["none"] = 0] = "none"; ShapeTypes[ShapeTypes["Rect"] = 1] = "Rect"; ShapeTypes[ShapeTypes["Ellipse"] = 2] = "Ellipse"; })(ShapeTypes || (ShapeTypes = {})); var TextLayout; (function (TextLayout) { TextLayout[TextLayout["none"] = 0] = "none"; TextLayout[TextLayout["Above"] = 1] = "Above"; TextLayout[TextLayout["Inside"] = 2] = "Inside"; TextLayout[TextLayout["Bellow"] = 3] = "Bellow"; })(TextLayout || (TextLayout = {})); var LineStyles; (function (LineStyles) { LineStyles[LineStyles["none"] = 0] = "none"; LineStyles[LineStyles["Solid"] = 1] = "Solid"; LineStyles[LineStyles["Dashed"] = 2] = "Dashed"; LineStyles[LineStyles["Dotted"] = 3] = "Dotted"; })(LineStyles || (LineStyles = {})); var LineTypes; (function (LineTypes) { LineTypes[LineTypes["none"] = 0] = "none"; LineTypes[LineTypes["Line"] = 1] = "Line"; LineTypes[LineTypes["Arc"] = 2] = "Arc"; })(LineTypes || (LineTypes = {})); const Types = Object.assign(Object.assign({}, DefaultTypes), CustomTypes); const Actions = Object.assign(Object.assign({}, DefaultActions), CustomActions); class Tools { Rotate(point, center, angle) { const origin = new Point(point.x - center.x, point.y - center.y); if (angle === 0) { return origin; } const radians = angle * Math.PI / 180.0; const nx = origin.x * Math.cos(radians) - origin.y * Math.sin(radians); const ny = origin.x * Math.sin(radians) + origin.y * Math.cos(radians); return new Point(nx, ny); } Normal(point, start, end) { if (end.x === start.x) return new Point(start.x, point.y); if (end.y === start.y) return new Point(point.x, start.y); const k1 = (end.y - start.y) / (end.x - start.x); const k2 = (start.x - end.x) / (end.y - start.y); const b1 = start.y - k1 * start.x; const b2 = point.y - k2 * point.x; const x = (b2 - b1) / (k1 - k2); const y = k1 * x + b1; return new Point(x, y); } DistanceTo(point, start, end) { return Math.abs((end.y - start.y) * point.x - (end.x - start.x) * point.y + end.x * start.y - end.y * start.x) / Math.sqrt(Math.pow(end.y - start.y, 2) + Math.pow(end.x - start.x, 2)); } Intersect_OLD(a, b, c, d) { /* (Ay-Cy)(Dx-Cx)-(Ax-Cx)(Dy-Cy) r = ----------------------------- (eqn 1) (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx) */ const p = this.Intersection(a, b, c, d); return (p.x !== 0 && p.y !== 0); } Intersect(a, b, c, d) { return this.doIntersect(a, b, c, d); } // Given three colinear points p, q, r, the function checks if // point q lies on line segment 'pr' onSegment(p, q, r) { if (q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y)) return true; return false; } // To find orientation of ordered triplet (p, q, r). // The function returns following values // 0 --> p, q and r are colinear // 1 --> Clockwise // 2 --> Counterclockwise orientation(p, q, r) { // See https://www.geeksforgeeks.org/orientation-3-ordered-points/ // for details of below formula. const val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y); if (val === 0) return 0; // colinear return (val > 0 ? 1 : 2); // clock or counterclock wise } // The main function that returns true if line segment 'p1q1' // and 'p2q2' intersect. doIntersect(p1, q1, p2, q2) { // Find the four orientations needed for general and // special cases const o1 = this.orientation(p1, q1, p2); const o2 = this.orientation(p1, q1, q2); const o3 = this.orientation(p2, q2, p1); const o4 = this.orientation(p2, q2, q1); // General case if (o1 !== o2 && o3 !== o4) return true; // Special Cases // p1, q1 and p2 are colinear and p2 lies on segment p1q1 if (o1 === 0 && this.onSegment(p1, p2, q1)) return true; // p1, q1 and q2 are colinear and q2 lies on segment p1q1 if (o2 === 0 && this.onSegment(p1, q2, q1)) return true; // p2, q2 and p1 are colinear and p1 lies on segment p2q2 if (o3 === 0 && this.onSegment(p2, p1, q2)) return true; // p2, q2 and q1 are colinear and q1 lies on segment p2q2 if (o4 === 0 && this.onSegment(p2, q1, q2)) return true; return false; // Doesn't fall in any of the above cases } Intersection(p1, p2, p3, p4) { // calculate differences let xD1 = p2.x - p1.x; let yD1 = p2.y - p1.y; let xD2 = p4.x - p3.x; let yD2 = p4.y - p3.y; const xD3 = p1.x - p3.x; const yD3 = p1.y - p3.y; // calculate the lengths of the two lines const Len1 = Math.sqrt(xD1 * xD1 + yD1 * yD1); const Len2 = Math.sqrt(xD2 * xD2 + yD2 * yD2); // calculate angle between the two lines. const dot = (xD1 * xD2 + yD1 * yD2); // dot product const deg = dot / (Len1 * Len2); // if Math.Abs(angle)==1 then the lines are parallell, // so no intersection is possible if (Math.abs(deg) === 1) return new Point(0, 0); // find intersection Pt between two lines const pt = new Point(0, 0); const div = yD2 * xD1 - xD2 * yD1; const ua = (xD2 * yD3 - yD2 * xD3) / div; const ub = (xD1 * yD3 - yD1 * xD3) / div; pt.x = p1.x + ua * xD1; pt.y = p1.y + ua * yD1; // calculate the combined length of the two segments // between Pt-p1 and Pt-p2 xD1 = pt.x - p1.x; yD1 = pt.y - p1.y; xD2 = pt.x - p2.x; yD2 = pt.y - p2.y; const len1 = Math.sqrt(xD1 * xD1 + yD1 * yD1) + Math.sqrt(xD2 * xD2 + yD2 * yD2); // calculate the combined length of the two segments // between Pt-p3 and Pt-p4 xD1 = pt.x - p3.x; yD1 = pt.y - p3.y; xD2 = pt.x - p4.x; yD2 = pt.y - p4.y; const len2 = Math.sqrt(xD1 * xD1 + yD1 * yD1) + Math.sqrt(xD2 * xD2 + yD2 * yD2); const diff1 = Math.abs(Len1 - len1); const diff2 = Math.abs(Len2 - len2); if (diff1 > 0.01 || diff2 > 0.01) return new Point(0, 0); return pt; } PointSide(point, start, end) { const D = (point.x - start.x) * (end.y - start.y) - (point.y - start.y) * (end.x - start.x); const result = (D === 0 ? 'INSIDE' : (D > 0 ? 'RIGHT' : 'LEFT')); return result; } RoundRect(ctx, x, y, width, height, radius, fill, stroke) { if (typeof stroke === 'undefined') { stroke = true; } if (typeof radius === 'undefined') { radius = 5; } // --width; // --height; // x -= 0.5; // y -= 0.5; ctx.beginPath(); ctx.moveTo(x + radius, y); ctx.lineTo(x + width - radius, y); ctx.quadraticCurveTo(x + width, y, x + width, y + radius); ctx.lineTo(x + width, y + height - radius); ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height); ctx.lineTo(x + radius, y + height); ctx.quadraticCurveTo(x, y + height, x, y + height - radius); ctx.lineTo(x, y + radius); ctx.quadraticCurveTo(x, y, x + radius, y); ctx.closePath(); if (fill) ctx.fill(); if (stroke) ctx.stroke(); } MeasureText(text, font, style) { let div = document.createElement('div'); document.body.appendChild(div); div.style.font = font; div.style.position = 'absolute'; div.style.left = '-1000'; div.style.top = '-1000'; div.style.fontStyle = style; div.innerHTML = text; const result = { width: div.clientWidth, height: div.clientHeight }; document.body.removeChild(div); div = null; return result; } } class Selector { constructor(canvas, service) { this.service = service; this.canvas = canvas; this.selected = new Array(); this.focused = null; this.tools = new Tools(); service.focusedMove$.subscribe((offset) => this.OnFocusedMove(offset)); } get StartX() { return this.startX; } set StartX(x) { this.startX = x; this.rect = null; } get StartY() { return this.startY; } set StartY(y) { this.startY = y; this.rect = null; } get EndX() { return this.endX; } set EndX(x) { this.endX = x; this.rect = null; } get EndY() { return this.endY; } set EndY(y) { this.endY = y; this.rect = null; } OnFocusedMove(offset) { for (let i = 0; i < this.selected.length; ++i) { if (this.selected[i].IsFocused) continue; if (this.selected[i].ParentID !== null) continue; this.selected[i].MoveOffset(offset.x, offset.y); } } GetPoints() { const x = Math.min(this.startX, this.endX); const y = Math.min(this.startY, this.endY); const w = Math.abs(this.startX - this.endX); const h = Math.abs(this.startY - this.endY); const points = [ { x: x, y: y }, { x: x + w, y: y }, { x: x + w, y: y + h }, { x: x, y: y + h }, { x: x, y: y } ]; return points; } Refresh() { if (this.rect !== null) return; const x = Math.min(this.startX, this.endX); const y = Math.min(this.startY, this.endY); const w = Math.abs(this.startX - this.endX); const h = Math.abs(this.startY - this.endY); this.rect = new Rect(x, y, w, h); } Add(object) { if (this.rect === null) return false; if (object === undefined) return false; if (object.IsSelected) return false; let flag = true; const x = this.rect.x / this.canvas.scale - this.canvas.canvasOffsetX; const y = this.rect.y / this.canvas.scale - this.canvas.canvasOffsetY; const modelRect = new Rect(x, y, this.rect.w / this.canvas.scale, this.rect.h / this.canvas.scale); const points = object.GetPolygon(); for (let j = 0; j < points.length; ++j) { if (!modelRect.IsContains(points[j])) { flag = false; break; } } if (!flag) return false; if (this.selected.length === 0) { this.focused = object; object.IsFocused = true; } this.selected.push(object); object.IsSelected = true; return true; } ClearSelection() { this.selected = new Array(); if (this.focused === null) return; this.focused.IsFocused = false; this.focused.activePoint = -1; this.focused.activeLine = -1; this.focused = null; } Select(point, isRightClick) { var toRedraw = []; var object = this.canvas.GetObjectClicked(point); if (object === undefined) { if (this.focused !== null) { const res = this.UnSelect(); this.canvas.DRAW(res); this.service.SelectedChanged(null); } return false; } if (!this.canvas.isAltKey) { if (object.type === Types.polyline) { } if (object.type === Types.polygon) { if (object.Text.IsFocused) { this.selected.push(object); } else { if (!object.IsSelected) { this.UnSelect(); } if (object.activeLine !== -1) { this.selected.push(object); } } } else { if (object.IsRef) { if (object.IsSelected) { object.Reference.IsVisible = !object.Reference.IsVisible; if (object.Reference.IsRef) { object.Reference.Reference.IsVisible = object.Reference.IsVisible; //????????????????????? } } else { object.Reference.IsVisible = true; } } if (!object.IsSelected) { toRedraw = this.UnSelect(); this.selected.push(object); if (CustomObject.Select(object)) { var layer = this.canvas.map.get(object.Type); if (layer !== undefined) { var type = Types[object.Type].toString(); if (toRedraw.indexOf(type) === -1) toRedraw.push(type); var child = this.canvas.mapChildren.get(object.Type); if (child !== undefined) { var type = Types[child].toString(); if (toRedraw.indexOf(type) === -1) toRedraw.push(type); } } var layer = this.canvas.map.get(object.ParentType); if (layer !== undefined) { var type = Types[object.ParentType].toString(); if (toRedraw.indexOf(type) === -1) toRedraw.push(type); } } if (object.type === Types.reference) { object.IsVisible = true; object.Select(); } } } if (this.focused !== null && this.focused !== object) { this.focused.IsFocused = false; this.focused.activePoint = -1; this.focused.activeLine = -1; if (!object.IsSelected) { this.focused.IsSelected = false; } } this.focused = object; this.focused.IsFocused = true; this.focused.IsSelected = true; this.focused.ClickOffsetX = point.x - this.focused.X; this.focused.ClickOffsetY = point.y - this.focused.Y; } else { if (object.type === Types.polygon) { if (object.Text.IsFocused) { this.selected.push(object); } else { if (!object.IsSelected) { this.UnSelect(); } if (object.activeLine !== -1) { this.selected.push(object); } } } else { if (!object.IsSelected) { this.selected.push(object); if (CustomObject.Select(object)) { var layer = this.canvas.map.get(object.Type); if (layer !== undefined) { var type = Types[object.Type].toString(); if (toRedraw.indexOf(type) === -1) toRedraw.push(type); } var layer = this.canvas.map.get(object.ParentType); if (layer !== undefined) { var type = Types[object.ParentType].toString(); if (toRedraw.indexOf(type) === -1) toRedraw.push(type); } } if (object.type === Types.reference) { object.IsVisible = true; } if (object.type === Types.shape) { if (object.IsRef) object.Reference.IsVisible = true; } if (this.focused !== null) { this.focused.IsFocused = false; this.focused.activePoint = -1; this.focused.activeLine = -1; } this.focused = object; this.focused.IsFocused = true; this.focused.IsSelected = true; this.focused.ClickOffsetX = point.x - this.focused.X; this.focused.ClickOffsetY = point.y - this.focused.Y; } else { const i = this.selected.indexOf(object); if (i > -1) { this.selected.splice(i, 1); } object.IsSelected = false; if (object.IsFocused) { this.focused.IsFocused = false; this.focused.activePoint = -1; this.focused.activeLine = -1; this.focused = null; if (this.selected.length > 0) { this.focused = this.selected[0]; this.focused.IsFocused = true; } } } } } var newSelected = Types[object.type]; if (toRedraw.indexOf(newSelected) === -1) toRedraw.push(Types[object.type]); if (toRedraw.indexOf('selected') === -1) toRedraw.push('selected'); if (object.isRef) if (toRedraw.indexOf('reference') === -1) toRedraw.push('reference'); if (object.type === Types.text && object.ParentType === Types.polygon) if (toRedraw.indexOf('polygon') === -1) toRedraw.push('polygon'); this.canvas.DRAW(toRedraw); return true; } UnSelect() { if (this.selected.length === 0) return []; const wasSelected = new Array(); wasSelected.push('selected'); for (let i = 0; i < this.selected.length; ++i) { this.selected[i].IsSelected = false; if (CustomObject.UnSelect(this.selected[i])) { var child = this.canvas.mapChildren.get(this.selected[i].type); if (child !== undefined) { var type = Types[child].toString(); if (wasSelected.indexOf(type) === -1) wasSelected.push(type); type = Types[this.selected[i].type].toString(); if (wasSelected.indexOf(type) === -1) wasSelected.push(type); } } switch (this.selected[i].type) { case Types.block: { if (wasSelected.indexOf('block') === -1) wasSelected.push('block'); } break; case Types.dimension: { if (wasSelected.indexOf('dimension') === -1) wasSelected.push('dimension'); } break; case Types.segment: { if (wasSelected.indexOf('segment') === -1) wasSelected.push('segment'); } break; case Types.arc: { if (wasSelected.indexOf('arc') === -1) wasSelected.push('arc'); } break; case Types.polygon: { if (wasSelected.indexOf('polygon') === -1) wasSelected.push('polygon'); } break; case Types.callout: { if (wasSelected.indexOf('callout') === -1) wasSelected.push('callout'); } break; case Types.polyline: { if (wasSelected.indexOf('polyline') === -1) wasSelected.push('polyline'); this.selected[i].activePoint = -1; this.selected[i].activeLine = -1; this.selected[i].activeLineKeeper = -1; } break; case Types.reference: { this.selected[i].IsVisible = false; if (wasSelected.indexOf('reference') === -1) wasSelected.push('reference'); for (var j = 0; j < this.selected[i].Children.length; ++j) { var toRedraw = Types[this.selected[i].Children[j].type]; if (wasSelected.indexOf(toRedraw) === -1) wasSelected.push(toRedraw); } } break; case Types.shape: { if (CustomObject.UnSelect(this.selected[i])) { var layer = this.canvas.map.get(this.selected[i].ParentType); if (layer !== null) { var type = Types[this.selected[i].ParentType].toString(); if (wasSelected.indexOf(type) === -1) wasSelected.push(type); } } if (this.selected[i].IsRef) { this.selected[i].Reference.IsVisible = false; if (this.selected[i].Reference.IsRef) { this.selected[i].Reference.Reference.IsVisible = false; } if (wasSelected.indexOf('reference') === -1) wasSelected.push('reference'); } if (wasSelected.indexOf('shape') === -1) wasSelected.push('shape'); } break; case Types.text: { if (this.selected[i].ParentType === Types.polygon) { if (wasSelected.indexOf('polygon') === -1) wasSelected.push('polygon'); } else { if (wasSelected.indexOf('text') === -1) wasSelected.push('text'); } } break; } } this.ClearSelection(); return wasSelected; } IsContains(point) { return false; } Draw(c) { if (c === null || c === undefined) return; this.Refresh(); const borderThickness = 0.25; c.clearRect(-0.5, -0.5, this.canvas.width + 1, this.canvas.height + 1); if (this.canvas.action === Actions.select || this.canvas.action === Actions.selectShapes) { c.save(); c.fillStyle = 'rgba(128, 159, 255, 0.15)'; c.strokeStyle = 'rgba( 0, 45, 179, 1.00)'; c.lineWidth = borderThickness; c.beginPath(); c.rect(this.rect.x + (0.5 / this.canvas.scale), this.rect.y + (0.5 / this.canvas.scale), this.rect.w, this.rect.h); c.closePath(); c.fill(); c.stroke(); c.restore(); } if (this.canvas.action === Actions.selectShapesInOrder) { c.save(); c.strokeStyle = 'rgba( 0, 45, 179, 1.00)'; c.lineWidth = borderThickness; c.beginPath(); c.moveTo(this.startX, this.startY); c.lineTo(this.endX, this.endY); c.closePath(); c.stroke(); c.restore(); } CustomObject.DoCustomAction(c, this.canvas.action, this.startX, this.startY, this.endX, this.endY, this.canvas.scale, borderThickness); } DrawRegularGondola(c) { const LocationW = 40; const LocationH = 20; const Start = 0; const End = 0; try { const start = new Point(this.StartX / this.canvas.scale, this.StartY / this.canvas.scale); const end = new Point(this.EndX / this.canvas.scale, this.EndY / this.canvas.scale); const vector = new Vector(start, end); const angle = vector.Angle(); const len = vector.Length(); const vectorStartCap = new Vector(start, end); vectorStartCap.Normalize(); vectorStartCap.Scale(-LocationH); const vectorEndCap = new Vector(start, end); vectorEndCap.Normalize(); vectorEndCap.Scale(LocationH); const vector1 = new Vector(start, end); vector1.Rotate90(); vector1.Normalize(); vector1.Scale(LocationH); const vector2 = new Vector(start, end); vector2.Rotate90(); vector2.Rotate90(); vector2.Rotate90(); vector2.Normalize(); vector2.Scale(LocationH); const gondola = new Line(this.startX, this.startY, this.endX, this.endY); const line1 = new Line(this.startX + vector2.x, this.startY + vector2.y, this.startX + vector1.x, this.startY + vector1.y); const line2 = new Line(this.startX + vector1.x, this.startY + vector1.y, this.endX + vector1.x, this.endY + vector1.y); const line3 = new Line(this.endX + vector1.x, this.endY + vector1.y, this.endX + vector2.x, this.endY + vector2.y); const line4 = new Line(this.endX + vector2.x, this.endY + vector2.y, this.startX + vector2.x, this.startY + vector2.y); const line5 = new Line(this.startX + vector1.x, this.startY + vector1.y, this.startX + vectorStartCap.x + vector1.x, this.startY + vectorStartCap.y + vector1.y); const line6 = new Line(this.startX + vectorStartCap.x + vector1.x, this.startY + vectorStartCap.y + vector1.y, this.startX + vectorStartCap.x + vector2.x, this.startY + vectorStartCap.y + vector2.y); const line7 = new Line(this.startX + vectorStartCap.x + vector2.x, this.startY + vectorStartCap.y + vector2.y, this.startX + vector2.x, this.startY + vector2.y); const line8 = new Line(this.endX + vector1.x, this.endY + vector1.y, this.endX + vectorEndCap.x + vector1.x, this.endY + vectorEndCap.y + vector1.y); const line9 = new Line(this.endX + vectorEndCap.x + vector1.x, this.endY + vectorEndCap.y + vector1.y, this.endX + vectorEndCap.x + vector2.x, this.endY + vectorEndCap.y + vector2.y); const line10 = new Line(this.endX + vectorEndCap.x + vector2.x, this.endY + vectorEndCap.y + vector2.y, this.endX + vector2.x, this.endY + vector2.y); c.beginPath(); c.moveTo(gondola.x1, gondola.y1); c.lineTo(gondola.x2, gondola.y2); c.moveTo(line1.x1, line1.y1); c.lineTo(line1.x2, line1.y2); c.lineTo(line2.x2, line2.y2); c.lineTo(line3.x2, line3.y2); c.lineTo(line4.x2, line4.y2); c.moveTo(line5.x1, line5.y1); c.lineTo(line5.x2, line5.y2); c.lineTo(line6.x2, line6.y2); c.lineTo(line7.x2, line7.y2); c.moveTo(line8.x1, line8.y1); c.lineTo(line8.x2, line8.y2); c.lineTo(line9.x2, line9.y2); c.lineTo(line10.x2, line10.y2); c.closePath(); c.stroke(); const vector3 = new Vector(start, end); const tempID = 1; // int tempID = Map.NextAreaID; const count = (len / LocationW); const areaCount = 2 * count + 2; for (let i = 1; i <= count; ++i) { vector3.Normalize(); vector3.Scale(LocationW * i); const line = new Line(this.startX + vector1.x + vector3.x, this.startY + vector1.y + vector3.y, this.startX + vector2.x + vector3.x, this.startY + vector2.y + vector3.y); c.beginPath(); c.moveTo(line.x1, line.y1); c.lineTo(line.x2, line.y2); c.closePath(); c.stroke(); } const vector5 = new Vector(start, end); const vector6 = new Vector(start, end); vector6.Normalize(); vector6.Scale(-LocationW / 2); const vector7 = new Vector(start, end); vector7.Rotate90(); vector7.Normalize(); vector7.Scale(LocationH / 2 - 4); let text = ''; let x = 0; let y = 0; for (let i = 1; i <= count; ++i) { c.save(); vector5.Normalize(); vector5.Scale(LocationW * i); // text = (tempID + i-1).toString(); text = (tempID + 2 * Math.floor(count) + 1 - i).toString(); x = this.startX + vector5.x + vector6.x + vector7.x; y = this.startY + vector5.y + vector6.y + vector7.y; c.translate(x, y); c.rotate(angle * Math.PI / 180); // c.font = '10px Source Sans Pro'; // c.font = '10px Open Sans'; c.font = '10px Sans'; c.fillStyle = 'black'; c.textAlign = 'center'; c.fillText(text, 0, 0); c.restore(); } text = (tempID + Math.floor(count)).toString(); const vector8 = new Vector(start, end); vector8.Normalize(); vector8.Scale(LocationH / 2 - 3); x = this.endX + vector8.x; y = this.endY + vector8.y; c.save(); c.translate(x, y); c.rotate((angle + 90) * Math.PI / 180); c.font = '10px Sans'; c.fillStyle = 'black'; c.textAlign = 'center'; c.fillText(text, 0, 0); c.restore(); vector7.Normalize(); vector7.Scale(-LocationH / 2 + 4); for (let i = 1; i <= count; ++i) { c.save(); vector5.Normalize(); vector5.Scale(LocationW * i); text = (tempID + i - 1).toString(); // text = (tempID + 2 * Math.floor(count) + 1 - i).toString(); x = this.startX + vector5.x + vector6.x + vector7.x; y = this.startY + vector5.y + vector6.y + vector7.y; c.translate(x, y); c.rotate((angle + 180) * Math.PI / 180); c.font = '10px Sans'; c.fillStyle = 'black'; c.textAlign = 'center'; c.fillText(text, 0, 0); c.restore(); } const vector9 = new Vector(start, end); vector9.Normalize(); vector9.Scale(-LocationH / 2 + 4); text = (tempID + 2 * Math.floor(count) + 1).toString(); x = this.startX + vector9.x; y = this.startY + vector9.y; c.save(); c.translate(x, y); c.rotate((angle + 270) * Math.PI / 180); c.font = '10px Sans'; c.fillStyle = 'black'; c.textAlign = 'center'; c.fillText(text, 0, 0); c.restore(); } catch (ex) { } } DrawWallGondola(c) { const LocationW = 40; const LocationH = 20; const Start = 0; const End = 0; try { const start = new Point(this.StartX / this.canvas.scale, this.StartY / this.canvas.scale); const end = new Point(this.EndX / this.canvas.scale, this.EndY / this.canvas.scale); const vector = new Vector(start, end); const angle = vector.Angle(); const len = vector.Length(); const vector2 = new Vector(start, end); vector2.Rotate90(); vector2.Normalize(); vector2.Scale(-LocationH); const gondola = new Line(this.startX, this.startY, this.endX, this.endY); const line1 = new Line(this.endX, this.endY, this.endX + vector2.x, this.endY + vector2.y); const line2 = new Line(this.endX + vector2.x, this.endY + vector2.y, this.startX + vector2.x, this.startY + vector2.y); const line3 = new Line(this.startX, this.startY, this.startX + vector2.x, this.startY + vector2.y); c.beginPath(); c.moveTo(gondola.x1, gondola.y1); c.lineTo(gondola.x2, gondola.y2); c.lineTo(line1.x2, line1.y2); c.lineTo(line2.x2, line2.y2); c.lineTo(line3.x2, line3.y2); c.closePath(); c.stroke(); const vector3 = new Vector(start, end); const tempID = 1; // int tempID = Map.NextAreaID; const count = (len / LocationW); const areaCount = 2 * count + 2; for (let i = 1; i <= count; ++i) { vector3.Normalize(); vector3.Scale(LocationW * i); const line = new Line(this.startX + vector3.x, this.startY + vector3.y, this.startX + vector2.x + vector3.x, this.startY + vector2.y + vector3.y); c.beginPath(); c.moveTo(line.x1, line.y1); c.lineTo(line.x2, line.y2); c.closePath(); c.stroke(); } const vector4 = new Vector(start, end); const vector5 = new Vector(start, end); vector5.Normalize(); vector5.Scale(-LocationW / 2 - 5); const vector6 = new Vector(start, end); vector6.Normalize(); vector6.Scale(LocationH / 2 - 3); let text = ''; let x = 0; let y = 0; for (let i = 1; i <= count; ++i) { c.save(); vector4.Normalize(); vector4.Scale(LocationW * i); text = (tempID + i - 1).toString(); x = this.startX + vector4.x + vector5.x + vector6.x; y = this.startY + vector4.y + vector5.y + vector6.x; c.translate(x, y); c.rotate((angle + 180) * Math.PI / 180); c.font = '10px Sans'; c.fillStyle = 'black'; c.textAlign = 'center'; c.fillText(text, 0, 0); c.restore(); } } catch (ex) { } } DrawArea(c) { if (this.startX > this.endX) return; if (this.startY > this.endY) return; const LocationW = 40; const LocationH = 20; const paddingLeft = 5; const paddingTop = 5; const paddingRight = 5; const paddingBottom = 5; const rect = new Rect(this.startX, this.startY, this.endX - this.startX, this.endY - this.startY); let itemX = rect.x + paddingLeft * this.canvas.scale; let itemY = rect.y + paddingTop * this.canvas.scale; let text = ''; const tempID = 1; c.globalAlpha = 0.75; c.strokeStyle = '#444'; c.fillStyle = '#eee'; c.save(); c.beginPath(); c.rect(rect.x, rect.y, rect.w, rect.h); c.closePath(); c.fill(); c.stroke(); c.restore(); c.save(); text = 'Area 1'; const x = itemX; const y = itemY; c.font = '10px Sans'; c.fillStyle = 'black'; c.textAlign = 'left'; c.fillText(text, rect.x + 1, rect.y - 3); c.restore(); c.strokeStyle = '#777'; c.fillStyle = '#eee'; if (rect.w < 45 || rect.h < 25) return; const vector4 = new Vector(100, 0); vector4.Normalize(); vector4.Scale(LocationW / 2); const vector5 = new Vector(0, 100); vector5.Normalize(); vector5.Scale(LocationH / 2 + 4); for (let i = 0;; ++i) { if (itemX + LocationW + 3 > rect.x + rect.w) { itemX = rect.x + paddingLeft * this.canvas.scale; itemY = itemY + LocationH + 3; if (itemY + LocationH + 3 > rect.y + rect.h) { break; } } c.save(); c.beginPath(); this.tools.RoundRect(c, itemX, itemY, LocationW, LocationH, 3, '#f00', '#000'); c.closePath(); c.stroke(); c.restore(); c.save(); vector4.Normalize(); vector4.Scale(LocationW / 2); text = (tempID + i).toString(); const x = itemX + vector4.x + vector5.x; const y = itemY + vector4.y + vector5.y; c.font = '10px Sans'; c.fillStyle = 'black'; c.textAlign = 'center'; c.fillText(text, x, y); c.restore(); itemX = itemX + LocationW + 3; } } } class WireText { constructor() { this.MaxHeight = 32; // First dimension: Modern, Roman, Script // Second dimension: ASCII code - 0x20 this.chars = [ [ new StrokeCharacter(16, ""), new StrokeCharacter(10, "M 5 4 L 5 18 M 5 23 L 4 24 5 25 6 24 5 23"), new StrokeCharacter(16, "M 4 4 L 4 11 M 12 4 L 12 11"), new StrokeCharacter(21, "M 11 0 L 4 32 M 17 0 L 10 32 M 4 13 L 18 13 M 3 19 L 17 19"), new StrokeCharacter(20, "M 8 0 L 8 29 M 12 0 L 12 29 M 17 7 L 15 5 12 4 8 4 5 5 3 7 3 9 4 11 5 12 7 13 13 15 15 16 16 17 17 19 17 22 15 24 12 25 8 25 5 24 3 22"), new StrokeCharacter(24, "M 21 4 L 3 25 M 8 4 L 10 6 10 8 9 10 7 11 5 11 3 9 3 7 4 5 6 4 8 4 10 5 13 6 16 6 19 5 21 4 M 17 18 L 15 19 14 21 14 23 16 25 18 25 20 24 21 22 21 20 19 18 17 18"), new StrokeCharacter(26, "M 23 13 L 23 12 22 11 21 11 20 12 19 14 17 19 15 22 13 24 11 25 7 25 5 24 4 23 3 21 3 19 4 17 5 16 12 12 13 11 14 9 14 7 13 5 11 4 9 5 8 7 8 9 9 12 11 15 16 22 18 24 20 25 22 25 23 24 23 23"), new StrokeCharacter(10, "M 5 6 L 4 5 5 4 6 5 6 7 5 9 4 10"), new StrokeCharacter(14, "M 11 0 L 9 2 7 5 5 9 4 14 4 18 5 23 7 27 9 30 11 32"), new StrokeCharacter(14, "M 3 0 L 5 2 7 5 9 9 10 14 10 18 9 23 7 27 5 30 3 32"), /*10*/ new StrokeCharacter(16, "M 8 10 L 8 22 M 3 13 L 13 19 M 13 13 L 3 19"), new StrokeCharacter(26, "M 13 7 L 13 25 M 4 16 L 22 16"), new StrokeCharacter(10, "M 5 23 L 4 24 5 25 6 24 5 23 M 6 24 L 6 26 5 28 4 29"), new StrokeCharacter(26, "M 4 16 L 22 16"), new StrokeCharacter(10, "M 5 23 L 4 24 5 25 6 24 5 23"), new StrokeCharacter(22, "M 20 0 L 2 32"), new StrokeCharacter(20, "M 9 4 L 6 5 4 8 3 13 3 16 4 21 6 24 9 25 11 25 14 24 16 21 17 16 17 13 16 8 14 5 11 4 9 4"), new StrokeCharacter(20, "M 6 8 L 8 7 11 4 11 25"), new StrokeCharacter(20, "M 4 9 L 4 8 5 6 6 5 8 4 12 4 14 5 15 6 16 8 16 10 15 12 13 15 3 25 17 25"), new StrokeCharacter(22, "M 5 4 L 16 4 10 12 13 12 15 13 16 14 17 17 17 19 16 22 14 24 11 25 8 25 5 24 4 23 3 21"), /*20*/ new StrokeCharacter(20, "M 13 4 L 3 18 18 18 M 13 4 L 13 25"), new StrokeCharacter(20, "M 15 4 L 5 4 4 13 5 12 8 11 11 11 14 12 16 14 17 17 17 19 16 22 14 24 11 25 8 25 5 24 4 23 3 21"), new StrokeCharacter(20, "M 16 7 L 15 5 12 4 10 4 7 5 5 8 4 13 4 18 5 22 7 24 10 25 11 25 14 24 16 22 17 19 17 18 16 15 14 13 11 12 10 12 7 13 5 15 4 18"), new StrokeCharacter(20, "M 17 4 L 7 25 M 3 4 L 17 4"), new StrokeCharacter(20, "M 8 4 L 5 5 4 7 4 9 5 11 7 12 11 13 14 14 16 16 17 18 17 21 16 23 15 24 12 25 8 25 5 24 4 23 3 21 3 18 4 16 6 14 9 13 13 12 15 11 16 9 16 7 15 5 12 4 8 4"), new StrokeCharacter(20, "M 16 11 L 15 14 13 16 10 17 9 17 6 16 4 14 3 11 3 10 4 7 6 5 9 4 10 4 13 5 15 7 16 11 16 16 15 21 13 24 10 25 8 25 5 24 4 22"), new StrokeCharacter(10, "M 5 11 L 4 12 5 13 6 12 5 11 M 5 23 L 4 24 5 25 6 24 5 23"), new StrokeCharacter(10, "M 5 11 L 4 12 5 13 6 12 5 11 M 6 24 L 5 25 4 24 5 23 6 24 6 26 5 28 4 29"), new StrokeCharacter(24, "M 20 7 L 4 16 20 25"), new StrokeCharacter(26, "M 4 13 L 22 13 M 4 19 L 22 19"), /*30*/ new StrokeCharacter(24, "M 4 7 L 20 16 4 25"), new StrokeCharacter(18, "M 3 9 L 3 8 4 6 5 5 7 4 11 4 13 5 14 6 15 8 15 10 14 12 13 13 9 15 9 18 M 9 23 L 8 24 9 25 10 24 9 23"), new StrokeCharacter(27, "M 18 12 L 17 10 15 9 12 9 10 10 9 11 8 14 8 17 9 19 11 20 14 20 16 19 17 17 M 12 9 L 10 11 9 14 9 17 10 19 11 20 M 18 9 L 17 17 17 19 19 20 21 20 23 18 24 15 24 13 23 10 22 8 20 6 18 5 15 4 12 4 9 5 7 6 5 8 4 10 3 13 3 16 4 19 5 21 7 23 9 24 12 25 15 25 18 24 20 23 21 22 M 19 9 L 18 17 18 19 19 20"), new StrokeCharacter(18, "M 9 4 L 1 25 M 9 4 L 17 25 M 4 18 L 14 18"), new StrokeCharacter(21, "M 4 4 L 4 25 M 4 4 L 13 4 16 5 17 6 18 8 18 10 17 12 16 13 13 14 M 4 14 L 13 14 16 15 17 16 18 18 18 21 17 23 16 24 13 25 4 25"), new StrokeCharacter(21, "M 18 9 L 17 7 15 5 13 4 9 4 7 5 5 7 4 9 3 12 3 17 4 20 5 22 7 24 9 25 13 25 15 24 17 22 18 20"), new StrokeCharacter(21, "M 4 4 L 4 25 M 4 4 L 11 4 14 5 16 7 17 9 18 12 18 17 17 20 16 22 14 24 11 25 4 25"), new StrokeCharacter(19, "M 4 4 L 4 25 M 4 4 L 17 4 M 4 14 L 12 14 M 4 25 L 17 25"), new StrokeCharacter(18, "M 4 4 L 4 25 M 4 4 L 17 4 M 4 14 L 12 14"), new StrokeCharacter(21, "M 18 9 L 17 7 15 5 13 4 9 4 7 5 5 7 4 9 3 12 3 17 4 20 5 22 7 24 9 25 13 25 15 24 17 22 18 20 18 17 M 13 17 L 18 17"), /*40*/ new StrokeCharacter(22, "M 4 4 L 4 25 M 18 4 L 18 25 M 4 14 L 18 14"), new StrokeCharacter(8, "M 4 4 L 4 25"), new StrokeCharacter(16, "M 12 4 L 12 20 11 23 10 24 8 25 6 25 4 24 3 23 2 20 2 18"), new StrokeCharacter(21, "M 4 4 L 4 25 M 18 4 L 4 18 M 9 13 L 18 25"), new StrokeCharacter(17, "M 4 4 L 4 25 M 4 25 L 16 25"), new StrokeCharacter(24, "M 4 4 L 4 25 M 4 4 L 12 25 M 20 4 L 12 25 M 20 4 L 20 25"), new StrokeCharacter(22, "M 4 4 L 4 25 M 4 4 L 18 25 M 18 4 L 18 25"), new StrokeCharacter(22, "M 9 4 L 7 5 5 7 4 9 3 12 3 17 4 20 5 22 7 24 9 25 13 25 15 24 17 22 18 20 19 17 19 12 18 9 17 7 15 5 13 4 9 4"), new StrokeCharacter(21,