feat: v1.4 组合画布旋转编辑+方向核验+双向门符号
- 组合画布旋转编辑: 选中单元 ⟲/⟳ 90°旋转(绕几何中心) 分割线法向与开向角度同步旋转, 水平镜像(开向镜像) - 数据方向核验: 以31729/31740真实图纸比对确认2D渲染Y向正确 - 2D渲染补双向开启门虚线交叉符号(wtf) - Node数学验证: 旋转后宽高互换/法向转轴/可逆性全部通过
This commit is contained in:
@@ -247,7 +247,7 @@ function drawFrame(
|
||||
|
||||
// 扇(推断: 有效bd → polyId区域(双扇对半) → 帧bbox按扇数均分)
|
||||
const regionBBs = regions.map(pts => bboxOf(pts))
|
||||
type Glyph = { x0: number; y0: number; x1: number; y1: number; od: number; openToward?: string; isDoor?: boolean }
|
||||
type Glyph = { x0: number; y0: number; x1: number; y1: number; od: number; openToward?: string; isDoor?: boolean; wtf?: boolean }
|
||||
const glyphs: Glyph[] = []
|
||||
const bdRect = (bd: NonNullable<SashShape['bd']>) => {
|
||||
const r = {
|
||||
@@ -263,6 +263,7 @@ function drawFrame(
|
||||
od: (e.od ?? sub.od ?? 90) as number,
|
||||
openToward: (e.openToward ?? sub.openToward) as string | undefined,
|
||||
isDoor: Boolean(e.isDoor ?? sub.isDoor),
|
||||
wtf: Boolean(e.wtf ?? sub.wtf ?? sub.withTurningFrame),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -316,22 +317,32 @@ function drawFrame(
|
||||
ctx.lineWidth = 1.3
|
||||
ctx.strokeRect(bx0 + 2, by0 + 2, w - 4, h - 4)
|
||||
ctx.setLineDash([])
|
||||
const ang = ((g.od || 90) * Math.PI) / 180
|
||||
const cx = (bx0 + bx1) / 2, cy = (by0 + by1) / 2
|
||||
const L = Math.min(w, h) * 0.32
|
||||
const ax = cx + Math.cos(ang) * L, ay = cy - Math.sin(ang) * L
|
||||
const wx = Math.cos(ang + Math.PI / 2) * L * 0.38
|
||||
const wy = -Math.sin(ang + Math.PI / 2) * L * 0.38
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(ax, ay)
|
||||
ctx.lineTo(cx - wx, cy - wy)
|
||||
ctx.lineTo(cx + wx, cy + wy)
|
||||
ctx.closePath()
|
||||
ctx.fillStyle = g.openToward === 'inward' ? 'rgba(255,255,255,0.55)' : 'rgba(70,76,82,0.25)'
|
||||
ctx.fill()
|
||||
ctx.strokeStyle = 'rgba(70,76,82,0.95)'
|
||||
ctx.lineWidth = 1.4
|
||||
ctx.stroke()
|
||||
if (g.wtf) {
|
||||
// 双向开启门:对角虚线交叉符号(对齐原站图纸样式)
|
||||
ctx.strokeStyle = 'rgba(70,76,82,0.7)'
|
||||
ctx.lineWidth = 1
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(bx0 + 4, by0 + 4); ctx.lineTo(bx1 - 4, by1 - 4)
|
||||
ctx.moveTo(bx1 - 4, by0 + 4); ctx.lineTo(bx0 + 4, by1 - 4)
|
||||
ctx.stroke()
|
||||
} else {
|
||||
const ang = ((g.od || 90) * Math.PI) / 180
|
||||
const cx = (bx0 + bx1) / 2, cy = (by0 + by1) / 2
|
||||
const L = Math.min(w, h) * 0.32
|
||||
const ax = cx + Math.cos(ang) * L, ay = cy - Math.sin(ang) * L
|
||||
const wx = Math.cos(ang + Math.PI / 2) * L * 0.38
|
||||
const wy = -Math.sin(ang + Math.PI / 2) * L * 0.38
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(ax, ay)
|
||||
ctx.lineTo(cx - wx, cy - wy)
|
||||
ctx.lineTo(cx + wx, cy + wy)
|
||||
ctx.closePath()
|
||||
ctx.fillStyle = g.openToward === 'inward' ? 'rgba(255,255,255,0.55)' : 'rgba(70,76,82,0.25)'
|
||||
ctx.fill()
|
||||
ctx.strokeStyle = 'rgba(70,76,82,0.95)'
|
||||
ctx.lineWidth = 1.4
|
||||
ctx.stroke()
|
||||
}
|
||||
if (g.isDoor) {
|
||||
ctx.fillStyle = 'rgba(70,76,82,0.85)'
|
||||
ctx.font = '10px sans-serif'
|
||||
|
||||
Reference in New Issue
Block a user