fix: 门窗渲染语义区分(门=贯穿长把手+锁点+型材同色裙板, 窗=短把手), 对照官方参考图三渲染器同步
This commit is contained in:
@@ -84,6 +84,12 @@ function render() {
|
||||
// 扇层:扇内子格(裙板/格条/编号) + 扇料框 + 开向符号 + 把手(语义同 WindoorCanvas,视觉对齐 2D 图纸)
|
||||
const rp = replayShape(shape)
|
||||
const glyphs = inferSashGlyphs(shape, rp).sashes
|
||||
// 裙板色 = 型材色(cm.g rgba 字符串 → 不透明深色), 解析失败退中性深灰
|
||||
const cmRaw = typeof shape.cm?.g === 'string' ? shape.cm.g : ''
|
||||
const cmMatch = cmRaw.match(/(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/)
|
||||
const frameTint = cmMatch
|
||||
? `rgb(${Math.round(+cmMatch[1] * 0.62)},${Math.round(+cmMatch[2] * 0.62)},${Math.round(+cmMatch[3] * 0.62)})`
|
||||
: '#6b6e73'
|
||||
const sashShapes: SashShape[] = []
|
||||
const collect = (s: FrameShape | SashShape) => {
|
||||
if (!['Frame', 'Slide'].includes(String(s.type))) sashShapes.push(s as SashShape)
|
||||
@@ -105,10 +111,10 @@ function render() {
|
||||
const px0 = tx(p.x0), px1 = tx(p.x1), py0 = ty(p.y0), py1 = ty(p.y1)
|
||||
if (px1 - px0 < 4 || py1 - py0 < 4) continue
|
||||
if (!p.glass) {
|
||||
// 裙板/实板:暖米色 + 内凹描边
|
||||
ctx.fillStyle = '#ddd3c0'
|
||||
// 裙板/实板:型材同色系(取 cm.g, 官方图纸裙板与框扇同色) + 内凹描边
|
||||
ctx.fillStyle = frameTint
|
||||
ctx.fillRect(px0, py0, px1 - px0, py1 - py0)
|
||||
ctx.strokeStyle = 'rgba(90,84,72,0.55)'
|
||||
ctx.strokeStyle = 'rgba(0,0,0,0.35)'
|
||||
ctx.lineWidth = 1.5
|
||||
ctx.strokeRect(px0 + 3, py0 + 3, px1 - px0 - 6, py1 - py0 - 6)
|
||||
} else if (p.deco) {
|
||||
@@ -183,9 +189,9 @@ function render() {
|
||||
ctx.stroke()
|
||||
ctx.setLineDash([])
|
||||
}
|
||||
// 把手: 铰链对面侧白条
|
||||
// 把手: 铰链对面侧白条(门=贯穿长条, 窗=短条) + 门上下锁点块
|
||||
const dir = g.openDirection ?? 'left'
|
||||
const hl = Math.max(10, h * (g.isDoor ? 0.34 : 0.2))
|
||||
const hl = Math.max(10, h * (g.isDoor ? 0.55 : 0.2))
|
||||
const hw2 = Math.max(4, 5)
|
||||
ctx.fillStyle = '#f4f4f6'
|
||||
ctx.strokeStyle = '#3c4147'
|
||||
@@ -200,6 +206,17 @@ function render() {
|
||||
}
|
||||
ctx.fill()
|
||||
ctx.stroke()
|
||||
// 门锁点(把手上下两端小方块)
|
||||
if (g.isDoor && g.kind === 'casement' && !dir.startsWith('up')) {
|
||||
const dx = dir.startsWith('left') ? bx1 - hw2 / 2 - 3 : bx0 + hw2 / 2 + 3
|
||||
const dot = Math.max(3, hw2 * 0.8)
|
||||
for (const oy of [cy - hl / 3, cy + hl / 3]) {
|
||||
ctx.beginPath()
|
||||
ctx.rect(dx - dot / 2, oy - dot / 2, dot, dot)
|
||||
ctx.fill()
|
||||
ctx.stroke()
|
||||
}
|
||||
}
|
||||
})
|
||||
// 外框
|
||||
const all = dd.sm.flatMap(s => replayShape(s).regions.flat().map(seg => seg.ps))
|
||||
|
||||
@@ -596,10 +596,15 @@ function drawFrame(
|
||||
const px0 = tx(p.x0), px1 = tx(p.x1), py0 = ty(p.y0), py1 = ty(p.y1)
|
||||
if (px1 - px0 < 4 || py1 - py0 < 4) continue
|
||||
if (!p.glass) {
|
||||
ctx.fillStyle = '#e5dfd3'
|
||||
// 裙板: 型材深色(官方图纸裙板与框扇同色系) + 竖纹肌理
|
||||
ctx.fillStyle = '#5f6268'
|
||||
ctx.fillRect(px0, py0, px1 - px0, py1 - py0)
|
||||
ctx.strokeStyle = STYLE.profileDark
|
||||
ctx.strokeStyle = 'rgba(255,255,255,0.14)'
|
||||
ctx.lineWidth = 1
|
||||
for (let vx = px0 + 7; vx < px1 - 3; vx += 7) {
|
||||
ctx.beginPath(); ctx.moveTo(vx, py0 + 3); ctx.lineTo(vx, py1 - 3); ctx.stroke()
|
||||
}
|
||||
ctx.strokeStyle = STYLE.profileDark
|
||||
ctx.strokeRect(px0 + 2, py0 + 2, px1 - px0 - 4, py1 - py0 - 4)
|
||||
} else if (p.deco) {
|
||||
// hc 等分主格 + gp 内框 + 四角回纹块(近似源站 decorationChinese)
|
||||
@@ -627,7 +632,7 @@ function drawFrame(
|
||||
}
|
||||
if (p.glassText) {
|
||||
const fs2 = Math.max(9, Math.min(14, (px1 - px0) * 0.1))
|
||||
ctx.fillStyle = p.glass ? 'rgba(255,255,255,0.92)' : STYLE.label
|
||||
ctx.fillStyle = 'rgba(255,255,255,0.92)'
|
||||
ctx.font = `bold ${fs2}px sans-serif`
|
||||
ctx.textAlign = 'center'
|
||||
ctx.textBaseline = 'middle'
|
||||
@@ -668,9 +673,9 @@ function drawFrame(
|
||||
ctx.stroke()
|
||||
ctx.setLineDash([])
|
||||
}
|
||||
// 把手: 铰链对面侧(白条+描边+上下锁点)
|
||||
// 把手: 铰链对面侧(白条+描边; 门=贯穿长条, 窗=短条)+上下锁点
|
||||
const dir = g.openDirection ?? 'left'
|
||||
const hl = Math.max(8, h * (g.isDoor ? 0.36 : 0.2))
|
||||
const hl = Math.max(8, h * (g.isDoor ? 0.55 : 0.2))
|
||||
const hw2 = Math.max(3.5, lw * 0.55)
|
||||
ctx.fillStyle = '#f4f4f6'
|
||||
ctx.strokeStyle = STYLE.profileDark
|
||||
|
||||
@@ -361,8 +361,9 @@ function build(drawing: DrawingData) {
|
||||
const lmy = (gRect.y1 / 2 + gRect.y0 / 2 - (p.y0 + p.y1) / 2) * S
|
||||
if (![pw, ph, lmx, lmy].every(Number.isFinite) || pw <= 0.01 || ph <= 0.01) continue
|
||||
if (!p.glass) {
|
||||
// 裙板: 型材深色系(与框扇同色域, 对齐官方门板观感)
|
||||
const board = new THREE.Mesh(new THREE.BoxGeometry(pw, ph, 0.012),
|
||||
new THREE.MeshStandardMaterial({ color: 0xd9cdb8, roughness: 0.7, metalness: 0.05 }))
|
||||
new THREE.MeshStandardMaterial({ color: 0x606369, roughness: 0.65, metalness: 0.1 }))
|
||||
board.position.set(lmx, lmy, 0.004)
|
||||
group.add(board)
|
||||
} else if (p.deco) {
|
||||
|
||||
Reference in New Issue
Block a user