mightyscape-1.2/extensions/fablabchemnitz/dxf_dwg_importer/node_modules/dxf/src/denormalise.js

119 lines
4.1 KiB
JavaScript

import cloneDeep from 'lodash/cloneDeep'
import logger from './util/logger'
export default (parseResult) => {
const blocksByName = parseResult.blocks.reduce((acc, b) => {
acc[b.name] = b
return acc
}, {})
const gatherEntities = (entities, transforms) => {
let current = []
entities.forEach((e) => {
if (e.type === 'INSERT') {
const insert = e
const block = blocksByName[insert.block]
if (!block) {
logger.error('no block found for insert. block:', insert.block)
return
}
const rowCount = insert.rowCount ?? 1
const columnCount = insert.columnCount ?? 1
const rowSpacing = insert.rowSpacing ?? 0
const columnSpacing = insert.columnSpacing ?? 0
const rotation = insert.rotation ?? 0
// It appears that the rectangular array is affected by rotation, but NOT by scale.
let rowVec, colVec
if (rowCount > 1 || columnCount > 1) {
const cos = Math.cos((rotation * Math.PI) / 180)
const sin = Math.sin((rotation * Math.PI) / 180)
rowVec = { x: -sin * rowSpacing, y: cos * rowSpacing }
colVec = { x: cos * columnSpacing, y: sin * columnSpacing }
} else {
rowVec = { x: 0, y: 0 }
colVec = { x: 0, y: 0 }
}
// For rectangular arrays, add the block entities for each location in the array
for (let r = 0; r < rowCount; r++) {
for (let c = 0; c < columnCount; c++) {
// Adjust insert transform by row and column for rectangular arrays
const t = {
x: insert.x + rowVec.x * r + colVec.x * c,
y: insert.y + rowVec.y * r + colVec.y * c,
scaleX: insert.scaleX,
scaleY: insert.scaleY,
scaleZ: insert.scaleZ,
extrusionX: insert.extrusionX,
extrusionY: insert.extrusionY,
extrusionZ: insert.extrusionZ,
rotation: insert.rotation,
}
// Add the insert transform and recursively add entities
const transforms2 = transforms.slice(0)
transforms2.push(t)
// Use the insert layer
const blockEntities = block.entities.map((be) => {
const be2 = cloneDeep(be)
be2.layer = insert.layer
// https://github.com/bjnortier/dxf/issues/52
// See Issue 52. If we don't modify the
// entity coordinates here it creates an issue with the
// transformation matrices (which are only applied AFTER
// block insertion modifications has been applied).
switch (be2.type) {
case 'LINE': {
be2.start.x -= block.x
be2.start.y -= block.y
be2.end.x -= block.x
be2.end.y -= block.y
break
}
case 'LWPOLYLINE':
case 'POLYLINE': {
be2.vertices.forEach((v) => {
v.x -= block.x
v.y -= block.y
})
break
}
case 'CIRCLE':
case 'ELLIPSE':
case 'ARC': {
be2.x -= block.x
be2.y -= block.y
break
}
case 'SPLINE': {
be2.controlPoints.forEach((cp) => {
cp.x -= block.x
cp.y -= block.y
})
break
}
}
return be2
})
current = current.concat(gatherEntities(blockEntities, transforms2))
}
}
} else {
// Top-level entity. Clone and add the transforms
// The transforms are reversed so they occur in
// order of application - i.e. the transform of the
// top-level insert is applied last
const e2 = cloneDeep(e)
e2.transforms = transforms.slice().reverse()
current.push(e2)
}
})
return current
}
return gatherEntities(parseResult.entities, [])
}