Class: RMath3D::RMtx3

Inherits:
Object
  • Object
show all
Defined in:
lib/rmath3d/rmath3d_plain.rb

Overview

Document-class: RMath3D::RMtx3 provies 3x3 matrix arithmetic.

Notice

  • elements are stored in column-major order.

Instance Method Summary collapse

Constructor Details

#initialize(*a) ⇒ RMtx3

call-seq:

RMtx3.new -> ((1,0,0),(0,1,0),(0,0,1))
RMtx3.new(e) -> ((e,e,e), (e,e,e), (e,e,e))
RMtx3.new( other ) : Copy Constructor
RMtx3.new( e0, e1, ..., e8 ) -> ((e0,e1,e2), (e3,e4,e5), (e6,e7,e8))

Creates a new 3x3 matrix.



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/rmath3d/rmath3d_plain.rb', line 23

def initialize( *a )
  # [NOTE] elemetns are stored in column-major order.

  @e = []
  case a.length
  when 0
    @e = [ 0.0, 0.0, 0.0,
           0.0, 0.0, 0.0,
           0.0, 0.0, 0.0 ]
  when 1
    case a[0]
    when Fixnum, Float
      @e = [ a[0], a[0], a[0],
             a[0], a[0], a[0],
             a[0], a[0], a[0] ]
    when RMtx3
      # Copy Constructor

      @e = [ a[0].e00, a[0].e10, a[0].e20,
             a[0].e01, a[0].e11, a[0].e21,
             a[0].e02, a[0].e12, a[0].e22 ]
    else
      raise TypeError, "RMtx3#initialize : Unknown type #{a[0].class}."
      return nil
    end
  when 9
    # Element-wise setter

    for row in 0...3 do
      for col in 0...3 do
        index = 3*row + col
        case a[index]
        when Fixnum, Float
          setElement( row, col, a[index] )
        else
          raise TypeError, "RMtx3#initialize : Unknown type #{a[0].class}."
          return nil
        end
      end
    end
  else
    raise RuntimeError, "RMtx3#initialize : wrong # of arguments (#{a.length})"
    return nil
  end

  return self
end

Instance Method Details

#*(arg) ⇒ Object

call-seq: *

mtx1 * mtx2 : Binary multiply operator.



569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
# File 'lib/rmath3d/rmath3d_plain.rb', line 569

def *( arg )
  case arg
  when Fixnum, Float, Bignum
    return RMtx3.new( arg*self.e00, arg*self.e01, arg*self.e02,
                      arg*self.e10, arg*self.e11, arg*self.e12,
                      arg*self.e20, arg*self.e21, arg*self.e22 )

  when RMtx3
    result = RMtx3.new
    for row in 0...3 do
      for col in 0...3 do
        sum = 0.0
        for i in 0...3 do
          sum += getElement( row, i ) * arg.getElement( i, col )
        end
        result.setElement( row, col, sum )
      end
    end
    return result

  else
    raise TypeError, "RMtx3#*(arg) : Unknown type #{arg.class} given."
    return nil
  end
end

#+(arg) ⇒ Object

call-seq: +

mtx1 + mtx2 : Binary plus operator.



527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
# File 'lib/rmath3d/rmath3d_plain.rb', line 527

def +( arg )
  if ( arg.class != RMtx3 )
    raise TypeError, "RMtx3#+(arg) : Unknown type #{arg.class} given as RMtx3."
    return nil
  end

  result = RMtx3.new
  for row in 0...3 do
    for col in 0...3 do
      result.setElement( row, col, getElement(row,col) + arg.getElement(row,col) )
    end
  end

  return result
end

#+@Object

call-seq: +

+mtx : Unary plus operator.



509
510
511
# File 'lib/rmath3d/rmath3d_plain.rb', line 509

def +@
  return self
end

#-(arg) ⇒ Object

call-seq: -

mtx1 - mtx2 : Binary minus operator.



548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
# File 'lib/rmath3d/rmath3d_plain.rb', line 548

def -( arg )
  if ( arg.class != RMtx3 )
    raise TypeError, "RMtx3#-(arg) : Unknown type #{arg.class} given as RMtx3."
    return nil
  end

  result = RMtx3.new
  for row in 0...3 do
    for col in 0...3 do
      result.setElement( row, col, getElement(row,col) - arg.getElement(row,col) )
    end
  end

  return result
end

#-@Object

call-seq: -

-mtx : Unary minus operator.



518
519
520
# File 'lib/rmath3d/rmath3d_plain.rb', line 518

def -@
  return RMtx3.new( self * -1.0 )
end

#==(other) ⇒ Object

call-seq: ==

mtx1 == mtx2 : evaluates equality.



600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
# File 'lib/rmath3d/rmath3d_plain.rb', line 600

def ==( other )
  if ( other.class != RMtx3 )
    raise TypeError, "RMtx3#==(other) : Unknown type #{other.class} given as RMtx3."
    return nil
  end

  for row in 0...3 do
    for col in 0...3 do
      if ( (getElement(row,col) - other.getElement(row,col)).abs > TOLERANCE )
        return false
      end
    end
  end
  return true
end

#[](row, col) ⇒ Object Also known as: getElement

call-seq: [row,col] -> value

Returns the element at (row,col).



138
139
140
141
# File 'lib/rmath3d/rmath3d_plain.rb', line 138

def [](row,col)
  # [NOTE] elemetns are stored in column-major order.

  return @e[col*3+row]
end

#[]=(row, col, value) ⇒ Object Also known as: setElement

call-seq: [row,col]= value

Stores value at (row,col).



127
128
129
130
# File 'lib/rmath3d/rmath3d_plain.rb', line 127

def []=(row,col,value)
  # [NOTE] elemetns are stored in column-major order.

  @e[col*3+row] = value
end

#add!(other) ⇒ Object

call-seq: mtx1.add!( mtx2 )

mtx1 += mtx2 : appends the elements of mtx2 into corresponding mtx1 elements.



621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
# File 'lib/rmath3d/rmath3d_plain.rb', line 621

def add!( other )
  if ( other.class != RMtx3 )
    raise TypeError, "RMtx3#add! : Unknown type #{other.class} given as RMtx3."
    return nil
  end

  result = RMtx3.new
  for row in 0...3 do
    for col in 0...3 do
      self.setElement( row, col, getElement(row,col) + other.getElement(row,col) )
    end
  end

  return self
end

#coerceObject

call-seq: coerse(other)

Resolves type mismatch.



93
94
95
96
97
98
99
100
101
# File 'lib/rmath3d/rmath3d_plain.rb', line 93

def coerce
  case arg
  when Fixnum, Float, Bignum
    return [ self, arg ]
  else
    raise TypeError, "RMtx3#coerce : #{arg.self} can't be coerced into  #{self.class}."
    return nil
  end
end

#e00Object

Returns the element at row 0 and column 0.



145
# File 'lib/rmath3d/rmath3d_plain.rb', line 145

def e00() getElement(0,0) end

#e00=(value) ⇒ Object

Replaces the element at row 0 and column 0 by value.



164
# File 'lib/rmath3d/rmath3d_plain.rb', line 164

def e00=(value) setElement(0,0,value) end

#e01Object

Returns the element at row 0 and column 1.



147
# File 'lib/rmath3d/rmath3d_plain.rb', line 147

def e01() getElement(0,1) end

#e01=(value) ⇒ Object

Replaces the element at row 0 and column 1 by value.



166
# File 'lib/rmath3d/rmath3d_plain.rb', line 166

def e01=(value) setElement(0,1,value) end

#e02Object

Returns the element at row 0 and column 2.



149
# File 'lib/rmath3d/rmath3d_plain.rb', line 149

def e02() getElement(0,2) end

#e02=(value) ⇒ Object

Replaces the element at row 0 and column 2 by value.



