sketchucation logo sketchucation
    • Login
    ℹ️ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info

    This tripped me up (again) today

    Scheduled Pinned Locked Moved Developers' Forum
    25 Posts 6 Posters 3.5k Views 6 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.
    • thomthomT Offline
      thomthom
      last edited by

      I use clone a lot for SketchUp's objects...
      What is the issue with SU's .clone?

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

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

        @thomthom said:

        I use clone a lot for SketchUp's objects...
        What is the issue with SU's .clone?

        It WILL work for any classes that are subclasses of standard Ruby classes, such as Length, which is a subclass of Float.

        It WILL work for any custom Sketchup classes that provide an overidden version of clone, such as:
        Geom::Point3d
        Geom::Transformation
        Geom::Vector3d

        • note that these work like dup and not clone (in that they do not copy the frozen state of the receiver.)

        The Ruby inherited edition will not work for many C++ objects like Sketchup::Face.

        To get around this, TIG shows in the other thread, how to use Sketchup::Group.copy to "clone" Sketchup::Drawingelement subclass objects, like Faces, Edges, etc.

        Geom::BoundingBox objects can be copied by using their .add method (if clone or dup does not work):
        bb2 = Geom::BoundingBox.new.add( bb1 )

        I'm not here much anymore.

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

          So SU doesn't override .dup for Point3d and Vector3d?
          That would explain why I had problems before when I tried .dup for Point3d. I've had to use .clone.

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

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

            @thomthom said:

            So SU doesn't override .dup for Point3d and Vector3d?
            That would explain why I had problems before when I tried .dup for Point3d. I've had to use .clone.

            Yepper... I remember having that discussion with you in another topic thread.

            Either most the Sketchup classes need to override Ruby's .dup and .clone with methods that work, or they should be removed for those classes.

            And... a point about .freeze, we would not want to freeze most of the Ruby objects that Sketchup needs to modify (data classes and any object class that is kept in the model.) So copying the frozen state doesn't mean much, so the overriden dup could likely be just an alias for the overriden clone.

            In most Sketchup classes the .freeze method should be also removed. It can be done for many of them, by removing it from Sketchup::Entity.

            I'm not here much anymore.

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

              I passing... IF you want to make a completely separate array based on another array's 'reference' then us
              []+
              so
              a=[1,2] b=[]+a
              makes array a and array b separate arrays as
              a[0]=99
              gives
              a ==> [99,2]
              but b is not affected
              b ==> [1,2]
              ?

              TIG

              1 Reply Last reply Reply Quote 0
              • A Offline
                August
                last edited by

                I am SO glad that I found this 5-year-old thread. I, too, was having trouble copying an array and having the copy be independent of the original.

                In my case, I had an array of points that I had generated, and I wanted to create a closed curve from them. My strategy was to copy the point array
                curve = []
                curve = point
                and then add point[0] to the end,
                curve << point[0]
                so that a curve created from the new curve[] array would return to its beginning point.
                path = ents.add_curve curve

                But the above sequence kept adding the extra point to the point array too.

                What I finally kludged around to was
                curve = []
                curve = point[0..(point.length - 1)]
                curve << point[0]
                path = ents.add_curve curve

                Using the sample code from the above discussion, I have tested and confirmed that
                b = a.dup
                and
                b = a.clone
                both have the same problem as my initial
                curve = point

                And I have confirmed that
                b = a.dclone
                gives an error.
                I'm using SU 15, which is supposed to have Ruby 2.0 and Dan notes that dclone is in 1.9, so I'm confused.

                I do have a kludge that works. Maybe it's not so much of a kludge after all. I understand the issue a little more, and hopefully I will remember it in the future.

                FWIW, I hope this helps,
                August

                “An idea, like a ghost, must be spoken to a little before it will explain itself.”
                [floatr:v1mcbde2]-- Charles Dickens[/floatr:v1mcbde2]

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

                  The assignment
                  curve = point
                  means the array 'curve' refers to the array 'point' - they are essentially referencing the same thing, whereas...
                  curve = point.clone
                  means the array 'curve' is a separate array, which has been made as a copy from the array 'point',
                  Consider this...
                  curve = point + [ point[0] ]
                  which achieves you aim for a 'curve' array defining a 'loop', but done in the one step.
                  It combines the array 'point' and a new array made from the first element of that array, all in a new array named 'curve'.

                  Incidentally consider naming arrays and other collections in the plural - it is is easy to follow the code - so the array named 'points' consists of a collection of elements, each of which is a 'point'.
                  The 'curve' array would also perhaps be better named 'curve_points'

                  TIG

                  1 Reply Last reply Reply Quote 0
                  • A Offline
                    August
                    last edited by

                    Thanks TIG.

                    I had not tried using that additional set of square brackets. It makes sense.

                    As for naming, I thought about using plural in the first place, but most of my usages were as singular references, point[0], point[1], ... point[n-1], point[n] where the singular read better to me. I like "curve_points" -- that is always used as a group, never individually, so plural reads much better there.

                    Thanks,
                    August

                    “An idea, like a ghost, must be spoken to a little before it will explain itself.”
                    [floatr:v1mcbde2]-- Charles Dickens[/floatr:v1mcbde2]

                    1 Reply Last reply Reply Quote 0
                    • A Offline
                      August
                      last edited by

                      TIG, I'm not sure that clone does what you say it does.

                      This page, http://lukaszwrobel.pl/blog/copy-object-in-ruby suggests that a clone's elements still point to the original elements so some changes to one will indeed show up in the other. That's what I found with my initial testing.

                      Above, Dan says
                      @unknownuser said:

                      It WILL work for any custom Sketchup classes that provide an overidden version of clone, such as:
                      Geom::Point3d
                      Geom::Transformation
                      Geom::Vector3d

                      • note that these work like dup and not clone (in that they do not copy the frozen state of the receiver.)

                      The Ruby inherited edition will not work for many C++ objects like Sketchup::Face.
                      So I didn't use .clone.

                      And yet, I just tried in the SU Ruby console:

                      > a = ["a","b", "c"]
                      ["a", "b", "c"]
                      > b = a
                      ["a", "b", "c"]
                      > c = a.clone
                      ["a", "b", "c"]
                      > d = a << "d"
                      ["a", "b", "c", "d"]
                      > a
                      ["a", "b", "c", "d"]
                      > b
                      ["a", "b", "c", "d"]
                      > c
                      ["a", "b", "c"]
                      > a[2] = "3"
                      3
                      > a
                      ["a", "b", "3", "d"]
                      > b
                      ["a", "b", "3", "d"]
                      > c
                      ["a", "b", "c"]
                      > d
                      ["a", "b", "3", "d"]
                      
                      

                      which shows that for these two kinds of changes, the clone is not affected.

                      I'm still not clear on when I can use .clone and when not, nor do I really understand shallow vs. deep copies and frozen objects, so for now, unless I'm doing tens of thousands of copies, I may use a brute force method becuase the shortcuts seem so problematical.

                      Thanks,
                      =A=

                      “An idea, like a ghost, must be spoken to a little before it will explain itself.”
                      [floatr:v1mcbde2]-- Charles Dickens[/floatr:v1mcbde2]

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

                        @august said:

                        I'm using SU 15, which is supposed to have Ruby 2.0 and Dan notes that dclone is in 1.9, so I'm confused.

                        What I actually said was that the REXML library (beginning in Ruby 1.9,) modified the Array class, by adding the dclone method.

                        In order to use it, you must either precede it's use with:
                        require "rexml/document"
                        or use a refinement.

                        (1) Using the REXML library:
                        ` require "rexml/document"

                        true
                        a = []
                        []
                        a.respond_to?(:dclone)
                        true`

                        (2) Refinement module:

                        <span class="syntaxdefault"><br />module&nbsp;August<br />&nbsp;&nbsp;module&nbsp;DeepCopy<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;refine&nbsp;</span><span class="syntaxkeyword">Array&nbsp;do<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">def&nbsp;dclone<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;klone&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">self</span><span class="syntaxkeyword">.clone<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">klone</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">clear<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">each</span><span class="syntaxkeyword">{|</span><span class="syntaxdefault">v</span><span class="syntaxkeyword">|&nbsp;</span><span class="syntaxdefault">klone&nbsp;</span><span class="syntaxkeyword"><<&nbsp;</span><span class="syntaxdefault">v</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">dclone</span><span class="syntaxkeyword">}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">klone<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />&nbsp;&nbsp;&nbsp;&nbsp;end&nbsp;</span><span class="syntaxcomment">#&nbsp;class&nbsp;Array<br /><br />&nbsp;&nbsp;</span><span class="syntaxdefault">end&nbsp;</span><span class="syntaxcomment">#&nbsp;refinement&nbsp;module&nbsp;DeepCopy<br /></span><span class="syntaxdefault">end&nbsp;</span><span class="syntaxcomment">#&nbsp;Author's&nbsp;namespace<br /><br /><br /></span><span class="syntaxdefault">using&nbsp;August</span><span class="syntaxkeyword">;;</span><span class="syntaxdefault">DeepCopy<br /><br />module&nbsp;August<br />&nbsp;&nbsp;module&nbsp;SomePlugin<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;a&nbsp;</span><span class="syntaxkeyword">=&nbsp;[</span><span class="syntaxstring">"august"</span><span class="syntaxkeyword">,</span><span class="syntaxstring">"dan"</span><span class="syntaxkeyword">,</span><span class="syntaxstring">"tig"</span><span class="syntaxkeyword">]<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">b&nbsp;</span><span class="syntaxkeyword">=&nbsp;</span><span class="syntaxdefault">a</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">dclone<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;</span><span class="syntaxstring">"a&nbsp;is;&nbsp;#{a.inspect}"<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">puts&nbsp;</span><span class="syntaxstring">"b&nbsp;is;&nbsp;#{b.inspect}"<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">puts&nbsp;</span><span class="syntaxstring">"changing&nbsp;a[1]&nbsp;to&nbsp;\"bob\""<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">a</span><span class="syntaxkeyword">[</span><span class="syntaxdefault">1</span><span class="syntaxkeyword">]=&nbsp;</span><span class="syntaxstring">"bob"<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">puts&nbsp;</span><span class="syntaxstring">"a&nbsp;is;&nbsp;#{a.inspect}"<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="syntaxdefault">puts&nbsp;</span><span class="syntaxstring">"b&nbsp;is;&nbsp;#{b.inspect}"<br /><br />&nbsp;&nbsp;</span><span class="syntaxdefault">end&nbsp;</span><span class="syntaxcomment">#&nbsp;module&nbsp;SomePlugin<br /></span><span class="syntaxdefault">end&nbsp;</span><span class="syntaxcomment">#&nbsp;Author's&nbsp;namespace<br />&nbsp;</span><span class="syntaxdefault"></span>
                        

                        Any call to using() must occur within the TOPLEVEL_BINDING.
                        This restriction has been removed in later versions of Ruby 2.2+, and the experimental warning that is output on calls to refine has also been removed. (Ie, refinements are no longer experimental and calls to using can happen inside specific module and class scopes.)

                        If you want to see that all the elements of the arrays are different objects, you can iterate them and compare their object id numbers.

                        I'm not here much anymore.

                        1 Reply Last reply Reply Quote 0
                        • A Offline
                          August
                          last edited by

                          Thanks Dan,

                          So refine allows me to add my own operators to an existing class? That's a sweet (and dangerous) concept.

                          I'll have to put that on the back burner for now. I'm still working on basic Ruby.

                          “An idea, like a ghost, must be spoken to a little before it will explain itself.”
                          [floatr:v1mcbde2]-- Charles Dickens[/floatr:v1mcbde2]

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

                            @august said:

                            So refine allows me to add my own operators to an existing class? That's a sweet (and dangerous) concept.

                            Refinements do not affect other people's scripts that do not "use" the refinement module. (They are only valid within the file that has the using call.)

                            I'm not here much anymore.

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

                              Another basic concept is the mixin module, which uses include() and extend().

                              In this case, in order to affect only the array you are using, you need to only "extend" the specific array instance object.

                              So, assume you have previously loaded a mixin module thus:

                              <span class="syntaxdefault">module August<br />  module DeepCopy<br /><br />    def dclone<br />      klone </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> self</span><span class="syntaxkeyword">.clone<br /></span><span class="syntaxdefault">      klone</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">clear<br />      self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">each</span><span class="syntaxkeyword">{|</span><span class="syntaxdefault">v</span><span class="syntaxkeyword">|</span><span class="syntaxdefault"> klone </span><span class="syntaxkeyword"><<</span><span class="syntaxdefault"> v</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">dclone</span><span class="syntaxkeyword">}<br /></span><span class="syntaxdefault">      klone<br />    end<br /><br />  end </span><span class="syntaxcomment"># mixin module DeepCopy<br /></span><span class="syntaxdefault">end </span><span class="syntaxcomment"># Author's namespace&nbsp;</span><span class="syntaxdefault"></span>
                              

                              Then you need to extend a specific array instance:

                              <span class="syntaxdefault">a </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">[</span><span class="syntaxstring">"august"</span><span class="syntaxkeyword">,</span><span class="syntaxstring">"dan"</span><span class="syntaxkeyword">,</span><span class="syntaxstring">"tig"</span><span class="syntaxkeyword">]<br /><br /></span><span class="syntaxdefault">a</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">extend</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">August</span><span class="syntaxkeyword">;;</span><span class="syntaxdefault">DeepCopy</span><span class="syntaxkeyword">)<br /><br /></span><span class="syntaxdefault">b </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> a</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">dclone</span>
                              

                              I'm not here much anymore.

                              1 Reply Last reply Reply Quote 0
                              • A Offline
                                August
                                last edited by

                                Back to TIG's comment about plural vs. singular names for arrays, here is the way I'm naming things. In this context, the singular terms seem to work better for me, probably because I think of it as the mathematical notation P[sub:2dctu78y]0[/sub:2dctu78y], P[sub:2dctu78y]1[/sub:2dctu78y], ... P[sub:2dctu78y]N[/sub:2dctu78y].

                                =begin
                                
                                          point[N]
                                                  x-------------x point[0]  angle[0] = angle_between vector[N], vector[0]
                                                     vector[N]   \
                                  vector[N] = point[N], point[0]  \
                                                                   \
                                                          vector[0] \
                                      vector[0] = point[0], point[1] \
                                                                      x point[1]  angle[1] = angle_between vector[0], vector[1]
                                                                     /
                                                          vector[1] /
                                    vector[1] = point[1], point[2] /
                                                                  /
                                                                 /
                                                                x point[2]  angle[2] = angle_between vector[1], vector[2]
                                
                                =end
                                

                                “An idea, like a ghost, must be spoken to a little before it will explain itself.”
                                [floatr:v1mcbde2]-- Charles Dickens[/floatr:v1mcbde2]

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

                                Advertisement