Transform array


#1

I am trying to set a transformation object to the identity matrix but I am unable to access the 16 element array.
If I try to inspect the values with a call to trans.to_a the value returned is an empty array.

 trans = Geom::Transformation.scaling(1,1,1)

or
arr = [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]
trans = Geom::Transformation.new(arr)

  trans.to_a => []

I have even attempted to inspect the transform array of a constructed transform which I know is properly constructed since the tranformations are correct in the model but I stll cannot access the array.
Does anyone have any ideas?


#2

No idea @AlanMatthews. Could the to_a method have been redefined somehow?

p IDENTITY # => #<Geom::Transformation:0x0001d653b3eec8>
p IDENTITY.to_a # => [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0]

#3

Also not what I get. Something is funky in your setup, though maybe it is calling the methods with the wrong arguments?

> t=Geom::Transformation.new
#<Geom::Transformation:0x007fbd5e272ef0>
> t.to_a
[1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0]
> t2=Geom::Transformation.scaling([10,20,30],5.0)
#<Geom::Transformation:0x007fbd5e270e70>
> t2.to_a
[1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -8.0, -16.0, -24.0, 0.2]
> t3=Geom::Transformation.new([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1])
#<Geom::Transformation:0x007fbd5e263cc0>
> t3.to_a
[1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0]

#4

I remember a bug having to do with SketchUp’s idea of whether a transform was identity or not.
There was some operation which caused an identity transform to “lose” it’s identity. (pun intended, but yes there was a bug. Don’t know if it got fixed.)

ADD: Okay, I remember now. Using Steve’s 3rd example:

t3=Geom::Transformation.new([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1])
#<Geom::Transformation:0x0000000fa57a58>

> t3.to_a
#=>
[
  1.0, 0.0, 0.0, 0.0,
  0.0, 1.0, 0.0, 0.0, 
  0.0, 0.0, 1.0, 0.0, 
  0.0, 0.0, 0.0, 1.0
]

t3.identity?
#=> false

The #identity?() method should return true here, but obviously does not.

MORE …

t3 == IDENTITY
#=> false

t3.to_a == IDENTITY.to_a
#=> true

… strange. Reason is apparently the Geom::Transformation class does not provide an overridden == method so “sameness” can be properly calculated. (It defaults to Object#==.)


#5

Why would you even want to do it?

Geom::Transformation::new creates a new identity transform. (Ie, no arguments)

t = Geom::Transformation::new
t.identity?
#=> true

#6

This appears to be true. Transformation’s == does not compare the values in the Transformations, just the identity of the two referenced objects, which makes it IMO pretty useless.


#7

You’d be surprised Dan. If you’re dealing with a function that you wish to operate on either a component instance or a group the component will require transforming whereas the group will not.

It is just one way of avoiding lots of if blocks as transforming a group with an identity transform will leave it ucnchanged.

Regards

Alan


#8

Further to my post I should report that the issue appears to be one of visibility. This is consistant with my earlier observation regarding correctly constructed transforms. If I write a simple test utility (see below) the visibility works fine.

require 'sketchup.rb'

class TTest
  
  def initialize(*args)
    trans = Geom::Transformation.scaling(1,1,1)
    puts trans.to_a
  end

end
#-----------------------------------------------------------------------------

if( not file_loaded?("test.rb") )
    UI.menu("Draw").add_item("Test"){TTest.new}
    file_loaded("test.rb")
end

#-----------------------------------------------------------------------------

I will attempt to chase down the problem and report back when I’ve found the errant coding.
To be continued …


#9

Hooray! I’ve found it. The problem was the use of = in a conditional test instead of ==. This is a nasty syntactical error since, unlike Embarcadero pascal, the code interperator doesn’t give the coder warning and it can be a hard one to detect.
I think this might be one for the wish list unless there is a legitimate use of an if = combination. the following shows the error

class TTest
  
  def initialize(*args)
    trans = Geom::Transformation.new
    printTransform(trans)
    printTransform1(trans)
  end

  def printTransform1 trans
    if trans = nil              # <<-----error
      print("trans = nil\n")
    else
      printArray("TTest.printTransform1", trans.to_a)
    end
  end

  def printTransform trans
    if trans == nil
      print("trans = nil\n")
    else
      printArray("TTest.printTransform", trans.to_a)
    end
  end

  def printArray strg, a
    puts strg
    for i in 0..3 
      puts arrayRowString(a, 4 * i)
    end
  end

  def arrayRowString(a, start)
    strg = ""
    finish = start + 3
    for i in start..finish
      strg += ((a == nil) || (a[i] == nil))? "nil":a[i].round(2).to_s
      strg += "," if i < finish
    end
    return strg
  end
end

The output from this would be as expected
TTest.printTransform
1.0,0.0,0.0,0.0
0.0,1.0,0.0,0.0
0.0,0.0,1.0,0.0
0.0,0.0,0.0,1.0
TTest.printTransform1
nil,nil,nil,nil
nil,nil,nil,nil
nil,nil,nil,nil
nil,nil,nil,nil


#10

I am glad you found it. It is an easy and common mistake to make. However, it should have generated a warning in the ruby console which would have pointed you to the location of the error.


#11

@AlanMatthews Would you please edit your prior posts,
and wrap your code in the forum markdown code delimiters, ie:

```ruby

code here

```

Those are backticks, the character that shares the key with the tilde (~) to the left of the 1 key. (You’ll likely need to re-indent the code as the forum has stripped out the leading whitespace.)


This is a Ruby Core interpreter issue. And assignment in any expression, is allowed under Ruby’s multi-paradigm philosophy. However, most coding style guides strongly discourage it, (or outlaw it for particular projects,) for the very reason that you found. It promotes errors that are hard to find.

So you’ll see the style guides say to make the assignment on the line preceding the conditional test (if, unless, while, until,) etc.

Saving one line of code is not worth it.


I meant why would you wish to create an identity transform
in the way you were attempting. (Ie, it doesn’t really work.)

I refer you to my post above, where I show that the API currently
has only one good way to create a new identity transform.
:arrow_right: Transform array
And that the #identity? method is currently bugged.

Then I refer you to a post above, where Jim shows you that you can just use the global identity transform which is there for this very purpose. (It is a shared object so do not change it.)
:arrow_right: Transform array


#12

And for @AlanMatthews, and any others interested in working with transformations,
I suggest you get Thomas Thomasen’s Transformation Inspector plugin:


#13

Dan,

I would if I knew how.

Alan


#14

knew how to do what ?

  • wrap code ? (I told you how.)

  • edit a previous post ? (use the edit “pencil” icon)