168
# File 'lib/rmath3d/rmath3d_plain.rb', line 168

def e02=(value) setElement(0,2,value) end

#e10Object

Returns the element at row 1 and column 0.



151
# File 'lib/rmath3d/rmath3d_plain.rb', line 151

def e10() getElement(1,0) end

#e10=(value) ⇒ Object

Replaces the element at row 1 and column 0 by value.



170
# File 'lib/rmath3d/rmath3d_plain.rb', line 170

def e10=(value) setElement(1,0,value) end

#e11Object

Returns the element at row 1 and column 1.



153
# File 'lib/rmath3d/rmath3d_plain.rb', line 153

def e11() getElement(1,1) end

#e11=(value) ⇒ Object

Replaces the element at row 1 and column 1 by value.



172
# File 'lib/rmath3d/rmath3d_plain.rb', line 172

def e11=(value) setElement(1,1,value) end

#e12Object

Returns the element at row 1 and column 2.



155
# File 'lib/rmath3d/rmath3d_plain.rb', line 155

def e12() getElement(1,2) end

#e12=(value) ⇒ Object

Replaces the element at row 1 and column 2 by value.



174
# File 'lib/rmath3d/rmath3d_plain.rb', line 174

def e12=(value) setElement(1,2,value) end

#e20Object

Returns the element at row 2 and column 0.



157
# File 'lib/rmath3d/rmath3d_plain.rb', line 157

def e20() getElement(2,0) end

#e20=(value) ⇒ Object

Replaces the element at row 2 and column 0 by value.



176
# File 'lib/rmath3d/rmath3d_plain.rb', line 176

def e20=(value) setElement(2,0,value) end

#e21Object

Returns the element at row 2 and column 1.



159
# File 'lib/rmath3d/rmath3d_plain.rb', line 159

def e21() getElement(2,1) end

#e21=(value) ⇒ Object

Replaces the element at row 2 and column 1 by value.



178
# File 'lib/rmath3d/rmath3d_plain.rb', line 178

def e21=(value) setElement(2,1,value) end

#e22Object

Returns the element at row 2 and column 2.



161
# File 'lib/rmath3d/rmath3d_plain.rb', line 161

def e22() getElement(2,2) end

#e22=(value) ⇒ Object

Replaces the element at row 2 and column 2 by value.



180
# File 'lib/rmath3d/rmath3d_plain.rb', line 180

def e22=(value) setElement(2,2,value) end

#getColumn(column) ⇒ Object

call-seq: mtx3.getColumn© -> RVec3

Returns c-th column vector.



197
198
199
# File 'lib/rmath3d/rmath3d_plain.rb', line 197

def getColumn( column )
  return RVec3.new( self[0,column], self[1,column], self[2,column] )
end

#getDeterminantObject

call-seq: getDeterminant -> determinant

Calculates determinant.



259
260
261
262
263
# File 'lib/rmath3d/rmath3d_plain.rb', line 259

def getDeterminant
  e00 * (e11*e22 - e12*e21) -
  e01 * (e10*e22 - e12*e20) +
  e02 * (e10*e21 - e11*e20)
end

#getInverseObject

call-seq: getInverse -> inverse

Returns the inverse.



292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
# File 'lib/rmath3d/rmath3d_plain.rb', line 292

def getInverse
  result = RMtx3.new

  result.e00 =  (self.e11*self.e22 - self.e12*self.e21)
  result.e01 = -(self.e01*self.e22 - self.e02*self.e21)
  result.e02 =  (self.e01*self.e12 - self.e02*self.e11)

  result.e10 = -(self.e10*self.e22 - self.e12*self.e20)
  result.e11 =  (self.e00*self.e22 - self.e02*self.e20)
  result.e12 = -(self.e00*self.e12 - self.e02*self.e10)

  result.e20 =  (self.e10*self.e21 - self.e11*self.e20)
  result.e21 = -(self.e00*self.e21 - self.e01*self.e20)
  result.e22 =  (self.e00*self.e11 - self.e01*self.e10)

  det = e00 * result.e00 + e01 * result.e10 + e02 * result.e20

  if ( det.abs < TOLERANCE )
    raise RuntimeError, "RMtx3#getInverse : det.abs < TOLERANCE"
    return nil
  end

  d = 1.0 / det

  result.mul!( d )

  return result
