Powered By Blogger
Showing posts with label ruby. Show all posts
Showing posts with label ruby. Show all posts

22 November 2008

ruby sketchup export to *.x ( for directx)

exportx.rb
place in folder Plugins
C:\Program Files\Google\Google SketchUp 6\Plugins

# add item if menu is not already loaded
if( $directxExport_loaded != true ) then
UI.menu("PlugIns").add_item("Export DirectX...") { export_directx3 }
$directxExport_loaded = true
end

#Collect objects and explode group or components, apply transformation
def get_all_model_faces(entities, trans)
# get the array of entities
if entities.class == Sketchup::ComponentInstance
entity_list=entities.definition.entities
elsif entities.class == Sketchup::Group
entity_list=entities.entities
else
entity_list=entities
end
# for each element
for e in entity_list
# if the element is a Group or a Component
if (e.layer.visible? and (e.class == Sketchup::Group or e.class == Sketchup::ComponentInstance)) then
$groups +=1 if e.class == Sketchup::Group
$components += 1 if e.class == Sketchup::ComponentInstance
#check for material to set it to the children on next recusive call
if e.material != nil
$parent_mat.push(e.material)
else
$parent_mat.push($parent_mat.last)
end
# recurs call on the group or component
get_all_model_faces(e, trans*e.transformation)
$parent_mat.pop
end
# if the object is a simple Face
if( e.class == Sketchup::Face and e.layer.visible?) then
# check for material
if e.material == nil
mat=$parent_mat.last
else
mat = e.material
end
# add object to the global collection
$face_trans_collection.push([e,trans,mat])
#print e.to_s + "#" + trans.to_s + "\n"
$faces += 1
end
end
end

# Main entry point
def export_directx3()
# display ruby panel for messages
Sketchup.send_action "showRubyPanel:"
# call Save Dialog function
filename = get_filename
if filename == nil then # exit if cancel was choosen
return
end
print "Saving to : #{filename} \n"

# get the active sketchup model
model = Sketchup.active_model
# get a new writer for textures export
texturewriter = Sketchup.create_texture_writer

#global array that stores each individual text mesh
meshes = []
vertex_collection = []
normal_objects = []
normal_collection = []
normal_faces = []
texture_coords = []
face_collection = []
material_collection = []
material_face = []
# array to store material
all_materials = []
# add a default material when nothing special is specified for a face
material_collection += ["{ Default_Material }"]

# global push/pop array for children material propagation
$parent_mat = []
# global collection that stores a triplet [face, transformation, material]
$face_trans_collection = []
$faces = 0
$groups = 0
$components = 0

#get model entities
entities = model.entities

$parent_mat.push(nil)
# collect faces
get_all_model_faces(entities, Geom::Transformation.new)

print "#{$groups} group(s), #{$components} component(s), #{$faces} faces."

startindex = 0
# for all Faces
for ft in $face_trans_collection
entity = ft[0]
trans = ft[1]
mat = ft[2]
if(entity.typename == "Face") then
# Get a the MeshPolygon from the Face
#0 (Include PolygonMeshPoints), 1 (Include PolygonMeshUVQFront), 2 (Include PolygonMeshUVQBack), 4 (Include PolygonMeshNormals).
mesh = entity.mesh 1 4
# apply transformation when the object was in a group or in a component
mesh.transform! trans
# For all points
#print "mesh\n"
for p in (1..mesh.count_points)
# get the 3D point
pos = mesh.point_at(p).to_a
# get the normal at this point
norm = mesh.normal_at(p)
normal_objects +=[norm]
norm = norm.to_a
# default texture size
texsize = Geom::Point3d.new(1,1,1)

# if the material was obtained from the group or component
if mat!=nil and mat.texture!=nil and entity.material==nil then
# get the texture size
texsize = Geom::Point3d.new(mat.texture.width, mat.texture.height, 1)
end
# get the mesh texture coords (texture deformation: texture can only be streshed, rotated, translated (no parallel deformation)
uv = [mesh.uv_at(p,1).x/texsize.x, mesh.uv_at(p,1).y/texsize.y, mesh.uv_at(p,1).z/texsize.z]
# change to left hand counter clockwise
pos = counterclockwise(pos)
v = "#{"%.4f" %(pos[0])};#{"%.4f" %(pos[1])};#{"%.4f" %(pos[2])};"
vertex_collection += [v]
# change to left hand counter clockwise
norm = counterclockwise(norm)
n = "#{"%.4f" %(norm[0])};#{"%.4f" %(norm[1])};#{"%.4f" %(norm[2])};"
normal_collection += [n]
u = "#{"%.4f" %(uv[0]+1)},#{"%.4f" %(-uv[1])};"
texture_coords += [u]
end

# for each polygon
for poly in mesh.polygons
v1 = (poly[0]>=0?poly[0]:-poly[0])+startindex
v2 = (poly[1]>=0?poly[1]:-poly[1])+startindex
v3 = (poly[2]>=0?poly[2]:-poly[2])+startindex
f = "3;#{v3-1},#{v2-1},#{v1-1}"
face_collection += [f]

mat_index = 0
# get the material
material = mat
if material then
# add the material to the global list if this is a new one
# ! only export texture on front faces (back faces are ignored)
if !(all_materials.index(material)) then
all_materials += [material]
if material.texture then
# build a filename based on the targetfilename and the texture name
f = filename + File.basename(material.texture.filename)
# load the texture of the entity into the texture writer object
texturewriter.load entity, true
# serialize the texture to disk
texturewriter.write entity, true, f
end
m = material.name.gsub(/[^a-zA-Z0-9]/, "_")
material_collection += ["{ " + m + " }"]
end
# get the index for the future added material
mat_index = all_materials.index(material)+1
end
# add the index of the material in the list
material_face += [mat_index.to_s]
end
startindex = startindex + mesh.count_points
end
end

text = "xof 0303txt 0032
// SketchUp 6 -> DirectX (c)2008 edecadoudal, supports: faces, normals and textures
Material Default_Material{
1.0;1.0;1.0;1.0;;
3.2;
0.000000;0.000000;0.000000;;
0.000000;0.000000;0.000000;;
}
"
#model.materials.purge_unused

all_materials.each{mat
# replace '[' and ']' in name by a '_'
n = mat.name.gsub(/[^a-zA-Z0-9]/, "_")
mat_string = "Material " + n + "{ \n"
# faceColor
mat_string += (mat.color.red/255.0).to_s + ";" +(mat.color.green/255.0).to_s + ";" + (mat.color.blue/255.0).to_s + ";"
# Alpha
mat_string += mat.alpha.to_s + ";;\n"
#power
mat_string += "3.2;\n"
# specularColor ColorRGB
mat_string += "0.000000;0.000000;0.000000;;\n"
# emissiveColor ColorRGB
mat_string += "0.000000;0.000000;0.000000;;\n"
if mat.texture && mat.texture.filename != "" then
mat_string += " TextureFilename { "
mat_string += "\"" + File.basename(filename) + File.basename(mat.texture.filename) + "\";"
mat_string += " } \n"
end
mat_string += "} \n"
text += mat_string
}
text+= "Mesh {\n"
text+= " #{vertex_collection.length};\n"
stxt = vertex_collection.to_a.join(",\n ")
text+= " #{stxt};\n"
text+= " #{face_collection.length};\n"
stxt = face_collection.to_a.join(",\n ")
text+= " #{stxt};;\n"
text+= " MeshMaterialList {\n"
text+= " #{material_collection.length};\n"
text+= " #{material_face.length};\n"
stxt = material_face.to_a.join(",\n ")
text+= " #{stxt};\n"
stxt = material_collection.to_a.join("\n ")
text+= " #{stxt}\n"
text+= " }\n"
text+= " MeshTextureCoords {\n"
text+= " #{texture_coords.length};\n"
stxt = texture_coords.to_a.join("\n ")
text+= " #{stxt};\n"
text+= " }\n"
text+= " MeshNormals {\n"
text+= " #{normal_collection.length};\n "
stxt = normal_collection.to_a.join("\n")
text+= " #{stxt};\n"
text+= " #{face_collection.length};\n"
stxt = face_collection.to_a.join(";\n ")
text+= " #{stxt};;\n"

text+= " }\n"
text+= " }\n"

write_file(filename, text)
print "end.\n"
end

def get_filename
model = Sketchup.active_model
model_filename = File.basename(model.path)
if model_filename != ""
model_name = model_filename.split(".")[0]
model_name += ".x"
else
model_name = "Untitled.x"
end
my_str = UI.savepanel("Export as", "", model_name)
end

#convert a clockwise vector in a counterclockwise vector
def counterclockwise(v)
v2 = Array.new
v2 += [-v.to_a[1]]
v2 += [v.to_a[2]]
v2 += [v.to_a[0]]
my_a = v2
end

def write_file(filename, text)
fout = File.open(filename, "w")
fout.puts text
fout.close
end

04 July 2007

ruby ,trim , strip , sketchup script , rails กับภาษาไทย

วันนี้ มาพูดถึง Ruby On Rails ( RoR ) กันต่อ
จดไว้กันลืม ด้วยครับ

ruby ไม่มีคำสั่ง trim แต่มี คำสั่ง ที่เหมือนกัน คือ strip
เช่น
" foo ".strip # returns "foo"
[first_name, last_name].each { s s.strip! } # ทำทั้ง array
หรือใช้ strip! เพื่อปรับปรุงทันที
เช่น
mydata = " test this is a book "
mydata.strip!
puts mydata # จะได้ "test this is a book"



ibrary สามารถ ใช้ได้ กับ Rails ได้ โดยแยกเป็น แฟ้มๆ
แล้วแทรกไว้ ใน controller หรือ view ได้ เช่น
ใน *.rhtml แทรกโค้ด ต่อไ ปนี้ไว้ เพื่อ add library


โดย ใน lib1.rb มีคลาสอยู่ จะทำให้เรียกใช้งานได้
lib1.rb เก็บไว้ใน path ที่หาได้ โดย Dir.pwd ( หา Current Directory )
แต่ปัญหา ของ rail ก็มีอยู่ที่ *.rb ไม่ support thai ( เท่าที่ผมลองดู ใช้แล้วแจ้ง error , utf ก็error ) เลย
งาน ที่ต้องใช้แสดงผลภาษาไทย เลยไม่เหมาะจะอยู่ใน library นี้
ยังรอดอยู่บ้างตรงที่ *.rhtml support ไทย ดังนั้น code ต่างๆของฟังก์ชัน
ที่ใช้ภาษาไทย เช่น วันที่ อาจเก็บไว้ที่ *.rhtml ของวิว แทน

ตัวอย่างโค้ดเก็บวันที่ เช่น



<%     def monthname_th(m)       nm =  ['มค.','กพ.','มีค.','เมษ','พค.','มิย.' , 'กค.' , 'สค.','กย.' ,'ตค.', 'พย' , 'ธค' ]       nm[m-1]   end %>

เป็นโค้ดแสดงเดือนไทยจาก วันที่ เมื่อ m เป็นตัวแปรชนิด date

และก็เพิ่งรู้ว่า sketchup (free)

สามารถ รัน Ruby Script ได้

ลองดูแล้วก็ทำได้จริงๆ ใช้ Generate line แบบง่ายๆได้ แสดง Html Form ได้

แสดง webpage window ได้ และอื่นๆ อีกมาก

ลอง ทดสอบ generate line ของสมาการ พาราโบลา 2 มิติง่ายๆ ดู พอได้แต่ไม่ชำนาญ

ทำโดย สร้าง file *.rb สมมุดิ ชื่อ Info.rb

สร้าง class ภายใน และเรียกใช้ class ดังนี้











class Info
def getCurDir
Dir.pwd
end
def msgbox(s )
UI.messagebox( s )
end
def draw_line_test()
model = Sketchup.active_model
pt1 = [0, 0, 0]
pt2 = [10, 10, 10]
model.entities.add_line(pt1, pt2)
pt2 = [0, 10, 10]
model.entities.add_line(pt1, pt2)
pt2 = [10, 0, 10]
model.entities.add_line(pt1, pt2)
end
def draw_line_test2()
model = Sketchup.active_model
z0 = 0
zn = 0
(-20).step(20,0.5){ x
z1= y = x * x / 10
z2 = y = (x+1) * (x+1) / 10
if x == -20
z0 = z1
elsif x == 20
zn = z2
end
pt1 = [x, 0 , z1]
pt2 = [x+1, 0 , z2]
model.entities.add_line(pt1, pt2)
}
end
end # class

