jscad / io

DEPRECATED : Input Output handling for JSCAD (see the link below)
https://github.com/jscad/OpenJSCAD.org/tree/V2/packages
34 stars 13 forks source link

[sugestion] Import stl #8

Closed z3dev closed 3 years ago

z3dev commented 7 years ago

From @paddelkraft on August 22, 2016 9:3

Thanks for a great tool OpenJSCAD is my tool of choice for 3D modeling and i use it a lot. One feature that i miss is the ability to import STL files and interact with them. I believe that this feature would lift the tool to a new level.

Im A curious developer with experience in JS development so I would be willing to help out in the effort to add this feature if someone who is more familiar with the project can give me some pointers on where to start.

Copied from original issue: Spiritdude/OpenJSCAD.org#170

z3dev commented 7 years ago

@paddelkraft Cool! We would love any contribution to code or documents.

STL file can be imported (and converted) via drag and drop. What else did you have in mind?

z3dev commented 7 years ago

From @paddelkraft on August 22, 2016 11:52

i did not know that i could not find that info in the user guide. Then this turns into a question. how do i get a handle to the CSG object of the model imported from an STL so that i can perform operations on it?

is there a way to do something like this

//dummy example
var stlObject = importedSTL("file.stl");
stlObject.translate([10,10,10]).subtract(otherObject)

or do i need to copy paste the generated polyhedron?

z3dev commented 7 years ago

@paddelkraft First, drag and drop any STL file to the page. The STL will be converted to CSG function calls. You can rename "function main()" to something like "function importedSTL()". And create...