end

#getRow(row) ⇒ Object

call-seq: mtx3.getRow® -> RVec3

Returns r-th row vector.



188
189
190
# File 'lib/rmath3d/rmath3d_plain.rb', line 188

def getRow( row )
  return RVec3.new( self[row,0], self[row,1], self[row,2] )
end

#getTransposedObject

call-seq: getTransposed

Returns transposed matrix.



270
271
272
273
274
# File 'lib/rmath3d/rmath3d_plain.rb', line 270

def getTransposed
  return RMtx3.new( @e[0], @e[1], @e[2],
                    @e[3], @e[4], @e[5],
                    @e[6], @e[7], @e[8] )
end

#invert!Object

call-seq: invert! -> self

Makes itself as the inverse of the original matrix.



326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
# File 'lib/rmath3d/rmath3d_plain.rb', line 326

def invert!
  elements = Array.new( 9 )

  elements[3*0+0] =  (self.e11*self.e22 - self.e12*self.e21)
  elements[3*0+1] = -(self.e01*self.e22 - self.e02*self.e21)
  elements[3*0+2] =  (self.e01*self.e12 - self.e02*self.e11)

  elements[3*1+0] = -(self.e10*self.e22 - self.e12*self.e20)
  elements[3*1+1] =  (self.e00*self.e22 - self.e02*self.e20)
  elements[3*1+2] = -(self.e00*self.e12 - self.e02*self.e10)

  elements[3*2+0] =  (self.e10*self.e21 - self.e11*self.e20)
  elements[3*2+1] = -(self.e00*self.e21 - self.e01*self.e20)
  elements[3*2+2] =  (self.e00*self.e11 - self.e01*self.e10)

  det = e00 * elements[3*0+0] + e01 * elements[3*1+0] + e02 * elements[3*2+0]

  if ( det.abs < TOLERANCE )
    raise RuntimeError, "RMtx3#invert! : det.abs < TOLERANCE"
    return nil
  end

  d = 1.0 / det

  setElement( 0, 0, d * elements[3*0+0] )
  setElement( 0, 1, d * elements[3*0+1] )
  setElement( 0, 2, d * elements[3*0+2] )
  setElement( 1, 0, d * elements[3*1+0] )
  setElement( 1, 1, d * elements[3*1+1] )
  setElement( 1, 2, d * elements[3*1+2] )
  setElement( 2, 0, d * elements[3*2+0] )
  setElement( 2, 1, d * elements[3*2+1] )
  setElement( 2, 2, d * elements[3*2+2] )

  return self
end

#mul!(other) ⇒ Object

call-seq: mtx1.mul!( mtx2 )

mtx1 *= mtx2



663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
# File 'lib/rmath3d/rmath3d_plain.rb', line 663

def mul!( other )
  case other
  when Fixnum, Float, Bignum
    self.e00 = other*self.e00
    self.e01 = other*self.e01
    self.e02 = other*self.e02
    self.e10 = other*self.e10
    self.e11 = other*self.e11
    self.e12 = other*self.e12
    self.e20 = other*self.e20
    self.e21 = other*self.e21
    self.e22 = other*self.e22

    return self
  when RMtx3
    result = RMtx3.new
    for row in 0...3 do
      for col in 0...3 do
        sum = 0.0
        for i in 0...3 do
          sum += getElement( row, i ) * other.getElement( i, col )
        end
        result.setElement( row, col, sum )
      end
    end

    self.e00 = result.e00
    self.e01 = result.e01
    self.e02 = result.e02
    self.e10 = result.e10
    self.e11 = result.e11
    self.e12 = result.e12
    self.e20 = result.e20
    self.e21 = result.e21
    self.e22 = result.e22

    return self
  end