#### start create class and call function
i = Info.new
i.draw_line_test
i.draw_line_test2
i.drawtext_test
i = nil






เซฟไว้ที่ c:\Info.rb
แล้ว เรียกใช้ ผ่าน RubyConsole ของ Sketchup
โดย ใช้คำสั่ง load
load 'c:\Info.rb'

ข้อควรระวัง คือ ต้องเป็น โคด แบบเดี่ยว ' ไม่ใช่ แบบ " ไม่เช่นนั้น อาจต้องใช้ string

แบบ "c:\\Info.rb" แทน แต่ยังไม่ได้ทดลอง

หลังจาก กดEnter ให้รัน จะได้ รูป ทรงแบบง่ายๆ ใน sketchup pro



เขียนไว้กันตัวเอง ลืมด้วยครับ
ช่วงนี้ ศึกษาหลายภาษา




13 June 2007

new program uploaded & Ruby generate html

เมื่อวาน เพิ่งทำโปรแกรมแกรมดูข้อมูล HardDisk ใช้เอง ที่ทำงาน เสร็จ
Tsb::FileSize.NET
แสดงขนาดของแฟ้ม พร้อมด้วย แสดงกราฟแบบวงกลมได้ (Pie Graph )
รวมถึง อาจใช้เพื่อคำนวณ ขนาดของ Folder ที่เลือกหลายๆ Folder ได้ด้วย
แล้วก้อบ ไป ไว้ที่ MS Excel เพื่อทำกราฟ ออกรายงานต่อไป ก็ได้
( อันนี้ต้อง Manual หน่อย นะครับ )







วันนี้ ลองใช้ Ruby มา Generate HTmL File ดู
หลังจากเคยลองด้วย vb.netแล้ว
แต่ Ruby เขียนสั้นดี

ทีแรกกะว่าจะลองเขียน Parse TextFile ด้วย Ruby ด้วยแต่ยังไม่ค่อยชำนาญ
ช่วงๆนี้เลยแค่ๆ ลองเขียน ด้วย VB.netก่อน

ตัวอย่าง โค้ด Ruby ก็ดังนี้นะครับ


ให้เปลี่ยน < ===> "<"
> ==> ">"






def contentheight
200
end
def html
"<html>#{title}#{body}"
end
def title
"<title>Test Html Gen</title>"
end
def menuitem(i )
"<div style='background-color:lightblue;'>
menu #{i}</div>
"
end
def leftmenu
tab2("
#{menuitem(1)}
#{menuitem(2)}
#{menuitem(3)}
#{menuitem(4.2)}
",
"width=150 bgcolor=silver ",
"height=#{contentheight} valign=top " )
end
def tab1(s , att)
"<table border=0 cellspacing=0 cellpadding=1 #{att}>
<tr><td>
#{s}
</td></tr>
</table>"
end
def tab2(s , att ,attrtd)
"<table border=0 cellspacing=0 cellpadding=1 #{att}>
<tr><td #{attrtd}>
#{s}
</td></tr>
</table>"
end
def footer
tab2(" Copyright ",
"width=100% bgcolor=lightyellow " ,
" colspan=2 valing=center align=center ")
end
def topmenu
tab1("home download ","width=100% bgcolor=orange")
end
def data
tab2(
"data ",
"bgcolor=white width=100% height=#{contentheight}",
" valign=top " )
end
def tabtr
"
</td></tr>
<tr><td>
"
end
def tabtd(attr)
"
</td>
<td #{attr}>
"
end
def content
s = leftmenu + tabtd("align=left valign=top")
s = s +data
tab2(s ,
"width=100% bgcolor=lightnavy" ,
"width=100 valign=top ")
end
def body
topmenu + content + footer
end
def main
html
end

