sketchucation logo sketchucation
    • Login
    โ„น๏ธ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info

    Untagged deleted element after using outer_shell on group

    Scheduled Pinned Locked Moved Developers' Forum
    12 Posts 4 Posters 646 Views 4 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • S Offline
      spring.freediver
      last edited by

      I have run across an odd problem and wanted to see if anyone has seen something similar.

      I use the group.outer_shell on two manifold groups. I then use model.raytest on a resulting face, and use the following code to verify none of the returned items are invalid:

      item[1].each_index {|i| printf("ITEM %d:%s; valid?(%s); deleted?(%s)\n", i, item[1][i].inspect, item[1][i].valid?, item[1][i].deleted?)}

      And they are all valid. I then use entity.all_connected on the entity returned by raytest, and again check that all entities are valid:

      cnn = entity.all_connected
      cnn.each_index {|i| printf("CONNECTED %d of %d:%s; valid?(%s); deleted?(%s)\n", i, cnn.length, cnn[i].inspect, cnn[i].valid?, cnn[i].deleted?)}

      All connected entities are reported as valid and not deleted. But then I get this on the floowing line which scans the all_connect list:

      CONNECTED 140 of 143:#Sketchup::Edge:0x863fc60; valid?(true); deleted?(false)
      CONNECTED 141 of 143:#Sketchup::Edge:0x863fc4c; valid?(true); deleted?(false)
      CONNECTED 142 of 143:#Sketchup::Edge:0x863fc38; valid?(true); deleted?(false)
      Error: #<TypeError: reference to deleted Edge>
      C:/Program Files/Google/Google SketchUp 8/Plugins/<xxx>.rb:280:in `all_connected'

      This only happens after I use group.outer_shell. And after doing that, I use model.commit_operation

      Any thoughts? Is the something I need to do to purge deleted entities?

      1 Reply Last reply Reply Quote 0
      • TIGT Offline
        TIG Moderator
        last edited by

        Why are you doing this?
        If a deleted edge is causing an issue use
        cnn = entity.all_connected cnn.each_index{|i|cnn.delete(cnn[i])if not cnn[i].valid?}
        ???

        TIG

        1 Reply Last reply Reply Quote 0
        • S Offline
          spring.freediver
          last edited by

          The example code shows that I am checking to see if any of the elements are deleted. The problem is that the valid? and deleted? methods are both telling me that the entity is OK, but then when I try to actually use the entity, it suddenly says that it is deleted.

          1 Reply Last reply Reply Quote 0
          • S Offline
            spring.freediver
            last edited by

            Sorry. I didn't show line 280, which generates the error:

            e1 = entity.all_connected.find {|e| e.valid? && !e.deleted? && e.get_attribute("<xxx>", "Type", false) =~ /yyy/}

            This line assumes that Ruby, like C, will stop evaluating && expressions as soon as one is false. But in this case, the first two are not false, which I verified with the printf statements I showed above.

            The printf's are just for debugging purposes. This is code I have been using for a long time. But it suddenly doesn't work when I use it on a group created with outer_shell. In only that case do I get the situation where valid? and deleted? tell me the entity is OK. But when I check for an attribute on the entity, it suddenly says the entity is deleted. And it is only when I use outer_shell from a Ruby app. If I use the Solid Tool Outer Shell interactively, I do not get the problem.

            (I replaced some application specific info with xxx and yyy. Actual values were different, but not relavent.)

            1 Reply Last reply Reply Quote 0
            • Dan RathbunD Offline
              Dan Rathbun
              last edited by

              Speculation..
              a) there may still be a bug in model.raytest() (or this is a new one, in addition to the others.)

              b) somehow the model or group entities collection has not finished purging itself, by the time you call ent.all_connected() (which by the way returns an Array copy of a subset of the context's entities C-side collection. If the actual connected entities changes on the C-side, in the duration, then the Array objects, and the actual objects in the C-side collection will be "out-of-sync.")

              Suggest that after doing the group.outer_shell(), that you call GC.start so that (hopefully,) any Ruby-side references are cleaned up, before you begin using all_connected().

              Also be sure you use a begin .. rescue .. end block for your operation:

              begin
                model.start_operation("#{group.name} outer shell")
                #
                # your code goes here
                #
                # you can also use nested rescue blocks in here
                begin
                  # do something touchy here
                rescue
                  model.abort_operation()
                end
                #
                model.commit_operation()
              rescue
                model.abort_operation()
              end
              
              

              I'm not here much anymore.

              1 Reply Last reply Reply Quote 0
              • Dan RathbunD Offline
                Dan Rathbun
                last edited by

                @spring.freediver said:

                e1 = entity.all_connected.find {|e| e.valid? && !e.deleted? && e.get_attribute("<xxx>", "Type", false) =~ /yyy/}

                This line assumes that Ruby, like C, will stop evaluating && expressions as soon as one is false. But in this case, the first two are not false, which I verified with the printf statements I showed above.

                Don't assume:

                e1 = entity.all_connected.find {|e|
                  next unless e.valid?
                  next if e.deleted? 
                  e.get_attribute("<xxx>", "Type", false) =~ /yyy/
                }
                

                I'm not here much anymore.

                1 Reply Last reply Reply Quote 0
                • TIGT Offline
                  TIG Moderator
                  last edited by

                  The method e.valid? is virtually equivalent to !e.deleted? so there is no need to test for both.

                  The use of multiple && tests can be flaky - try substituting the more forgiving and tests instead - although by choosing only one '?' method you only need the one && anyway!

                  'Raytesting' is not 100% foolproof. The original groups' have 'vanished' during the 'outer_shell' processing IF the two groups are manifold. Why not use the newly created group's entities - these should of course all be 'valid' ๐Ÿ˜•
                  I still don't quite understand what you are trying to achieve by doing these tests after you've run the 'outer_shell'... What objects are you testing to see if they are valid, and why?

                  Also I note your 'attributes' are somewhat unconventional.
                  The library name should start with a letter, contain no spaces or punctuation, except '' - so ^[A-Za-z][A-Za-z0-9]...
                  The key name should be similar, and by convention it is in lowercase ^[a-z][a-z0-9_]... - It can start with a '_' but these are usually reserved for DC standard attributes.
                  I don't suspect them in this issue but it's perhaps useful for the future...

                  TIG

                  1 Reply Last reply Reply Quote 0
                  • thomthomT Offline
                    thomthom
                    last edited by

                    @tig said:

                    The use of multiple && tests can be flaky - try substituting the more forgiving and tests instead - although by choosing only one '?' method you only need the one && anyway!

                    I prefer && over and because it has higher precedence. http://www.themomorohoax.com/2008/12/08/and-vs-amperand-in-ruby
                    Regardless of what one prefer - it isn't "flaky" - as that indicate it doesn't always work. It does what is is supposed to do.

                    http://avdi.org/devblog/2010/08/02/using-and-and-or-in-ruby/
                    http://blog.jayfields.com/2007/08/ruby-operator-precedence-of-and-which.html

                    Thomas Thomassen โ€” SketchUp Monkey & Coding addict
                    List of my plugins and link to the CookieWare fund

                    1 Reply Last reply Reply Quote 0
                    • S Offline
                      spring.freediver
                      last edited by

                      Thanks for all the feedback guys.

                      TIG: the xxx and yyy are not the actual values. Since they aren't relevent, I replaced the longer names used in the actual code. As for what the application is doing, it is simply allowing the user to intersect a ray with one of the faces of a newly created outer_shell group, and then finding all the connected elements of that face or edge. I used raytest so I can get all the transformations for a nested entity from the item[1] array. As I mentioned, this is old code I have been using for over a year. It just started displaying this problem when I used it on the result of outer_shell. The code that I showed was some hastily added debuging code. I suspected that valid? and deleted? were redundant, but was just trying to find out what was happening.

                      Dan: Based on your suggestion, I read the docs on GC.start. When should I use it? Immediately after doing the group.outer_shell? I was not aware that entity lists could be changing in the background while a Ruby script was running. I assumed that when I called outer_shell, Sketchup would not return control to my script until it had done all of it's cleanup of entity lists. GC.start would not affect what they have going on the C side, would it?

                      1 Reply Last reply Reply Quote 0
                      • Dan RathbunD Offline
                        Dan Rathbun
                        last edited by

                        @tig said:

                        Why are you doing this?
                        If a deleted edge is causing an issue use
                        cnn = entity.all_connected cnn.each_index{|i|cnn.delete(cnn[i])if not cnn[i].valid?}
                        ???

                        also:
                        cnn.delete_if {|e| e.deleted? }

                        ...which is an inline method even though it does not use ! in the name (ie, it really should be named delete_if!)

                        I'm not here much anymore.

                        1 Reply Last reply Reply Quote 0
                        • Dan RathbunD Offline
                          Dan Rathbun
                          last edited by

                          @spring.freediver said:

                          Dan: Based on your suggestion, I read the docs on GC.start. When should I use it? Immediately after doing the group.outer_shell?

                          YES ... and BEFORE getting a new Ruby-side reference to any C-side collection object.

                          @spring.freediver said:

                          I was not aware that entity lists could be changing in the background while a Ruby script was running.

                          Oh yea.. this forum is peppered with posts where coders get strange results when iterating Sketchup API collections... followed by the normal advice from the experienced, that they should always make an Array copy of the collection, and iterate that Array (.. this is a must if you will be changing the collection during the loop.)

                          @spring.freediver said:

                          I assumed that when I called outer_shell, Sketchup would not return control to my script until it had done all of it's cleanup of entity lists.

                          Yea.. well you can't assume that. Ruby garbage collection in the 1.8 trunk.. sucks. It's also a periodic task... and it may wish to wait till some other time to "sweep" up the Ruby garbage, but you need to tell GC to sweep things up now.

                          @spring.freediver said:

                          GC.start would not affect what they have going on the C side, would it?

                          GC is a Ruby class, and it cleans up Ruby.. which actually IS compiled C. The Sketchup engine itself is C++, which has a better garbage collector than Ruby.

                          P.S.: Whenever I say "C-side", I am really referring generically to the Sketchup C++ engine, it's C-wrappers for the Ruby API, and Ruby's C core engine.

                          I'm not here much anymore.

                          1 Reply Last reply Reply Quote 0
                          • Dan RathbunD Offline
                            Dan Rathbun
                            last edited by

                            BTW.. there might be some API call that also has the effect of triggering garbage collection.

                            Try view.refresh()

                            Hmm.. it also occurs to me, that Sketchup may be wanting to keep references to deleted entities around, just in case the user decides to do an undo.
                            But a call to all_connected() should not return these entities in the result Array. If it does, then it's the all_connected() method that is bugged.

                            You said that you were wrapping your code in your own operation... if you didn't (ie you just let Sketchup handle the undo,) I wonder if the error would also occur? Meaning it could be an operation bug.

                            I'm not here much anymore.

                            1 Reply Last reply Reply Quote 0
                            • 1 / 1
                            • First post
                              Last post
                            Buy SketchPlus
                            Buy SUbD
                            Buy WrapR
                            Buy eBook
                            Buy Modelur
                            Buy Vertex Tools
                            Buy SketchCuisine
                            Buy FormFonts

                            Advertisement