function main() { var obj = importedSTL(); // now you can do anything to the obj obj = obj.scale([5,5,5]}.rotateZ(45); return obj; }

z3dev commented 7 years ago

Here's my take on the "direct" import...

First and foremost, "direct" import should create a native object. That means that the 'direct' import should create CSG or CAG object(s). This is for performance reasons. So, "conversions" from another format should be performed outside of the "direct" import.

Thoughts?

z3dev commented 7 years ago

From @kaosat-dev on December 8, 2016 10:16

By 'direct' import do you mean the drag & drop version or the one using the importSTL( or even better importGeometry ?) The problem is I am not sure you can have the same API whether you are working in the 'online' version, or a locally hosted one, or cli etc

perhaps drag & droping stls could add them to the current 'workspace' and convert to native format as you say path resolution from within the script could be something like this: in browser, once you dragged and dropped it: local path is 'workspace': advantage, can also work the same way in command line / node version if the files are in the same folder const foo = importGeometry("./file.stl")

z3dev commented 7 years ago

From @paddelkraft on December 21, 2016 14:21

i do not really care exactly how its implemented but being able to import an stl via code or if you work with a folder and the .stl objects being available as objects named after the file name or something similar.

the point is to not have to create a .jscad file of it to use it and have it auto update on change.

z3dev commented 7 years ago

@paddelkraft Yup! That's what I want...

z3dev commented 7 years ago

From @kaosat-dev on December 29, 2016 8:32

I have started to look into implementing this but there is a crucial question : are you ok with it to support only 'local' files ? (in the 'same folder' / set of drag & dropped files)

z3dev commented 7 years ago

From @kaosat-dev on December 29, 2016 9:15

Actually never mind on second thought it could be done in the same way 'include' works

z3dev commented 7 years ago

We should differentiate import (conversion) to "source" versus import of "geometry". Somethings cannot be imported as pure "geometry".

z3dev commented 7 years ago

From @kaosat-dev on January 6, 2017 6:0

@z3dev do you mean something like 3mf / amf files with the extra structure & metadata etc ?

z3dev commented 7 years ago

Let me clarify... Geometry means vertexes and points; fixed and calculated.

For an example, SVG supports Bezer curves, which should be imported as functions calls to those routines. If imported as pure "geometry" (2D vertexes and points) then there design loss.

z3dev commented 7 years ago

From @gilboonet on March 12, 2017 15:48

I'm not experienced enough to make reliable changes directly to OpenJSCAD code but I'm using a mechanism that works on a web application where user is asked to select a STL file, and then a .jscad script runs using it. What i did is :

To access the STL model the .jscad script just need to call it function name. It would really be great if such a mechanism could be directly accessible from OpenJSCAD, directly from the code or even better from an input parameter, and why not for other sources than STL.

(it can be seen here : http://gilboo.carton.free.fr/OJSC5/edit_mat8b.html )

udif commented 5 years ago

Let me add my small take on STL import:

I find it really useful for modifying objects from thingiverse etc. which are usually only shared as STL files. The problem is that the code built by OpenJSCAD requires too much manual editing before it can be manipulated. It typically calls polyhedron(points: [[...], [..], ...], polygons: [[...], [..], ...]); where the 2 arrays can be very large (many thousands of lines). Sometimes I wish to manipulates the points and polygons myself, which means I want to put them into arrays I can manipulate. At the moment I manually edit the imported code, but if this is a large object, It is very cumbersome. For example: https://openjscad.org/?uri=https://gist.githubusercontent.com/udif/9c9b41b52df27b51e9e4e726ae1ca13a/raw/525d6a187cbabf3f6b69f3e97e56d8ed22725981/filament_holder_prusa.jscad This object is ~120000 lines. As I've turned the embedded points and polygons arrays into array variables, I had to manually find the ending point of the points array somewhere within these 120000 lines in order to change it into an array assignment. This is really cumbersome, esp. when prototyping withing the embedded editor. The example above stretches one arm of the object by moving some of the points based on their existing location.

My request/suggestion: Change the STIL import template code into:

var points = [[...],
[...],
...
];
var poygons = [[...],
[...],
...
];
function main() {
  return union(polyhedron(points: points, polygons: polygons));
);

(I assume the union() call is because the STL might contain multiple objects). This way it is easy to go to the end of the file. and make all the changes there.

In an ideal world, I would like to be able to have a file selector added as an input type to getParameterDefinitions(), then do the STL conversion as part of the script via a function call, so that I could share a generic URL for an STL manipulation tool using OpenJSCAD, that would let the user upload a different STL each time, instead of writing a unique script for each object.

EDIT: Actually, I would have provided a pull request had I known that the STL import code is in the jscad/io repository. I looked for it in the jscad/OpenJSCAD.org repo but found none. Today I found this STL issue, which was originally opened on jscad/OpenJSCAD.org, but moved later here. I've now found the STL deserializer code and could prepare a pull request if you would be willing to make such a change.

z3dev commented 5 years ago

@udif thanks

I like the idea but 12000 points still makes a lot of code. And I’m not sure that simplifies the issue.

STL is basically a set of triangles. And the data is converted into such a data structure as a series of function calls. Do you think a simple array of points would be better? And then just iterate across the array?

[ [[1,2,3],[1,2,3],[1,2,3]], // triangle ... ]

udif commented 5 years ago

@z3dev, I'm not sure I understand your response.

What I typically do is to drag-and-drop an STL file, and add my manipulations in the main() function. All I suggested, as a simple 1st stage, was to assign the points and triangles arrays into a variable before calling the polyhedron() function. It still requires me to do manipulation by hand, but it makes those hand manipulations much easier than before. Using the current STL import approach, I had to take the 120K+ lines JS output from STL, and:

  1. Cut everything from the start f the file to find the start of the points array, (easy, that's the beginning of the file) and change it to var points =
  2. Find the end of the points array (tedious, need to scroll the 120K+ lines and find the ending section), and replace it with ;
  3. replace the following code with var polygon = until the beginning of the polygon array data.
  4. Find the end of the polygon array (easy, a few lines from the end), and replace it with ;.
  5. Add my own main() that calls polyhedron(points: points, polygons: polygons)

Alternatively, the STL code generated would already contain var arrays points and polygons and the STL main would call polyhedron(points: points, polygons: polygons) instead of embedding the arrays within the function call. This means the steps I would need to take after importing an STL would be:

  1. Go to the end of the file, and find the main() function.
  2. Add my points/polygons array manipulation logic.

That's all!

gilboonet commented 5 years ago

To handle STL files, I wrote a little node.js that reads it (ascii STL only) and makes a .jscad where its data can be used, just like you do. To handle a huge STL you could modify it to read binary STL. It is here : https://github.com/gilboonet/auto_flattener/blob/master/stl2jscad.js just run from command line : node stl2jscad mySTLFile and it will create a jscad file from it that you can import into your jscad project.

z3dev commented 5 years ago

I understand. That’s what I was asking. Thanks. Creating the array of data seems like a good idea.

But 120K+ lines is still 120K+ lines.

I’m curious. What kind of manipulation logic are you going to do?

udif commented 5 years ago

@z3dev , Have you seen the example object I've linked to? It's an object from Thingiverse, that usually comes only in the form of STL files (no source files). In this case it was a filament holder. I needed to extend its arm since it was not wide enough for my filaments. The little JS code went over the points array and moved some of the points that belong to the arm (classified by x < 0, z > 40) by adding 10 to their Z value. The code also centered the object around x=0, y=0 and put it on z=0. This makes identifying the respective parts easier since the measurements don't depend on the arbitrary translation of the object in the cartesian space.

In the past I did similar processing to other STL objects (hard-kernel's Odroid-HC2 has a free STL for its case, but I wanted to manipulate it a bit to make it more 3d-printer friendly).

Not all STL post-processing tasks needs to work on points - some simply use union/intersect/subtract operations to combine openjscad objects with existing STLs, for example, adding an openjscad-designed custom mount to an existing STL-based object.

@gilboonet I'm not a JS developer, so I don't use node but I do know enough JS to write 3D objects. I usually develop my objects either directly in the built-in openjscad editor on the browser, or I'm using an editor, loading a local file into the browser and automatically reloading it when it changes.

I find the ability to create a single URL that loads my object extremely important. This way I can share customizable objects (using getParameterDefinitions() ) with people unfamiliar with OpenJSCAD by merely sending them a link.

@z3dev , so yes, 120K lines is not ideal, but if this is what it takes to let me shares objects via links, then this is what I do. I treat it like a binary blob. If I could get the model into geometrical shapes it would have been nicer, but for some of the models we get, we will have to settle for STLs.

kaosat-dev commented 5 years ago

@udif I actually like that more clean way of handling data in 'string mode' for stls really nice ! very close to what I usually do to manipulate things in jscad (simple arrays etc). My 2 cents:

udif commented 5 years ago

@kaosat-dev Not having much experience with node/npm I refreshed an old node/npm install, went through the instructions, installed lerna, npm run bootstrap, npm run web. What I got was a very unfamiliar GUI, (why is there no V2 beta playground on openjscad.org?), that crashed with OOM after I dragged a small STL into it, causing it to explode with 2GB RAM consumption. The same file easily loaded on the current openjscad.org EDIT: My node version was 9.3.0 . I'm now erasing everything and starting from scratch with the current 10.15.3-LTS version. EDIT2: Rebuilt from scratch on Linux (including node install and openjscad git clone) - same result - when dragging an STL to the window, the client process keeps growing until it is killed at 2GB+

kaosat-dev commented 5 years ago

@udif sorry about that, should have made it clear that drag & drop of external formats is not handled in V2 at this time (it is still pre-alpha) : we asked the community for feedback about 'text mode' vs data mode for drag & drops of external formats, and it was 50/50

z3dev commented 4 years ago

@udif V2 translates STL to JSCAD script like the attached. what do you think?

issue8.js.txt

udif commented 4 years ago

This is definitely better. I can manipulate the polygon list and points at the end of the function before the 'return' statement. As I have very little experience with node.js and other web technologies (other than basic pure Javascript knowledge) I can't suggest something better, but my ideal solution would be something that lets me accept a plain STL export file, and manipulate it via a separate JS script with no manual modification at all to the exported STL file. Is it possible to export the arrays directly, in addition to main() or export an additional function that returns the arrays directly without calling primitives.polyhedron()? Even if not, this change is still way better than what V1 offered.

z3dev commented 4 years ago

@paddlecraft V2 has the ability to directly import STL models as JSCAD objects. So, this kind of code is possible.

const { transforms } = require('@jscad/modeling')

const main = (params) => {
  let mesh1 = require('./shape.stl')
  mesh1 = transforms.scale([5, 5, 5], mesh1)
  return mesh1
}

No translation is required as the 'mesh' is instantiated directly into a JSCAD object.

z3dev commented 3 years ago

JSCAD V2 has additional functionality that covers everything in this issue. I’m closing this issue as this repository is DEPRECATED. Let’s open new issues for discussions and problems against V2.