Skip to content

Commit

Permalink
feat: add support for polyfaceMesh outline rendering (#138)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexanderBelokon authored Aug 8, 2023
1 parent b832c4e commit 38fd3a6
Show file tree
Hide file tree
Showing 5 changed files with 24,188 additions and 4 deletions.
66 changes: 64 additions & 2 deletions src/entityToPolyline.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,65 @@ export const interpolateBSpline = (
return polyline
}

export const polyfaceOutline = (entity) => {
const vertices = []
const faces = []

for (const v of entity.vertices) {
if (v.faces) {
const face = { indices: [], hiddens: [] }
for (const i of v.faces) {
if (i === 0) {
break
}
// Negative indices signify hidden edges
face.indices.push(i < 0 ? -i - 1 : i - 1)
face.hiddens.push(i < 0)
}
if ([3, 4].includes(face.indices.length)) faces.push(face)
} else {
vertices.push({ x: v.x, y: v.y })
}
}

// If a segment starts at the end of a previous line, continue it
const polylines = []
const segment = (a, b) => {
for (const prev of polylines) {
if (prev.slice(-1)[0] === a) {
return prev.push(b)
}
}
polylines.push([a, b])
}

for (const face of faces) {
for (let beg = 0; beg < face.indices.length; beg++) {
if (face.hiddens[beg]) {
continue
}
const end = (beg + 1) % face.indices.length
segment(face.indices[beg], face.indices[end])
}
}

// Sometimes segments are not sequential, in that case
// we need to find if they can mend gaps between others
for (const a of polylines) {
for (const b of polylines) {
if (a !== b && a[0] === b.slice(-1)[0]) {
b.push(...a.slice(1))
a.splice(0, a.length)
break
}
}
}

return polylines
.filter((l) => l.length)
.map((l) => l.map((i) => vertices[i]).map((v) => [v.x, v.y]))
}

/**
* Convert a parsed DXF entity to a polyline. These can be used to render the
* the DXF in SVG, Canvas, WebGL etc., without depending on native support
Expand All @@ -122,8 +181,11 @@ export default (entity, options) => {

if (entity.type === 'LWPOLYLINE' || entity.type === 'POLYLINE') {
polyline = []
if (entity.polygonMesh || entity.polyfaceMesh) {
// Do not attempt to render meshes
if (entity.polyfaceMesh) {
// Only return the first polyline because we can't return many
polyline.push(...polyfaceOutline(entity)[0])
} else if (entity.polygonMesh) {
// Do not attempt to render polygon meshes
} else if (entity.vertices.length) {
if (entity.closed) {
entity.vertices = entity.vertices.concat(entity.vertices[0])
Expand Down
23 changes: 23 additions & 0 deletions src/handlers/entity/vertex.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
export const TYPE = 'VERTEX'

const ensureFaces = (entity) => {
entity.faces = entity.faces || []
if('x' in entity && !entity.x) delete entity.x
if('y' in entity && !entity.y) delete entity.y
if('z' in entity && !entity.z) delete entity.z
}

export const process = (tuples) => {
return tuples.reduce((entity, tuple) => {
const type = tuple[0]
Expand All @@ -17,6 +24,22 @@ export const process = (tuples) => {
case 42:
entity.bulge = value
break
case 71:
ensureFaces(entity)
entity.faces[0] = value
break
case 72:
ensureFaces(entity)
entity.faces[1] = value
break
case 73:
ensureFaces(entity)
entity.faces[2] = value
break
case 74:
ensureFaces(entity)
entity.faces[3] = value
break
default:
break
}
Expand Down
Loading

0 comments on commit 38fd3a6

Please sign in to comment.