Get strokeWeight from PShape

edited September 2016 in How To...

I load an SVG and I need to get the strokeWeight from it. Is there anyway, no matter how hacky to do it?

So far the best way seems to be a find replace for 'private' to 'public' on the whole processing repository.

Answers

  • edited September 2016

    If you already know the member (be it a field or a method) which holds or returns that strokeWeight value, it's pretty easy to use Java's reflection technique in order to forcibly grab it! :ar!

  • here it is:

    ` public float get_stroke_weight(PShape s) {

        try {
            Field field = PShape.class.getDeclaredField("strokeWeight");
            field.setAccessible(true);
            try {
                return (float) field.get(s);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
    
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        return -1;
    }`
    

    Only processing saves the strokeWeight somewhere else :(

    PShape is one of the worst designed classes I have ever encountered.

  • **** me, it's even worse.

    If I have this SVG:

    <?xml version="1.0" encoding="utf-8"?>
    <!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
    <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
         viewBox="0 0 200 200" style="enable-background:new 0 0 200 200;" xml:space="preserve">
    <style type="text/css">
        .st0{fill:none;stroke:#231F20;stroke-width:55;stroke-miterlimit:10;}
    </style>
    <polyline class="st0" points="69.7,15.7 36.8,118.2 69.7,164.3 123.3,164.3 150.8,149.7 170.3,22.7 "/>
    </svg>
    

    Then it looks like this in illustrator:

    Screen Shot 2016-09-11 at 13.17.27

    But processing makes it a fill instead of a stroke :(

    Screen Shot 2016-09-11 at 13.17.47

    There goes my sunday.

  • This save option seems to help:

    Screen Shot 2016-09-11 at 13.27.10

  • edited September 2016

    Hi clankill3r -- it would be really helpful to see your Processing code sample and understand what you are trying to accomplish. Your SVG sample shows a six-point polyline. If you just use ".vertex" to load six points into a PShape it will assume you are describing the edge points of a polygon -- in other words, it will assume that those six points describe a shape, not a line.

    Maybe try using createShape(LINE) -- as per https://processing.org/reference/createShape_.html

    Alternately, export edge vertices. Your big "U" shape has twelve of those. If Illustrator isn't exporting an SVG file with twelve coordinates in its 'polyine' then it isn't exporting what you need for that purpose. I haven't used Illustrator in a while, but a "Stroke to Path" type command or tool might do it.

  • edited September 2016

    Only processing saves the strokeWeight somewhere else...

    Funny it worked for me; at least for createShape(). Dunno about loadShape() though: :(|)

    // forum.Processing.org/two/discussion/18119/get-strokeweight-from-pshape
    // 2016-Sep-11
    
    PShape square;
    
    void setup() {
      noLoop();
      stroke(#FF0000);
      fill(#00FFFF);
      shapeMode(CORNER);
      square = createShape(RECT, 0, 0, width>>1, height>>1);
      println(setShapeStrokeWeight(square, 16.35));
    }
    
    void draw() {
      background(0);
      shape(square, width>>2, height>>2);
    }
    
    static final float setShapeStrokeWeight(final PShape s, final float wgt) {
      try {
        java.lang.reflect.Field f = s.getClass().getDeclaredField("strokeWeight");
        f.setAccessible(true);
        f.setFloat(s, wgt);
        return f.getFloat(s);
      }
      catch (final ReflectiveOperationException e) {
        e.printStackTrace();
        throw new InternalError("strokeWeight doesn't exist in class PShape anymore!");
      }
    }
    
  • One of the issues with loadShape() specifically may also be that loadShape often (sometimes? always?) puts SVG elements in PShape "child" sub-PShapes. So you need to iterate over the children, and check them for weight.

    I encountered this recently with someone who was finding 0 vertices after using loadShape on an OBJ file. It was full of vertices, but they were all in the Child shapes, which had to be looped over. See: https://forum.processing.org/two/discussion/comment/74561/#Comment_74561

  • The thing was, cause I didn't save it as 'Presentation Attributes' processing was not able to parse the svg file correctly. That is why I thought the strokeWeight didn't work but it does now.

    Still a pain in the ass do, for something that just should have been public.

  • edited September 2016

    When creating our own PShape, it uses the current styles, like fill(), stroke(), etc.

    After that, in order to modify any of those, we need to use the corresponding setXXX() methods, like setFill() or setStroke().

    Apparently they've forgotten to mention method setStrokeWeight() @ PShape's web reference: 8-}
    https://Processing.org/reference/PShape.html

    But it's there and it works! No need to rely on reflection for that at all! :P

  • Setting is not the problem, getting is the problem. And I can't get that done without reflection. getStrokeWeight(int index) fails.

  • edited September 2016

    In general, Processing API lacks getters indeed. 3:-O
    In turn, most p5.js API functions become getters when calling them w/ empty argument. $-)

  • edited September 2016

    If you really want to do this without reflection and your SVG data is like the sample you give, then another option is to read it directly from the SVG file (PShape is really made for writing, and reading / modifying / copying is inconsistant).

    For example:

    1. use Processing's ParseXML() (an svg file is xml).
    2. access the XML value with XML methods

    The part you are looking to match is here:

    <style>
      .st0{...;stroke-width:55;...}
    </style>
    
  • I know but I made some code to interpolate between 2 svg files, and accessing the xml for that would make it a real pain in the ass.

  • edited September 2016

    If you want to share the code you might be able to get further feedback or suggestions.

    Reflection and XML loading may both be a pain, but they will both get the stroke weight. I'm not sure what you mean about interpolating -- if you are dynamically generating intermediate SVGs, or if you are just animating between two sets of loaded variables. If the key issue is that your sketch is generating and keeping a lot of data in SVGs, then a global solution might be to keep that data elsewhere -- in arrays and lists, for example. PShapes as they currently exist are really not made for reading / modifying / copying, so attempts to design in that way will often lead to some pain.

  • I already got it working. I think ben fry and casey reas need some feedback and suggestions...

  • Glad to hear it is working for you.

    Is there anything you would like to share about how you got it working as advice to others, to help someone who has a similar problem?

  • Post 3 and 5 should help them.

Sign In or Register to comment.