sketchucation logo sketchucation
    • Login
    1. Home
    2. Cleverbeans
    3. Posts
    ℹ️ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info
    C
    Offline
    • Profile
    • Following 0
    • Followers 0
    • Topics 0
    • Posts 41
    • Groups 1

    Posts

    Recent Best Controversial
    • RE: Inherit from Sketchup Classes

      Based on your description it seems unclear as to why you'd want to use inheritance here when the goal is to simply store the weights associated with the vector. I can envision either a class with a .vector and .weight attribute and some supporting methods. Here are some examples of what I think would be cleaner implementations of your idea.

      
      class MyClass
         attr_accessor ;weight
         def initialize(x,y,z,weight)
            @vector = Geom;;Vector3d.new(x,y,z)
            @weight = weight
         end
         def vector
            return @vector.transform(@weight)
         end
      end
      
      

      This would cleanly differentiate between the underlying Vector3d and the weight you want to store and allows you to update the weight while encapsulating the scaling behavior in the .vector method. The only downside of this approach is that occasionally you'll have to type my_class.vector.method instead of my_class.method but it avoids the semantic muddling of the underlying vector defined by the x,y,z values provided to initialize and the weighted version of it.

      posted in Developers' Forum
      C
      Cleverbeans
    • RE: Module class method defining confusion

      Considering the following code, we have MyClass defined in MyModule, which can be accessed with MyModule::MyClass. You do not require the prefix, and note that class methods are differentiated by the 'self.' prefix.

      
      module MyModule
        class MyClass
          def self.class_method
            return "I am a class method"
          end
          def instance_method
            return "I am an instance method"
          end
        end
      end
      
      

      Accessing another classes variables is simply a matter of creating getter methods for them. Since you need access to a class variable, you'll want a class method like the following. Note that I've changed it to @@value instead of @@data for the reasons Dan gave.

      
      class MyClass
        def self.value
          return @@value
        end
      end
      
      

      With that being said, It begs the question as to why you require access to a variable across multiple classes because global variables are really bad mojo. One of the great things about namespaces is localization, as it allows you to isolate bugs to a specific region of your code or to reuse your code without having to untangle it from other portions of your application. It's interesting to note that you can actually write every conceivable program without modifying any variables at all. This style of programming is generally called functional programming and it avoids the side effects that can crop up when you're modifying a variable.

      If you absolutely much have a global, then there are a few ways you can implement this. You can simply have a getter like the example above, or you can have a superclass which handles interaction with that global then have the classes which require access to that variable inherit from it. Note that if you want a class level variable which is isolated to a class and not accessible by it's subclasses/superclasses then you'd want a class instance variable. But once again I'd encourage you to avoid doing this at all costs, as you can likely avoid the global entirely and avoid a lot of headaches in the process.

      posted in Developers' Forum
      C
      Cleverbeans
    • RE: Ruby "split" in file line reading

      @shirazbj said:

      Heard of regular expressions before, This time I tried to understand it. Thanks.

      Regular expression are simultaneously very useful and painful to work with. There is a great quote by Jamie Zawinski which goes "Some people, when confronted with a problem, think “I know, I’ll use regular expressions.” Now they have two problems." I first ran into them at Dive into Python 3 which gives a couple simple case studies and although the language is slightly different the regular expressions are basically the same.

      Looking at the regular expression given by /[-|+]?\d.\dE[-|+]?\d\d\d/ we have the / on each end marking the start and end of the expression. There are two blocks of [-|+]? which matches an optional + or - sign. I would read this is "0 or 1 instances of + or -". Then we have \d.\dE which matches a single digit, then some arbitrary number of digits until it find an E, then we again have an option sign followed by exactly 3 digits. So this pattern will match a single numerical value in the string given. The .scan method then constructs an array out of every match. From here you can wrap blocks in parenthesis to create groups so you can break the matches up into their own arrays which is what I had done originally until I realized Ruby would parse scientific notation with the .to_f method.

      posted in Developers' Forum
      C
      Cleverbeans
    • RE: Drawing an array of boxes

      I would suggest breaking the code out into logical steps, and give each step a method. Normally I'd start with a blank file and write out what I want to happen in natural language as comments. Once I get it into a step-by-step form that makes sense I will declare method names around each step. Once I've done that I figure out what the inputs and outputs of each method should be and document them in a comment. Once that's done I pick the easiest one to test, write a simple test for it, then implement the method and see if it passes the test. Repeat until finished. It's hard to say why it's failing here because of all the variable kicking around, so maybe just try and split the methods into more bit sized portions then put it together at the end.

      posted in Developers' Forum
      C
      Cleverbeans
    • RE: Drawing an array of boxes

      Each kind of variable is referenced differently to indicate it's scope. @@var is a class variable, @var is an instance variable, and var without a modifier is a method variable. method variables can only be referenced within that method, instance variables have unique values for each instance, and class variables are shared by all instances of a class including super/sub classes. Class instance variables exist as well, and use the @var syntax, but are declared outside of a method which can trip up the unaware coder. They act like class variables but without super/sub classes having access to them. This gives you granular control over the scope for the reasons mentioned above - variables with limited scope are easier to debug. Using that as a rule of thumb then a best -> worst listing would be method -> instance -> class instance -> class -> global. In your case I believe simply changing the $ to @ would give you the behavior you're looking for assuming you want distinct values every time you call Building.new

      posted in Developers' Forum
      C
      Cleverbeans
    • RE: Drawing an array of boxes

      There are only four points, so the only condition under which there would be repeated points are $start_of_slab == $slabwidth. If $slabwidth is 0 initially then when it's incremented it will take on teh value of $start_of_slab. Are you sure you didn't mean to type it $start_of_slab += $slabwidth? If you're using $start_of_slab as the initial position I expect that's the trouble.

      As for the variables there are more than one level of scope a variable can have. If you're not calling the Building.new method anywhere you're probably wanting class methods, which should read "def self.method_name" rather than just "def method_name", which will have access to class variables rather then using globals. Also, you cannot declare variables anywhere, if you're going to declare an instance variable it must be done within an instance method. There is some subtlety here between a class instance variable (not to be confused with a class variable) and a object instance variable which requires some care, since it's easy to declare it in the wrong location and get unintended behavior.

      Even better though, would be to get rid of the variables all together and use parameters and return values for your methods instead. This really helps when trying to track down where a bug is introduced since if the problem is with a global variable, every method that interacts with that variable has to be checked and it requires tracing all the method calls. If you've got parameters and return values you can verify each block independently which can save a lot of headaches. You can always put in useful default values, and array unpacking in Ruby is a really nice feature when you've got multiple return values like depth, width,height triplets. I don't see any explicit need to store the values as variables with the provided code, so maybe consider that approach if you can swing it.

      posted in Developers' Forum
      C
      Cleverbeans
    • RE: Ruby "split" in file line reading

      After looking at this again, it seems ruby understands scientific notation natively, so there is no need to split the block into num and exp, it can just be grouped as a single value. Here is the modification which gives a noticeable increase in speed as well. I would expect in general the regular expression will be slower than index parsing too.

      def parse_line(line)
         #accepts a string of numbers in scientific notation
         #returns an array of [float,int] pairs
         pat = /[-|\+]?\d\.\d*E[-|\+]?\d\d\d/
         return line.scan(pat).map{|num| num.to_f}
      end
      
      posted in Developers' Forum
      C
      Cleverbeans
    • RE: Ruby "split" in file line reading

      @dan rathbun said:

      CB.. how about doing the conversion within the method, and returning an [x,y,z] array ?

      Certainly can be done, I just didn't presume that the three numbers were coordinate values, or that a line would only have three values, but under these assumptions. I would probably do it a little differently however by including the construction point within the map block which tightens up the code a bit more than even my original.

      
      def parse_line(line)
         #accepts a string of numbers in scientific notation
         #returns an array of [float,int] pairs
         pat = /([-|\+]?\d\.\d*)E([-|\+]?\d\d\d)/
         return line.scan(pat).map{|num,exp| num.to_f**exp.to_i}
      end 
      

      You could also convert to numerical values and then stride the array if the values are not neatly separated by line. I figured there are times when scientific notation may be the preferred output for whatever reason, so I chose that route for the example code. In any event, the regular expression is at the heart of the function and the rest is easily tailored to various needs.

      posted in Developers' Forum
      C
      Cleverbeans
    • RE: Ruby "split" in file line reading

      For something like this I like to use regular expressions. It has the advantage of allowing you to explicitly capture the pattern you're looking for, regardless of slight variations in the files. Here is how I would parse the line into [float,int] pairs, and note that even if the values are separated by white space this will still work. The pattern given matches an optional + or -, then a digit, a decimal place, then more digits till it finds then E, then again an optional + or -, and exactly 3 digits. the string.scan method finds every match in the string and puts it into an array, and the pattern has groups delimited by the parenthesis which split the matching string natural into pair as [num,exp], all that's left is to convert to numerical quantities. Here is the code.

      
      def parse_line(line)
         #accepts a string of numbers in scientific notation
         #returns an array of [float,int] pairs
         pat = /([-|\+]?\d\.\d*)E([-|\+]?\d\d\d)/
         return line.scan(pat).map{|num,exp| [num.to_f, exp.to_i]}
      end
      
      
      posted in Developers' Forum
      C
      Cleverbeans
    • RE: Integer vs string test time

      It seems to be slower to do the conversion then do the comparison. To test something like this you can use the Time.now() method to make a simple stopwatch. Here is how I tested it.

      
      def str_test()
         t = Time.now()
         (1..10000000).each{|i| "0" == "0"}
         puts(Time.now() - t)
      end
      
      def int_test()
         t = Time.now()
         (1..10000000).each{|i| "0".to_i == 0}
         puts(Time.now() - t)
      end
      
      

      str_test ran in 6.922 and int_test ran in 8.406, feel free to run the test yourself.

      posted in Developers' Forum
      C
      Cleverbeans
    • RE: Help with using begin, rescue, end

      As a good rule of thumb you should only use the begin..rescue..end construct for situations where if an error occurs you need to do something to prevent undesirable side effects. The most common example is with file handling, so say you open a file stream for reading and the program crashes in some way, it's important that you close the file even though it crashes. It is also considered good practice to only suppress the specific type of error that you're having trouble with, as suppressing all error can make debugging very difficult down the road.

      Also, you're testing using "arc_entities[0]!=nil" when you could test "!arc_entities.empty?" instead, which the code a bit more descriptive, although as already mentioned the .each method was designed for this sort of thing. 😄

      posted in Developers' Forum
      C
      Cleverbeans
    • RE: If else

      From the looks of your code you're interested specifically in blocks of four lines, in which case you may gain some mileage out of the array.slice method by doing the following.

      
      for i in 0..a.length/4 #there are i blocks of four lines
          machine,x,y,rot = a.slice(i*4,4)
          #more code
      end
      
      
      posted in Developers' Forum
      C
      Cleverbeans
    • RE: Compound Transformation

      @thedro said:

      Sorry, I realize how unclear that was since wanting to separate isn't related to the same situation as combining them.

      How very true. In the math world this is generally called matrix decomposition, and there are various schemes to do so depending on what information you're looking to extract. Some information is really easy to find, others are very hard.

      Scaling isn't to bad however. If you use the transforms .to_a method you'll get a 16 number array. It's best to think of this array as a 4x4 grid, with each group of four entries being one column of the matrix. The reason for this is that you can then interpret each column meaningfully by looking at your axis will change with respect to the transformation. If you think of your coordinate system as an x, y and z-axis together with an origin, then the first column is your x-axis, the second your y-axis, and the third your z-axis and the last column the origin. The only trouble here is that all of the columns have four entries while each of those vectors should only have three. This is pretty easy to resolve however since the last entry of the first three columns will always be 0, and the last entry of the final column will almost always be 1.

      I say almost always because there is one important exception, which is that if you use use the Transformation.scaling method, then this entry will be the reciprocal of the scaling factor. So for example Geom::Transformation.scaling(2).to_a[-1] will return 0.5, which is 1/2. This somewhat complicates finding the scale factor in that you can't just look at the length of the x-axis in the transformation to find the x-axis scaling, but you can however divide by the this value to achieve the full scaling in that direction. In general you can always take a transformation's array and divide each entry by the value in that last column to "normalize" the last value to 1 without actually changing how the transformation works. I won't bore you with the logic behind why they use this scheme, just know that it simplifies the math behind a number of common operations in computer graphics so they aren't just trying to invoke your wrath.

      posted in Developers' Forum
      C
      Cleverbeans
    • RE: Menu, require and .rb files

      Thankfully Ruby makes this simple, just wrap it all up in a module and you can split it over multiple files. For example...

      File 1

      
      module MyModule
          def foo(x)
              puts(x)
          end
      end
      
      

      File 2

      
      module MyModule
          def bar()
               foo("Hello World!")
          end
      end
      
      

      and by Ruby magik the call to bar works since it's in the same namespace.

      posted in Developers' Forum
      C
      Cleverbeans
    • RE: [solved] taking points at intervals from a line

      To get the points you'll want the vector from Edge.start to Edge.end, then scale it by your factor and transform the start point by the scaled down vector to get you first point, then repeat on that new point until you're done. Here is some code.

      
      def even_split(edge,splits)
      	point = edge.start.position 
      	vector = point.vector_to(edge.end.position)
      	scale = Geom;;Transformation.scaling(1.0/splits)
      	vector.transform!(scale)
      	for i in 1...splits
      		point.transform!(vector)
      		edge = edge.split(point)
      	end 
      end 
      
      
      posted in Developers' Forum
      C
      Cleverbeans
    • RE: Edges, angles on rectangle triangle

      Angles are only defined between two vectors, so finding the angle between a vector and a plane can vary depending on which vector in the plane you're interested in. Most of the time, the vector you're interested in is the angle between the vector and it's projection into the plane which can be calculated using the face.plane method and the Array.project_to_plane method. The only trick here is that vectors are not points, so you would have to either pick a point in the plane, then transform it by your vector or translating the plane to the origin and simply calling the vector3d.to_a method. As it turns out, the second method is much simpler since given a plane of of the form [x,y,z,c] then translating it to the origin is as easy as changing it to [x,y,z,0]. Here is the code

      
      def angle_between_vector_and_projection(vector,face)
          plane = face.plane
          plane[3] = 0
          projection = Geom;;Vector3d.new(vector.to_a.project_to_plane(plane))
          return vector.angle_between(projection)
      end
      
      
      posted in Developers' Forum
      C
      Cleverbeans
    • RE: [Info] Transformation Matrix Link

      The subject which studies matrices and vectors is called Linear Algebra, and you can find some good resources here.

      Khan Academy
      MIT OpenCourseWare

      If you're looking for some examples of matrices to experiment with you can find a list here with a number of examples which can help build a gestalt for what's going on.

      Rotations - http://en.wikipedia.org/wiki/Rotation_matrix
      Axis permutation - http://en.wikipedia.org/wiki/Permutation_matrix
      Axis Scaling - http://en.wikipedia.org/wiki/Scaling_(geometry
      Shear - http://en.wikipedia.org/wiki/Shear_matrix
      Coordinate Systems - http://www.math.hmc.edu/calculus/tutorials/changebasis/
      Translation - http://en.wikipedia.org/wiki/Affine_transformation#Representation

      For a better understanding of why they use a 4x4 matrix for their transform rather than a 3x3 matrix it helps to understand how vector addition (ie. translation) can be done using a 4x4 matrix and how the extra dimension can be used to assist with the calculation of perspective views. The OpenGL standard for computer graphics which is used by virtually all CAD systems uses the same 4x4 matrix representation so it's no surprise that Sketchup uses them as well. Information on those ideas can be found here.

      http://en.wikipedia.org/wiki/Affine_transformation
      http://en.wikipedia.org/wiki/3D_projection#Perspective_projection

      Also, it's good to know what a "change of basis" represents, as it's a core concept to understanding "local" vs "global" coordinate systems and can both be represented and accounted for using matrices which is really useful when dealing with components and groups.

      A good site for general computational geometry and from a computer science standpoint you can check out these course notes. Note that it assumes a certain amount of elementary linear algebra and calculus, but it is geared toward an entry level audience.

      http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/

      Note that it assumes a certain amount of elementary linear algebra to get started but it's done with a beginners audience in mind and I found it very insightful as to why certain objects are distinct like points vectors and vertices are distinct within the object model as well as why faces, vertices, and edges have no explicit constructors and must be added to the entities collection.

      For more advanced study I highly recommend Fundamentals of Computer Graphics which gives a broad survey CAD system topics from linear transformations, interpolation, boolean operations on solids, color theory, rendering, orthogonal and perspective views, and algorithmic considerations on all those operations.

      Also, the Sketchup Transform object has a couple quirks compared to "traditional" matrix arithmetic, most notably that for scaling the last entry in the 4x4 matrix, transform.to_a[-1] instead of the 3x3 matrix representing the linear transformation. The entry is called the homogeneous coordinate and it plays an important role in both translation transforms and the transforms related to perspective views. If we have a scale factor of F, then the homogeneous coordinate becomes 1/F. It's important to consider that when working with the matrices directly and when translation the matrices for use in other systems.

      posted in Developers' Forum
      C
      Cleverbeans
    • RE: Get Group Owner

      I believe g3.parent.instances[0] gives you the correct group.

      posted in Developers' Forum
      C
      Cleverbeans
    • RE: Getting view near and far planes through ruby?

      I haven't done much work with perspective projection, or the view object, but my first impression would be that the near plane would be normal to camera.direction and go through the point returned by camera.target, then the far plane would have the same normal and be translated in the direction of that vector by the distance returned by the camera.focal_length method. If that's correct, then the calculation should be straightforward.

      posted in Developers' Forum
      C
      Cleverbeans
    • RE: Ruby Code Snippets

      @dan rathbun said:

      "snippet" does not mean 'small' ...

      If we're being pedantic then "snippet" is the diminutive of "snip" so it does in fact mean "a small portion of".

      posted in Developers' Forum
      C
      Cleverbeans
    • 1
    • 2
    • 3
    • 1 / 3