Created
January 16, 2026 05:48
-
-
Save miura1729/1732313f77bf31ecefaa80da2f06fd21 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/local/bin/ruby -Ks -w | |
| # -*- coding: cp932 -*- | |
| # -*- mode: ruby; tab-width: 2; -*- | |
| require 'visio' | |
| require 'excelwriter' | |
| require 'config' | |
| $pipe150 = 0 | |
| class List | |
| def initialize(car, cdr) | |
| @car = car | |
| @cdr = cdr | |
| end | |
| def [](n) | |
| c = self | |
| while n > 0 do | |
| n = n - 1 | |
| c = c.cdr | |
| unless c then | |
| raise "Unexpected nil #{self}" | |
| end | |
| end | |
| c.car | |
| end | |
| def to_s | |
| inspect | |
| end | |
| def inspect | |
| "(" + inspect_aux + ")" | |
| end | |
| def inspect_aux | |
| ca = "nil" | |
| cd = "nil" | |
| if @car then | |
| ca = @car.inspect | |
| end | |
| if @cdr then | |
| if @cdr.kind_of?(List) then | |
| cd = @cdr.inspect_aux | |
| elsif @cdr != nil then | |
| cd = @cdr.inspect | |
| else | |
| return ca | |
| end | |
| end | |
| ca + " " + cd | |
| end | |
| attr_accessor :car | |
| attr_accessor :cdr | |
| end | |
| class Reader | |
| def initialize(stream) | |
| @stream = stream | |
| end | |
| def skip_space | |
| while /\s/ =~ (ch = @stream.read(1)) do | |
| if ch == nil then | |
| return nil | |
| end | |
| end | |
| return ch | |
| end | |
| def get_next_token | |
| ch = skip_space | |
| if ch == ';' then | |
| @stream.gets | |
| ch = skip_space | |
| end | |
| if ch == '"' then | |
| token = '' | |
| while ch = @stream.read(1) do | |
| if ch == '"' then | |
| break | |
| end | |
| token <<= ch | |
| end | |
| return token | |
| end | |
| token = ch | |
| while /\S/ =~ (ch = @stream.read(1)) do | |
| if ch == nil then | |
| break | |
| end | |
| if token == '(' then | |
| @stream.ungetc(ch[0]) | |
| break | |
| end | |
| if ch == ')' then | |
| @stream.ungetc(ch[0]) | |
| break | |
| end | |
| token <<= ch | |
| end | |
| if /^-?(([0-9]+)|([0-9]*\.[0-9]+))$/ =~ token then | |
| eval(token) | |
| elsif /^\".*\"$/ =~ token then | |
| eval(token) | |
| else | |
| token | |
| end | |
| end | |
| def read | |
| cl = nil | |
| rt = nil | |
| while tk = get_next_token do | |
| case tk | |
| when '(' | |
| if cl == nil then | |
| cl = List.new(read, nil) | |
| rt = cl | |
| else | |
| cl.cdr = List.new(read, nil) | |
| cl = cl.cdr | |
| end | |
| when ')' | |
| return rt | |
| else | |
| if cl == nil then | |
| cl = List.new(tk, nil) | |
| rt = cl | |
| else | |
| cl.cdr = List.new(tk, nil) | |
| cl = cl.cdr | |
| end | |
| end | |
| end | |
| rt | |
| end | |
| end | |
| class Parser | |
| def parse(tree) | |
| case tree.car | |
| when 'K' | |
| KoukyouMasu.new.parse(tree) | |
| when 'KD' | |
| DropKoukyouMasu.new.parse(tree) | |
| when 'N' | |
| NoneKoukyouMasu.new.parse(tree) | |
| else | |
| raise "公共マスの定義を書きます K (直桝), KD (ドロップ桝) " + | |
| tree.car.to_s | |
| end | |
| end | |
| end | |
| class Geometry | |
| def matle2screen(n) | |
| # Visioはinch単位 | |
| (n / 0.0254) | |
| end | |
| end | |
| class GeoPoint<Geometry | |
| def inside?(min, max) | |
| if (self.x < min.x) or (self.y < min.y) then | |
| return false | |
| end | |
| if (self.x > max.x) or (self.y > max.y) then | |
| return false | |
| end | |
| true | |
| end | |
| def initialize(x, y) | |
| @x = x | |
| @y = y | |
| end | |
| def x | |
| @x | |
| end | |
| def y | |
| @y | |
| end | |
| def scalex | |
| matle2screen(@x) | |
| end | |
| def scaley | |
| matle2screen(@y) | |
| end | |
| def roll(deg, org) | |
| rad = (deg * Math::PI) / 180.0 | |
| tx = (@x - org.x) * Math.cos(rad) - (@y - org.y) * Math.sin(rad) | |
| ty = (@x - org.x) * Math.sin(rad) + (@y - org.y) * Math.cos(rad) | |
| GeoPoint.new(tx + org.x, ty + org.y) | |
| end | |
| def move!(step, angle) | |
| rad = (angle * Math::PI) / 180.0 | |
| @x = @x + step * Math.cos(rad) | |
| @y = @y + step * Math.sin(rad) | |
| end | |
| def move(step, angle) | |
| rad = (angle * Math::PI) / 180.0 | |
| x = @x + step * Math.cos(rad) | |
| y = @y + step * Math.sin(rad) | |
| GeoPoint.new(x, y) | |
| end | |
| def +(point) | |
| GeoPoint.new(@x + point.x, @y + point.y) | |
| end | |
| def -(point) | |
| GeoPoint.new(@x - point.x, @y - point.y) | |
| end | |
| def distance(point) | |
| dx = @x - point.x | |
| dy = @y - point.y | |
| Math.sqrt(dx * dx + dy * dy) | |
| end | |
| def midPoint(point) | |
| GeoPoint.new((@x + point.x) / 2, (@y + point.y) / 2) | |
| end | |
| def join_to_a(*join) | |
| res = [scaley, scalex] | |
| join.each do |n| | |
| res.push n.scaley | |
| res.push n.scalex | |
| end | |
| res.reverse | |
| end | |
| def to_s | |
| "(#{@x}, #{@y})" | |
| end | |
| ORIGIN = GeoPoint.new(0, 0) | |
| end | |
| class RangeSet | |
| def initialize | |
| @ranges = [] | |
| end | |
| def add(range) | |
| min = range[0] | |
| max = range[1] | |
| _add(min, max) | |
| @ranges = @ranges.select {|r| r} | |
| end | |
| def _delete_subset(i, max) | |
| while i < @ranges.size and @ranges[i].last <= max do | |
| @ranges[i] = nil | |
| i = i + 1 | |
| end | |
| if i < @ranges.size and @ranges[i].first <= max then | |
| newmax = @ranges[i].last | |
| @ranges[i] = nil | |
| newmax | |
| else | |
| max | |
| end | |
| end | |
| def _delete_subset2(i, min) | |
| while 0 <= i and @ranges[i].first >= min do | |
| @ranges[i] = nil | |
| i = i - 1 | |
| end | |
| if 0 <= i and @ranges[i].last >= min then | |
| newmin = @ranges[i].first | |
| @ranges[i] = nil | |
| newmin | |
| else | |
| min | |
| end | |
| end | |
| def _add(min, max) | |
| @ranges.each_with_index do |r, i| | |
| if r.first <= min then | |
| if r.last >= min then | |
| if r.last < max | |
| newmax = _delete_subset(i + 1, max) | |
| @ranges[i] = Range.new(r.first, newmax) | |
| end | |
| return | |
| end | |
| else | |
| if r.last <= min then | |
| if r.last < max then | |
| newmax = _delete_subset(i + 1, max) | |
| @ranges[i] = Range.new(min, newmax) | |
| elsif r.first != min then | |
| newmin = _delete_subset2(i - 1, min) | |
| @ranges[i] = Range.new(newmin, r.last) | |
| end | |
| return | |
| end | |
| end | |
| end | |
| @ranges.push(Range.new(min, max)) | |
| @ranges.sort! {|a, b| a.first <=> b.first} | |
| end | |
| def neg(min, max) | |
| cmin = min | |
| ocmin = cmin | |
| cmax = min | |
| res = [] | |
| @ranges.each do |r| | |
| if r.last > max then | |
| if ocmin != cmax then | |
| res.push(Range.new(ocmin, cmax)) | |
| end | |
| return res | |
| end | |
| if r.first > cmax then | |
| cmax = r.first | |
| end | |
| if r.last > cmin then | |
| cmin = r.last | |
| end | |
| if ocmin != cmax then | |
| res.push(Range.new(ocmin, cmax)) | |
| end | |
| ocmin = cmin | |
| end | |
| if ocmin != max then | |
| res.push(Range.new(ocmin, max)) | |
| end | |
| return res | |
| end | |
| def to_s | |
| @ranges | |
| end | |
| end | |
| class VectorBag | |
| def initialize | |
| @parm = [] | |
| @temp = [] | |
| end | |
| def parm_add(vec) | |
| @parm.push vec | |
| end | |
| def temp_add(vec) | |
| @temp.push vec | |
| end | |
| def temp_clear | |
| @temp = [] | |
| end | |
| def temp_pop | |
| @temp.pop | |
| end | |
| def filter(point, len) | |
| res = [] | |
| @parm.each do |v| | |
| if point.distance(v[0]) < len or | |
| point.distance(v[1]) < len then | |
| res.push v | |
| end | |
| end | |
| @temp.each do |v| | |
| if point.distance(v[0]) < len or | |
| point.distance(v[1]) < len then | |
| res.push v | |
| end | |
| end | |
| res | |
| end | |
| end | |
| class Vector | |
| def initialize(p0, p1) | |
| @points = [p0, p1] | |
| end | |
| def [](n) | |
| @points[n] | |
| end | |
| def angle_range(pt) | |
| res = [] | |
| [0, 1].each do |i| | |
| tv = @points[i] - pt | |
| tvl = Math.sqrt(tv.x * tv.x + tv.y * tv.y) | |
| if tvl != 0 then | |
| res.push((Math.atan2(tv.y, tv.x) * 180 / Math::PI) % 360) | |
| end | |
| end | |
| if res.size == 1 then | |
| res = [res[0], res[0]] | |
| end | |
| if res.size == 0 then | |
| return [] | |
| end | |
| if res[0] > res[1] then | |
| if res[0] - res[1] > 180 then | |
| res = [[0, res[1]], [res[0], 360]] | |
| else | |
| res = [[res[1], res[0]]] | |
| end | |
| else | |
| if res[1] - res[0] > 180 then | |
| res = [[0, res[0]], [res[1], 360]] | |
| else | |
| res = [[res[0], res[1]]] | |
| end | |
| end | |
| res | |
| end | |
| end | |
| module AngleResolver | |
| @@vector_bag = VectorBag.new | |
| def init_resolver | |
| collect_vector | |
| compute_label_angle(nil) | |
| end | |
| def label_angle | |
| if not(defined? @label_angle) or @label_angle == nil then | |
| @label_angle = alt_search_free_angle + @angle - 30 | |
| end | |
| @label_angle | |
| end | |
| def add_vector(p1, p2) | |
| @@vector_bag.parm_add(Vector.new(p1, p2)) | |
| end | |
| def collect_vector | |
| addvect | |
| if @enter then | |
| @@vector_bag.parm_add(Vector.new(@enter.pos, @pos)) | |
| end | |
| if self.kind_of?(KoukyouMasu) then | |
| @@vector_bag.parm_add(Vector.new(@pos.move(0.01, @angle + 180), @pos)) | |
| end | |
| @exit.each do |n| | |
| n[1].collect_vector | |
| end | |
| end | |
| # ヒントは上流側のラベルの角度。角度がそろっていたほうが格好いいので | |
| # 出来る限り角度をあわせる。ただし、 | |
| # ・ パイプや他のラベルとぶつかってしまう時 | |
| # ・ ラベル同士がくっついている時 | |
| # はその限りではない。 | |
| def compute_label_angle(hint) | |
| # あまり近い時はヒントがあるとラベルが重なってしまうので | |
| # 無視 | |
| =begin | |
| if @enter_length and @enter_length < 0.5 * (scale / 100) then | |
| hint = nil | |
| end | |
| =end | |
| success = true | |
| @label_angle = nil | |
| newhint = hint | |
| while @label_angle == nil do | |
| if self.kind_of?(NotPrintParts) then | |
| @label_angle = 0 # 0はダミー。nilでなければなんでもいい | |
| else | |
| @label_angle = search_free_angle(hint, collect_disable_angle(scale)) | |
| end | |
| if @label_angle == nil then | |
| # successがfalseになるということはこのテストが1度は通って | |
| # 次で失敗してwhile trueでもう1度戻ってきたって事なので | |
| # 1度目の成功時のpushをpopしてやる。 | |
| if success == false then | |
| @@vector_bag.temp_pop | |
| end | |
| return nil | |
| else | |
| newhint = @label_angle | |
| end | |
| @exit.each do |n| | |
| if n[1].compute_label_angle(newhint) == nil then | |
| success = false | |
| end | |
| end | |
| if success then | |
| return @label_angle | |
| end | |
| end | |
| @label_angle | |
| end | |
| def collect_disable_angle(scale) | |
| va = @@vector_bag.filter(@pos, 5 * (scale / 100)) | |
| # 12pt | |
| # va = @@vector_bag.filter(@pos, 20 * (scale / 100)) | |
| range_set = RangeSet.new | |
| va.each do |n| | |
| ang = n.angle_range(@pos) | |
| ang.each do |a| | |
| range_set.add(a) | |
| end | |
| end | |
| range_set | |
| end | |
| def search_free_angle(hint, range_set) | |
| sz = 0 | |
| wr = nil | |
| free = range_set.neg(0, 360) | |
| free.each do |r| | |
| if hint and r === hint and r.first + 20 < hint and r.last - 20 > hint then | |
| # @@vector_bag.temp_add(Vector.new(@pos.move(5, hint), @pos)) | |
| return hint | |
| end | |
| if sz < r.size | |
| sz = r.size | |
| wr = r | |
| end | |
| end | |
| if sz <= 0 then | |
| return nil | |
| end | |
| ang = (wr.last * 2 + wr.first) / 3 | |
| @@vector_bag.temp_add(Vector.new(@pos.move(5, ang), @pos)) | |
| ang | |
| end | |
| # ベクターアルゴリズムが失敗した時の代替方法 | |
| # 初期のアルゴリズム | |
| # | |
| def alt_search_free_angle | |
| angarr = [180, 360] | |
| @exit.each do |n| | |
| angarr.push n[0] | |
| end | |
| angarr.sort! | |
| if angarr == [0, 180, 360] then | |
| hm = @exit[0][1] | |
| if hm == nil then | |
| return 90 | |
| else | |
| return hm.alt_search_free_angle | |
| end | |
| end | |
| prev = 0 | |
| max = 0 | |
| gang = 0 | |
| angarr.each do |n| | |
| if max < (n - prev) then | |
| max = n - prev | |
| gang = (prev + n) / 2 | |
| end | |
| prev = n | |
| end | |
| gang | |
| end | |
| end | |
| class Range | |
| def size | |
| last - first | |
| end | |
| end | |
| module DrawPrimitive | |
| def set_attr(device, sh) | |
| if enter_pipe_new == "OLD" | |
| device.set_line_attribute(sh, 0.72, 23, 0) | |
| else | |
| device.set_line_attribute(sh, 0.72, 1, 0) | |
| end | |
| end | |
| def draw_line(device, x1, y1, x2, y2) | |
| sh = device.draw_line(x1, y1, x2, y2) | |
| set_attr(device, sh) | |
| sh | |
| end | |
| def draw_oval(device, x1, y1, x2, y2) | |
| sh = device.draw_oval(x1, y1, x2, y2) | |
| set_attr(device, sh) | |
| sh | |
| end | |
| def draw_rectangle(device, x1, y1, x2, y2) | |
| sh = device.draw_rectangle(x1, y1, x2, y2) | |
| set_attr(device, sh) | |
| sh | |
| end | |
| end | |
| module DrawUtil | |
| include DrawPrimitive | |
| def draw_pipelen(device) | |
| if enter_pipe_new == "OLD" then | |
| return | |
| end | |
| midp = @pos.midPoint(@enter.pos) | |
| angle = @angle | |
| if angle >= 180 then | |
| angle = angle - 180 | |
| end | |
| if @enter_length < 0.5 then | |
| # 12pt | |
| # if @enter_length < 2 then | |
| midp.move!(0.2 * scale / 100, angle + 90) | |
| else | |
| midp.move!(0.1 * scale / 100, angle + 90) | |
| end | |
| if @enter_length != 0 then | |
| txtstr = "%.2f" % @enter_length | |
| if @enter_length > 3 and @koubai and @koubai != 0 then | |
| txtstr += " (%s)" % (((@koubai * 1000).to_i)/1000r) | |
| end | |
| device.draw_text(midp.scalex, midp.scaley, txtstr, angle) | |
| end | |
| end | |
| def vanilla_masu_draw(device) | |
| draw_pipelen(device) | |
| if enter_pipe_kind == "ヒューム管" or enter_pipe_kind == "鋼管" then | |
| draw_rectangle(device, @pos.scalex, @pos.scaley, 14, 14) | |
| end | |
| draw_oval(device, @pos.scalex - 5, | |
| @pos.scaley - 5, | |
| @pos.scalex + 5, | |
| @pos.scaley + 5) | |
| if $hdrawf then | |
| text = "No.%s H%2.2f GL %1.1f %s" % [@no, @level + @alevel, @alevel, name] | |
| else | |
| text = "No.%s GL %1.1f %s" % [@no, @alevel, name] | |
| end | |
| draw_label(device, text) | |
| end | |
| def draw_label(device, text) | |
| if enter_pipe_new == "OLD" then | |
| return | |
| end | |
| fangle = label_angle | |
| pos = @pos.move(0.5 * (scale / 100.0), fangle) | |
| tpos = pos.move(2 * (scale / 100.0), fangle) | |
| # 12pt | |
| # pos = @pos.move(2 * (scale / 100.0), fangle) | |
| # tpos = pos.move(8 * (scale / 100.0), fangle) | |
| lin = draw_line(device, pos.scalex, | |
| pos.scaley, | |
| tpos.scalex, | |
| tpos.scaley) | |
| device.set_line_attribute(lin, 0.1, 1, 0) | |
| tpos2 = tpos.move(0.1 * (scale / 100.0), fangle + 90) | |
| txt = device.draw_text(tpos2.scalex, | |
| tpos2.scaley, | |
| text, | |
| fangle) | |
| device.deselect | |
| device.select(txt) | |
| device.select(lin) | |
| device.group | |
| device.deselect | |
| end | |
| def drop_draw(device, size) | |
| x = @pos.scalex | |
| y = @pos.scaley | |
| rad = ((@angle + 180) * Math::PI) / 180.0 | |
| x1 = x + size * Math.cos(rad) | |
| y1 = y + size * Math.sin(rad) | |
| sh = draw_line(device, x, y, x1, y1) | |
| sh.Cells("LinePattern").Formula = "1" | |
| sh.Cells("LineColor").Formula = "1" | |
| (-10..10).each do |i| | |
| r1 = ((@angle + i * 2 + 180) * Math::PI) / 180.0 | |
| r2 = ((@angle + (i + 1) * 2 + 180) * Math::PI) / 180.0 | |
| draw_line(device,x + size * Math.cos(r1), | |
| y + size * Math.sin(r1), | |
| x + size * Math.cos(r2), | |
| y + size * Math.sin(r2)) | |
| end | |
| end | |
| def box_draw(device, xs, ys) | |
| xs2 = xs / 2 | |
| ys2 = ys / 2 | |
| x = @pos.scalex | |
| y = @pos.scaley | |
| rad = ((@angle + 180) * Math::PI) / 180.0 | |
| x1 = x + ys2 * Math.cos(rad) | |
| y1 = y + ys2 * Math.sin(rad) | |
| sh = draw_rectangle(device, x1, y1, xs, ys) | |
| sh.Cells("Angle").Formula = ((@angle + 90) % 360).to_s + " deg" | |
| end | |
| end | |
| module SekisanPipeMainParts | |
| @@used_pipe = Hash.new(0) | |
| def used_pipe | |
| @@used_pipe | |
| end | |
| def sekisan_pipe | |
| if @enter == nil then | |
| return | |
| end | |
| if enter_pipe_size >= 100 then | |
| sekisan_pipe_with_high | |
| else | |
| # sekisan_pipe_without_high | |
| sekisan_pipe_with_high | |
| end | |
| end | |
| def sekisan_pipe_with_high | |
| if @enter_length == 0 then | |
| return | |
| end | |
| edlevel = @enter.level + @enter.alevel | |
| stlevel = @level + @alevel | |
| delta = edlevel - stlevel | |
| length = @enter_length | |
| prelevel = stlevel | |
| curlevel = (stlevel * 5 + 0.9999).to_i / 5.0 | |
| while curlevel + 0.2 < edlevel do | |
| plen = ((length * (curlevel - prelevel)) / delta) | |
| plab = (curlevel).to_s + "■" + enter_pipe_size.to_s + "■" + enter_pipe_kind.to_s | |
| used_pipe[plab] += plen | |
| prelevel = curlevel | |
| curlevel = curlevel + 0.2 | |
| end | |
| if delta == 0 then | |
| plen = length | |
| else | |
| plen = ((length * (edlevel - prelevel)) / delta) | |
| end | |
| plab = curlevel.to_s + "■" + enter_pipe_size.to_s + "■" + enter_pipe_kind.to_s | |
| used_pipe[plab] += plen | |
| end | |
| def sekisan_pipe_without_high | |
| plab = "■" + enter_pipe_size.to_s + "■" + enter_pipe_kind.to_s | |
| used_pipe[plab] += @enter_length | |
| end | |
| end | |
| module TankaCalcDB | |
| CONNECTION_STRING = 'DSN=kyuusui' | |
| def TankaCalcDB.get_cleanup(connect) | |
| proc { | |
| connect.Close | |
| } | |
| end | |
| def initialize | |
| =begin | |
| @connect = WIN32OLE.new "ADODB.Connection" | |
| @connect.Open CONNECTION_STRING | |
| ObjectSpace.define_finalizer(self, TankaCalcDB.get_cleanup(@connect)) | |
| =end | |
| end | |
| def get_tanka(name, spec) | |
| =begin | |
| begin | |
| query = "SELECT price FROM tanka WHERE name='#{name}' AND spec='#{spec}'" | |
| rs = @connect.Execute query | |
| if not rs.Eof then | |
| rt = rs.Fields.Item('price').Value | |
| rs.MoveNext | |
| if not rs.Eof then | |
| raise "価格リストが重複しています #{name} #{spec}" | |
| end | |
| else | |
| rt = nil | |
| end | |
| ensure | |
| rs.Close | |
| end | |
| =end | |
| rt = nil | |
| rt | |
| end | |
| end | |
| class MitumorishoWirter | |
| def write(masu, pipe) | |
| wr_begin | |
| name = File.basename(ARGV[0], ".*") + " 様" | |
| wr_atesaki(name) | |
| wr_masu_begin | |
| masu.keys.sort {|a, b| | |
| si = ((a[1] == b[1]) ? 0 : 1) | |
| a[si] <=> b[si] | |
| }.each do |key| | |
| wr_masu(masu[key], key[0].split(/, /)) | |
| end | |
| wr_masu_end | |
| wr_pipe_begin | |
| pipe.keys.sort.each do |key| | |
| wr_pipe(pipe[key], key) | |
| end | |
| wr_pipe_end | |
| wr_end | |
| end | |
| end | |
| class ExcelMitumorishoWriter<MitumorishoWirter | |
| include TankaCalcDB | |
| def wr_begin | |
| @scan = ExcelScan.new("f:\\KD\\work\\管図面作製プログラム\\mitumori.xls") | |
| @masu_num = 0 | |
| @pipe_num = 0 | |
| end | |
| def wr_atesaki(name) | |
| @scan.set_row(1) | |
| (@scan.rows)[0] = name | |
| end | |
| def wr_masu_begin | |
| @scan.set_row(15) | |
| end | |
| def wr_masu(num, item) | |
| sa = @scan.insert | |
| sa[0] = item[0] | |
| sa[1] = item[1] | |
| sa[2] = num | |
| sa[3] = "ヶ" | |
| if (pri = get_tanka(item[0], item[1])) then | |
| sa[5] = pri | |
| sa[6] = "=RC[-1] * RC[-4]" | |
| end | |
| @masu_num += 1 | |
| end | |
| def wr_masu_end | |
| sa = @scan.insert | |
| sa[0] = "合計" | |
| sa[6] = "=SUM(R[-1]C:R[-#{@masu_num}]C)" | |
| end | |
| def wr_pipe_begin | |
| @scan.insert | |
| @scan.insert | |
| end | |
| def wr_pipe(len, spec) | |
| sa = @scan.insert | |
| name = "排水管" | |
| dpth, psize, pkind = spec.split(/■/) | |
| if dpth == "" then | |
| if pkind == "VU" then | |
| sspec = "φ#{psize}" | |
| else | |
| sspec = "φ#{psize}#{pkind}" | |
| end | |
| else | |
| if pkind == "VU" then | |
| sspec = "φ#{psize}×H#{dpth}~#{dpth.to_f + 0.2}" | |
| else | |
| sspec = "φ#{psize}#{pkind}×H#{dpth}~#{dpth.to_f + 0.2}" | |
| end | |
| end | |
| sa[0] = name | |
| sa[1] = sspec | |
| sa[2] = len | |
| sa[3] = "m" | |
| if (pri = get_tanka(name, sspec)) then | |
| sa[5] = pri | |
| sa[6] = "=RC[-1] * RC[-4]" | |
| end | |
| @pipe_num += 1 | |
| end | |
| def wr_pipe_end | |
| sa = @scan.insert | |
| sa[0] = "合計" | |
| sa[6] = "=SUM(R[-1]C:R[-#{@pipe_num}]C)" | |
| end | |
| def wr_end | |
| end | |
| end | |
| class Parts | |
| include AngleResolver | |
| include DrawUtil | |
| @@scale = 100 | |
| @@used_parts = Hash.new(0) | |
| def scale | |
| @@scale | |
| end | |
| def used_parts | |
| @@used_parts | |
| end | |
| def initialize | |
| @enter = nil | |
| @enter_length = nil | |
| @exit = [] | |
| @pos = nil | |
| @angle = nil | |
| @level = nil | |
| @tori_level = 0 | |
| @alevel = 0 | |
| @koubai = 0.02 # 1/50 | |
| end | |
| attr :pos | |
| attr :level | |
| attr :no | |
| attr_accessor :koubai | |
| def set_position(enter, length, angle) | |
| if $adjust_masulen then | |
| off = GeoPoint.new(length + 0.254 / 2, 0).roll(angle, GeoPoint::ORIGIN) | |
| else | |
| off = GeoPoint.new(length, 0).roll(angle, GeoPoint::ORIGIN) | |
| end | |
| @pos = enter.pos + off | |
| @enter = enter | |
| @enter_length = length | |
| @angle = angle | |
| end | |
| def set_pipe(size, kind, pnew, tlev, alevel) | |
| @pipe_size = size | |
| @pipe_kind = kind | |
| @pipe_new = pnew | |
| @tori_level = tlev | |
| @alevel = alevel | |
| end | |
| attr :pipe_size | |
| attr :pipe_kind | |
| attr :pipe_new | |
| attr :tori_level | |
| attr :alevel | |
| def enter_pipe_size | |
| if @enter then | |
| @enter.pipe_size | |
| else | |
| pipe_size | |
| end | |
| end | |
| def enter_pipe_kind | |
| if @enter then | |
| @enter.pipe_kind | |
| else | |
| pipe_kind | |
| end | |
| end | |
| def enter_pipe_new | |
| if @enter then | |
| @enter.pipe_new | |
| else | |
| pipe_new | |
| end | |
| end | |
| # angle は出の方向,通り方向が0で後は度で指定 | |
| def add_exit(exit, length, angle) | |
| @exit.push [angle, exit] | |
| exit.set_position(self, length, (@angle + angle) % 360) | |
| exit.set_pipe(@pipe_size, @pipe_kind, @pipe_new, @tori_level, @alevel) | |
| exit.calc_level | |
| if @level + @alevel < 0.1 then | |
| print "Recalc executed in #{self}\n" | |
| recalc_level(self, nil, 0) | |
| exit.calc_level | |
| end | |
| end | |
| # 文法 | |
| # 公共マス, KDはドロップマス | |
| # K (上流側深さ 縮尺 [角度]) | |
| # (放流反対側) | |
| # (右側) | |
| # (左側) | |
| # | |
| # インバートマス(チーズを兼ねる) | |
| # I (右) (左) 真っ直ぐ | |
| # | |
| # エルボ (0°にすると直マス) | |
| # L 角度 ... | |
| # | |
| # ドロップマス | |
| # D 角度 ... | |
| # | |
| # 2方向ドロップマス | |
| # DD 角度 (右) (左) | |
| # 角度は真ん中を基準(普通は0) | |
| # | |
| # トラップマス | |
| # T (右) (左) 真っ直ぐ | |
| # | |
| # マスの直後に文字列を書くとラベルの設定 | |
| # この場合は自動採番はされません。 | |
| # 例 I "10-1" () () ... | |
| # | |
| # ラベル | |
| # LABEL 名前(風呂とか洗面とか) | |
| # | |
| # 地盤 (主に用壁で用いる) | |
| # LEVEL 地盤上げ下げ | |
| # | |
| def command2class | |
| { | |
| 'I' => InvertMasu, # 合流マス | |
| 'ID' => DansaMasu, # 段差付合流マス | |
| 'L' => LMasu, # L桝 | |
| 'T' => TrapMasu, # トラップ | |
| 'DT' => DoubleTrapMasu, # ダブルトラップ | |
| 'KT' => KitenTrapMasu, # 起点トラップマス(出の角度を設定できる) | |
| 'D' => DropMasu, # ドロップマス | |
| 'DD' => DoubleDropMasu, # 2方向ドロップマス | |
| 'LABEL' => Label, # ラベル | |
| 'WC' => LabelBennjo, # 1Fトイレ | |
| 'SM' => LabelSenmen, # 洗面 | |
| 'ST' => LabelSentaku, # 洗濯 | |
| 'SS' => LabelSenmenSentaku, # 洗面・洗濯 | |
| 'KI' => LabelDaidokoro, # 台所 | |
| 'BT' => LabelBath, # 風呂 | |
| 'TE' => LabelTearai, # 手洗 | |
| '2FWC' => Label2FBenjo, # 2F便所 | |
| '2FSM' => Label2FSenmen, # 2F洗面 | |
| 'TT' => TTugite, # チーズ継手 マス無し | |
| 'LT' => LTugite, # L継手 マス無し | |
| 'CLT' => CLTugite, # 鋳鉄製L継手 マス無し | |
| 'YT' => YTugite, # Y継手 マス無し | |
| 'CYT' => CYTugite, # 鋳鉄製Y継手 マス無し | |
| 'MC' => MCTugite, # MC継手 | |
| 'LA' => LATugite, # ハイパワー | |
| 'VC' => VCTugite, # VCジョイント | |
| 'KC' => KCTugite, # KCジョイント | |
| 'GB' => GoodBoxMasu, # グッドボックス | |
| 'U' => GoodBoxMasu, # グッドボックス(雨水桝) | |
| 'JO' => Joukasou, # 浄化槽 | |
| 'SO' => Soshuuki, # 阻集器(グリストラップ・ランドリートラップなど) | |
| 'PO' => Pump, # ポンプ | |
| 'PS' => PipeSelect, # パイプ選択 | |
| 'TL' => ToridashiLevel, # 取出しのレベル設定 | |
| 'LEVEL' => Level, # 地盤高設定(相対指定) | |
| 'ALEVEL' => AbsoluteLevel, # 地盤高設定(絶対指定 公共マスを0とする) | |
| 'DummyLMasu' => DummyLMasu, | |
| nil => DummyMasu, # ダミー | |
| } | |
| end | |
| def parse_1direction(tree, angle) | |
| if tree == nil then | |
| return | |
| end | |
| length = tree.car | |
| unless length.is_a?(Numeric) then | |
| raise "ここには管の長さを書いて下さい #{tree} #{length}" | |
| end | |
| rest = tree.cdr | |
| masu = nil | |
| if rest == nil then | |
| masu = DummyMasu.new | |
| else | |
| unless rest.is_a?(List) then | |
| raise "ここには(桝 長さ ...)のリストを書いて下さい #{rest}" | |
| end | |
| masuc = command2class[rest.car] | |
| if masuc then | |
| masu = masuc.new | |
| else | |
| raise "Unkonw Masu #{rest.car}" | |
| end | |
| # マスの名前を設定する | |
| rest2 = rest.cdr | |
| rest2 = masu.parse_masuno(rest2) | |
| # carはマスの名前で多分使わないけど一応残してある | |
| rest = List.new(rest.car, rest2) | |
| end | |
| add_exit(masu, length, angle) | |
| masu.parse(rest) | |
| end | |
| def parse_masuno(tree) | |
| tree | |
| end | |
| def calc_level | |
| if @enter then | |
| @enter.calc_level_after | |
| @level = @enter.level - @enter_length * @koubai | |
| else | |
| @level = 0 | |
| end | |
| end | |
| def calc_level_after | |
| end | |
| def before_recalc_level(sender, prevtl, len) | |
| false | |
| end | |
| def recalc_level(sender, prevtl, len) | |
| if @enter.before_recalc_level(sender, prevtl, len) == false then | |
| @enter.recalc_level(self, prevtl, len + @enter_length) | |
| sender.koubai = @koubai | |
| sender.calc_level | |
| end | |
| end | |
| def before_draw(device) | |
| end | |
| def after_draw(device) | |
| end | |
| def addvect | |
| end | |
| Color_Table = { | |
| 40 => "2", | |
| 50 => "3", | |
| 65 => "4", | |
| 75 => "5", | |
| 100 => "6", | |
| } | |
| def draw(device) | |
| before_draw(device) | |
| # パイプを書く | |
| if @enter then | |
| entpos = @enter.pos | |
| lin = draw_line(device, @pos.scalex, | |
| @pos.scaley, | |
| entpos.scalex, | |
| entpos.scaley) | |
| # p enter_pipe_size | |
| # lin.Cells("LineColor").Formula = Color_Table[enter_pipe_size] | |
| end | |
| @exit.each do |n| | |
| n[1].draw(device) | |
| end | |
| after_draw(device) | |
| end | |
| def sekisan_parts | |
| nil | |
| end | |
| # def sekisan_pipe | |
| # nil | |
| # end | |
| # もし、枝管も集計したいならここのコメントを外して | |
| # sekisan_pipeをコメントアウトする 2004/8/11 | |
| # LevelやTLを考えると全部集計した方が良い | |
| # 枝管だった場合は別の方法で除去する | |
| include SekisanPipeMainParts | |
| def sekisan | |
| if enter_pipe_new == "NEW" then | |
| mname = sekisan_parts | |
| if mname then | |
| used_parts[mname] += 1 | |
| $pipe150 += (@level - 0.1) | |
| end | |
| sekisan_pipe | |
| end | |
| @exit.each do |n| | |
| n[1].sekisan | |
| end | |
| end | |
| end | |
| class MasuCommon<Parts | |
| @@no = 1 | |
| def assign_no | |
| if enter_pipe_new == "NEW" and not defined?(@no) then | |
| @no = @@no | |
| @@no += 1 | |
| end | |
| end | |
| def set_no(n) | |
| @no = n | |
| end | |
| def parse_masuno(tree) | |
| if tree.car.kind_of?(String) then | |
| @no = tree.car | |
| tree.cdr | |
| else | |
| tree | |
| end | |
| end | |
| end | |
| class KoukyouMasu<MasuCommon | |
| def initialize | |
| super | |
| @angle = 0 | |
| @pos = GeoPoint.new(0, 0) | |
| @enter = nil | |
| @pipe_size = 100 | |
| @pipe_kind = $default_material | |
| # @pipe_kind = 'VP' | |
| @pipe_new = 'NEW' | |
| end | |
| def name | |
| "公共マス" | |
| end | |
| include SekisanPipeMainParts | |
| def parse(tree) | |
| info = tree[1] | |
| forward = tree[2] | |
| right = tree[3] | |
| left = tree[4] | |
| if $scale then | |
| @@scale = $scale | |
| else | |
| @@scale = info[1] | |
| end | |
| @level = info[0] | |
| if @level == 0 then | |
| $hdrawf = false | |
| $savedir = $conf_savedir | |
| end | |
| eangle = 0 | |
| if info.cdr.cdr then | |
| @angle = info[2] | |
| if info.cdr.cdr.cdr then | |
| eangle = info[3] | |
| end | |
| end | |
| parse_1direction(forward, eangle) | |
| parse_1direction(right, (eangle + 270) % 360) | |
| parse_1direction(left, (eangle + 90) % 360) | |
| assign_no | |
| self | |
| end | |
| def before_draw(device) | |
| device.set_scale(@@scale) | |
| end | |
| def next_koubai(k) | |
| case k | |
| when 0.02 | |
| 0.015 | |
| when 0.015 | |
| 0.01 | |
| when 0.01 | |
| 0.0075 | |
| when 0.0075 | |
| 0.005 | |
| when 0.005 | |
| 0.0025 | |
| else | |
| k | |
| end | |
| end | |
| def recalc_level(sender, prevtl, len) | |
| if prevtl then | |
| sender.koubai += (prevtl.level - prevtl.tori_level) / len | |
| sender.calc_level | |
| # print "Recalc koubai in koukyo #{@koubai} -> #{sender.koubai}\n" | |
| @koubai = sender.koubai | |
| else | |
| sender.koubai = next_koubai(sender.koubai) | |
| sender.calc_level | |
| print "Recalc executed! #{@koubai} -> #{sender.koubai}\n" | |
| @koubai = sender.koubai | |
| end | |
| end | |
| def after_draw(device) | |
| x = @pos.scalex | |
| y = @pos.scaley | |
| rad = ((@angle + 180) * Math::PI) / 180.0 | |
| x1 = x + 20 * Math.cos(rad) | |
| y1 = y + 20 * Math.sin(rad) | |
| sh = draw_line(device, x, y, x1, y1) | |
| sh.Cells("EndArrowSize").Formula = "2" | |
| sh.Cells("EndArrow").Formula = "1" | |
| draw_oval(device, x - 6, y - 6, x + 6, y + 6) | |
| draw_oval(device, x - 4, y - 4, x + 4, y + 4) | |
| if $hdrawf then | |
| text = "No.%s H%2.2f GL %1.1f %s" % [@no, @level, @alevel, name] | |
| else | |
| text = "No.%s GL %1.1f %s" % [@no, @alevel, name] | |
| end | |
| draw_label(device, text) | |
| sh = device.draw_text(0, 0, "1/#{@@scale}", 0, 12) | |
| # device.set_font(sh, 12) | |
| end | |
| end | |
| class DropKoukyouMasu<KoukyouMasu | |
| def after_draw(device) | |
| super | |
| drop_draw(device, 9) | |
| end | |
| end | |
| class NoneKoukyouMasu<KoukyouMasu | |
| def after_draw(device) | |
| end | |
| end | |
| # 2004/10/5 分岐を90°以外の指定が出来るようにした | |
| # I 角度 右 左 | |
| # 角度が数字のときはノーマルを0としたオフセットとする | |
| # | |
| module TreeWayParser | |
| def eda_size(tree) | |
| if tree then | |
| if tree[0] == 0 and tree[1] == "PS" then | |
| return tree[2].car | |
| end | |
| end | |
| return nil | |
| end | |
| def parse_aux(tree) | |
| angoff = 0 | |
| right = tree[1] | |
| left = tree[2] | |
| forward = tree.cdr.cdr.cdr | |
| # 第1引数が数字ときはoffsetになる | |
| if right.is_a?(Numeric) then | |
| angoff = right | |
| right = tree[2] | |
| left = tree[3] | |
| forward = tree.cdr.cdr.cdr.cdr | |
| end | |
| unless right.is_a?(List) or right == nil then | |
| raise "ここには右分岐のリストを書いて下さい #{tree} " | |
| end | |
| unless left.is_a?(List) or left == nil then | |
| raise "ここには左分岐のリストを書いて下さい #{tree} " | |
| end | |
| if forward == nil then | |
| p tree | |
| end | |
| langle = 0 | |
| if forward and forward.car.is_a?(List) then | |
| langle = forward.car.car | |
| forward = forward.cdr | |
| end | |
| @connected_num = 1 | |
| @connected_num += 1 if forward | |
| @connected_num += 1 if left | |
| @connected_num += 1 if right | |
| parse_1direction(forward, langle) | |
| parse_1direction(left, 90 + angoff) | |
| lsize = eda_size(left) | |
| if lsize then | |
| eda_size = lsize | |
| end | |
| parse_1direction(right, 270 + angoff) | |
| rsize = eda_size(right) | |
| if rsize then | |
| eda_size = rsize | |
| end | |
| eda_size | |
| end | |
| end | |
| class TreeWayMasu<MasuCommon | |
| include TreeWayParser | |
| def parse(tree) | |
| parse_aux(tree) | |
| assign_no | |
| self | |
| end | |
| def connected_num | |
| @connected_num | |
| end | |
| include SekisanPipeMainParts | |
| def sekisan_parts | |
| lstep = ((@level + @alevel) * 5 + 0.9999).to_i / 5.0 | |
| ["#{name}, φ150×#{@pipe_size}×H#{lstep}", lstep] | |
| end | |
| end | |
| class InvertMasu<TreeWayMasu | |
| def name | |
| # "インバートマス" | |
| # "Tマス" | |
| "合流マス" | |
| end | |
| def calc_level | |
| @level = @enter.level - @enter_length * @koubai | |
| end | |
| def after_draw(device) | |
| vanilla_masu_draw(device) | |
| end | |
| end | |
| class DansaMasu<InvertMasu | |
| def name | |
| "合流マス(段差付)" | |
| end | |
| def calc_level | |
| @level = @enter.level - @enter_length * @koubai - 0.05 | |
| end | |
| end | |
| class GoodBoxMasu<TreeWayMasu | |
| def name | |
| "雨水桝" | |
| end | |
| def calc_level | |
| @level = @enter.level - @enter_length * @koubai - 0.05 | |
| end | |
| def after_draw(device) | |
| sh = box_draw(device, 7, 7) | |
| draw_label(device, "雨水桝") | |
| end | |
| end | |
| class TrapMasu<TreeWayMasu | |
| def name | |
| "トラップマス" | |
| end | |
| def after_draw(device) | |
| vanilla_masu_draw(device) | |
| sh = draw_oval(device, @pos.scalex - 1, | |
| @pos.scaley - 1, | |
| @pos.scalex + 1, | |
| @pos.scaley + 1) | |
| sh.Cells("FillPattern").Formula = "1" | |
| sh.Cells("FillBkgnd").Formula = "0" | |
| sh.Cells("FillForegnd").Formula = "0" | |
| end | |
| end | |
| class DoubleTrapMasu<TrapMasu | |
| def name | |
| "ダブルトラップマス" | |
| end | |
| def after_draw(device) | |
| vanilla_masu_draw(device) | |
| rad = ((@angle + 180) * Math::PI) / 180.0 | |
| [1, -1].each do |d| | |
| dx = d * Math::cos(rad) * 2 | |
| dy = d * Math::sin(rad) * 2 | |
| sh = draw_oval(device, @pos.scalex + dx + 0.5, | |
| @pos.scaley + dy + 0.5, | |
| @pos.scalex + dx - 0.5, | |
| @pos.scaley + dy - 0.5) | |
| sh.Cells("FillPattern").Formula = "1" | |
| sh.Cells("FillBkgnd").Formula = "0" | |
| sh.Cells("FillForegnd").Formula = "0" | |
| end | |
| end | |
| end | |
| class KitenTrapMasu<TrapMasu | |
| def parse(tree) | |
| @langle = tree[1] | |
| forward = tree.cdr.cdr | |
| parse_1direction(forward, @langle) | |
| assign_no | |
| self | |
| end | |
| end | |
| class Joukasou<Parts | |
| def name | |
| "浄化槽" | |
| end | |
| include SekisanPipeMainParts | |
| def sekisan_parts | |
| lstep = ((@level + @alevel) * 5 + 0.9999).to_i / 5.0 | |
| ["浄化槽", lstep] | |
| end | |
| def parse(tree) | |
| forward = tree.cdr | |
| parse_1direction(forward, 0) | |
| self | |
| end | |
| def after_draw(device) | |
| box_draw(device, 15, 30) | |
| draw_label(device, "浄化槽") | |
| sh | |
| end | |
| def set_position(enter, length, angle) | |
| off = GeoPoint.new(length + 2, 0).roll(angle, GeoPoint::ORIGIN) | |
| @pos = enter.pos + off | |
| @enter = enter | |
| @enter_length = length | |
| @angle = angle | |
| end | |
| end | |
| class Soshuuki<Parts | |
| def name | |
| @label | |
| end | |
| include SekisanPipeMainParts | |
| def sekisan_parts | |
| lstep = ((@level + @alevel) * 5 + 0.9999).to_i / 5.0 | |
| [@label, lstep] | |
| end | |
| def parse(tree) | |
| @label = tree[1] | |
| forward = tree.cdr.cdr | |
| parse_1direction(forward, 0) | |
| self | |
| end | |
| XS = 15 | |
| YS = 20 | |
| def after_draw(device) | |
| x = @pos.scalex | |
| y = @pos.scaley | |
| sh = draw_rectangle(device, x, y, XS, YS) | |
| sh.Cells("Angle").Formula = ((@angle + 90.0) % 360).to_s + " deg" | |
| xs2 = XS / 2.0 | |
| ys2 = YS / 2.0 | |
| rad = ((@angle + 90) * Math::PI) / 180.0 | |
| x1 = x + xs2 * Math.cos(rad) | |
| y1 = y + xs2 * Math.sin(rad) | |
| sh = draw_line(device, x, y, x1 , y1) | |
| x1 = x - xs2 * Math.cos(rad) | |
| y1 = y - xs2 * Math.sin(rad) | |
| sh = draw_line(device, x, y, x1 , y1) | |
| draw_label(device, @label) | |
| sh | |
| end | |
| end | |
| class Pump<Parts | |
| def name | |
| "ポンプ" | |
| end | |
| include SekisanPipeMainParts | |
| def sekisan_parts | |
| lstep = ((@level + @alevel) * 5 + 0.9999).to_i / 5.0 | |
| [name, lstep] | |
| end | |
| def level | |
| @level + @diff | |
| end | |
| def parse(tree) | |
| @diff = tree[1].to_f | |
| if @diff == 0 then | |
| @diff = 0.5 | |
| end | |
| forward = tree.cdr.cdr | |
| parse_1direction(forward, 0) | |
| self | |
| end | |
| def after_draw(device) | |
| x = @pos.scalex | |
| y = @pos.scaley | |
| draw_oval(device, x - 7, y - 7, x + 7, y + 7) | |
| device.draw_text(x, y, "P", @angle) | |
| draw_label(device, name) | |
| draw_pipelen(device) | |
| end | |
| end | |
| class LMasu<MasuCommon | |
| include SekisanPipeMainParts | |
| def sekisan_parts | |
| lstep = ((@level + @alevel) * 5 + 0.9999).to_i / 5.0 | |
| ["#{name} , φ150×#{@pipe_size}×H#{lstep}", lstep] | |
| end | |
| def name | |
| if @langle == 0 then | |
| "ストレートマス" | |
| else | |
| pan = @langle | |
| if pan > 180 then | |
| pan = 360 - pan | |
| end | |
| if pan < 0 then | |
| pan = -pan | |
| end | |
| "#{pan}° L" | |
| end | |
| end | |
| def parse(tree) | |
| @langle = tree[1] | |
| forward = tree.cdr.cdr | |
| parse_1direction(forward, @langle) | |
| assign_no | |
| self | |
| end | |
| def after_draw(device) | |
| vanilla_masu_draw(device) | |
| end | |
| end | |
| class DropMasu<MasuCommon | |
| include SekisanPipeMainParts | |
| def sekisan_parts | |
| lstep = ((@level + @alevel) * 5 + 0.9999).to_i / 5.0 | |
| ["ドロップマス, φ150×#{@pipe_size}×H#{lstep}", lstep] | |
| end | |
| def name | |
| "ドロップマス" | |
| end | |
| def parse(tree) | |
| parm = tree[1] | |
| @step = nil | |
| if parm.kind_of?(List) then | |
| @step = parm[1] | |
| @langle = parm[0] | |
| else | |
| @langle = parm | |
| end | |
| forward = tree.cdr.cdr | |
| parse_1direction(forward, @langle) | |
| assign_no | |
| self | |
| end | |
| def level | |
| if @step then | |
| @level - @step | |
| else | |
| (@level * 1) / 2 | |
| end | |
| end | |
| def after_draw(device) | |
| drop_draw(device, 7) | |
| vanilla_masu_draw(device) | |
| end | |
| end | |
| class DoubleDropMasu<DropMasu | |
| include SekisanPipeMainParts | |
| def sekisan_parts | |
| lstep = ((@level + @alevel) * 5 + 0.9999).to_i / 5.0 | |
| ["ダブルドロップマス, φ150×#{@pipe_size}×H#{lstep}", lstep] | |
| end | |
| def parse(tree) | |
| @langle = tree[1] | |
| right = tree[2] | |
| left = tree[3] | |
| forward = tree.cdr.cdr.cdr.cdr | |
| parse_1direction(forward, @langle) | |
| parse_1direction(right, @langle - 90) | |
| parse_1direction(left, @langle + 90) | |
| assign_no | |
| self | |
| end | |
| end | |
| class TugiteCommon<Parts | |
| def initialize | |
| @eda_size = nil | |
| super | |
| end | |
| def sekisan_parts | |
| p @eda_size | |
| if @eda_size and enter_pipe_size != @eda_size then | |
| ["#{name}, #{enter_pipe_kind} φ#{enter_pipe_size}×#{@eda_size}", 0] | |
| else | |
| ["#{name}, #{enter_pipe_kind} φ#{enter_pipe_size}", 0] | |
| end | |
| end | |
| def parse(tree) | |
| @label = tree[1] | |
| parse_1direction(tree.cdr, 0) | |
| self | |
| end | |
| def after_draw(device) | |
| if $scale or enter_pipe_size >= 100 then | |
| draw_pipelen(device) | |
| end | |
| if $scale then | |
| draw_label(device, "#{enter_pipe_kind} #{name} φ#{enter_pipe_size}") | |
| end | |
| end | |
| end | |
| class LTugite<TugiteCommon | |
| def name | |
| pan = @langle | |
| if pan > 180 then | |
| pan = 360 - pan | |
| end | |
| if pan < 0 then | |
| pan = -pan | |
| end | |
| "#{pan}°L" | |
| end | |
| def parse(tree) | |
| @langle = tree[1] | |
| forward = tree.cdr.cdr | |
| parse_1direction(forward, @langle) | |
| self | |
| end | |
| end | |
| class CLTugite<LTugite | |
| def name | |
| pan = @langle | |
| if pan > 180 then | |
| pan = 360 - pan | |
| end | |
| if pan < 0 then | |
| pan = -pan | |
| end | |
| "#{pan}°鋳鉄製L" | |
| end | |
| end | |
| class TTugite<TugiteCommon | |
| include TreeWayParser | |
| def parse(tree) | |
| @eda_size = parse_aux(tree) | |
| self | |
| end | |
| def name | |
| "T" | |
| end | |
| end | |
| class YTugite<TugiteCommon | |
| include TreeWayParser | |
| def sekisan_parts | |
| if enter_pipe_size == @eda_size then | |
| ["#{name}, #{enter_pipe_kind} φ#{enter_pipe_size}", 0] | |
| else | |
| ["#{name}, #{enter_pipe_kind} φ#{enter_pipe_size}×#{@eda_size}", 0] | |
| end | |
| end | |
| def name | |
| pan = @langle | |
| if pan > 180 then | |
| pan = 360 - pan | |
| end | |
| if pan < 0 then | |
| pan = -pan | |
| end | |
| "#{pan}°YT" | |
| end | |
| def parse(tree) | |
| @connected_num = 1 | |
| @langle = tree[1] | |
| @eda_size = enter_pipe_size | |
| forwardr = tree.cdr.cdr | |
| forwardl = forwardr.cdr | |
| rest = forwardl.cdr | |
| @connected_num += 1 | |
| parse_1direction(rest, 0) | |
| tree = forwardr.car | |
| if tree then | |
| if tree[0] == 0 and tree[1] == "PS" then | |
| @eda_size = tree[2].car | |
| end | |
| cont = List.new(-@langle + 45, tree) | |
| cont = List.new('DummyLMasu', cont) | |
| cont = List.new(0.1, cont) | |
| parse_1direction(cont, -45) | |
| @connected_num += 1 | |
| end | |
| tree = forwardl.car | |
| if tree then | |
| if tree[0] == 0 and tree[1] == "PS" then | |
| @eda_size = tree[2].car | |
| end | |
| cont = List.new(@langle - 45, tree) | |
| cont = List.new('DummyLMasu', cont) | |
| cont = List.new(0.1, cont) | |
| parse_1direction(cont, 45) | |
| @connected_num += 1 | |
| end | |
| self | |
| end | |
| end | |
| class CYTugite<YTugite | |
| def name | |
| pan = @langle | |
| if pan > 180 then | |
| pan = 360 - pan | |
| end | |
| if pan < 0 then | |
| pan = -pan | |
| end | |
| "#{pan}°鋳鉄製YT" | |
| end | |
| end | |
| class MCTugite<TugiteCommon | |
| def name | |
| "MC" | |
| end | |
| end | |
| class LATugite<TugiteCommon | |
| def name | |
| "LA" | |
| end | |
| end | |
| class KCTugite<TugiteCommon | |
| def name | |
| "KC" | |
| end | |
| end | |
| class VCTugite<TugiteCommon | |
| def name | |
| "VC" | |
| end | |
| end | |
| class NotPrintParts<Parts | |
| end | |
| class Label<NotPrintParts | |
| def parse(tree) | |
| @label = tree[1] | |
| parse_1direction(tree.cdr.cdr, @angle) | |
| self | |
| end | |
| def addvect | |
| off = 0.25 + @label.size * 0.0005 * Math.sin(@angle).abs * scale | |
| pos = @pos.move(off, @angle) | |
| spos = pos.move(-0.15 * @label.size, 0) | |
| epos = pos.move(0.15 * @label.size, 0) | |
| add_vector(spos, epos) | |
| # p @label.size | |
| # p @label | |
| =begin | |
| draw_line(device, spos.scalex, spos.scaley, epos.scalex, epos.scaley) | |
| =end | |
| end | |
| def after_draw(device) | |
| off = 0.25 + @label.size * 0.0005 * Math.sin(@angle).abs * scale | |
| pos = @pos.move(off, @angle) | |
| device.draw_text(pos.scalex, pos.scaley, @label, 0) | |
| # pipelen | |
| # 12pt(枝の寸法が必要なときコメントアウトをとる) | |
| # draw_pipelen(device) | |
| end | |
| end | |
| class FixLabel<Label | |
| def parse(tree) | |
| set_label | |
| parse_1direction(tree.cdr, @angle) | |
| self | |
| end | |
| end | |
| class LabelBennjo<FixLabel | |
| def set_label | |
| @label = "便所" | |
| end | |
| end | |
| class LabelSenmen<FixLabel | |
| def set_label | |
| @label = "洗面" | |
| end | |
| end | |
| class Label2FSenmen<FixLabel | |
| def set_label | |
| @label = "2F洗面" | |
| end | |
| end | |
| class LabelSentaku<FixLabel | |
| def set_label | |
| @label = "洗濯" | |
| end | |
| end | |
| class LabelSenmenSentaku<FixLabel | |
| def set_label | |
| @label = "洗面・洗濯" | |
| end | |
| end | |
| class LabelTearai<FixLabel | |
| def set_label | |
| @label = "手洗" | |
| end | |
| end | |
| class Label2FBenjo<FixLabel | |
| def set_label | |
| @label = "2F便所" | |
| end | |
| end | |
| class LabelDaidokoro<FixLabel | |
| def set_label | |
| @label = "台所" | |
| end | |
| end | |
| class LabelBath<FixLabel | |
| def set_label | |
| @label = "風呂" | |
| end | |
| end | |
| class Level<NotPrintParts | |
| def parse(tree) | |
| # @step = tree[1] | |
| @alevel += tree[1].to_f | |
| parse_1direction(tree.cdr.cdr, 0) | |
| self | |
| end | |
| def after_draw(device) | |
| if $scale or enter_pipe_size >= 100 then | |
| draw_pipelen(device) | |
| end | |
| end | |
| def level | |
| @level | |
| end | |
| def calc_level | |
| @level = @enter.level - @enter_length * @koubai | |
| end | |
| end | |
| class AbsoluteLevel<NotPrintParts | |
| def parse(tree) | |
| @alevel = tree[1].to_f | |
| parse_1direction(tree.cdr.cdr, 0) | |
| self | |
| end | |
| def after_draw(device) | |
| # if $scale or enter_pipe_size >= 100 then | |
| draw_pipelen(device) | |
| # end | |
| end | |
| def calc_level | |
| @level = @enter.level - @enter_length * @koubai | |
| end | |
| end | |
| class PipeSelect<NotPrintParts | |
| def parse(tree) | |
| @old_pipe_size = @pipe_size | |
| pipe = tree[1] | |
| @pipe_size = pipe[0] | |
| p pipe | |
| if pipe.cdr then | |
| @pipe_kind = pipe[1] | |
| if pipe.cdr.cdr then | |
| @pipe_new = pipe[2] | |
| end | |
| end | |
| parse_1direction(tree.cdr.cdr, 0) | |
| self | |
| end | |
| def sekisan_parts | |
| if @old_pipe_size != @pipe_size then | |
| mx = [@old_pipe_size, @pipe_size].max | |
| mn = [@old_pipe_size, @pipe_size].min | |
| ["S, φ#{mx}×#{mn}", 0] | |
| else | |
| nil | |
| end | |
| end | |
| def after_draw(device) | |
| if $scale or enter_pipe_size >= 100 then | |
| draw_pipelen(device) | |
| end | |
| end | |
| end | |
| class ToridashiLevel<NotPrintParts | |
| def parse(tree) | |
| @tori_level = tree[1] | |
| parse_1direction(tree.cdr.cdr, 0) | |
| self | |
| end | |
| attr :tori_level | |
| def calc_level_after | |
| @level = @enter.level - @enter_length * @koubai | |
| if (@level - @tori_level).abs > 0.001 then | |
| @enter.recalc_level(self, self, @enter_length) | |
| end | |
| print "Level: #{@level} #{@tori_level} \n" | |
| end | |
| def before_recalc_level(sender, prevtl, len) | |
| # 取出しレベルが設定されている場合は勾配を細かくあわせる | |
| if prevtl then | |
| print "TORI: #{prevtl.tori_level} #{tori_level} \n" | |
| old = sender.koubai | |
| sender.koubai += (prevtl.level - prevtl.tori_level) / len | |
| sender.calc_level | |
| else | |
| @enter.recalc_level(self, self, len + @enter_length) | |
| sender.koubai = @koubai | |
| sender.calc_level | |
| end | |
| true | |
| end | |
| def after_draw(device) | |
| if $scale or enter_pipe_size >= 100 then | |
| draw_pipelen(device) | |
| end | |
| end | |
| end | |
| class DummyMasu<NotPrintParts | |
| def parse(tree) | |
| self | |
| end | |
| end | |
| class DummyLMasu<NotPrintParts | |
| def parse(tree) | |
| @langle = tree[1] | |
| forward = tree.cdr.cdr | |
| parse_1direction(forward, @langle) | |
| self | |
| end | |
| end | |
| if __FILE__ == $0 then | |
| pa = Parser.new | |
| rt = nil | |
| $default_material = "VU" | |
| $hdrawf = true | |
| $drawf = true | |
| $sekisanf = true | |
| $scale = nil | |
| $sekisansubpipe = false | |
| $adjust_masulen = false | |
| argv = ARGV[0].dup # .force_encoding('cp932') | |
| argv = ARGV[0].dup.encode('cp932') | |
| while (/\"?^(.*)\.ge~?\"?$/ =~ argv) == nil do | |
| case argv | |
| when /--sekisan-sub-pipe/ | |
| # この機能は現在実現されていない。2004/8/11 で検索するといいかも | |
| $sekisansubpipe = true | |
| when /--output-dir=(.*)/ | |
| $savedir = $1 + '/' | |
| when /--no-height-draw/ | |
| $hdrawf = false | |
| when /--no-draw/ | |
| $drawf = false | |
| when /--no-sekisan/ | |
| $sekisanf = false | |
| when /--scale=(\d+)/ | |
| $scale = $1.to_i | |
| when /--adjust-masu-len/ | |
| $adjust_masulen = true | |
| end | |
| ARGV.shift | |
| argv = ARGV[0].dup.encode('cp932', 'utf-8') | |
| # argv = ARGV[0].dup | |
| p argv | |
| end | |
| infile = ARGV[0].dup.encode('cp932', 'utf-8').gsub(/\"/, "") | |
| outfile = File.basename(infile, ".*") + ".vsd" | |
| # outfile.force_encoding('sjis') | |
| # p outfile.encoding | |
| p infile | |
| File.open(infile.encode('utf-8'), "r") do |fp| | |
| rt = pa.parse(Reader.new(fp).read) | |
| end | |
| if $sekisanf then | |
| rt.sekisan | |
| wr = ExcelMitumorishoWriter.new | |
| wr.write(rt.used_parts, rt.used_pipe) | |
| end | |
| if $drawf then | |
| visio = VISIO::VisioDevice.instance | |
| if rt.init_resolver == nil then | |
| print "Wanning --- Label conflict happened. I use naive algorithm.\n" | |
| end | |
| rt.draw(visio) | |
| savef = $savedir + outfile | |
| if test(?e, savef) and File.mtime(infile) < File.mtime(savef) then | |
| savef = savef + "~" | |
| end | |
| p savef | |
| visio.save_as(savef) | |
| end | |
| print $pipe150, "\n" | |
| end # __FILE__ == $0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment