fml 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. data/.gitignore +8 -0
  2. data/README +1 -0
  3. data/Rakefile +3 -0
  4. data/bin/fml2dae.rb +15 -0
  5. data/bin/fml2obj.rb +10 -0
  6. data/fml.gemspec +36 -0
  7. data/lib/collada/document.rb +101 -0
  8. data/lib/collada/geometry.rb +110 -0
  9. data/lib/config.yml +17 -0
  10. data/lib/floorplanner/area_builder.rb +42 -0
  11. data/lib/floorplanner/asset.rb +185 -0
  12. data/lib/floorplanner/collada_export.rb +118 -0
  13. data/lib/floorplanner/design.rb +108 -0
  14. data/lib/floorplanner/document.rb +68 -0
  15. data/lib/floorplanner/obj_export.rb +24 -0
  16. data/lib/floorplanner/opening3d.rb +140 -0
  17. data/lib/floorplanner/rib_export.rb +24 -0
  18. data/lib/floorplanner/svg_export.rb +25 -0
  19. data/lib/floorplanner/wall3d.rb +97 -0
  20. data/lib/floorplanner/wall_builder.rb +165 -0
  21. data/lib/floorplanner.rb +52 -0
  22. data/lib/geom/connection.rb +14 -0
  23. data/lib/geom/ear_trim.rb +52 -0
  24. data/lib/geom/edge.rb +89 -0
  25. data/lib/geom/glu_tess.rb +34 -0
  26. data/lib/geom/intersection.rb +38 -0
  27. data/lib/geom/matrix3d.rb +141 -0
  28. data/lib/geom/number.rb +104 -0
  29. data/lib/geom/plane.rb +36 -0
  30. data/lib/geom/polygon.rb +264 -0
  31. data/lib/geom/triangle.rb +38 -0
  32. data/lib/geom/triangle_mesh.rb +94 -0
  33. data/lib/geom/vertex.rb +33 -0
  34. data/lib/geom.rb +13 -0
  35. data/lib/keyhole/archive.rb +36 -0
  36. data/tasks/github-gem.rake +315 -0
  37. data/views/design.dae.erb +439 -0
  38. data/views/design.obj.erb +17 -0
  39. data/views/design.rib.erb +17 -0
  40. data/views/design.svg.erb +42 -0
  41. data/xml/collada_schema_1_4.xsd +11046 -0
  42. data/xml/fml.rng +268 -0
  43. data/xml/fml2kml.xsl +59 -0
  44. metadata +117 -0
@@ -0,0 +1,439 @@
1
+ <?xml version="1.0"?>
2
+ <COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
3
+ <asset>
4
+ <contributor>
5
+ <author>john doe &lt;johnny@floorplanner.com&gt;</author>
6
+ </contributor>
7
+ <created>2006-06-21T21:23:22Z</created>
8
+ <modified>2006-06-21T21:23:22Z</modified>
9
+ <unit meter="1.00" name="meter"/>
10
+ <up_axis>Z_UP</up_axis>
11
+ </asset>
12
+
13
+ <library_cameras>
14
+ <camera id="main-cam">
15
+ <optics>
16
+ <technique_common>
17
+ <perspective>
18
+ <yfov>70</yfov>
19
+ </perspective>
20
+ </technique_common>
21
+ </optics>
22
+ </camera>
23
+ </library_cameras>
24
+
25
+ <library_materials id="surrounding-materials">
26
+ <material id="walls-material" name="WallsMaterial">
27
+ <instance_effect url="#walls-fx"/>
28
+ </material>
29
+ <material id="windows-material" name="WindowsMaterial">
30
+ <instance_effect url="#windows-fx"/>
31
+ </material>
32
+ <% @areas.each do |area_mesh| %>
33
+ <material id="area_<%= area_mesh.data[:id] %>-material" name="<%= area_mesh.data[:name] %>">
34
+ <instance_effect url="#area_<%= area_mesh.data[:id] %>-fx"/>
35
+ </material>
36
+ <% end %>
37
+ <% unless @xrefs; @assets.each_value do |asset| %>
38
+ <% asset.library_materials.each do |materials| %>
39
+ <%= materials.to_s %>
40
+ <% end %>
41
+ <% end; end %>
42
+ </library_materials>
43
+
44
+ <library_effects id="surrounding-effects">
45
+ <effect id="walls-fx">
46
+ <profile_COMMON>
47
+ <technique>
48
+ <phong>
49
+ <emission>
50
+ <color>0.05 0.05 0.05 1</color>
51
+ </emission>
52
+ <ambient>
53
+ <color>0.15 0.15 0.15 1</color>
54
+ </ambient>
55
+ <diffuse>
56
+ <color>0.9 0.9 0.9 1</color>
57
+ </diffuse>
58
+ <specular>
59
+ <color>0 0 0 1</color>
60
+ </specular>
61
+ <shininess>
62
+ <float>0.0</float>
63
+ </shininess>
64
+ <reflective>
65
+ <color>1 1 1 1</color>
66
+ </reflective>
67
+ <reflectivity>
68
+ <float>0.0</float>
69
+ </reflectivity>
70
+ <transparent>
71
+ <color>1 1 1 1</color>
72
+ </transparent>
73
+ <transparency>
74
+ <float>0.0</float>
75
+ </transparency>
76
+ </phong>
77
+ </technique>
78
+ </profile_COMMON>
79
+ </effect>
80
+ <effect id="windows-fx">
81
+ <profile_COMMON>
82
+ <technique>
83
+ <phong>
84
+ <emission>
85
+ <color>0.0 0.0 0.0 1</color>
86
+ </emission>
87
+ <ambient>
88
+ <color>0.15 0.15 0.15 1</color>
89
+ </ambient>
90
+ <diffuse>
91
+ <color>0.9 0.9 1.0 1</color>
92
+ </diffuse>
93
+ <specular>
94
+ <color>0 0 0 1</color>
95
+ </specular>
96
+ <shininess>
97
+ <float>0.0</float>
98
+ </shininess>
99
+ <reflective>
100
+ <color>1 1 1 1</color>
101
+ </reflective>
102
+ <reflectivity>
103
+ <float>0.2</float>
104
+ </reflectivity>
105
+ <transparent>
106
+ <color>1 1 1 1</color>
107
+ </transparent>
108
+ <transparency>
109
+ <float>0.9</float>
110
+ </transparency>
111
+ </phong>
112
+ </technique>
113
+ </profile_COMMON>
114
+ </effect>
115
+ <% @areas.each do |area_mesh|; id = area_mesh.data[:id].to_s %>
116
+ <effect id="area_<%= id %>-fx" name="<%= area_mesh.data[:name] %>">
117
+ <% if area_mesh.data[:texture] %>
118
+ <extra>
119
+ <technique sid="sunflow">
120
+ <diffuse><%= area_mesh.data[:color].join(' ') %></diffuse>
121
+ </technique>
122
+ </extra>
123
+ <% end %>
124
+ <profile_COMMON>
125
+ <% if area_mesh.data[:texture] %>
126
+ <newparam sid="area_<%= id %>-surface">
127
+ <surface type="2D">
128
+ <init_from>area_<%= id %>-image</init_from>
129
+ </surface>
130
+ </newparam>
131
+ <newparam sid="area_<%= id %>-sampler">
132
+ <sampler2D>
133
+ <source>area_<%= id %>-surface</source>
134
+ </sampler2D>
135
+ </newparam>
136
+ <% end %>
137
+ <technique>
138
+ <phong>
139
+ <emission>
140
+ <color>0.05 0.05 0.05 1</color>
141
+ </emission>
142
+ <ambient>
143
+ <color>0.1 0.1 0.1 1</color>
144
+ </ambient>
145
+ <diffuse>
146
+ <% if area_mesh.data[:texture] %>
147
+ <texture texture="area_<%= id %>-sampler"/>
148
+ <% else %>
149
+ <color><%= area_mesh.data[:color].join(' ') %> 1</color>
150
+ <% end %>
151
+ </diffuse>
152
+ <specular>
153
+ <color>0 0 0 1</color>
154
+ </specular>
155
+ <shininess>
156
+ <float>0.0</float>
157
+ </shininess>
158
+ <reflective>
159
+ <color>1 1 1 1</color>
160
+ </reflective>
161
+ <reflectivity>
162
+ <float>0.0</float>
163
+ </reflectivity>
164
+ <transparent>
165
+ <color>1 1 1 1</color>
166
+ </transparent>
167
+ <transparency>
168
+ <float>0.0</float>
169
+ </transparency>
170
+ </phong>
171
+ </technique>
172
+ </profile_COMMON>
173
+ </effect>
174
+ <% end %>
175
+ <% unless @xrefs; @assets.each_value do |asset| %>
176
+ <% asset.library_effects.each do |effects| %>
177
+ <%= effects.to_s %>
178
+ <% end %>
179
+ <% end; end %>
180
+ </library_effects>
181
+
182
+ <library_images>
183
+ <% @areas.each do |area_mesh|; if area_mesh.data[:texture] %>
184
+ <image id="area_<%= area_mesh.data[:id] %>-image" name="<%= area_mesh.data[:name] %>">
185
+ <init_from><%= Floorplanner.config['area_textures_path'] +
186
+ area_mesh.data[:texture].gsub('textures/2d/','').gsub(/\.swf$/,'.png') %></init_from>
187
+ </image>
188
+ <% end; end %>
189
+
190
+ <% unless @xrefs; @assets.each_value do |asset| %>
191
+ <% asset.library_images.each do |image| %>
192
+ <%= image.to_s %>
193
+ <% end %>
194
+ <% end; end %>
195
+ </library_images>
196
+
197
+ <library_geometries id="surrounding-geometry">
198
+
199
+ <geometry id="walls-geom" name="WallsGeometry">
200
+ <mesh>
201
+ <source id="walls-positions" name="position">
202
+ <float_array id="walls-positions-array" count="<%= @walls.vertices.length*3 %>">
203
+ <%= @walls.vertices.collect {|v| v.to_floats }.join(' ') %>
204
+ </float_array>
205
+
206
+ <technique_common>
207
+ <accessor count="<%= @walls.vertices.length %>" offset="0" source="#walls-positions-array" stride="3">
208
+ <param name="X" type="float"></param>
209
+ <param name="Y" type="float"></param>
210
+ <param name="Z" type="float"></param>
211
+ </accessor>
212
+ </technique_common>
213
+ </source>
214
+
215
+ <vertices id="walls-vertices">
216
+ <input semantic="POSITION" source="#walls-positions"/>
217
+ </vertices>
218
+
219
+ <triangles count="<%= @walls.faces.length %>" material="Walls">
220
+ <input semantic="VERTEX" source="#walls-vertices" offset="0"/>
221
+ <p>
222
+ <%= @walls.faces.collect{|f| f.vertices.collect{|v| @walls.vertices.index(v)}}.flatten.join(' ') %>
223
+ </p>
224
+ </triangles>
225
+ </mesh>
226
+ </geometry>
227
+
228
+ <geometry id="windows-geom" name="WindowsGeometry">
229
+ <%
230
+ windows_vertices = @walls.windows.collect {|w| w.vertices}.flatten
231
+ windows_faces = @walls.windows.collect {|w| w.faces}.flatten
232
+ %>
233
+ <mesh>
234
+ <source id="windows-positions" name="position">
235
+ <float_array id="windows-positions-array" count="<%= @walls.vertices.length*3 %>">
236
+ <%= windows_vertices.collect {|v| v.to_floats }.join(' ') %>
237
+ </float_array>
238
+
239
+ <technique_common>
240
+ <accessor count="<%= windows_vertices.length %>" offset="0" source="#windows-positions-array" stride="3">
241
+ <param name="X" type="float"></param>
242
+ <param name="Y" type="float"></param>
243
+ <param name="Z" type="float"></param>
244
+ </accessor>
245
+ </technique_common>
246
+ </source>
247
+
248
+ <vertices id="windows-vertices">
249
+ <input semantic="POSITION" source="#windows-positions"/>
250
+ </vertices>
251
+
252
+ <triangles count="<%= windows_faces.length %>" material="Window">
253
+ <input semantic="VERTEX" source="#windows-vertices" offset="0"/>
254
+ <p>
255
+ <% offset = 0
256
+ @walls.windows.each do |w|
257
+ %>
258
+ <%= w.faces.collect{|f| f.vertices.collect{|v| w.vertices.index(v) + offset}}.flatten.join(' ') %>
259
+ <% offset += w.vertices.length ; end %>
260
+ </p>
261
+ </triangles>
262
+ </mesh>
263
+ </geometry>
264
+ <% @areas.each do |area_mesh|; id = area_mesh.data[:id] %>
265
+ <geometry id="area_<%= id %>-geom" name="Area_<%= id %>_<%= area_mesh.data[:name] %>-Geometry">
266
+ <mesh>
267
+ <source id="area_<%= id %>-positions" name="position">
268
+
269
+ <float_array id="area_<%= id %>-positions-array" count="<%= area_mesh.vertices.length*3 %>">
270
+ <%= area_mesh.vertices.collect {|v| v.to_floats }.join(' ') %>
271
+ </float_array>
272
+
273
+ <technique_common>
274
+ <accessor count="<%= area_mesh.vertices.length %>" offset="0" source="#area_<%= id %>-positions-array" stride="3">
275
+ <param name="X" type="float"></param>
276
+ <param name="Y" type="float"></param>
277
+ <param name="Z" type="float"></param>
278
+ </accessor>
279
+ </technique_common>
280
+ </source>
281
+
282
+ <source id="area_<%= id %>-uvs" name="texcoord">
283
+ <float_array id="area_<%= id %>-uvs-array" count="<%= area_mesh.texcoord.length %>">
284
+ <%= area_mesh.texcoord.map{|n| [n.u,n.v]}.flatten.join(' ') %>
285
+ </float_array>
286
+ <technique_common>
287
+ <accessor count="44" source="#area_<%= id %>-uvs-array" stride="2">
288
+ <param name="S" type="float"/>
289
+ <param name="T" type="float"/>
290
+ </accessor>
291
+ </technique_common>
292
+ </source>
293
+
294
+ <vertices id="area_<%= id %>-vertices">
295
+ <input semantic="POSITION" source="#area_<%= id %>-positions"/>
296
+ </vertices>
297
+
298
+ <triangles count="<%= area_mesh.faces.length %>" material="<%= "Area_"+id %>">
299
+ <input semantic="VERTEX" source="#area_<%= id %>-vertices" offset="0"/>
300
+ <input semantic="TEXCOORD" source="#area_<%= id %>-uvs" offset="1"/>
301
+ <p>
302
+ <%=
303
+ area_mesh.faces.collect { |f|
304
+ v = f.vertices.collect { |v| area_mesh.vertices.index(v) }
305
+ t = f.texcoord.collect { |t| area_mesh.texcoord.index(t) }
306
+ [v[0],t[0],v[1],t[1],v[2],t[2]]
307
+ }.flatten.join(' ')
308
+ %>
309
+ </p>
310
+ </triangles>
311
+ </mesh>
312
+ </geometry>
313
+ <% end %>
314
+ <% unless @xrefs; @assets.each_value do |asset| %>
315
+ <% asset.library_geometries.each do |geometries| %>
316
+ <%= geometries.to_s %>
317
+ <% end %>
318
+ <% end; end %>
319
+ </library_geometries>
320
+ <% unless @xrefs %>
321
+ <library_nodes>
322
+ <% @assets.each_value do |asset| %>
323
+ <% asset.library_nodes.each do |nodes| %>
324
+ <%= nodes.to_s %>
325
+ <% end %>
326
+ <% end %>
327
+ </library_nodes>
328
+ <% end %>
329
+ <library_visual_scenes>
330
+ <visual_scene id="VisualSceneNode" name="<%= @name %>">
331
+ <extra>
332
+ <technique sid="sunflow">
333
+ <image>
334
+ <resolution>800 600</resolution>
335
+ <aa>0 2</aa>
336
+ <filter>gaussian</filter>
337
+ </image>
338
+ <trace_depths>
339
+ <diffuse>4</diffuse>
340
+ <reflection>2</reflection>
341
+ </trace_depths>
342
+ <gi>
343
+ <type>ambocc</type>
344
+ <bright>1 1 1</bright>
345
+ <dark>0 0 0</dark>
346
+ <samples>64</samples>
347
+ <maxdist>3.0 </maxdist>
348
+ </gi>
349
+ <background>
350
+ <color>1.0 1.0 1.0</color>
351
+ </background>
352
+ <!--sunsky>
353
+ <up>0 0 1</up>
354
+ <east>1 0 0</east>
355
+ <sundir>0.2 0.4 0.7</sundir>
356
+ <ground>1 1 1</ground>
357
+ </sunsky-->
358
+ </technique>
359
+ </extra>
360
+ <!--node id="Camera" name="Camera">
361
+ <lookat>
362
+ 9.0 -1.0 1.4
363
+ 8.0 -2.0 1.4
364
+ 0.0 0.0 1.0
365
+ </lookat>
366
+ <instance_camera url="#main-cam"/>
367
+ </node-->
368
+ <node id="Walls" name="Walls">
369
+ <instance_geometry url="#walls-geom">
370
+ <bind_material>
371
+ <technique_common>
372
+ <instance_material symbol="Walls" target="#walls-material"/>
373
+ </technique_common>
374
+ </bind_material>
375
+ </instance_geometry>
376
+ </node>
377
+ <node id="Windows" name="Windows">
378
+ <instance_geometry url="#windows-geom">
379
+ <bind_material>
380
+ <technique_common>
381
+ <instance_material symbol="Window" target="#windows-material"/>
382
+ </technique_common>
383
+ </bind_material>
384
+ </instance_geometry>
385
+ </node>
386
+ <node id="Areas" name="Areas">
387
+ <% @areas.each do |area_mesh|; id = area_mesh.data[:id] %>
388
+ <node id="Area_<%= id %>" name="Area_<%= id %>">
389
+ <instance_geometry url="#area_<%= id %>-geom">
390
+ <bind_material>
391
+ <technique_common>
392
+ <instance_material symbol="Area_<%= id %>" target="#area_<%= id %>-material"/>
393
+ </technique_common>
394
+ </bind_material>
395
+ </instance_geometry>
396
+ </node>
397
+ <% if area_mesh.data[:type] == 'generated_area' %>
398
+ <node id="Area_<%= id %>-cap" name="Area_<%= id %>-cap">
399
+ <translate>0.0 0.0 <%= @areas.ceiling_z %></translate>
400
+ <instance_geometry url="#area_<%= id %>-geom">
401
+ <bind_material>
402
+ <technique_common>
403
+ <instance_material symbol="Area_<%= id %>" target="#walls-material"/>
404
+ </technique_common>
405
+ </bind_material>
406
+ </instance_geometry>
407
+ </node>
408
+ <% end %>
409
+ <% end %>
410
+ </node>
411
+ <% @elements.each do |element| %>
412
+ <node name="<%= element[:asset].title %>">
413
+ <translate><%= element[:position].to_floats %></translate>
414
+ <% if element[:matrix] %>
415
+ <matrix><%= element[:matrix].to_a.join ' ' %></matrix>
416
+ <% end %>
417
+ <% if element[:rotation].x > 0 %>
418
+ <rotate sid="rotateX">1 0 0 <%= element[:rotation].x %></rotate>
419
+ <% end %>
420
+ <% if element[:rotation].y > 0 %>
421
+ <rotate sid="rotateY">0 1 0 <%= element[:rotation].y %></rotate>
422
+ <% end %>
423
+ <% if element[:rotation].z > 0 %>
424
+ <rotate sid="rotateZ">0 0 1 <%= element[:rotation].z %></rotate>
425
+ <% end %>
426
+ <scale><%= element[:scale].to_floats %></scale>
427
+ <% if @xrefs %>
428
+ <instance_node url="<%= element[:asset].dae_path %>"/>
429
+ <% else %>
430
+ <%= element[:asset].visual_scene_node.to_s %>
431
+ <% end %>
432
+ </node>
433
+ <% end %>
434
+ </visual_scene>
435
+ </library_visual_scenes>
436
+ <scene>
437
+ <instance_visual_scene url="#VisualSceneNode"/>
438
+ </scene>
439
+ </COLLADA>
@@ -0,0 +1,17 @@
1
+ # Floorplanner.com
2
+ # <%= @name %>
3
+ <%
4
+ vertices = @walls.vertices + @areas.vertices
5
+ faces = @walls.faces + @areas.faces
6
+ %>
7
+ <% vertices.each do |v| %>
8
+ v <%= [v.x,v.z,v.y].join(' ') %><% end %>
9
+ <%
10
+ faces.each do |f|
11
+ v = [
12
+ vertices.index(f.vertices[0]),
13
+ vertices.index(f.vertices[1]),
14
+ vertices.index(f.vertices[2])
15
+ ]
16
+ if v.compact.length == 3 %>
17
+ f <%= v.collect{|w|w+1}.join(' ') %><% end ; end %>
@@ -0,0 +1,17 @@
1
+ Display "design.tif" "file" "rgb"
2
+ Format 480 320 -1
3
+ Projection "perspective" "fov" 45
4
+ Translate -5 -2 22
5
+ Rotate 240 1 0 0
6
+ Rotate -40 0 0 1
7
+ WorldBegin
8
+   LightSource "ambientlight" 1 "intensity" 1.0
9
+   LightSource "distantlight" 2 "from" [0 0 4] "to" [0 0 0] "intensity" 5.0
10
+   Color [ 0.95 0.95 0.95 ]
11
+ <% @walls.faces.each do |face| %>
12
+   Polygon "P" [ <%= face.vertices.collect{|v| [v.x,v.y,v.z]}.flatten.join(' ') %> ]
13
+ <% end %>
14
+ <% @areas.faces.each do |face| %>
15
+   Polygon "P" [ <%= face.vertices.collect{|v| [v.x,v.y,v.z]}.flatten.join(' ') %> ]
16
+ <% end %>
17
+ WorldEnd
@@ -0,0 +1,42 @@
1
+ <?xml version="1.0" standalone="no"?>
2
+ <svg
3
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
4
+ xmlns:cc="http://creativecommons.org/ns#"
5
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
6
+ xmlns:svg="http://www.w3.org/2000/svg"
7
+ xmlns="http://www.w3.org/2000/svg"
8
+ width="<%= Floorplanner.config['svg']['width'] %>px"
9
+ height="<%= Floorplanner.config['svg']['height'] %>px"
10
+ version="1.1"
11
+ id="svg2">
12
+
13
+ <metadata id="metadata39">
14
+ <rdf:RDF>
15
+ <cc:Work
16
+ rdf:about="">
17
+ <dc:format>image/svg+xml</dc:format>
18
+ <dc:type
19
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
20
+ <dc:title><%= @name %></dc:title>
21
+ <dc:creator>
22
+ <cc:Agent>
23
+ <dc:title><%= @author %></dc:title>
24
+ </cc:Agent>
25
+ </dc:creator>
26
+ <dc:publisher>
27
+ <cc:Agent>
28
+ <dc:title>Floorplanner.com</dc:title>
29
+ </cc:Agent>
30
+ </dc:publisher>
31
+ </cc:Work>
32
+ </rdf:RDF>
33
+ </metadata>
34
+ <g id="areas"><%
35
+ @areas.each do |area| %>
36
+ <polygon points="<%= area.vertices.collect{|v| [(v.x+mod_x)*ratio,(v.y+mod_y)*ratio].join(',')}.join(' ') %>" style="fill:<%= area.data[:color] %>;stroke-width:1;stroke:rgb(100,100,100);stroke-linejoin:round;stroke-dasharray:1, 1;stroke-dashoffset:0"/><% end %>
37
+ </g>
38
+ <g id="walls"><%
39
+ @walls.each do |wall| %>
40
+ <polygon points="<%= wall.outline.vertices.collect{|v| [(v.x+mod_x)*ratio,(v.y+mod_y)*ratio].join(',')}.join(' ') %>" style="fill:<%= wall.data[:color] %>;stroke-width:1;stroke:rgb(0,0,0);stroke-linejoin:round"/><% end %>
41
+ </g>
42
+ </svg>