skymakerolof / dxf Goto Github PK
View Code? Open in Web Editor NEWDXF parser for node/browser
Home Page: https://www.npmjs.com/package/dxf
License: MIT License
DXF parser for node/browser
Home Page: https://www.npmjs.com/package/dxf
License: MIT License
I use webpack build my project and I am very sure the dIxf module has been load success when the project running. I try to find the point by debug with chrome but when i step into the dxf-lib function I was total puzzled by the source code. I upload two dxf file, they are only contain simply 2d entity, test2.dxf could be read normally and test1.dxf could‘t . It's worth noting that test2.dxf only contain lowpolyline entities but test1.dxf not.
There is my code
typesript:
import * as THREE from "three";
import { ExtrudeGeometryOptions, Color, Curve, Vector2 } from "three";
import { TrackballControls } from 'three/examples/jsm/controls/TrackballControls';
import DxfParser from "dxf-parser";
import dxf = require("dxf");
var numberOfEntities = document.getElementById('numberOfEntities')
var svgContainer = document.getElementById('svg')
var fileInput = document.getElementById('file')
interface HTMLInputEvent extends Event {
target: HTMLInputElement & EventTarget;
}
function OnSelectFile(event: HTMLInputEvent): void {
var file = event.target.files[0];
var reader = new FileReader();
numberOfEntities.innerHTML = 'reading...'
reader.onload = function (e) {
if (e.target.readyState === 2) {
var dxfContents = e.target.result;
var dxfHelper = new dxf.Helper(dxfContents);
numberOfEntities.innerHTML = dxfHelper.denormalised.length;
const parsed = dxfHelper.parsed;
const svg = dxfHelper.toSVG();
const lines = dxfHelper.toPolylines();
svgContainer.innerHTML = svg;
}
}
reader.readAsBinaryString(file)
}
fileInput.addEventListener('change', OnSelectFile);
let camera, scene: THREE.Scene, renderer, controls: TrackballControls;
function init() {
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
scene = new THREE.Scene();
scene.background = new THREE.Color(0xb0b0b0);
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 500);
controls = new TrackballControls(camera, renderer.domElement);
controls.minDistance = 200;
controls.maxDistance = 500;
scene.add(new THREE.AmbientLight(0xcccccc));
var directionalLight = new THREE.DirectionalLight(0xffffff, 0.6);
directionalLight.position.set(0.75, 0.75, 1.0).normalize();
scene.add(directionalLight);
var group = new THREE.Group();
scene.add(group);
var helper = new THREE.GridHelper(160, 10);
helper.rotation.x = Math.PI / 2;
group.add(helper);
let axis = new THREE.AxesHelper(1000)
scene.add(axis);
let closedSpline = new THREE.CatmullRomCurve3([
new THREE.Vector3(0, 0, 0),
new THREE.Vector3(0, 0, 100),
]);
let pts = new Array<THREE.Vector2>();
pts.push(new Vector2(0, 0));
pts.push(new Vector2(10, 0));
pts.push(new Vector2(10, 10));
pts.push(new Vector2(0, 10));
// for (let i = 0; i < 4; ++i) {
// var l = 20;
// var a = 2 * i / 4 * Math.PI;
// pts.push(new THREE.Vector2(Math.cos(a) * l, Math.sin(a) * l));
// }
let shape = new THREE.Shape(pts);
let extrudeOptions: ExtrudeGeometryOptions = { steps: 100, bevelEnabled: false, extrudePath: closedSpline };
let geometry = new THREE.ExtrudeGeometry(shape, extrudeOptions)
let material = new THREE.MeshLambertMaterial({ color: 0xE9DC04, wireframe: false });
let mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
}
init();
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
animate();
html part :
<!DOCTYPE html>
<html>
<head>
<title>threejs-learn</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.box {
border: 1px;
width: 300px;
height: 300px;
}
</style>
</head>
<body>
<input type="file" id="file" />
<div>Number of entities:<span id="numberOfEntities">-</span></div>
<div id="svg" class="box"></div>
<script type="text/javascript" src="./dist/main.js"></script>
</body>
</html>
Debug with chrome and test1.dxf can not be read and show
Debug with chrome and test2.dxf can be read and show well
dxf files I want to be parse
dxf-text.zip
Hi,
When I try to use the command line tool, the dxf file is converted to svg flawlessly, but when I try to follow the steps mentioned in the Readme, i end up with this error - Cannot read property 'reduce' of undefined.
Am new at this so if please let me know if any more/other information is required. Please help @bjnortier
Thank you!
This is really a minor thing, but it would be nice if polylines with a bulge could be converted to arcs in SVG paths, rather than interpolated line segments. Sometimes the line segments are visible. I really love how all the other DXF entities get converted perfectly to SVG paths, like splines and ellipses.
I have a dxf file exported from autocad. For some reason there's like 9 lwpolylines in there that have only one vertex and the closed attribute.
{ type: 'LWPOLYLINE', vertices: [ { x: 294.598692, y: 168.66373 } ], layer: '0', colorNumber: 7, closed: true, transforms: [] }
Now I understand this could be a pointless entity, but it throws an error in entityToPolyline.js on line 110, because the resulting polyline array is empty, so no polyline[0][0] or [0][1] values exist.
Should we catch this sort of error in this library? LibreCAD and AutoCAD have no problems opening this file.
Whilst I can appreciate the main goal is to parse DXF.
I am currently using it to implement a render to SVG and SVG Path. (with much older verison of the library)
The interpolate.js is nice if only working with lines with a fixed size.
However may I suggest to have the methods inside it exported also, so that they can be reused in other rendering code that may be added in as modules.
Some things that render modules might need to do:
Re-using some of the interpolate code would be helpful as then we can get the points to use whilst having access to other details on the DXF entities that would change the rendered appearance.
Interpolated points don't have a way to link to the entity they are for obviously.
I have a part that has an array of circles, but only the first circle is being parsed. I'm using helper.denormalised
to access the parsed entities.
The part should look like this:
Instead, it is being rendered like this (using helper.toSVG()
):
Here is the DXF of the part:
Is is possible to support arrayed features? The library has been a wonderful tool for me and I'd like to contribute if I can, but I'm not sure where to start.
The unit of the DXF measurements is given under the heading "$INSUNITS". I would like to be able to read this out and additionally scale the DXF to another dimension.
The b-spline lib domain check can fail due to a floating point error - either the lib must be updated or the error caught and handled.
Sorry to keep blasting you with issues, I wouldn't be asking if your library wasn't extremely useful to me!
I've ran into a somewhat weird problem with splines while converting DXFs to SVGs. I realize that SVG only supports a small subset of the possible splines that DXF supports, and that the dxf library falls back to polylines whenever a DXF spline cannot be represented as an SVG bezier curve. In the DXF below, it seems like one or more splines are being converted to SVG format incorrectly. Converting to polylines instead of SVG does give correct output, so perhaps this is simply a case of a DXF spline that cannot be represented in SVG. I'm sorry that I don't understand enough about splines to be of much help here... what I do know is that the file size is much smaller with native SVG splines, and they're so smooooth....
Here's the weird spline:
https://raw.githubusercontent.com/ericman314/test-arc-bbox/master/dxfs/weird-splines.dxf
Expected output:
Actual output:
Note some parts on the 5 and the 6 that are supposed to be curved, which are flat. Also of note is that the dxf library renders the left side of the 6 as polylines, not bezier curves, and those are correct.
Thank you!
I've been searching around the internet again for a definitive color index. Once again, there are lots of lists, which don't match.
However, I ran into a discussion on the Autocad support blogs. And there was a very nice gentlemen that created color indexes for Autocad 2018 and Autocad 2017. I attached the spread sheet for your use.
I suspect that the color index changes whenever Autocad wants. Which is why DXF is such a huge mess.
If you have someone that has Autocad installed, they could verify the color index fairly quickly.
Could you write a little intro how to get it running?
Sometimes, the viewBox in an SVG is all NaNs. This one was a tough nut to crack, but I think the sequence of events goes like this:
polygonMesh
or polygonFace
property sethelper.toSVG
entityToPolyline.js
, polygonMeshes and polygonFaces are not rendered, so vertices
is an empty arrayvertices
is empty, the bounding box is { min: { x: Infinity, y: Infinity }, max: { x: -Infinity, y: -Infinity } }
So far so good.transformBoundingBoxAndElement
, the bounding box is transformed, and somewhere in there it does Infinity - Infinity
which becomes NaN
NaN
s for its viewBoxI'm not sure where the appropriate place would be to interrupt this chain of events. Possibly, skip transforming a bounding box if it is infinite? Or skip output of a path entirely if it contains no vertices? I'm happy to submit a PR if you can give some direction.
Is it possible to provide some more documentation, at present it say to look in the test/functional folder for examples but there are none there.
I'm digging through unit tests and code to try to figure out how it works.
I am looking at doing this also :).
As the grouping and reuse functionality is required.
Most of the DXFs I deal with have hundreds of thousands of points and SVG tends to struggle.
So, I'd like to use a <canvas>
. My plan at the moment is to use your toSVG()
, then extract the d
attribute out of each <path>
and pass it to the Path2D constructor (which accepts an SVG path string, and can then be rendered to a canvas).
But it isn't ideal for me to get a whole SVG string, then mount it as a DOM node to traverse over it to extract the paths.
Would you consider separating the 'get paths from DXF' part of the function from the 'build SVG string' part? (Or accepting a PR that does?)
It would still need to return the bounding box and colour data.
Edit: feel free to close this issue since it's just a question.
I'm trying to get some feedback when an error or warning occurs during parsing--specifically, if an unsupported entity is encountered (3DSOLID, in this case). I see that the warning is output to the console but I was hoping for something a little more sophisticated.
I don't care about the entity at all, except to know that it's there so I can warn the user about it. Is there any mechanism in place to retrieve warnings that occurred during parsing? If not, is that something we would be interested in adding? Something like helper.warnings
or similar. Thanks.
I have file that contains meshes, when trying to rendering them it looks broken like this:
I've also loaded the file with librecad and it ignores those meshes completely.
Doing this myself (by ignoring all polylines that have the "polyface mesh" flag set, results in a clean rendering:
So the fix would be to detect meshes in entity/polyline.js and ignore those when rengering the SVG. Would you accept a patch?
Hi,
First of all thanks for your job, is awesome.
How you can see, the header object has wrong values, I'm unable to parse some files like this.
This is my code
router.post('/dxf', s3Upload.single('dxf'), function (req, res, next) {
var fileInfo = req.file.key.split("/");
var params = {Bucket: 'bucketname', Key: req.file.key};
s3.getObject(params, function(err, data) {
if (err)
return err;
let objectData = data.Body.toString('utf-8');
const parsed = dxf.parseString(objectData);
const entities = dxf.denormalise(parsed);
const groups = dxf.groupEntitiesByLayer(entities);
const svg = dxf.toSVG(parsed);
res.send({
header: parsed.header,
data: groups,
svg: svg,
filename: fileInfo[1]
});
});
});
Any help please?
Thanks in advanced.
Hello,
I'm using your library for which I want to thank you first, it has been a huge help. Most of the DXF work like a charm but some are deformed and some even fail so I figured I'll let you know, maybe you are unaware.
These are the DXF files that are deformed (downloadable through the link):
http://www.dewesp.com/v6/DXF/cardboard-cupcake-stand-easy-diy-craft-idea.dxf
http://www.dewesp.com/v6/DXF/laser-cut-ornaments-christmas-wood-tree-idea.dxf
http://www.dewesp.com/v6/DXF/plywood-candle-holder-laser-cutter-idea.dxf
http://www.dewesp.com/v6/DXF/rocking-elephant-cnc-router-plans-wood-rocking-horse-idea.dxf
Further I have some that completely fail:
http://www.dewesp.com/v6/DXF/chair.dxf
http://www.dewesp.com/v6/DXF/FV4EBZBGDVZF630.dxf
http://www.dewesp.com/v6/DXF/StaticBoot3-R14.dxf
http://www.dewesp.com/v6/DXF/Velociraptor.dxf
If I can be of any assistance, please let me know 👍
Kind regards and again, big thank you for the library!
Jelle
I've been looking for a library to convert dxf floor plans to svg or pdf. Your project is the only one I've found that almost works and that does not cost a fortune.
Unfortunately, some of the converted files have artifacts like for example a big black ellipse or a big grey rectangle in it.
Any help appreciated.
Hi,
Is it possible to add support for 3Dfaces?
Kind regards,
Xander
First, I just wanted to say thanks for creating a really nice set of sample files. I've been looking for small samples for a long long time.
If you are also interested, there is a set of sample files found at JSCAD; https://github.com/jscad/sample-files
Our focus is more on 3D designs but many designs start from 2D shapes, etc.
I'll be back to take a look at the spline implementation, as we need to add that to our parser in the future.
Thanks much!
When knots repeat in the knot vector, we can split the spline into cubic splines and use native SVG rendering instead of using b-spline interpolation
In the attached file no tables are defined, if I understand dxf right (I am new to dxf).
Therefore the library fails at https://github.com/bjnortier/dxf/blob/master/src/toSVG.js#L49
I was able to "fix" this behaviour by adding one line here: https://github.com/bjnortier/dxf/blob/master/src/index.js#L98
tables: {layers: {}, styles: {}}
Though it works for me I am in doubt if that is a proper fix. I don't understand the dxf format well enough to decide where to fix it. I hope this is helpful in any way. Feel free to give me a hint where to fix it properly, then I will provide a pull request.
p.s. keep up the good work! Thanks.
In entityToPolyline.js, the following code is used to produce the parameter t to generate points along the polyline:
var t = (u - domain[0]) / (domain[1] - domain[0]);
I'm not sure what causes the problem, but some splines produce a t value just outside the allowed range of [0,1]:
Error: t out of bounds [0,1]: 1.0000000000000002
at _default (C:_oshcut\Software\cadproc\node_modules\dxf\lib\util\bSpline.js:22:11)
at interpolateBSpline (C:_oshcut\Software\cadproc\node_modules\dxf\lib\entityToPolyline.js:101:39)
Could be a numerical precision issue. The following fixes the problem:
var t = Math.min(1, Math.max(0, (u - domain[0]) / (domain[1] - domain[0])));
It might be a band-aid fix, but it does the job. I can send you the file that causes the issue if you want to see it.
The README.md advertises that this will also be for the browser, but there is no further information, and none of the .js files look suitable for inclusion into the browser.
Having scratched my head with someone who knows more about node than I do (ie he knows more than nothing), we can get something to run in the browser, like so:
test2.js:
const dxf = require('..')
exports.dxf = dxf;
Then the command:
browserify test2.js --standalone bdxf -o examples/bundledxf.js
And then it's possible to access the dxf parser the following code in an html page:
<script type="text/javascript" src="bundledxftrial.js"></script>
<script>var k = "some DXF content";
var h = bdxf.dxf.parseString(k);
console.log(h);
var svg = bdxf.dxf.toSVG(h)
console.log(svg);
</script>
I'm sure there's got to be a more preferred way of doing it that you could recommend in your documentation.
It would be a pretty useful capability to be able to parse/extract data or plot DXF files that have been downloaded natively in the browser without any server-side scripts.
Problem file:
https://discuss-assets.s3.amazonaws.com/original/3X/f/7/f754fb4dfe8ea2be046c2a23cf8f3e7ed8f5e8c9.dxf
Issue a warning, but fall back to black
Hi!
I've found this package extremely useful in trying to run some experiments with AutoCAD/DXF files.
I wanted to understand if there is a way to get entity attributes through this parser? Specifically, attributes for an inserted block entity.
Thanks in advance!
I converted the attached dxf file using the cli dxf-to-svg. While all path elements in the resulting svg are placed fine, the circle elements have wrong coordinates (very far away). Find the conversion result in the .zip as well.
Thanks in advance for all your efforts.
Hello, first of all thank you for your wonderful parser.
I'm trying to load an DXF file into an svg (which just contains a circle), which works nice after some adjustments:
Im using the toPolylines() method and iterate over all polylines.
My Problem is filling the inner of the Path. If i group all lines in a g-tag and do fill="white" it looks like that:
When I put all polyline in a single Path/Polyline (and fill white) i get:
Do you have any ideas to fill the inner?
Thank you for your help.
Hello! I find this package very interesting.
I've been testing it and I don't know if there is a simple way to work with the SVG. Specifically, I do not know if it is possible to access the elements of the SVG by layers once it has already been included in the DOM.
I know that the DXF entities are available within the helper.parsed
object, however, they are not directly linked to the SVG since the DOM, once the SVG is embedded, hardly contains any information about the original DXF (i.e. layers).
So far I have been able to directly modify the SVG before adding it to the DOM (eg adding ids or custom properties to the elements) but I don't think this is the most efficient approach, mainly because I can only add some simple properties that are not directly linked to the original DXF.
Here is my attempt.
foo(): string {
const helper = new Helper(dxf);
let svg = helper.toSVG();
const parser = new DOMParser();
const html = parser.parseFromString(svg, 'text/html');
const svg = html.getElementsByTagName('svg')[0];
svg.querySelectorAll('g').forEach((g, i) => {
if(g.hasAttribute('stroke')) g.setAttribute('id', i + '');
});
const encoder = new XMLSerializer();
return encoder.serializeToString(svg);
}
So, to sum up, I'd like to add a property to the elements for filtering them by layer in a later processing step (i.e. displaying elements by layer or hidding them). Any ideas are welcome.
Many thanks in advanced
Hi there,
I'm using the lib to draw on some section based on dxf file, but for no reason the Hatch Pattern is ignored during de conversion to polylines, then those parts are aways missing.
Could anyone help me?
Thank you
I am working to build some graph and i want to make it become a dexf file let other people can open it in autoCAD.is there any way to parse a json string into a dxf file?
Thanks for this awesome library! It's super accurate and fast.
I'm using the library to convert some DXFs to SVGs for rendering in a browser. Some of the DXFs have arcs that are very nearly flat. The arcs themselves are small but the bounding box calculated in toSVG
is too large. It looks like it contains the entire circle the arc came from. I would expect that the bounding box only contain the arc itself.
I set up a repo demonstrating this: https://github.com/ericman314/test-arc-bbox
Using Inkscape to open the generated SVG, you can see that the document size (viewBox) is much larger than the actual arc:
As for a possible cause, I think this might be the culprit: https://github.com/bjnortier/dxf/blob/a732803e065479747f1ac706781860c942d97c4b/src/toSVG.js#L65-L78
I think what this does is it takes the corners of the rectangle containing the ellipse, and rotates them by rotationAngle
. A more accurate bounding box would only include the endpoints of the rotated arc, as well as any points on the rotated arc that have a vertical or horizontal tangent line. Definitely more tricky, but it would be a true bounding box for the arc.
Just something I noticed, the insert block primitive forEach uses cloneDeep on the entity even if it is not included in the displayEntities output by the layers filter passed in as an argument.
No harm done really, but it seems like something that should be executed after the filter condition is met.
First of all, thank you for the great job!
I'm experimenting some troubles while converting models somes elements such as ARC and CIRCLES are shifted to x axis.
It seems like it may not be a good idea to use __defineGetter__
What are your thoughts?
See the following:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/__defineGetter__
Is this something that would be desired? We are thinking about supporting binary DXFs in our application and thought that this existing parser would be the perfect place to implement it. If so, I will give it a try and submit a PR.
The dimensions mention a block that they are related to.
I think that these are similar to an insert, but without transformation information.
Do you think that dimension entities should have their blocks entities cloned and inserted into displayEntities also?
DXF submitted which generated a block insert bug
From what I can tell the code 8 is for Layer String.
See the following:
http://www.autodesk.com/techpubs/autocad/acadr14/dxf/common_group_codes_for_symbol_table_entries_al_u05_c.htm
https://github.com/thomasdesmoulin/dxf-parsing/blob/master/libs/parser.js#l=70-71
https://github.com/duckinator/dxf2svg/blob/master/entities.cpp
I will possibly code this in for all entities.
I would also like to pull the layers and group objects by layer.
I have branched and can look at doing this.
Firstly - love this package, thanks for creating it!
I needed some Typescript support so I went ahead and created types for it within DefinitelyTyped. It does need some review however and while I'm comfortable contributing I'm sure it'd be good for the contributors here to have eyes on it as well.
Best!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.