end

#rotationAxis(axis, radian) ⇒ Object

call-seq: rotationAxis(axis,radian) -> self

Makes a matrix that rotates around the axis.



422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
# File 'lib/rmath3d/rmath3d_plain.rb', line 422

def rotationAxis( axis, radian )
  if ( axis.class != RVec3 )
    raise TypeError, "RMtx3#rotationAxis : Unknown type #{axis.class} given as axis."
    return nil
  end
  s   = Math.sin( radian )
  c   = Math.cos( radian )
  omc = 1.0 - c
  x   = axis.x.to_f
  y   = axis.y.to_f
  z   = axis.z.to_f

  self.e00 = x*x*omc + c
  self.e01 = x*y*omc - z*s
  self.e02 = z*x*omc + y*s
  self.e10 = x*y*omc + z*s
  self.e11 = y*y*omc + c
  self.e12 = y*z*omc - x*s
  self.e20 = z*x*omc - y*s
  self.e21 = y*z*omc + x*s
  self.e22 = z*z*omc + c

  return self
end

#rotationQuaternion(q) ⇒ Object

call-seq: rotationQuaternion(q) -> self

Makes a rotation matrix from a normalized quaternion q.



452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
# File 'lib/rmath3d/rmath3d_plain.rb', line 452

def rotationQuaternion( q )
  if ( q.class != RQuat )
    raise TypeError, "RMtx3#rotationQuaternion : Unknown type #{q.class} given as RQuat."
    return nil
  end
  x  = q.x
  y  = q.y
  z  = q.z
  w  = q.w

  x2 = 2.0 * x
  y2 = 2.0 * y
  z2 = 2.0 * z

  xx2 = x * x2
  yy2 = y * y2
  zz2 = z * z2

  yz2 = y * z2
  wx2 = w * x2
  xy2 = x * y2
  wz2 = w * z2
  xz2 = x * z2
  wy2 = w * y2

  self.e00 = 1.0 - yy2 - zz2
  self.e10 = xy2 + wz2
  self.e20 = xz2 - wy2
  self.e01 = xy2 - wz2
  self.e11 = 1.0 - xx2 - zz2
  self.e21 = yz2 + wx2
  self.e02 = xz2 + wy2
  self.e12 = yz2 - wx2
  self.e22 = 1.0 - xx2 - yy2

  return self
end

#rotationX(radian) ⇒ Object

call-seq: rotationX(radian) -> self

Makes a matrix that rotates around the x-axis.



368
369
370
371
372
373
374
375
376
377
378
379
# File 'lib/rmath3d/rmath3d_plain.rb', line 368

def rotationX( radian )
  s = Math.sin( radian )
  c = Math.cos( radian )

  setIdentity()
  self.e11 =  c
  self.e12 = -s
  self.e21 =  s
  self.e22 =  c

  return self
end

#rotationY(radian) ⇒ Object

call-seq: rotationY(radian) -> self

Makes a matrix that rotates around the y-axis.



386
387
388
389
390
391
392
393
394
395
396
397
# File 'lib/rmath3d/rmath3d_plain.rb', line 386

def rotationY( radian )
  s = Math.sin( radian )
  c = Math.cos( radian )

  setIdentity()
  self.e00 =  c
  self.e02 =  s
  self.e20 = -s
  self.e22 =  c

  return self
end

#rotationZ(radian) ⇒ Object

call-seq: rotationZ(radian) -> self

Makes a matrix that rotates around the z-axis.



404
405
406
407
408
409
410
411
412
413
414
415
# File 'lib/rmath3d/rmath3d_plain.rb', line 404

def rotationZ( radian )
  s = Math.sin( radian )
  c = Math.cos( radian )

  setIdentity()
  self.e00 =  c
  self.e01 = -s
  self.e10 =  s
  self.e11 =  c

  return self