p main

f = File.open('htm.html',"w")
f.print(main )
f.close


08 June 2007

ตัวอย่างโปรแกรม Ruby ลบแฟ้มและ directory



ตัวอย่างโปแกรม Ruby สำหรับ ลบ TempFile
ใน Internet Explorer
โดยลบทั้ง file และ folder
และป้องกันปัญหาที่เกิดขึ้นเมื่อ มีการ ลบแฟ้มที่ลบไม่ได้ ซึ่งจะแจ้ง error แล้ว ทำงานต่อไป

ในที่นี้ สมมุติ user login windowsxp คือ css1

listtempfile(false) สำหรับ แสดงข้อมูล เท่านั้น
listtempfile(true) สำหรับลบ ด้วย

การ Run Program
C:\>ruby app1.rb


#---------------------------------
#file : app1.rb

dir1 = 'C:\Documents and Settings\css1\Local Settings\Temp'
dir1 ='C:\Documents and Settings\css1\Local Settings\Temporary Internet Files'
dir1 ='C:\Documents and Settings\css1\Local Settings\Temporary Internet Files\Content.IE5'


def listallfile(dir1)
puts dir1
i = 0
delcount = 0
Dir.chdir(dir1 )
Dir.foreach(dir1) { x
i += 1
print("Got #{i} " + x + ' ' + File.size(x).to_s)
if FileTest.directory?(x) and x != '.' and x != '..'
print (' [dir]')
Dir.foreach(x) {y
puts " Gots #{y}" + ' ' + FileTest.directory?(y).to_s
}
end
puts ""
}
end

def listtempfile( isdel )
dir1 ='C:\Documents and Settings\css1\Local Settings\Temporary Internet Files\Content.IE5'
puts dir1
i = 0
delcount = 0
Dir.chdir(dir1 )
Dir.foreach(dir1) { x
i += 1
print("Got #{i} " + x + ' ' + File.size(x).to_s)
if FileTest.directory?(x) and x != '.' and x != '..'
print (' [dir]')
Dir.foreach(x) {y
puts " Gots #{y}" + ' ' + FileTest.directory?(y).to_s
if isdel and ( not FileTest.directory?(y))
begin
fname = x + '\\' + y
print 'try delete ' + fname
File.delete(fname )
print " deleted"
rescue Exception => ex
print " can not delete " + ex
end
puts "" #new line
end

}
# del dir
if isdel
begin
puts "try to delete " + x
Dir.delete(x )
rescue
puts "can not delete dir " + x
end
end
end
puts ""
}
end


def delallfile(dir1)
i = 0
delcount = 0
Dir.chdir(dir1 )
Dir.foreach(dir1) { x
i += 1
puts("Got #{i} " + x )
begin
if ( File.stat(x).file? )
delcnt = File.delete(x )
delcount += delcnt
end
rescue Exception => detail
puts "can not delete " + x + " " + detail
end
}
puts "deleted #{delcount} file(s) "
end

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

#listtempfile(false)
listtempfile(true)

#---- end of file



อย่ารันเล่นนะครับ ไม่รับประกัน ความผิดพลาด นะครับ

05 June 2007

Ruby On Rails กับ MySQL , Thai Character display

การแสดงผล ภาษาไทย
รับข้อมูล ภาษาไทย จาก form
ใส่ใน mysql อาจทำให้ ตัวหนังสือที่แสดงออกภายหลัง กลายเป็น ???????? แทน

แก้ไขได้ ดังนี้ คือ

เพิ่ม โค้ด

---------------------------------------------
before_filter :configure_charsets

def configure_charsets
@headers["Content-Type"] = "text/html; charset=TIS620"

suppress(ActiveRecord::StatementInvalid) do
ActiveRecord::Base.connection.execute 'SET NAMES TIS620'

end
end
----------------------------------------------

ไว้ที่ส่วนต้น ของ ทุกๆ Controlers แล้วก็ ลองป้อนและแสดงข้อมูลใหม่ทาง browser
ไม่จำเป็น ต้อง Restart webserver ครับ ลองๆ
ดูแล้ว ก็ใช้งานได้

ผมใช้ AppServ mysql เป็น ฐานข้อมูล ก็ใช้งานได้ เปลี่ยนจาก ??? มาเป็น ภาษาไทยได้ทันที

ตัวอย่าง เช่น
class EbitController < ApplicationController
before_filter :configure_charsets

def configure_charsets
@headers["Content-Type"] = "text/html; charset=TIS620"

suppress(ActiveRecord::StatementInvalid) do
ActiveRecord::Base.connection.execute 'SET NAMES TIS620'
end

end #def

...... โค้ด ส่วนอื่นๆ เช่น def

end #class
----------------------------------

จริงๆแล้วก็ไม่เข้าใจความหมายหรอก
อ่านมาจาก คนที่ชำนาญกว่า ที่เวปนี้ครับ
http://weblog.punneng.com/index.php?m=200607&paged=2

Ruby update ข้อมูล กับ database ด้วย console

หลังจาก ลองมั่วๆ Ruby OnRails มาสักสามสี่วันแล้ว มึนๆเลย

ก็เลยลองทวน basic กันหน่อย
โดยใช้

Ruby script/console เพื่อช่วยเรียน rubyเอง

สร้าง model ชื่อว่า user (table users )
ด้วย ruby script/generate model user user <-- ไม่ค่อยแน่ใจ
กับ controller
ด้วย ruby script/generator scaffold mydb user
แล้วเปิด ruby script/server เป็น web server
แล้ว เข้า page ด้วย http://localhost:3000/user

พอดีต้อง ปรับปรุง model แต่ไม่ค่อยเข้าใจ ActiveRecord เลยหาทาง
ทำความเข้าใจ ก็เลย ลองใช้วิธี console ช่วยให้เข้าใจ มากนิดนึง

ก็ เปิด ruby script/console
ทีนี้ ลองสร้าง
u = User.new ( ) ทำเท่าไร ก็ error เลยหาข้อมูลสักพัก หลังจากไปนั่งอ่านเวปสนุกๆ
พอ กลับมา ก็เปิด fxri ปรากฏว่าโหลดนานพอดู เพราะเครื่องช้าไปนิด
แล้วก็ ใส่ keyword ลองเดามั่วๆ หาคำว่า connection

พบ ActiveRecord::Base.establish_connection ก็เป็นการเดาล้วนๆ
เดาจาก ADODB ของ VB6 เพราะว่า ก่อน ใช้ RecordSet ต้องเปิด connectionก่อน
เพราะ เดิม แจ้ง error ว่า login เข้าเบส ไม่ได้คล้ายๆ ไม่มี การใส่ password

ได้คำอธิบายว่า ทำแนวๆนี้
ActiveRecord::Base.establish_connection( :adapter => "mysql", :host => "localhost", :username => "myuser", :password => "mypass", :database => "somedatabase" )

ก็เลยแก้ไขนิดหน่อย แล้วก็ไป Paste ใน console
ผลคือ มันคล้ายๆทำงานแทน database.yml ใน directroy config
ซึ่งก็คือ มีการเปิด connection ใหม่ให้
คราวนี้
ก็ลอง

u = User.new( )
ได้ผล ใช้งานได้ ได้ instance u สำหรับจัดการ Table Users มาแล้ว

ทีนี้ลองใช้ ดึงข้อมูลล่ะ
rows = User.find ( :all ) ได้ผลครับ ออกมา 2 แถว
อ้างได้ด้วย
rows[0].name = "new name"
rows[0].save
ผล คือ database ใน phpMyAdmin เปลี่ยนตามทันทีเลย

หรือจะลองด้วย เงื่อนไข where กับ first
cond = [ "name=? and password = ? " , "myname" ,"mypass" ]
row = User.find (:first , :conditions => cond )
ก็ได้ผลเหมือนกัน แต่ได้ แถวเดียว
แล้วแก้ไขโดย
row.name= "newname1"
row.save


หากจะค้นหาด้วยเงื่อนไขอื่นๆ อาจใช้ like เช่น
row = User.find(:first, :conditions=> "name like '%user%'" ) ก็ได้