Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
376 changes: 375 additions & 1 deletion dist/dxf-parser.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"main": "dist/dxf-parser.js",
"scripts": {
"test": "mocha --require @babel/register test",
"test-debug": "mocha --inspect-brk --require @babel/register test",
"start": "webpack --mode development",
"build": "webpack --mode production"
},
Expand Down
4 changes: 3 additions & 1 deletion src/DxfParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import AttDef from './entities/attdef';
import Circle from './entities/circle';
import Dimension from './entities/dimension';
import Ellipse from './entities/ellipse';
import Hatch from './entities/hatch';
import Insert from './entities/insert';
import Line from './entities/line';
import LWPolyline from './entities/lwpolyline';
Expand Down Expand Up @@ -35,6 +36,7 @@ function registerDefaultEntityHandlers(dxfParser) {
dxfParser.registerEntityHandler(Circle);
dxfParser.registerEntityHandler(Dimension);
dxfParser.registerEntityHandler(Ellipse);
dxfParser.registerEntityHandler(Hatch);
dxfParser.registerEntityHandler(Insert);
dxfParser.registerEntityHandler(Line);
dxfParser.registerEntityHandler(LWPolyline);
Expand Down Expand Up @@ -717,7 +719,7 @@ DxfParser.prototype._parse = function(dxfString) {
return point;
}
point.z = curr.value;

return point;
};

Expand Down
129 changes: 129 additions & 0 deletions src/entities/hatch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@

import * as helpers from '../ParseHelpers'

export default function EntityParser() { }

EntityParser.ForEntityName = 'HATCH';