end

#scaling(sx, sy, sz) ⇒ Object

call-seq: scaling(sx,sy,sz) -> self

Makes itself as a scaling matrix.



495
496
497
498
499
500
501
502
# File 'lib/rmath3d/rmath3d_plain.rb', line 495

def scaling( sx, sy, sz )
  setIdentity()
  setElement( 0, 0, sx )
  setElement( 1, 1, sy )
  setElement( 2, 2, sz )

  return self
end

#setColumn(v, column) ⇒ Object

call-seq: mtx3.setColumn(v,c)

Returns sets c-th column by vector v.



217
218
219
220
221
# File 'lib/rmath3d/rmath3d_plain.rb', line 217

def setColumn( v, column )
  self[0,column] = v.x
  self[1,column] = v.y
  self[2,column] = v.z
end

#setElements(*a) ⇒ Object

call-seq: setElements( e0, e1, …, e8 )

Stores given 9 new values.



108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/rmath3d/rmath3d_plain.rb', line 108

def setElements( *a )
  if a.length != 9
    raise RuntimeError, "RMtx3#setElements : wrong # of arguments (#{a.length})"
    return nil
  end

  for row in 0...3 do
    for col in 0...3 do
      index = 3*row + col
      setElement( row, col, a[index] )
    end
  end
end

#setIdentityObject

call-seq: setIdentity

Sets as identity matrix.



240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/rmath3d/rmath3d_plain.rb', line 240

def setIdentity
  for row in 0...3 do
    for col in 0...3 do
      index = 3*row + col
      if ( row == col )
        setElement( row, col, 1.0 )
      else
        setElement( row, col, 0.0 )
      end
    end
  end
  return self
end

#setRow(v, row) ⇒ Object

call-seq: mtx3.setRow(v,r)

Returns sets r-th row by vector v.



206
207
208
209
210
# File 'lib/rmath3d/rmath3d_plain.rb', line 206

def setRow( v, row )
  self[row,0] = v.x
  self[row,1] = v.y
  self[row,2] = v.z
end

#setZeroObject

call-seq: setZero

Clears all elements by 0.0



228
229
230
231
232
233
# File 'lib/rmath3d/rmath3d_plain.rb', line 228

def setZero
  9.times do |i|
    @e[i] = 0.0
  end
  return self
end

#sub!(other) ⇒ Object

call-seq: mtx1.sub!( mtx2 )

mtx1 -= mtx2 : subtracts the elements of mtx2 from corresponding mtx1 elements.



642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
# File 'lib/rmath3d/rmath3d_plain.rb', line 642

def sub!( other )
  if ( other.class != RMtx3 )
    raise TypeError, "RMtx3#sub! : Unknown type #{other.class} given as RMtx3."
    return nil
  end

  result = RMtx3.new
  for row in 0...3 do
    for col in 0...3 do
      self.setElement( row, col, getElement(row,col) - other.getElement(row,col) )
    end
  end

  return self
end

#to_aObject

call-seq: to_a

Returns its elements as a new Array.



84
85
86
# File 'lib/rmath3d/rmath3d_plain.rb', line 84

def to_a
  return @e
end

#to_sObject

call-seq: to_s

Returns human-readable string.



73
74
75
76
77
# File 'lib/rmath3d/rmath3d_plain.rb', line 73

def to_s
  "( #{@e[0]}, #{@e[3]}, #{@e[6]} )\n" +
  "( #{@e[1]}, #{@e[4]}, #{@e[7]} )\n" +
  "( #{@e[2]}, #{@e[5]}, #{@e[8]} )\n"
end

#transpose!Object

call-seq: transpose!

Transposeas its elements.



281
282
283
284
285
# File 'lib/rmath3d/rmath3d_plain.rb', line 281

def transpose!
  @e[1], @e[3] = @e[3], @e[1]
  @e[2], @e[6] = @e[6], @e[2]
  @e[5], @e[7] = @e[7], @e[5]
end