Advertisement
Bkmz

Untitled

Oct 22nd, 2011
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 5.55 KB | None | 0 0
  1. #!/usr/bin/env ruby
  2. require 'tk'
  3. require 'matrix'
  4.  
  5. # need for correct math operations
  6. require 'mathn'
  7.  
  8. # $lastX = 0
  9. # $lastY = 0
  10.  
  11. # adding support for 3D conversion
  12. class Point
  13.   # attr_reader :x, :y, :z
  14.   attr_accessor :x, :y, :z
  15.  
  16.  
  17.   def initialize(x,y,z)
  18.     @x, @y, @z = x, y, z
  19.     @matr = Matrix[[@x, @y, @z, 1]]
  20.   end
  21.  
  22.   def to_s
  23.     # "x: #{@x}\ny: #{y}\nz: #{z}"
  24.     "(#{@x}, #{@y}, #{z})"
  25.   end
  26.  
  27.   # transfer to a distance
  28.   def moveTo(a,b,c)
  29.     operMatrix = Matrix[
  30.       [1, 0, 0, 0],
  31.       [0, 1, 0, 0],
  32.       [0, 0, 1, 0],
  33.       [a, b, c, 1]
  34.     ]
  35.     @matr *= operMatrix
  36.     # show 3 ways to get data from matrix by given indexeses
  37.     # @TODO: maybe need to call _parseMatr
  38.     @x = @matr.element(0,0)
  39.     @y = @matr[0,1]
  40.     @z = @matr.component(0,2)
  41.     # returning value, actually needs?
  42.     @matr
  43.   end
  44.  
  45.   def rotateZ phi
  46.     phi = phi * Math::PI / 180
  47.     operMatrix = Matrix[
  48.       [Math.cos(phi), Math.sin(phi), 0, 0],
  49.       [-Math.sin(phi), Math.cos(phi), 0, 0],
  50.       [0, 0, 1, 0],
  51.       [0, 0, 0, 1]
  52.     ]
  53.     @matr *= operMatrix
  54.     _parseMatr
  55.  
  56.     @matr
  57.   end
  58.  
  59.   def rotateX phi
  60.     phi = phi * Math::PI / 180
  61.     operMatrix = Matrix[
  62.       [1, 0, 0, 0],
  63.       [0, Math.cos(phi), Math.sin(phi), 0],
  64.       [0, -Math.sin(phi), Math.cos(phi), 0],
  65.       [0, 0, 0, 1]
  66.     ]
  67.     @matr *=  operMatrix
  68.     _parseMatr
  69.  
  70.     @matr
  71.   end
  72.  
  73.   def rotateY phi
  74.     phi = phi * Math::PI / 180
  75.     operMatrix = Matrix[
  76.       [Math.cos(phi), 0, -Math.sin(phi), 0],
  77.       [0, 1, 0, 0],
  78.       [Math.sin(phi), 0, Math.cos(phi), 0],
  79.       [0, 0, 0, 1]
  80.     ]
  81.     @matr *=  operMatrix
  82.     _parseMatr
  83.  
  84.     @matr
  85.   end
  86.  
  87.   def scale(x,y,z)
  88.     operMatrix = Matrix[
  89.       [x, 0, 0, 0],
  90.       [0, y, 0, 0],
  91.       [0, 0, z, 0],
  92.       [0, 0, 0, 1]
  93.     ]
  94.     @matr *= operMatrix
  95.     _parseMatr
  96.  
  97.     @matr
  98.   end
  99.  
  100.  
  101.  
  102. # next methods are private declared
  103. private
  104.  
  105.   def _parseMatr
  106.     @x = @matr[0,0]
  107.     @y = @matr[0,1]
  108.     @z = @matr[0,2]
  109.   end
  110.  
  111.  
  112.   private :_parseMatr
  113. end
  114.  
  115. $cylinder = []
  116.  
  117. def $cylinder.generate_skeleton faces, face_lenght, height
  118.   if faces > 1
  119.     # code
  120.     perimetr = face_lenght*faces
  121.     radius = perimetr/(2*Math::PI)
  122.  
  123.     center = 0
  124.     # phi is degre of start point
  125.     phi = 0
  126.  
  127.     # round value
  128.     rnd = 3
  129.  
  130.  
  131.     # add 1 to faces need to close circuit
  132.     (faces+1).times do  |i|
  133.       if i != faces+1
  134.         x = (center + radius*Math::cos(phi+(2*Math::PI*i)/faces)).round(rnd)
  135.         y = (center + radius*Math::sin(phi+(2*Math::PI*i)/faces)).round(rnd)
  136.        
  137.         # generating next points, to be an array of [Point, Point] and simple drawing
  138.         xn = (center + radius*Math::cos(phi+(2*Math::PI*(i+1))/faces)).round(rnd)
  139.         yn = (center + radius*Math::sin(phi+(2*Math::PI*(i+1))/faces)).round(rnd)
  140.  
  141.         # pushing into array an array of 2 point to simple draw
  142.         push [Point.new(x, y, 0), Point.new(xn, yn, 0)]
  143.       end
  144.     end
  145.  
  146.     # pushing higher face of cylinder
  147.     # size.times{ |i|
  148.     #   push [Point.new(self[i][0].x, self[i][0].y, height), Point.new(self[i][1].x, self[i][1].y, height)]
  149.     #   # print self[i]
  150.     # }
  151.  
  152.     # adding vertical vertex's
  153.     # offset = size/2
  154.     size.times{  |i|
  155.       push [Point.new(self[i][0].x, self[i][0].y, 0), Point.new(0, 0, height)]
  156.     }
  157.  
  158.     push [Point.new(0,0,0), Point.new(500,0,0)]
  159.     push [Point.new(0,0,0), Point.new(0,500,0)]
  160.     push [Point.new(0,0,0), Point.new(0,0,500)]
  161.  
  162.   else
  163.     raise ArgumentError, "Number of faces must be more or = then 2"
  164.   end
  165. end
  166.  
  167. def $cylinder.each_point
  168.   each { |i| yield i[0]; yield i[1]}
  169. end
  170.  
  171. def $cylinder.draw
  172.   $canvas.delete("all")
  173.   of = 0
  174.   # puts self
  175.   for i in 0..length-1
  176.     TkcLine.new($canvas, of+self[i][0].x, of+self[i][0].y, of+self[i][1].x, of+self[i][1].y, 'tags' => 'Line')
  177.   end
  178.  
  179.   # TkcLine.new($canvas, of+self[-1].x, of+self[-1].y, of+self[0].x, of+self[0].y, 'tags' => 'Line')
  180.  
  181.  
  182.  
  183. end
  184.  
  185.  
  186. $width   = 640
  187. $height  = 480
  188.  
  189.  
  190. def _resize()
  191.   $cylinder.each_point {|i| i.moveTo(-$width/2, -$height/2, 0)}
  192.   # use this to get geometry of main widget
  193.   $width = $root.winfo_width()
  194.   $height = $root.winfo_height()
  195.  
  196.   $canvas.width  $width
  197.   $canvas.height  $height
  198.  
  199.   $cylinder.each_point {|i| i.moveTo($width/2, $height/2, 0)}
  200.   $cylinder.draw
  201.  
  202.  
  203. end
  204. # initializing main window
  205. $root = TkRoot.new do
  206.   title "Machine Graphics. lab3"
  207.   geometry("#{$width}x#{$height}-0+20")
  208. end
  209.  
  210. $canvas = TkCanvas.new do
  211.   bg "gray"
  212.   width "#{$width}"
  213.   height "#{$height}"
  214.   bind('Configure', proc  { _resize } )
  215.   pack
  216. end
  217.  
  218. $canvas.bind("ButtonPress-1", proc{|x,y| $lastX, $lastY = x, y}, "%x %y") {
  219.   puts "Press"
  220.   $stdout.flush
  221.  
  222. }
  223.  
  224. $canvas.bind("ButtonRelease-1") {
  225. }
  226.  
  227. $canvas.bind("B1-Motion", proc{|x,y| rotation(x,y)},  "%x %y")
  228.  
  229. def rotation (x, y)
  230.  
  231.   $cylinder.each_point {|i| i.moveTo(-$width/2, -$height/2, 0)}
  232.  
  233.  
  234.   dx, dy = x-$lastX, $lastY-y
  235.   dx /= 1.0
  236.   dy /= 1.0
  237.   $cylinder.each_point {|i| i.rotateX dy}
  238.   $cylinder.each_point {|i| i.rotateY dx}
  239.  
  240.   $cylinder.each_point {|i| i.moveTo($width/2, $height/2, 0)}
  241.  
  242.  
  243.  
  244.   $cylinder.draw
  245.   $lastX, $lastY = x, y
  246.  
  247. end
  248.  
  249. $cylinder.generate_skeleton(8,90,220)
  250. $cylinder.each_point {|i| i.moveTo($width/2, $height/2, 0)}
  251.  
  252.  
  253. # $cylinder.each_point {|i| i.rotateX 4 70}
  254. # $cylinder.each_point {|i| i.rotateY 10}
  255. # $cylinder.each_point {|i| i.moveTo(200, 150, 0) }
  256.  
  257. $cylinder.draw()
  258.  
  259. # print $cylinder, "\n"
  260.  
  261. # need to output all need's data, because in Tk loop nothing will output
  262. $stdout.flush
  263.  
  264. $root.mainloop
  265.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement