diff --git a/src/hook/algorithm/range-tree.js b/src/hook/algorithm/range-tree.js index 0cdcfd7..908e3ab 100644 --- a/src/hook/algorithm/range-tree.js +++ b/src/hook/algorithm/range-tree.js @@ -1,16 +1,83 @@ export class RangeTreeMap { constructor() { /** - * + * @type {Map} */ this.horizontal = new Map(); /** - * + * @type {Map} */ this.vertical = new Map(); } + /** + * @param {SimpleSegment} segment + */ + insert(segment) { + if (segment.x1 === segment.x2) { + // 竖直线 + const x = segment.x1; + if (!this.vertical.has(x)) { + // TODO: 优化这里 + this.vertical.set(x, []); + } + this.vertical.get(x).push(segment); + } else { + // 水平线 + const y = segment.y1; + if (!this.horizontal.has(y)) { + // TODO: 优化这里 + this.horizontal.set(y, []); + } + this.horizontal.get(y).push(segment); + } + } + + /** + * @description 计算给定点的度 + * @param {SimplePoint} point + */ + getDegree(point) { + // 分别从两个方向进行统计 + const x = point.x; + const y = point.y; + + let degree = 0; + const horizontalSegments = this.horizontal.get(y) || []; + const verticalSegments = this.vertical.get(x) || []; + for (const segment of horizontalSegments) { + const x1 = Math.min(segment.x1, segment.x2); + const x2 = Math.max(segment.x1, segment.x2); + if (x1 <= x && x <= x2) { + degree ++; + } + } + + for (const segment of verticalSegments) { + const y1 = Math.min(segment.y1, segment.y2); + const y2 = Math.max(segment.y1, segment.y2); + if (y1 <= y && y <= y2) { + degree ++; + } + } + + return degree; + } } + +/** + * @typedef SimpleSegment + * @property {number} x1 + * @property {number} y1 + * @property {number} x2 + * @property {number} y2 + */ + +/** + * @typedef SimplePoint + * @property {number} x + * @property {number} y + */ \ No newline at end of file diff --git a/src/hook/render/cross-dot.js b/src/hook/render/cross-dot.js index e87e751..69d7f14 100644 --- a/src/hook/render/cross-dot.js +++ b/src/hook/render/cross-dot.js @@ -33,6 +33,7 @@ export class CrossDotRender { id: this.crossId, x, y, + r: 3.5 }); this.crossId ++; diff --git a/src/hook/render/index.js b/src/hook/render/index.js index 31b4e0f..1db285d 100644 --- a/src/hook/render/index.js +++ b/src/hook/render/index.js @@ -13,6 +13,7 @@ import { pinkLog, redLog } from '../utils'; import { treeviewData } from '@/components/treeview/tree'; import { dotConnect } from './yosys'; import { CrossDotRender } from './cross-dot'; +import { RangeTreeMap } from '../algorithm/range-tree'; export class NetlistRender { /** @@ -287,6 +288,8 @@ export class NetlistRender { this.wireRender = new WireRender(parentSelection, this); this.crossDotRender = new CrossDotRender(parentSelection, this); + const rangeTree = new RangeTreeMap(); + for (const edge of computedLayout.edges) { for (const section of edge.sections || []) { const points = []; @@ -296,10 +299,34 @@ export class NetlistRender { } points.push(section.endPoint); this.wireRender.addAsD3DataItems(points, edge); + + // 加入 range tree 中 + for (let i = 0; i < points.length - 1; ++ i) { + rangeTree.insert({ + x1: points[i].x, + y1: points[i].y, + x2: points[i + 1].x, + y2: points[i + 1].y + }); + } + } + } + + // 找出所有的交叉点 + for (const edge of computedLayout.edges) { + for (const section of edge.sections || []) { + // 交叉点一定不是起点和终点 + for (const point of section.bendPoints || []) { + const degree = rangeTree.getDegree(point); + if (degree >= 3) { + this.crossDotRender.addAsD3DataItem(point.x, point.y); + } + } } } this.wireRender.render(); + this.crossDotRender.render(); } /** diff --git a/src/hook/render/wire.js b/src/hook/render/wire.js index 5201802..c56cf62 100644 --- a/src/hook/render/wire.js +++ b/src/hook/render/wire.js @@ -54,12 +54,11 @@ export class WireRender { // 判断当前的朝向 const endPoint = points.at(-1); const direction = endPoint.x > points.at(-2).x ? 'right' : 'left'; - const arrowX = direction === 'right' ? endPoint.x - LAYOUT_CONSTANT.CELL_PORT_WIDTH - this.arrowWidth: - endPoint.x + LAYOUT_CONSTANT.CELL_PORT_WIDTH - + const arrowX = direction === 'right' ? endPoint.x - LAYOUT_CONSTANT.CELL_PORT_WIDTH - this.arrowWidth + 2.5: + endPoint.x + LAYOUT_CONSTANT.CELL_PORT_WIDTH - 2.5 + const arrowY = endPoint.y - this.arrowHeight / 2; - this.data.push({ id: this.idCounter, svg: lineSvg, diff --git a/src/hook/skin/plusation.js b/src/hook/skin/plusation.js index a95ace7..61c7259 100644 --- a/src/hook/skin/plusation.js +++ b/src/hook/skin/plusation.js @@ -8,7 +8,6 @@ export class PulseLine { this.pluseId = undefined; } - /** * * @param {d3.Selection} parentSelection