Some, but not all, definition attributes are set

Some, but not all, definition attributes are set

Postby klpauba » Thu Nov 02, 2017 7:09 pm

I have another little problem that I just can't figure out (after perusing the forums for a few hours).

I have a solid component (the "original") that I add a few attributes to the definition before I copy it, perform some solid "trim" operations on the copy and then attempt to save the volume of the copy as an definition attribute of the original.

original = Sketchup.active_model.selection[0]

if original.volume != original.definition.set_attribute("timber", "volume_uncut", original.volume)
print("ERROR: Unable to set original's attribute\n")
end

theCopy = model.entities.add_instance(original.definition, original.transformation)
theCopy.make_unique

# perform a number of "trim" operations on theCopy and other solid components

if theCopy.volume != original.definition.set_attribute("timber", "volume", theCopy.volume)
print("ERROR: Unable to write data: #{theCopy.volume}")
end


Using the Eneroth Attribute Editor, I can select the original component and see only the "volume_uncut" attribute -- the "volume" attribute is missing.

The console doesn't report any of the ERROR messages and I've verified the the values for original.volume and theCopy.volume are valid numbers just before invoking the set_attribute methods.

Nothing else is done with the original component than shown here.

I'm at a loss as to where I've screwed up and don't have any more ideas on how to fix it. Any hints?

Thanks
0

klpauba 
Premium Member
Premium Member
 

Re: Some, but not all, definition attributes are set

Postby Dan Rathbun » Thu Nov 02, 2017 10:53 pm

Solid operations create a resultant Group. A Group is a special component that has a group flag set and does not appear in the Component Browser. But like any component has a definition.
So a group is really a "special" component instance.

Both instances and definition can be assigned attributes. Normally an instance type data attribute would be assigned to an instance's dictionary, not a definition's.
This is because instances can be scaled to change the volume. Sometimes the scaling is along a single axis resulting in a "stretch" of the original. (Different instances of the same definition can be scaled and stretched differently.)

Volume: Manifold solid instances of group and components have a built in API method to return the volume, named volume(), so there is no real need to waste time computing it and saving it to a dictionary attribute.
http://ruby.sketchup.com/Sketchup/Group.html#volume-instance_method



Now, Jim Foltz created a plugin called Trim and Keep that works around some of the annoying creating of new group from solid operations.