EntityParser.prototype.parseEntity = function (scanner, curr) {
var entity;
entity = { type: curr.value, boundaries: [] };
curr = scanner.next();
while (curr !== 'EOF') {
if (curr.code === 0) break;
// console.log("parseHatch pointer: " + scanner._pointer);
// console.log("parseHatch code: " + curr.code);
// console.log("parseHatch value: " + curr.value);
switch (curr.code) {
case 2:
entity.patternName = curr.value;
break;
case 10:
entity.elevationX = curr.value;
break;
case 20:
entity.elevationY = curr.value;
break;
case 30:
entity.elevationZ = curr.value;
break;
case 41: // Hatch pattern scale or spacing (pattern fill only)
entity.scale = curr.value;
break;
case 47:
entity.pixelSize = curr.value;
case 70: // Solid fill flag (solid fill = 1; pattern fill = 0); for MPolygon, the version of MPolygon
entity.solidFill = (curr.value & 1) !== 0;
break;
case 71: // Associativity flag (associative = 1; non-associative = 0); for MPolygon, solid-fill flag (has solid fill = 1; lacks solid fill = 0)
entity.associativity = (curr.value & 1) !== 0;
break;
// case 72: // 16-bit integer value
case 73: // For MPolygon, boundary annotation flag (boundary is an annotated boundary = 1; boundary is not an annotated boundary = 0)
entity.annotatedBoundary = (curr.value & 1) !== 0;
break;
case 75: // Hatch style: 0 = Hatch “odd parity” area (Normal style), 1 = Hatch outermost area only (Outer style), 2 = Hatch through entire area (Ignore style)
entity.style = curr.value;
break;
case 76: // Hatch pattern type: 0 = User-defined; 1 = Predefined; 2 = Custom
entity.patternStyle = curr.value;
break;
case 91: // Number of boundary paths (loops)
entity.boundaryPathsCount = curr.value;
break;
// case 92: // Number of bytes in the proxy entity graphics represented in the subsequent 310 groups, which are binary chunk records (optional)
// This one is from common entity propierties
case 93:
var boundryVerticeCount = curr.value;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should this be boundaryVertexCount.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @bzuillsmith,
First off, thank you for creating and maintaining dxf-parser. It's a fantastic tool that has saved us a huge amount of effort.
I'm commenting on this old but critical Pull Request because, like many others, our project's primary challenge is rendering HATCH entities, especially SOLID fills which are very common. After much debugging, we confirmed that the official parser version does not handle them, and this PR (#45) is the community's long-standing hope for a solution.
I see the main blocker now is the merge conflict. I know that resolving conflicts on a 5-year-old branch is a significant task.
Is there anything we, as users who desperately need this feature, can do to help move this forward? For example:
Could we help test a new branch if someone attempts to resolve the conflicts?
Would a detailed list of common HATCH use cases we encounter be helpful?
Any guidance on what it would take to get this merged would be amazing. This single feature would unlock the full potential of dxf-parser for a huge range of applications.
Thanks again for all your hard work.

var boundry = parseHatchVertices(boundryVerticeCount, scanner)
entity.boundaries.push(boundry);
// case 97: // 32-bit integer value
case 98:
entity.seedPointsCount = curr.value;
break;
case 210:
entity.extrusionDirectionX = curr.value;
break;
case 220:
entity.extrusionDirectionY = curr.value;
break;
case 230:
entity.extrusionDirectionZ = curr.value;
break;
default:
helpers.checkCommonEntityProperties(entity, curr);
break;
}
curr = scanner.next();
}
// console.log("parseHatch exit");

return entity;
};

function parseHatchVertices(n, scanner) {
if (!n || n <= 0) throw Error('n must be greater than 0 verticies');
var vertices = [], i;
var vertexIsStarted = false;
var vertexIsFinished = false;
var curr = scanner.next();

for (i = 0; i < n; i++) {
// console.log("parseHatchVertices.i: " + i);
var vertex = {};
while (curr !== 'EOF') {
if (curr.code === 0 || vertexIsFinished) break;

switch (curr.code) {
case 10: // X
if (vertexIsStarted) {
vertexIsFinished = true;
continue;
}
vertex.x = curr.value;
vertexIsStarted = true;
break;
case 20: // Y
vertex.y = curr.value;
break;
case 42: // bulge
if (curr.value != 0) vertex.bulge = curr.value;
break;
default:
// if we do not hit known code return vertices. Code might belong to entity
if (vertexIsStarted) {
vertices.push(vertex);
}
// console.log("parseHatchVertices exit from default");
return vertices;
}
curr = scanner.next();
}
vertices.push(vertex);
vertexIsStarted = false;
vertexIsFinished = false;
}
// console.log("parseHatchVertices exit");
scanner.rewind();
return vertices;
};
36 changes: 27 additions & 9 deletions test/DxfParser.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ describe('Parser', function() {
tables.should.have.property('layer');

var expectedOutputFilePath = path.join(__dirname,'data','layer-table.expected.json');

var expected = fs.readFileSync(expectedOutputFilePath, {encoding: 'utf8'});
tables.layer.should.eql(JSON.parse(expected));
});
Expand All @@ -54,7 +54,7 @@ describe('Parser', function() {
var expected = fs.readFileSync(expectedOutputFilePath, {encoding: 'utf8'});
tables.lineType.should.eql(JSON.parse(expected));
});

it('should parse the dxf viewPort table', function() {
should.exist(tables);
tables.should.have.property('viewPort');
Expand All @@ -65,10 +65,28 @@ describe('Parser', function() {
tables.viewPort.should.eql(JSON.parse(expected));
});

it('should parse a complex BLOCKS section', function() {
verifyDxf(path.join(__dirname, 'data', 'blocks.dxf'))
});

it('should parse HATCH', function() {
verifyDxf
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new way to do this would be to just call verifyDxf(path.join(__dirname, 'data', 'hatch.dxf')); and the result will be suffixed with .received.json instead of .actual.json.

var file = fs.readFileSync(path.join(__dirname, 'data', 'hatch.dxf'), 'utf8');

var parser = new DxfParser();
var dxf;
try {
dxf = parser.parseSync(file);
fs.writeFileSync(path.join(__dirname, 'data', 'hatch.actual.json'), JSON.stringify(dxf, null, 2));
}catch(err) {
should.not.exist(err);
}
should.exist(dxf);

var expected = fs.readFileSync(path.join(__dirname, 'data', 'hatch.expected.json'), {encoding: 'utf8'});
dxf.should.eql(JSON.parse(expected));
});

// it('should parse a complex BLOCKS section', function() {
// verifyDxf(path.join(__dirname, 'data', 'blocks.dxf'))
// });

it('should parse a simple BLOCKS section', function() {
var file = fs.readFileSync(path.join(__dirname, 'data', 'blocks2.dxf'), 'utf8');

Expand All @@ -86,7 +104,7 @@ describe('Parser', function() {
var expected = fs.readFileSync(path.join(__dirname, 'data', 'blocks2.expected.json'), {encoding: 'utf8'});
dxf.should.eql(JSON.parse(expected));
});

it('should parse POLYLINES', function() {
verifyDxf
var file = fs.readFileSync(path.join(__dirname, 'data', 'polylines.dxf'), 'utf8');
Expand Down Expand Up @@ -123,7 +141,7 @@ describe('Parser', function() {
var expected = fs.readFileSync(path.join(__dirname, 'data', 'ellipse.expected.json'), {encoding: 'utf8'});
dxf.should.eql(JSON.parse(expected));
});

it('should parse SPLINE entities', function() {
var file = fs.readFileSync(path.join(__dirname, 'data', 'splines.dxf'), 'utf8');

Expand Down Expand Up @@ -157,7 +175,7 @@ describe('Parser', function() {
var expected = fs.readFileSync(path.join(__dirname, 'data', 'extendeddata.expected.json'), {encoding: 'utf8'});
dxf.should.eql(JSON.parse(expected));
});

it('should parse SPLINE entities that are like arcs and circles', function() {
verifyDxf(path.join(__dirname, 'data', 'arcs-as-splines.dxf'));
});
Expand Down
Loading