dxf-viewer
Version:
JavaScript DXF file viewer
116 lines (108 loc) • 3.85 kB
JavaScript
import { Vector2 } from "three"
/**
* @typedef PatternLineDef
* @property {number} angle Line angle in radians.
* @property {?Vector2} base Base point for scaling, rotation and anchoring. [0,0] if not specified.
* @property {Vector2} offset Offset for line instantiation.
* @property {?number[]} dashes Dash lengths. Solid line if not specified. Negative numbers for
* spaces, positive for dashes, zero for dots.
*/
export class Pattern {
/**
* @param {PatternLineDef[]} lines
* @param {boolean} offsetInLineSpace Line offset is defined in line space when true, in pattern
* space when false. Pattern space offset is the observed behavior of AutoDesk viewer for
* patterns defined in hatch entity itself.
*/
constructor(lines, name = null, offsetInLineSpace = true) {
this.lines = lines
this.name = name
this.offsetInLineSpace = offsetInLineSpace
}
/** Detect QCAD default pattern embedded in HATCH entity. It does not correspond to real pattern
* referenced by name.
*/
get isQcadDefault() {
if (this.lines.length != 1) {
return false
}
const line = this.lines[0]
if (line.dashes) {
return false
}
if (Math.abs(line.angle - Math.PI / 4) > 10e-14) {
return false
}
return true
}
static ParsePatFile(content) {
const lines = content.split(/\r?\n/)
if (lines.length < 2) {
throw new Error("Invalid .pat file content")
}
let name = null
const lineDefs = []
for (let line of lines) {
line = line.trim()
if (line == "") {
continue
}
if (line.startsWith(";")) {
continue
}
if (name === null) {
const m = line.match(/\*([^,]+)(?:,.*)?/)
if (!m) {
throw new Error("Bad header for .pat file content")
}
name = m[1]
continue
}
const commentPos = line.indexOf(";")
if (commentPos != -1) {
line = line.substring(0, commentPos).trim()
}
let params = line.split(/\s*,\s*/)
/* Tolerate trailing comma. */
if (params[params.length - 1] == "") {
params.length = params.length - 1
}
params = params.map(s => {
const x = parseFloat(s)
if (isNaN(x)) {
throw new Error("Failed to parse number in .pat file: " + s)
}
return x
})
const lineDef = {
angle: params[0] * Math.PI / 180,
base: new Vector2(params[1], params[2]),
offset: new Vector2(params[3], params[4])
}
if (params.length > 5) {
lineDef.dashes = params.slice(5)
}
lineDefs.push(lineDef)
}
return new Pattern(lineDefs, name)
}
}
const patternsRegistryMetric = new Map()
const patternsRegistryImperial = new Map()
/** @param {Pattern} pattern */
export function RegisterPattern(pattern, isMetric = true) {
if (!pattern.name) {
throw new Error("Anonymous pattern cannot be registered")
}
const name = pattern.name.toUpperCase()
const registry = isMetric ? patternsRegistryMetric : patternsRegistryImperial
if (registry.has(name)) {
console.warn(`Pattern with name ${name} is already registered`)
return
}
registry.set(name, pattern)
}
/** @return {?Pattern} */
export function LookupPattern(name, isMetric = true) {
return (isMetric ? patternsRegistryMetric : patternsRegistryImperial).get(name.toUpperCase())
}