ca859c4aa4
Standalone-Browser-Port von DOSSIER. Enthaelt das semantische Modell mit Plan-/3D-Ableitung, Zeichen- und Editierwerkzeuge, Rhino-artiges Befehlssystem, dockbares Panel-System, Resource-Manager, DXF/.lin/.pat-Import, i18n (de/en) sowie Projektdokumentation und Probe-Harness.
89 lines
2.8 KiB
TypeScript
89 lines
2.8 KiB
TypeScript
// Parser für AutoCAD .lin Linientyp-Definitionsdateien.
|
|
// Liefert benannte Strichmuster (dash patterns) zur späteren Übernahme in die LineStyle-Bibliothek.
|
|
|
|
export interface LinPattern {
|
|
name: string;
|
|
description: string;
|
|
dash: number[] | null;
|
|
}
|
|
|
|
// Punkt (0) wird als sehr kurzer Strich dargestellt, da SVG dasharray keine echten Punkte kennt.
|
|
const DOT_LENGTH = 0.01;
|
|
|
|
// Zerlegt eine Musterzeile in Tokens und entfernt eingeklammerte Shape-/Text-Segmente.
|
|
function extractNumericSegments(patternLine: string): number[] {
|
|
// Klammer-Segmente (z. B. ["TEXT",STYLE,...]) entfernen.
|
|
const withoutBrackets = patternLine.replace(/\[[^\]]*\]/g, '');
|
|
const tokens = withoutBrackets.split(',');
|
|
const numbers: number[] = [];
|
|
for (const raw of tokens) {
|
|
const token = raw.trim();
|
|
if (token === '') continue;
|
|
// Alignment-Token überspringen (üblicherweise 'A').
|
|
if (/^[A-Za-z]/.test(token)) continue;
|
|
const value = Number(token);
|
|
if (Number.isFinite(value)) {
|
|
numbers.push(value);
|
|
}
|
|
// Nicht-numerische Tokens werden ignoriert.
|
|
}
|
|
return numbers;
|
|
}
|
|
|
|
// Wandelt die Roh-Segmente in ein positives alternierendes dash/gap-Array um.
|
|
function toDashArray(segments: number[]): number[] | null {
|
|
if (segments.length === 0) return null;
|
|
const dash: number[] = [];
|
|
for (const seg of segments) {
|
|
if (seg === 0) {
|
|
dash.push(DOT_LENGTH);
|
|
} else {
|
|
dash.push(Math.abs(seg));
|
|
}
|
|
}
|
|
return dash.length > 0 ? dash : null;
|
|
}
|
|
|
|
export function parseLin(text: string): LinPattern[] {
|
|
const result: LinPattern[] = [];
|
|
// CRLF/CR vereinheitlichen.
|
|
const lines = text.replace(/\r\n?/g, '\n').split('\n');
|
|
|
|
for (let i = 0; i < lines.length; i++) {
|
|
const line = lines[i].trim();
|
|
if (line === '') continue;
|
|
if (line.startsWith(';')) continue;
|
|
if (!line.startsWith('*')) continue;
|
|
|
|
// Definitionszeile: *NAME,Description
|
|
const body = line.slice(1);
|
|
const commaIndex = body.indexOf(',');
|
|
const name = (commaIndex >= 0 ? body.slice(0, commaIndex) : body).trim();
|
|
const description = commaIndex >= 0 ? body.slice(commaIndex + 1).trim() : '';
|
|
if (name === '') continue;
|
|
|
|
// Folgende Musterzeile suchen (Kommentare/Leerzeilen überspringen).
|
|
let j = i + 1;
|
|
while (j < lines.length) {
|
|
const candidate = lines[j].trim();
|
|
if (candidate === '' || candidate.startsWith(';')) {
|
|
j++;
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
// Keine folgende Zeile oder direkt nächste Definition -> Eintrag überspringen.
|
|
if (j >= lines.length || lines[j].trim().startsWith('*')) {
|
|
continue;
|
|
}
|
|
|
|
const patternLine = lines[j].trim();
|
|
const segments = extractNumericSegments(patternLine);
|
|
const dash = toDashArray(segments);
|
|
result.push({ name, description, dash });
|
|
i = j;
|
|
}
|
|
|
|
return result;
|
|
}
|