rendered paste bodyclass V3 attr_accessor :x attr_accessor :y attr_accessor :z def initialize( x, y, z ) self.x = x self.y = y self.z = z end def +( v3 ) V3.new( self.x+v3.x, self.y+v3.y, self.z+v3.z ) end def to_s() "#{x},#{y},#{z}" endendclass Node attr_accessor :ruleId, :parent, :position, :rotation, :scope, :subNodes, :shapeType def initialize( ruleId, parent, shapeType, position=nil, rotation=nil, scope=nil ) self.ruleId = ruleId self.parent = parent self.position = position self.rotation = rotation self.scope = scope self.shapeType = shapeType self.subNodes = [] end def <<( subNode ) self.subNodes << subNode end def to_s() shapeType.to_s() + ":" + ruleId.to_s() + "@(" + position.to_s() + ")(" + scope.to_s() + ")[" + subNodes.to_s() + "]" endendclass Splitendclass Bottom < Splitendclass Top < Splitendclass SubShape attr_accessor :shapeType, :position, :rotation, :scope def initialize( shapeType, position, rotation, scope ) self.shapeType = shapeType self.position = position self.rotation = rotation self.scope = scope endendclass Shape def self.component( splitType, position, rotation, scope ) endendclass Box < Shape def self.componentBottom( position, rotation, scope ) SubShape.new( Rectangle, position, rotation, Scope.new(V3.new(scope.x,scope.y,0)) ) end def self.component( splitType, position, rotation, scope ) [ componentBottom( position, rotation, scope ) ] endendclass Cylinder < Shapeendclass Rectangle < Shapeendclass Rule attr_accessor :id, :condition, :generativeParts, :probability def initialize( id, generativeParts, probability=1 ) self.id = id self.generativeParts = generativeParts self.probability = probability end def apply( node ) generate( node, self.generativeParts, node.position, node.rotation, node.scope ) end def generate( node, generativeParts, position, rotation, scope ) returns = [] generativeParts.each { |generativePart| if generativePart.is_a?(ContextEdit) then (position, rotation, scope) = generativePart.apply( position, rotation, scope ) elsif generativePart.is_a?(Instantiate) then returns << generativePart.apply( position, rotation, scope ) elsif generativePart.is_a?(SubContext) then returns.concat( generate( node, generativePart.generativeParts, position, rotation, scope ) ) elsif generativePart.is_a?(Component) then returns.concat( generativePart.apply( node.shapeType, position, rotation, scope ) ) end } return returns endendclass GenerativePart def apply() endendclass SubContext < GenerativePart attr_accessor :generativeParts def initialize( generativeParts ) self.generativeParts = generativeParts endendclass ContextEdit < GenerativePart attr_accessor :v3 def initialize( v3 ) self.v3 = v3 end def apply( position, rotation, scope ) [ position, rotation, scope ] endendclass Translation < ContextEdit def apply( position, rotation, scope ) [ position+v3, rotation, scope ] endendclass Rotation < ContextEdit def apply( position, rotation, scope ) [ position, rotation+v3, scope ] endendclass Scope < ContextEdit def apply( position, rotation, scope ) [ position, rotation, v3 ] endendclass Component < GenerativePart attr_accessor :splitType attr_accessor :ids def initialize( splitType, ids ) self.splitType = splitType self.ids = ids end def apply( shapeType, position, rotation, scope ) subNode = [] p shapeType shapeType.component( splitType, position, rotation, scope ).each{ |subShape| if ids != [] and ids != nil then id = ids.shift() end subNode << Node.new( id, nil, subShape.shapeType, subshape.position, subShape.rotation, subShape.scope ) } endendclass Instantiate < GenerativePart attr_accessor :shapeType, :id def initialize( shapeType, id ) self.shapeType = shapeType self.id = id end def apply( position, rotation, scope ) Node.new( id, nil, shapeType, position, rotation, scope ) endendclass RulesSet attr_accessor :rules def initialize() self.rules = [] end def <<(rule) self.rules << rule end def apply( node ) self.rules.each{ |rule| if rule.id == node.ruleId then node.subNodes = rule.apply( node ) node.subNodes.each{ |subNode| apply( subNode ) } break end } return node endendrulesSet = RulesSet.new()rulesSet << Rule.new( "root", [Scope.new(V3.new(2,2,2)), SubContext.new([Translation.new(V3.new(1,1,0)), Instantiate.new(Cylinder,"b")]), Instantiate.new(Cylinder,"b")] )rulesSet << Rule.new( "b", [Scope.new(V3.new(1,1,1)), Instantiate.new(Box,"c")] )rulesSet << Rule.new( "c", [Component.new(Bottom,nil)] )root = Node.new( "root", nil, Box, V3.new(0,0,0), V3.new(0,0,0), V3.new(5,5,3) )tree = rulesSet.apply( root )print tree.to_s() + "\n"