实现 range tree
This commit is contained in:
parent
ebb45b12a1
commit
c403c8434c
@ -1,16 +1,83 @@
|
||||
export class RangeTreeMap {
|
||||
constructor() {
|
||||
/**
|
||||
*
|
||||
* @type {Map<number, SimpleSegment[]>}
|
||||
*/
|
||||
this.horizontal = new Map();
|
||||
|
||||
/**
|
||||
*
|
||||
* @type {Map<number, SimpleSegment[]>}
|
||||
*/
|
||||
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
|
||||
*/
|
@ -33,6 +33,7 @@ export class CrossDotRender {
|
||||
id: this.crossId,
|
||||
x,
|
||||
y,
|
||||
r: 3.5
|
||||
});
|
||||
|
||||
this.crossId ++;
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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,
|
||||
|
@ -8,7 +8,6 @@ export class PulseLine {
|
||||
this.pluseId = undefined;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {d3.Selection} parentSelection
|
||||
|
Loading…
x
Reference in New Issue
Block a user