Welcome to the Onshape forum! Ask questions and join in the discussions about everything Onshape.

First time visiting? Here are some places to start:
  1. Looking for a certain topic? Check out the categories filter or use Search (upper right).
  2. Need support? Ask a question to our Community Support category.
  3. Please submit support tickets for bugs but you can request improvements in the Product Feedback category.
  4. Be respectful, on topic and if you see a problem, Flag it.

If you would like to contact our Community Manager personally, feel free to send a private message or an email.

Reading in data

billy2billy2 Member, OS Professional, Mentor, Developers, User Group Leader Posts: 2,068 PRO
ilya I took this code from your spline example

FeatureScript 293;
import(path : "onshape/std/geometry.fs", version : "293.0");
import(path : "d444c222f52a949ad0c4bad3", version : "8a1976b65c772b1fe500125a");
annotation { "Feature Type Name" : "obj import" }
export const objImport = defineFeature(function(context is Context, id is Id, definition is map)
    precondition
    {        
    }
    {
        const data = BLOB_DATA.csvData;
        for (var row in data) 
        {
            for (var height in row)
            {
                println('height ' ~ height);
            }
        }
    });

It's not reading the data:


Here's the tab with the data and the id matches up:


Here's my data:


const data = BLOB_DATA.csvData;

Not sure where BLOB_DATA comes from?