Look it up in the PluginStore.
0
    I'm not here much anymore. But a PM will fire email notifications.
    User avatar
    Dan Rathbun 
    PluginStore Author
    PluginStore Author
     

    Re: Some, but not all, definition attributes are set

    Postby Dan Rathbun » Thu Nov 02, 2017 11:02 pm

    I notice some errors in your coding:

    if original.volume != original.definition.set_attribute("timber", "volume_uncut", original.volume)

    You cannot both test and set in the same statement like above. This statement will always be true because it sets the attribute every time.

    Same for the second attribute volume test later.

    You would need to first set the attribute when the instance is first created. Then test later something like:
    original.definition.set_attribute("timber", "volume_uncut", original.volume) if original.volume != original.definition.get_attribute("timber", "volume_uncut")
    1
      I'm not here much anymore. But a PM will fire email notifications.
      User avatar
      Dan Rathbun 
      PluginStore Author
      PluginStore Author
       

      Re: Some, but not all, definition attributes are set

      Postby klpauba » Fri Nov 03, 2017 3:59 am

      Hi, Dan. Thanks for taking the time to respond to my question.

      Dan Rathbun wrote:
      Both instances and definition can be assigned attributes. Normally an instance type data attribute would be assigned to an instance's dictionary, not a definition's.
      This is because instances can be scaled to change the volume. Sometimes the scaling is along a single axis resulting in a "stretch" of the original. (Different instances of the same definition can be scaled and stretched differently.)

      In the problem domain in which this code will be used (Timber Framing), there isn't usually the need to scale any of the instances but I didn't state that figuring I'd keep it simple (sorry about that!). If a timber is different in dimensions, a new component is typically created.

      The extension I'm writing allows me to select any one instance of the timber and it then trims the beams (with tenons), braces (also with tenons), pegs, roof rafters, etc. that intersect with it. The resultant solid is then formatted as a shop drawing, saved to a separate .skp file, and then deleted from the model (thus, losing the any attributes that would have been saved with the instance). I want to use the difference between the volume of the selected component and the volume of the resultant solid to determine the amount of wood that needs to be removed -- this would be used to arrive at a rough estimate of the effort required to cut the timber. Saving this information in the definition makes much more sense in this case since it's the same for all instances using the same definition.

      Moreover, if the dimensions of a timber were to change, a new shop drawing would be generated and the definition attributes related to the dimensions would then be updated.

      Dan Rathbun wrote:Volume: Manifold solid instances of group and components have a built in API method to return the volume, named volume(), so there is no real need to waste time computing it and saving it to a dictionary attribute.
      http://ruby.sketchup.com/Sketchup/Group.html#volume-instance_method


      Point taken. I used volume as an example for the code but there are a number of other attributes (section modulus, moment of inertia, etc.) that I plan on saving.

      Dan Rathbun wrote:

      Now, Jim Foltz created a plugin called Trim and Keep that works around some of the annoying creating of new group from solid operations.

      Look it up in the PluginStore.

      Kewl, I'll look this one up.

      In light of all this, might you have an idea on why the second set_attribute would not work?

      Also, I (re)discovered Layout Tables, maybe this might be a better way to collect up the data associated with the timbers and get it into the 2D drawing. Thoughts?
      0

      klpauba 
      Premium Member
      Premium Member
       

      Re: Some, but not all, definition attributes are set

      Postby klpauba » Fri Nov 03, 2017 4:11 am

      Dan Rathbun wrote:I notice some errors in your coding:

      if original.volume != original.definition.set_attribute("timber", "volume_uncut", original.volume)

      You cannot both test and set in the same statement like above. This statement will always be true because it sets the attribute every time.

      I think you meant "This statement will always be false ...", right (the comparison is !=)?

      Yes. I had read the documentation of set_attribute and it mention that it returns "the newly set value if successful". It doesn't mention what it'll return if unsuccessful so I assumed 'nil' or a null string (in Python, they're different but I'll have to look it up for Ruby). My assumptions were incorrect so I'll change the code to your suggestion (besides, I like your code better) --- THANKS!

      Great to have people like you, Dan, to help us neophytes out!
      0

      klpauba 
      Premium Member
      Premium Member
       

      Re: Some, but not all, definition attributes are set

      Postby klpauba » Sat Nov 04, 2017 12:20 pm

      I have resolved the issue I originally described. The code that performed the trimming and second original.set_attribute() operations were between a model.start_operation() and model.commit_operation(). When I moved the second original.set_attribute() after the model.commit_operation(), I got an error on the console implying original was deleted. I modified the code to save a reference to operation.definition and then using this to set the attributes,.
      After doing this, the code worked as I first expected (I hope that all makes sense).
      0

      klpauba 
      Premium Member
      Premium Member
       

      Re: Some, but not all, definition attributes are set

      Postby Dan Rathbun » Wed Nov 08, 2017 4:17 pm

      klpauba wrote:I think you meant "This statement will always be false ...", right (the comparison is !=)?


      yes.

      klpauba wrote:I had read the documentation of set_attribute and it mention that it returns "the newly set value if successful". It doesn't mention what it'll return if unsuccessful so I assumed 'nil' or a null string (in Python, they're different but I'll have to look it up for Ruby). My assumptions were incorrect so I'll change the code to your suggestion (besides, I like your code better) --- THANKS!


      Since v2016 if the key is nil or empty, it will raise an exception:
      Error: #<ArgumentError: Key cannot be empty>

      Otherwise the method will convert any argument to a string if it can, and if it cannot for the value, then it'll just silently store "nil" in the dictionary.

      So, basically do validation in your code. (Ie, test for nil values etc.)

      Ruby core has a #nil? instance method for all objects that is preferable to:
      obj == nil
      ie:
      obj.nil? or !obj.nil?
      0
        I'm not here much anymore. But a PM will fire email notifications.
        User avatar
        Dan Rathbun 
        PluginStore Author
        PluginStore Author
         

        Re: Some, but not all, definition attributes are set

        Postby Dan Rathbun » Wed Nov 08, 2017 4:46 pm

        klpauba wrote:I got an error on the console implying original was deleted.

        It probably was. As I said, boolean operations create a new original instance that is always a Sketchup::Group object, which is an instance of a new cloned Sketchup::ComponentDefinition object (with it's #group? flag set true.)

        This has bothered users and coders in the past who'd rather like the instances to remain as Sketchup::ComponentInstance objects. (Hence Jim's Trim and Keep plugin.)

        klpauba wrote:The extension I'm writing allows me to select any one instance of the timber and it then trims the beams (with tenons), braces (also with tenons), pegs, roof rafters, etc. that intersect with it.

        The problem is that in SketchUp instances do not have geometry collections, only definitions do. So every instance of a certain definition must be geometrically identical. When the user double-clicks to enter the editing context of an instance, they are actually then within it's definition's local geometry collection. So the user is actually editing every one of the definition's instances simultaneously.

        To get around this, a user or coder can (like sometimes the Dynamic Component engine does,) make the instance unique, which clones the original picked instance's definition to a new unique definition. Then the user or coder can modify that definition's geometry without effecting any instance's of the original definition.
        http://ruby.sketchup.com/Sketchup/ComponentInstance.html#make_unique-instance_method

        klpauba wrote:I want to use the difference between the volume of the selected component and the volume of the resultant solid to determine the amount of wood that needs to be removed -- this would be used to arrive at a rough estimate of the effort required to cut the timber.

        Certainly doable as both definition's would be in the model. You can save the original's volume as you've been doing in the "trimmed" definition, or save an attribute that points at the original definition object.

        klpauba wrote:The resultant solid is then formatted as a shop drawing, saved to a separate .skp file, and then deleted from the model (thus, losing the any attributes that would have been saved with the instance).

        Right, because saving a component saves it as a component definition SKP.

        But usually coders do not separate out the components into separate files. It is easier to insert a new instance perhaps off to the side of the assembly, and have it assigned to a scene specific layer that is visible only on that scene, then this scene will correspond to a viewport in LayOut.

        DaveR (who designs furniture) has explained this a myriad of times in the forums.
        0
          I'm not here much anymore. But a PM will fire email notifications.
          User avatar
          Dan Rathbun 
          PluginStore Author
          PluginStore Author
           

          Re: Some, but not all, definition attributes are set

          Postby Dave R » Thu Nov 09, 2017 4:49 am

          Dan asked me to chime in.

          I'm curious about this:

          klpauba wrote:The resultant solid is then formatted as a shop drawing, saved to a separate .skp file, and then deleted from the model (thus, losing the any attributes that would have been saved with the instance).


          That doesn't seem like an especially good way to work for creating shop drawings. If you need to edit the shop drawings to make changes to dimensions or other details, it sounds like you have a lot of work to do to make sure everything gets updated. If I applied your process to the plans I create for furniture and other woodworking projects, they'd never get completed before deadlines and the inevitable edits would be killers.

          As Dan mentioned, it's easier if you make copies of the components and keep them in the same model. And don't delete them from anywhere. For example, this is what the overall model looks like for a recent plan for a workbench.
          Screenshot - 11_8_2017 , 9_32_58 PM.png


          This is the second sheet of the plan. Each viewport is from a scene created in the SketchUp model.
          Screenshot - 11_8_2017 , 9_34_01 PM.png


          Since every single part of the bench is a component, modifications to the model and the plan are trivial. I can change something in the assembled version of the model, at the origin, and they are made throughout the model. When the reference is updated in LayOut, the dimensions update as do the labels with dimensions. It's automatic and no errors.
          2
          Etaoin Shrdlu


          %

          (THERE'S NO PLACE LIKE)

          G28 X0.0 Y0.0 Z0.0

          M30

          %
          User avatar
          Dave R 
          Global Moderator
           

          Re: Some, but not all, definition attributes are set

          Postby klpauba » Thu Nov 09, 2017 9:50 pm

          Dan & Dave,

          Thanks for the feedback you've provided. I'll be re-reading your comments (probably many times) as the methods you both describe would probably work better for me.
          0

          klpauba 
          Premium Member
          Premium Member
           

          Re: Some, but not all, definition attributes are set

          Postby klpauba » Fri Nov 10, 2017 9:27 pm

          Dan & Dave,

          I was wondering if your collective experience could help me work out a more efficient workflow. The one I've been using is based off of the way the "Timber Framing Rubies" extension worked. That extension works with the free version of Sketchup but I think the Pro version (with its solid tools and Layout), and with the help of some custom code, is much better suited for timber framing design.

          Here's a simple "bent" (collection of joined timbers) for the sake of discussion. This bent consists of six components: right and left posts, a beam, right and left braces and a peg (six instances). Only the "male" parts of the joinery are drawn (the tenons) so, in this case, the post is simply a rectangular volume.
          Screen Shot 2017-11-10 at 11.04.41 AM.png


          Let's say the design is pretty much finished and I wish to generate a shop drawing for the left post. I would select the post and choose the "Make Shop Drawing" item from the context menu. The script would copy the selected post, make it unique and trim the post with each intersecting component (the beam, right brace and two pegs).
          It would then create a group (maybe in a layer named "Shop Drawing" perhaps) with four copies of the post (now with all of the mortises and peg holes). The four copies give the parallel projection view of each of the sides of the post that can be brought into a layout viewport for dimensioning. I have the ruby script doing these steps right now (short of creating the new layer) but the shop drawings are saved to a separate file. I was thinking of modifying the script to create a "Post Shop Drawing" Scene showing just the "Shop Drawing" layer the group of four copies positioned in the window with all the right settings (if the script doesn't do that for me).
          Screen Shot 2017-11-10 at 11.32.06 AM.png


          I would like to keep the original (unmodified) post in place so that if I later decide to, say, replace the 30-60-90 degree brace that's shown with a more conventional 45 degree brace, I can just replace the one that's there, select the post and execute the script once again (presuming I can replace the group in the "Post Shop Drawing" layer with the new one).

          I do like the idea of keeping all of this in a single skp file and doing away with the separate shop drawings. Does the workflow I describe above seem reasonable? I welcome any suggested improvements.
          0

          klpauba 
          Premium Member
          Premium Member
           

          Re: Some, but not all, definition attributes are set

          Postby Dan Rathbun » Wed Nov 15, 2017 5:57 pm

          klpauba wrote:Let's say the design is pretty much finished and I wish to generate a shop drawing for the left post. I would select the post and choose the "Make Shop Drawing" item from the context menu. The script would copy the selected post, make it unique and trim the post with each intersecting component (the beam, right brace and two pegs).

          This is correct.

          (Not a timber person, but am a fan of "BarnBuilders". Wouldn't the peg holes be drilled in place after the bent is assembled on site? I could see starting a pilot hole in the post.)

          klpauba wrote:It would then create a group (maybe in a layer named "Shop Drawing" perhaps) with four copies of the post (now with all of the mortises and peg holes). The four copies give the parallel projection view of each of the sides of the post that can be brought into a layout viewport for dimensioning.
          ...
          I was thinking of modifying the script to create a "Post Shop Drawing" Scene showing just the "Shop Drawing" layer the group of four copies positioned in the window with all the right settings (if the script doesn't do that for me).

          NO. This is not how it is done for LayOut. ONE copy is made and moved off to the side, and perhaps set to use it's own "detail" layer.
          Then, four scenes (camera positions) are created for the 4 viewports in LayOut, each showing one of the post's sides (in each of the 4 scenes the "detail" layer is set "visible" whilst all others are "off" [except for "Layer0" the primitives layer which must always be visible].)

          klpauba wrote:I have the ruby script doing these steps right now (short of creating the new layer) but the shop drawings are saved to a separate file.

          You can have many pages in a LayOut document each with as many viewports that correspond to a scene page in the SketchUp model. It is not really necessary to have separate documents.

          BUT, you may if you choose to. A single LayOut document may have scene viewports from multiple SKP models, or a multiple LayOut documents can have scenes from a single SKP model. (The latter seems to be the closest to what you are doing now.)

          klpauba wrote:I would like to keep the original (unmodified) post in place so that if I later decide to, say, replace the 30-60-90 degree brace that's shown with a more conventional 45 degree brace, I can just replace the one that's there, select the post and execute the script once again (presuming I can replace the group in the "Post Shop Drawing" layer with the new one).

          The original "unmods" could be associated with the "working" layer up until the point when you do the intersection, and make them unique. The code could create a "unmod" copy and put it on a hidden layer, but in proper position for possible mod later.

          OR, the code could have a command to recreate (instantiate) an "unmod" post at a later date using the current transform of the "moded" post. (This way you don't have unused geometry bloating the model. The same would need to be done with the beams. I prefer this workflow.)

          Another alternative is to build the frame and copy the entire thing perhaps as a unique assembly component, before adding the bracing ? This could be all on a hidden later "in limbo" so to say. So that any timber can be copied "in place" (already having the correct transform) to the main "working" layer.
          0
            I'm not here much anymore. But a PM will fire email notifications.
            User avatar
            Dan Rathbun 
            PluginStore Author
            PluginStore Author
             

            Re: Some, but not all, definition attributes are set

            Postby Dan Rathbun » Wed Nov 15, 2017 7:23 pm

            klpauba wrote:That extension works with the free version of Sketchup but I think the Pro version (with its solid tools and Layout), and with the help of some custom code, is much better suited for timber framing design.

            Yesterday SketchUp 2018 Pro was released, and with it we now have a Ruby API for creating and accessing LayOut documents from SketchUp. (A live in LayOut API with application hooks has not yet been implemented, but is likely within a version or two.)

            Doc: LayOut API overview
            Doc: Layout module

            This is important for you to know that SketchUp Make is discontinued (and will not be updated beyond v2017.) It is replaced by the cloud SketchUp Free (formerly my.sketchup) which as yet has no API, and when it gets one it'll likely be Javascript rather than Ruby.
            0
              I'm not here much anymore. But a PM will fire email notifications.
              User avatar
              Dan Rathbun 
              PluginStore Author
              PluginStore Author
               

              Re: Some, but not all, definition attributes are set

              Postby klpauba » Thu Nov 16, 2017 4:26 am

              Dan Rathbun wrote:(Not a timber person, but am a fan of "BarnBuilders". Wouldn't the peg holes be drilled in place after the bent is assembled on site? I could see starting a pilot hole in the post.)

              You're correct ... the holes are typically laid out in pencil and not drilled until shortly before raising when the joints are "fit up" to ensure all the joints fit together. Posts are drilled first and then the beam and braces are removed and drilled separately with the hole slightly offset ("draw-bored") so that pounding the peg in will draw the joint tightly together.

              Dan Rathbun wrote:NO. This is not how it is done for LayOut. ONE copy is made and moved off to the side, and perhaps set to use it's own "detail" layer.
              Then, four scenes (camera positions) are created for the 4 viewports in LayOut, each showing one of the post's sides (in each of the 4 scenes the "detail" layer is set "visible" whilst all others are "off" [except for "Layer0" the primitives layer which must always be visible].)

              I could imagine twenty or thirty unique timbers that would need shop drawings in a more complex timber frame. That's a lot of scenes! Automating it would make it easier to generate the scenes/pages but importing all those models and arranging the viewports in Layout would be a pain. However, I'll experiment with generating the scenes as you suggest.

              Dan Rathbun wrote:The original "unmods" could be associated with the "working" layer up until the point when you do the intersection, and make them unique. The code could create a "unmod" copy and put it on a hidden layer, but in proper position for possible mod later.

              OR, the code could have a command to recreate (instantiate) an "unmod" post at a later date using the current transform of the "moded" post. (This way you don't have unused geometry bloating the model. The same would need to be done with the beams. I prefer this workflow.)

              Another alternative is to build the frame and copy the entire thing perhaps as a unique assembly component, before adding the bracing ? This could be all on a hidden later "in limbo" so to say. So that any timber can be copied "in place" (already having the correct transform) to the main "working" layer.


              All excellent suggestions. Your preferred method would be my choice also. Beams (and sometimes posts), however, often have tenons (or other complex geometries) at the ends that would probably make the first suggestion more viable (although I'll think about the others a bit more).

              I don't expect to take up more of your time, Dan, but if you have more suggestions please keep them coming!
              1

              klpauba 
              Premium Member
              Premium Member
               

              Re: Some, but not all, definition attributes are set

              Postby klpauba » Thu Nov 16, 2017 4:36 am

              Dan Rathbun wrote:Yesterday SketchUp 2018 Pro was released, and with it we now have a Ruby API for creating and accessing LayOut documents from SketchUp. (A live in LayOut API with application hooks has not yet been implemented, but is likely within a version or two.)

              Doc: LayOut API overview
              Doc: Layout module

              Thanks, I'll be reading the docs to see how they might automate the workflow we've discussed.

              Dan Rathbun wrote:This is important for you to know that SketchUp Make is discontinued (and will not be updated beyond v2017.) It is replaced by the cloud SketchUp Free (formerly my.sketchup) which as yet has no API, and when it gets one it'll likely be Javascript rather than Ruby.

              This will be a disappointment to those who currently use (or plan to use) the TF Rubies extension. I suspect they will continue to use the 2017 version until the web-based version allows the use of extensions. I don't have much concern since I have Pro.
              1

              klpauba 
              Premium Member
              Premium Member
               

              Re: Some, but not all, definition attributes are set

              Postby Dan Rathbun » Fri Dec 08, 2017 3:50 am

              Wanted to point you towards a tutorial that is posted on the "official" Trimble forums:

              [Tutorial] Ten Fundamentals About LayOut for Architects

              [Create LayOut File from Scenes] talk, bugs & feature requests
              0
                I'm not here much anymore. But a PM will fire email notifications.
                User avatar
                Dan Rathbun 
                PluginStore Author
                PluginStore Author
                 

                Re: Some, but not all, definition attributes are set

                Postby klpauba » Fri Dec 08, 2017 5:41 pm

                Thanks for your continued help, Dan.

                I've been closely following the methods outlined in "Sketchup & Layout for Architects" by Sonder and Donley (see http://sketchupbook.com). I use the Sketchup and Layout templates that are provided with great success -- the documents that are generated from all of the scenes look great (although I'm still learning -- there's a lot of information provided in the book that I have yet to understand and/or utilize). The methods in the book appear to expand the concepts outlined in the "Ten Fundamentals about LayOut for Architects" tutorial.

                Modern, stick-built structures don't require the architect to detail each unique lumber component, fortunately. Timber Frame builders, however, often require detailed dimensions for each unique timber. This is where I think the methods for timber construction might need to add some new steps to the process.

                A frame I'm currently working on (a 744 sf garage) has 24 different frame members. Using the same type of methods in the book I would have to create 76 different scenes (24 * 4) for the four views of each member. I would then create 24 layout pages each having four viewports for each of the members so that dimensions can be added. I'm just trying to wrap my head around how I might automate these tasks in an effective way -- especially when there are several design iterations that would require regenerating some scenes and layout pages.
                1

                klpauba 
                Premium Member
                Premium Member
                 

                SketchUcation One-Liner Adverts

                by Ad Machine » 5 minutes ago



                Ad Machine 
                Robot
                 



                 

                Return to Developers' Forum

                Who is online

                Users browsing this forum: No registered users and 12 guests

                Visit our sponsors: