From 5690db42cd4c204290bc90e2830f3f89dadacff2 Mon Sep 17 00:00:00 2001 From: ziajka Date: Tue, 28 Nov 2017 10:30:14 +0100 Subject: [PATCH] Serial Link, fixes: #4 --- .../shared/widgets/ethernet-link.widget.ts | 32 +++++++ .../shared/widgets/links.widget.ts | 85 +++++++++---------- .../shared/widgets/serial-link.widget.ts | 57 +++++++++++++ 3 files changed, 129 insertions(+), 45 deletions(-) create mode 100644 src/app/cartography/shared/widgets/ethernet-link.widget.ts create mode 100644 src/app/cartography/shared/widgets/serial-link.widget.ts diff --git a/src/app/cartography/shared/widgets/ethernet-link.widget.ts b/src/app/cartography/shared/widgets/ethernet-link.widget.ts new file mode 100644 index 00000000..69240a10 --- /dev/null +++ b/src/app/cartography/shared/widgets/ethernet-link.widget.ts @@ -0,0 +1,32 @@ +import {Widget} from "./widget"; +import {SVGSelection} from "../../../map/models/types"; + +import { line } from "d3-shape"; +import {Link} from "../models/link.model"; + +export class EthernetLinkWidget implements Widget { + + public draw(view: SVGSelection, link: Link) { + const link_data = [[ + [link.source.x, link.source.y], + [link.target.x, link.target.y] + ]]; + + const value_line = line(); + + let link_path = view.select('path'); + + if (!link_path.node()) { + link_path = view.append('path'); + } + + const link_path_data = link_path.data(link_data); + + link_path_data + .attr('d', value_line) + .attr('stroke', '#000') + .attr('stroke-width', '2'); + + } + +} diff --git a/src/app/cartography/shared/widgets/links.widget.ts b/src/app/cartography/shared/widgets/links.widget.ts index 0e2903e2..05455c3e 100644 --- a/src/app/cartography/shared/widgets/links.widget.ts +++ b/src/app/cartography/shared/widgets/links.widget.ts @@ -6,11 +6,20 @@ import { SVGSelection } from "../../../map/models/types"; import { Link } from "../models/link.model"; import { LinkStatus } from "../models/link-status.model"; import { MultiLinkCalculatorHelper } from "../../map/helpers/multi-link-calculator-helper"; +import {SerialLinkWidget} from "./serial-link.widget"; +import {EthernetLinkWidget} from "./ethernet-link.widget"; export class LinksWidget implements Widget { private multiLinkCalculatorHelper = new MultiLinkCalculatorHelper(); + private getLinkWidget(link: Link) { + if (link.link_type === 'serial') { + return new SerialLinkWidget(); + } + return new EthernetLinkWidget(); + } + public draw(view: SVGSelection, links: Link[]) { const self = this; @@ -31,64 +40,50 @@ export class LinksWidget implements Widget { link.merge(link_enter) .each(function (this: SVGGElement, l: Link) { - const link_data = [[ - [l.source.x, l.source.y], - [l.target.x, l.target.y] - ]]; - const link_group = select(this); - const value_line = line(); + const link_widget = self.getLinkWidget(l); - let link_path = link_group.select('path'); + link_widget.draw(link_group, l); - if (!link_path.node()) { - link_path = link_group.append('path'); - } + const link_path = link_group.select('path'); - const link_path_data = link_path.data(link_data); + const start_point: SVGPoint = link_path.node().getPointAtLength(50); + const end_point: SVGPoint = link_path.node().getPointAtLength(link_path.node().getTotalLength() - 50); - link_path_data - .attr('d', value_line) - .attr('stroke', '#000') - .attr('stroke-width', '1'); + const statuses = [ + new LinkStatus(start_point.x, start_point.y, l.source.status), + new LinkStatus(end_point.x, end_point.y, l.target.status) + ]; - const start_point: SVGPoint = link_path.node().getPointAtLength(50); - const end_point: SVGPoint = link_path.node().getPointAtLength(link_path.node().getTotalLength() - 50); + const status_started = link_group.selectAll('circle.status_started') + .data(statuses.filter((link_status: LinkStatus) => link_status.status === 'started')); - const statuses = [ - new LinkStatus(start_point.x, start_point.y, l.source.status), - new LinkStatus(end_point.x, end_point.y, l.target.status) - ]; + const status_started_enter = status_started.enter().append('circle'); - const status_started = link_group.selectAll('circle.status_started') - .data(statuses.filter((link_status: LinkStatus) => link_status.status === 'started')); + status_started.merge(status_started_enter) + .attr('class', 'status_started') + .attr('cx', (ls: LinkStatus) => ls.x) + .attr('cy', (ls: LinkStatus) => ls.y) + .attr('r', 4) + .attr('fill', '#2ecc71'); - const status_started_enter = status_started.enter().append('circle'); + status_started.exit().remove(); - status_started.merge(status_started_enter) - .attr('class', 'status_started') - .attr('cx', (ls: LinkStatus) => ls.x) - .attr('cy', (ls: LinkStatus) => ls.y) - .attr('r', 4) - .attr('fill', '#2ecc71'); + const status_stopped = link_group.selectAll('rect.status_stopped') + .data(statuses.filter((link_status: LinkStatus) => link_status.status === 'stopped')); - status_started.exit().remove(); + const status_stopped_enter = status_stopped.enter().append('rect'); + const STOPPED_STATUS_RECT_WIDTH = 6; - const status_stopped = link_group.selectAll('rect.status_stopped') - .data(statuses.filter((link_status: LinkStatus) => link_status.status === 'stopped')); + status_stopped.merge(status_stopped_enter) + .attr('class', 'status_stopped') + .attr('x', (ls: LinkStatus) => ls.x - STOPPED_STATUS_RECT_WIDTH / 2.) + .attr('y', (ls: LinkStatus) => ls.y - STOPPED_STATUS_RECT_WIDTH / 2.) + .attr('width', STOPPED_STATUS_RECT_WIDTH) + .attr('height', STOPPED_STATUS_RECT_WIDTH) + .attr('fill', 'red'); - const status_stopped_enter = status_stopped.enter().append('rect'); - const STOPPED_STATUS_RECT_WIDTH = 6; - - status_stopped.merge(status_stopped_enter) - .attr('class', 'status_stopped') - .attr('x', (ls: LinkStatus) => ls.x - STOPPED_STATUS_RECT_WIDTH / 2.) - .attr('y', (ls: LinkStatus) => ls.y - STOPPED_STATUS_RECT_WIDTH / 2.) - .attr('width', STOPPED_STATUS_RECT_WIDTH) - .attr('height', STOPPED_STATUS_RECT_WIDTH) - .attr('fill', 'red'); - - status_stopped.exit().remove(); + status_stopped.exit().remove(); }) .attr('transform', function(l) { diff --git a/src/app/cartography/shared/widgets/serial-link.widget.ts b/src/app/cartography/shared/widgets/serial-link.widget.ts new file mode 100644 index 00000000..325b1dfd --- /dev/null +++ b/src/app/cartography/shared/widgets/serial-link.widget.ts @@ -0,0 +1,57 @@ +import {Widget} from "./widget"; +import {SVGSelection} from "../../../map/models/types"; +import {Link} from "../models/link.model"; +import { path } from "d3-path"; + + +export class SerialLinkWidget implements Widget { + + public draw(view: SVGSelection, link: Link) { + const dx = link.target.x - link.source.x; + const dy = link.target.y - link.source.y; + + const vector_angle = Math.atan2(dy, dx); + const rot_angle = -Math.PI / 4.0; + const vect_rot = [ + Math.cos(vector_angle + rot_angle), + Math.sin(vector_angle + rot_angle) + ]; + + const angle_source = [ + link.source.x + dx / 2.0 + 15 * vect_rot[0], + link.source.y + dy / 2.0 + 15 * vect_rot[1] + ]; + + const angle_target = [ + link.target.x - dx / 2.0 - 15 * vect_rot[0], + link.target.y - dy / 2.0 - 15 * vect_rot[1] + ]; + + const line_data = [ + [link.source.x, link.source.y], + angle_source, + angle_target, + [link.target.x, link.target.y] + ]; + + let link_path = view.select('path'); + + if (!link_path.node()) { + link_path = view.append('path'); + } + + const line_generator = path(); + line_generator.moveTo(line_data[0][0], line_data[0][1]); + line_generator.lineTo(line_data[1][0], line_data[1][1]); + line_generator.lineTo(line_data[2][0], line_data[2][1]); + line_generator.lineTo(line_data[3][0], line_data[3][1]); + + link_path + .attr('d', line_generator.toString()) + .attr('stroke', '#B22222') + .attr('fill', 'none') + .attr('stroke-width', '2'); + + } + +}