Comments

  • kevin_o_toole_1kevin_o_toole_1 Onshape Employees, Developers, HDM Posts: 565
    Short answer: The CSV element is imported like any other. You'll need to point that second import to your CSV element (right now, it points to Ilya's), using its element id. We'll soon have a better interface for specifying which element should be imported, but the underlying functionality is there.

    For more info on FS imports (and how to get an element id), see this post
  • ilya_baranilya_baran Onshape Employees, Developers, HDM Posts: 1,212
    I only have a few secs to look -- but I think the import is correct -- I think the issue is that the extension needs to be csv for us to recognize it as a csv file.
    Ilya Baran \ VP, Architecture and FeatureScript \ Onshape Inc
  • billy2billy2 Member, OS Professional, Mentor, Developers, User Group Leader Posts: 2,068 PRO
    Thanks guys, *.csv who would have thought.



    Kevin, I did look at that link, it's really quite simple.

    Thanks,


  • kevin_o_toole_1kevin_o_toole_1 Onshape Employees, Developers, HDM Posts: 565
    Awesome! I see what led me off now – your code's import element id matched "Ilya's" snippet, so I assumed, since those ids are globally unique, that you just hadn't changed the import.

    Glad to see it working smoothly!

  • billy2billy2 Member, OS Professional, Mentor, Developers, User Group Leader Posts: 2,068 PRO
    String parsing? Ok, so this isn't javascript. What string methods are there?

    How do I parse an input string?
            for (var row in data)
            {
                for (var txt in row)
                {
                    println('txt ' ~ txt);
                    str=toString(txt);
                    res = str.split(" ");
                    println('res[0] ' ~ res[0]);
                    println('res[1] ' ~ res[1]);
                    println('res[2] ' ~ res[2]);
                    println('res[3] ' ~ res[3]);
                }
            }

    Is this it?


    Will I have to write my own split() function?




  • ilya_baranilya_baran Onshape Employees, Developers, HDM Posts: 1,212
    String processing hasn't really been our focus so far -- so what you're seeing is it for now.  I think it should be possible to write a robust split function in terms of match.  I am curious -- what is your use-case?
    Ilya Baran \ VP, Architecture and FeatureScript \ Onshape Inc
  • billy2billy2 Member, OS Professional, Mentor, Developers, User Group Leader Posts: 2,068 PRO
    Ok, so now I'm down to the character level:


    Let's say I want to build a library of string parsing routines so I can include it whenever. What does this look like? 
  • billy2billy2 Member, OS Professional, Mentor, Developers, User Group Leader Posts: 2,068 PRO
    giving up on split:




    How  do you use split()? It's not showing an error with the syntax checker? Is it valid or not?


  • kevin_o_toole_1kevin_o_toole_1 Onshape Employees, Developers, HDM Posts: 565
    edited February 2016
    Unlike JS, in FeatureScript you cannot attach methods to anything you'd like (e.g. str.split()). You need to instead pass your string into a function you define, like
    export function split(str is string, splitToken is string) returns array
    {
        // split the string w/ regexes
        return [];
    }
    
    var substrings is array = split(str);
    As for the method itself, I think the following would do what you want:
    1. Use match() with a custom regex with two capture groups: one to grab everything up to the first occurrence of splitToken, and one for everything after.
    2. Add the first capture to your returned array
    3. Replace str with the second capture (i.e. the rest of the string)
    4. Repeat 1-3 until no match is found (and put the remainder on the end of your array)


    Perhaps a better question: What format are the rows of your CSV that requires this split method? You'll probably be happiest in a world where each cell of your CSV only contains one number, or a known string. We provide stringToNumber(), and I imagine processing a cell will be much easier (and faster!) if stringToNumber() is all you need.

    To take a step back: Our impression has been that string manipulation isn't that common right now, and that for the time being there are bigger fish for us to fry. If the lack of these utilities is really preventing you from getting things done, definitely let us know.

  • billy2billy2 Member, OS Professional, Mentor, Developers, User Group Leader Posts: 2,068 PRO
    I'm reading in an obj file and would like to create points at each scan location. A point cloud from a scanner.

    Look at the Obj spec, I'm only interested in the lines beginning with v. Then need to parse x, y, z. It won't be that bad.

    Obj format:
    # Generated.
    mtllib Model.mtl
    v 0.0919 0.0442 0.0310
    vn 0.08 -0.07 -0.99
    vt 0.02660 0.98611
    v 0.0882 0.0431 0.0310
    vn 0.04 -0.13 -0.99
    vt 0.02483 0.98656
    v 0.0867 0.0441 0.0308
    vn -0.07 -0.09 -0.99
    vt 0.02410 0.98607
    v 0.0906 0.0421 0.0312
    vn 0.03 -0.08 -1.00
    vt 0.02595 0.98709
    v 0.0874 0.0452 0.0308
    vn 0.01 -0.03 -1.00
    vt 0.02442 0.98555
    v 0.0914 0.0459 0.0309
    vn 0.05 -0.04 -1.00
    vt 0.02633 0.98529
    # End of file.


    Questions:
    -Is there a 3D point? I see 2D point on a sketch. Was going to create a 3d line: 1pt @ origin, the other @ scan point to show point cloud.
    Hoping there's a 3D point. Why do you have a 3D circle and no 3D point? Can I define a sketch with a 3D point defined in it? a point with a 'z'?

    -If I wrote many string functions in a FS tab, couldn't I import them into another FS and use them?



    String manipulations, I only use a few and could knock'm out in no time. Bring in a text file and parsing it for goodness. I'll roll my own for now.

    Thanks

  • ilya_baranilya_baran Onshape Employees, Developers, HDM Posts: 1,212
    I'd probably just use a regexp:
    function parseVertex(s is string) // Returns a unitless 3D Vector or undefined
    {
        const regexp = "v\\s+" ~ REGEX_NUMBER_CAPTURE ~
                        "\\s+" ~ REGEX_NUMBER_CAPTURE ~
                        "\\s+" ~ REGEX_NUMBER_CAPTURE ~ "\\s*";
        const matches = match(s, regexp);
        if (!matches.hasMatch)
            return undefined;
        var result = makeArray(3);
        for (var i in [0, 1, 2])
            result[i] = stringToNumber(matches.captures[i + 1]);
        return vector(result);
    }
    But a split function should also work. You can import feature studios into each other and reuse functions -- for now, see https://cad.onshape.com/FsDoc/toplevel.html#imports but we're working to make this easier.

    We don't have a "create a 3D circle" operation -- we have a type Circle, which represents a 3D circle just like a Vector of lengths represents a point in space.  To actually create a construction point, you can currently do:
    opPoint(context, id + "point1", { "point" : vector(1, 2, 3) * inch, "origin" : true });
    Unfortunately we don't currently display points that are not marked as "origin" -- we're working on that bug.  If you are ok with a point that you don't need to select and that is only visible while the feature is edited, you can do
    debug(context, vector(1, 2, 3) * inch);
    Hope this helps.
    Ilya Baran \ VP, Architecture and FeatureScript \ Onshape Inc
  • billy2billy2 Member, OS Professional, Mentor, Developers, User Group Leader Posts: 2,068 PRO
    Thanks for parseVertex, it's perfect.

    I want to select them, so I'll use opPoint.

    Once again, thanks
  • billy2billy2 Member, OS Professional, Mentor, Developers, User Group Leader Posts: 2,068 PRO
    This is really cool.


  • ilya_baranilya_baran Onshape Employees, Developers, HDM Posts: 1,212
    Nice -- "guess which one is the real origin" :smile: 
    Ilya Baran \ VP, Architecture and FeatureScript \ Onshape Inc
  • billy2billy2 Member, OS Professional, Mentor, Developers, User Group Leader Posts: 2,068 PRO
    edited February 2016
    Only 4 hours to center point cloud about OS origin, there's something wrong with me.



    One thing that's clear is that I have to parse the obj file and figure out how many points there are. Converting all scanned points to OS points sends servers into a frenzy. 

    Seems like OS handles 1,000 points to display easily, which is good enough to see the overall scanned shape. I'll create another algorithm to rescan and refine points along a cross sectional plane. Pick a plane, then OS shows points that lie close to that plane. I like this refinement technique, at least I think I do. I'll have to write it and see if it works.

    questions:
    -how do I window select points and delete points?
    -what does "clusterPoints (points is array, tolerance is number) returns  array" do?
    -how do I  wrap all points into a group and perform transforms on the group vs. transforming one point at a time?


    Thanks



  • ilya_baranilya_baran Onshape Employees, Developers, HDM Posts: 1,212
    Unfortunately, as we haven't had "construction" points as first-class entities/bodies in the UI so far, support for hiding, deleting, and doing some other things with them is lacking.

    clusterPoints does what the documentation says -- it's basically a fast and robust way of finding groups of points in a given set that are close together.  One place where it's used is the hole feature so that making a hole with a vertex selected twice makes only one hole at that location (rather than causing problems).

    You can pass a query for many point bodies to opTransform and they will be transformed.  Again interactively working with a cloud of points is not something where everything works yet.
    Ilya Baran \ VP, Architecture and FeatureScript \ Onshape Inc
  • billy2billy2 Member, OS Professional, Mentor, Developers, User Group Leader Posts: 2,068 PRO
    I get it, a point, the most uninteresting CAD entity. Other things are more important right now.




  • billy2billy2 Member, OS Professional, Mentor, Developers, User Group Leader Posts: 2,068 PRO
    edited February 2016
    Ok, so I must be getting better at featurescript or today I was just lucky. I wrote this in an hour.
    My goal was to create sub-clouds defined from faces to produce higher resolution point clouds. It was really easy to do.


    So my scan has 59822 points which OS won't render and I don't care that it won't render.




    So this is the overview of the scan which I limit to around 1000 points. It's actually 1013 points because of the round off error when calculating point density.




    The scanner does a good job with up & down orientation but it doesn't position the cloud perfectly. I have no user transforms written yet so the cloud is stuck in space. I created a bisecting primary slice face that's not true to X, Y, Z planes to pick up greater handle detail. The rescan is working to 1mm of this plane and produced 225 sub-cloud points with a higher resolution than the original overscan.




    Sub-slices from the primary face generated 94 points around the circumference of the cup, 27 points through the upper handle and 27 points through the lower handle.



    In less than a  hundred lines of featurescript code, I've created a useful tool. I'm currently using SW, converting obj files to stl, and importing into SW. Once in SW it's very difficult to use. This little scan featurescript is so much more powerful than my SW approach and far more useful for reverse engineering.







  • MBartlett21MBartlett21 Member, OS Professional, Developers Posts: 2,050 ✭✭✭✭✭
    @billy2
    Can you share the FS?
    mb - draftsman - also FS author: View FeatureScripts
    IR for AS/NZS 1100
  • billy2billy2 Member, OS Professional, Mentor, Developers, User Group Leader Posts: 2,068 PRO
    @MBartlett21

    "Holly Crap Batman"

    That's such an old file. That was before we had meshes. Please use with caution, or better yet, don't use at all.

    https://cad.onshape.com/documents/18339e846c8cac6d61510d3a/w/b51557f546eee2bdc8a489e9/e/ef4729a66e116f079b07f09b


Sign In or Register to comment.