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

    Returning a value from a Class method

    Scheduled Pinned Locked Moved Developers' Forum
    17 Posts 6 Posters 738 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.
    • J Offline
      johnwmcc
      last edited by

      I'm now beginning to wonder if in some way my approach of defining a new class PointsArray is heading me down a blind alley.

      Would I do better just to define some extra methods for the class Array?

      As in, for example:

      
      class Array
      def newMethod
        # code for new method here, creating a new array newArray from a clone of the old one
        ...
        return newArray
      end
      
      

      Might there might be fewer traps for the unwary in that approach?

      I've already done the equivalent - extending an existing Class - (using code slightly adapted from Martin Rinehart's From Edges to Rubies) to add a method .to_matrix to the Geom::Transformation class, to output the transformation in a 4 x 4 matrix format that as well as displaying the Transformation matrix in human-readable form can also be read in as an array of arrays - altering Martin's code to insert square brackets and comma element separators appropriately.

      1 Reply Last reply Reply Quote 0
      • sdmitchS Offline
        sdmitch
        last edited by

         thickness = @contents.max.y - @contents.min.y
        

        Does this actually work for you? I get this error, Error: #<ArgumentError: comparison of Geom::Point3d with Geom::Point3d failed>

        Nothing is worthless, it can always be used as a bad example.

        http://sdmitch.blogspot.com/

        1 Reply Last reply Reply Quote 0
        • J Offline
          Jim
          last edited by

          I'd willing to have a look. Do you have the current source somewhere we can get at?

          Hi

          1 Reply Last reply Reply Quote 0
          • J Offline
            johnwmcc
            last edited by

            @sdmitch said:

             thickness = @contents.max.y - @contents.min.y
            

            Does this actually work for you? I get this error, Error: #<ArgumentError: comparison of Geom::Point3d with Geom::Point3d failed>

            It does, for me. It was intended to select out the y coordinate (a scalar) from the point coordinates.

            puts @contents[0].class outputs **Array**. Each point coordinate seems to be stored as a 3-element array, not a Point3d object - not really a surprise, since I defined and use them that way most of the time. I haven't needed so far to have a 'real' Point3d, but I would convert to one with Geom::Point3d.new(x, y , z).

            If you are storing Point3d objects, would you need @contents.to_a first, before .max.y or min.y?

            I wasn't sure if the .x and .y methods would work on arrays, but they seem to in my example code.

            I'm unclear about the near-but-not-complete equivalence between SU Point3d(x, y, z) and Array[x, y, z]- it seems I can use either a lot of the time, but not quite always!

            As you may have already gathered, though, I remain a relative novice in understanding the innards of Ruby, let alone SU Ruby! I mostly try to adapt others' code examples, thought I'm now trying much harder to understand why and how they work - with mixed results, as you see from my questions here!

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

              😲
              May I inject a pause, for reflection...
              If you explained [in words - NOT code] what it is you are trying to do, then we might better advise you...
              My own scripts do many convoluted things, but I have never seen the necessity to write a whole new 'Point' class to do something...
              I am sure that whatever it is you plan to do is quite possible, and probably considerably less complicated than you have so far contrived it to be... 😉

              Happy New Year...
              ☀

              TIG

              1 Reply Last reply Reply Quote 0
              • J Offline
                johnwmcc
                last edited by

                @jim said:

                I'd willing to have a look. Do you have the current source somewhere we can get at?

                Jim, that's an extremely generous offer, and I'd love you to look and comment.

                My current source is a mess at the moment. Since I'm in the middle of rewriting it to try and change from in-line calculations to object based functions, and also to work with asymmetrical profiles, some of the later executed code is still 'old stuff', inconsistent, and can error distractingly.

                Given another day or so, I could probably comment out the error-generating bits, and either attach a file here, or put the latest version on GitHub, where I have earlier versions too - see

                Link Preview Image
                Commits · johnwmcc/draw_framing

                Sketchup ruby to draw timber framing in standard UK softwood sizes - Commits · johnwmcc/draw_framing

                favicon

                GitHub (github.com)

                I'm still trying to figure out branching in GitHub - and haven't even started any branches as a result.

                V 0.70 is the latest uploaded version, and works usably for symmetrical (rectangular) profiles. I have part-working but pre-object based versions that almost work for non-rectangular profiles saved locally - it was in trying to improve these that I thought it would be simpler to start over with PointsArray objects!

                I had got in a horrible tangle trying to keep track of the profile rotation (in any of four quadrants), orientation (horizontal or vertical), flip state (basic profile shape can be flipped along Y, X, or both X and Y directions, or back to original), getting components drawn at the origin with axes aligned to the sides, and transforming both drawn geometry and created geometry to the original pickpoint and (if picked on a face) the face normal!

                It's possible I'll have time to get a tidied up version that doesn't error unnecessarily by the end of this evening (UK time), but it's more likely it won't be until tomorrow - I'll post here again when I've done it.

                Thanks again - the help on this forum is very generous, and I thank you both in retrospect and in advance.


                PS. Happy New Year!

                My posts here get stamped an hour later than I make them - perhaps I'm regarded as still on British Summer Time? We're back to GMT in the winter, so it isn't quite so nearly midnight as it may appear, but not long.

                1 Reply Last reply Reply Quote 0
                • sdmitchS Offline
                  sdmitch
                  last edited by

                  I figured that was the case regarding the points not being Point3d's

                  For me
                  @profile_pointsH = PointsArray.new @profile[2..-1] doesn't return anything. I assume because the class initialize merely saves @profile[2..-1] in @contents.

                  @profile_pointsV = @profile_pointsH.shiftYrotateZ90 returns the transformed values since it processes @contents and returns temp.


                  Johnwmcc.jpg

                  Nothing is worthless, it can always be used as a bad example.

                  http://sdmitch.blogspot.com/

                  1 Reply Last reply Reply Quote 0
                  • J Offline
                    johnwmcc
                    last edited by

                    @sdmitch said:

                    @profile_pointsH = PointsArray.new @profile[2..-1] doesn't return anything. I assume because the class initialize merely saves @profile[2..-1] in @contents.

                    @profile_pointsV = @profile_pointsH.shiftYrotateZ90 returns the transformed values since it processes @contents and returns temp.

                    Sorry, @profile[2..-1] contains the values:
                    [[0, 0, 0], [0.875, 0, 0], [1.75, 0.4375, 0], [1.75, 0.875, 0], [0, 0.875, 0], [0, 0, 0]]

                    which is a nominal 2" x 1" timber, with one corner planed off mid-line to mid-line.

                    I get quite sensible results when I run the code direct in the console as a function. But not when run in the tool.

                    Will post later a cleaned up version of the current non-working code as suggested by Jim.

                    1 Reply Last reply Reply Quote 0
                    • J Offline
                      johnwmcc
                      last edited by

                      Have now put a simplified but non-erroring partially working copy of draw_framing.rb and changelog.txt on GitHub as v0.7.2.2 at

                      Link Preview Image
                      Commits · johnwmcc/draw_framing

                      Sketchup ruby to draw timber framing in standard UK softwood sizes - Commits · johnwmcc/draw_framing

                      favicon

                      GitHub (github.com)

                      I've also attached an installable .rbz file to this post. If you install that, you'll get the other needed files to make the draw_framing.rb code work - icon files, etc - and also some earlier versions copied into Plugins, but not loading.

                      Run it inside Ruby console in SketchUp to see the behaviour I'm trying to fix - the V and H profiles always move together - V is drawn in 3px wide orange and H is 1px black.

                      Mouse movement should (but doesn't) rotate the profile smoothly round the first pick point changing profile rotation quadrant, and orientation (width horizontal or vertical) as you go. I HAVE had that working (in v0.7.0 if you'd like to try it) for a rectangular profile.

                      J


                      Installable v0.7.2.2 with other earlier versions included in file

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

                        I think I got it:

                        Change PointsArray constructor to this:

                        
                        def initialize(*args)
                          @contents = []
                          if args[0].is_a?(Array)
                            for i in 0...args[0].size
                              @contents[i] = args[0][i].dup
                            end
                          end
                        end
                        
                        

                        Change temp.clone in shiftYrotateZ90 to temp = PointsArray.new()

                        1 Reply Last reply Reply Quote 0
                        • J Offline
                          johnwmcc
                          last edited by

                          That's cracked it! At last, the @profile_pointsH and @profile_pointsV have separate contents.

                          And in retrospect, I can see why this works. Though not quite so sure (yet anyway) why the original PointsArray didn't.

                          Thank you so much.

                          Now I can get on with making the rest of it work again - I've had almost all the parts working at one time or another, but not using PointsArray - except for this last part, of getting the rotation and flipping to work together - one or the other but never both.

                          1 Reply Last reply Reply Quote 0
                          • J Offline
                            johnwmcc
                            last edited by

                            @tig said:

                            :shock:
                            May I inject a pause, for reflection...
                            If you explained [in words - NOT code] what it is you are trying to do, then we might better advise you...
                            My own scripts do many convoluted things, but I have never seen the necessity to write a whole new 'Point' class to do something...
                            I am sure that whatever it is you plan to do is quite possible, and probably considerably less complicated than you have so far contrived it to be... 😉

                            Happy New Year...
                            ☀

                            TIG, a very helpful pause - I do get carried away, and I do tend sometimes to over-complicate! Your post crossed with my reply to Jim.

                            I want to be able to draw frames for woodwork construction (mainly for our local amateur theatre stage scenery), using standard sizes of timber. Here's an example:

                            Double window flat.jpg

                            I have a working program (see last reply to Jim) which does this for rectangular timber. I'm trying to extend it to work with non-rectangular profile timber, and instead of PushPulling to length, to FollowMe round a selected path.

                            In parallel with this aim, I'm also trying to teach myself better coding in Ruby, in particular, using objects with methods - IF it turns out to be appropriate (it may not, in this instance, as you rightly point out - but I did enjoy trying, anyway!)

                            The drawing process in SU is:

                            1. Use a Right Click to select the (nominal) timber size you want to use from a menu, or specify an actual custom size. Nominal sizes are 1/8th inch (3mm) or 1/4 inch (6mm) larger than the finished size. Remember the choice during the SU session, or until it is changed again.

                            2. Pick a point, optionally on a face, optionally with an axis locked to X, Y, or Z_AXIS (toggle selected by cursor key). The timber's long axis (normal to its cross sectional profile) will be along the face normal if a face was picked, or the pre-selected axis if one was locked, or otherwise the Z_AXIS.

                            3. Move or drag the mouse round the point, to set the direction of the timber profile with width horizontal or vertical, in any of four quadrants around the point. *If the camera view is looking 'down' the face normal or axis lock, then change the rotation so it still goes the right way round on screen, even though it is 'looking' at the 'back' of the face or axis.

                            4. Use the TAB key to cycle the flip state of the profile (only useful for non-rectangular profiles, the next development that I'm trying to make). It can be flipped along its X, Y, or both X and Y directions, or restored to original.

                            5. Click again or release the mouse button after dragging to fix the rotation, orientation and flip state of the cross section.

                            6. Give a name to the component about to be created.

                            7. Drag the mouse, or click again, with inferencing, or type a length in the VCB, to determine the length of timber to draw and create it as a component with its origin at the originally picked corner, and the component axes aligned with its width, thickness and length.

                            8. For the drawn piece of timber, record its length and cross-section size and name in the ComponentInstance and its nominal or actual cross section in its ComponentDefinition.

                            9. Return the tool to its original state, ready to pick again and draw another piece, usually though not necessarily picking on a corner, edge, or face of any previously drawn piece of timber, or another object.

                            Ideally, you should be able to flip the cross section before or after the component is drawn, until the tool is next activated.

                            [NOTE: * I added this bit about the camera viewpoint in a revision of the post]

                            I hope that make the overall purpose clear.

                            I've been fairly clear all along WHAT I wanted to do. The bits I've had most trouble with are HOW to do that in code, since I'm still not very familiar with Ruby, in particular how it handles arrays.

                            I frequently get both the syntax and the semantics wrong - either can't get something to work at all, or it doesn't do what I expected it would, so I've experimented a lot, and usually get somewhere useful in the end. But I suspect that much of my code is horrible! I was trying both to simplify it, and learn about object-based programming in Ruby (which I understand in principle, and have done before in Visual Basic for Applications in MS Word, Access and to a small degree in Excel), and to a very limited extend in PHP.

                            But all have been self-taught, or learnt from books and code examples on the Internet, with help from forums like this one (or similar for other languages).

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

                              @johnwmcc said:

                              If you are storing Point3d objects, would you need @contents.to_a first, before .max.y or min.y?

                              The min and max methods come from the Enumerable mixin module.
                              Enumerable is mixed into Array, but not Geom::Point3d, nor Geom::Vector3d.
                              To see what modules may be mixed into a class, use
                              *Classname*.ancestors

                              So to answer the question, yes, or if using your own collection class, you might mix in the Enumerable module into it.

                              @johnwmcc said:

                              It does, for me. It was intended to select out the y coordinate (a scalar) from the point coordinates.

                              ary = [pt1, pt2, pt3, pt4, ... ]
                              To select the point which has the minimum y value, from an array of points, do this:
                              miny_pt = ary.min {|a,b| a.y <=> b.y }
                              To select the point which has the maximum y value, from an array of points, do this:
                              maxy_pt = ary.max {|a,b| a.y <=> b.y }
                              ... then get your thickness:
                              thickness = maxy_pt.y - miny_pt.y

                              To translate: [ruby:247d5h9w]ary.max {|a,b| a.y <=> b.y }[/ruby:247d5h9w], into plain English:
                              "iterate [ruby:247d5h9w]ary[/ruby:247d5h9w], each loop compare the current member ([ruby:247d5h9w]a[/ruby:247d5h9w])'s y value, against the next member ([ruby:247d5h9w]b[/ruby:247d5h9w])'s y value, and return the member that resolves to the maximum." The comparison is defined using Ruby's comparison operator, [ruby:247d5h9w]<=>[/ruby:247d5h9w].
                              Remember that the entire member is returned, so later you still need to ask for just the y value.

                              @johnwmcc said:

                              I wasn't sure if the [ruby:247d5h9w].x[/ruby:247d5h9w] and [ruby:247d5h9w].y[/ruby:247d5h9w] methods would work on arrays, but they seem to in my example code.

                              Because the SketchUp API adds those methods to the Ruby Array class. (It is part of making Ruby arrays compatible with API points and vectors.)

                              @johnwmcc said:

                              I'm unclear about the near-but-not-complete equivalence between SU [ruby:247d5h9w]Point3d(x, y, z)[/ruby:247d5h9w] and [ruby:247d5h9w]Array[x, y, z][/ruby:247d5h9w]- it seems I can use either a lot of the time, but not quite always!

                              Read the API regarding how it adds to Array class:
                              http://www.sketchup.com/intl/en/developer/docs/ourdoc/array

                              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