geotree 1.1.1 → 1.1.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.txt +4 -2
- data/README.txt +6 -8
- data/lib/geotree/blockfile.rb +0 -28
- data/lib/geotree/geotree.rb +55 -119
- data/lib/geotree/multitree.rb +2 -21
- data/lib/geotree/pswriter.rb +217 -150
- data/lib/geotree/tools.rb +1 -0
- data/test/test_blockfile.rb +1 -1
- data/test/test_externalsort.rb +15 -1
- data/test/test_geotree.rb +24 -7
- data/test/test_ps.rb +1 -1
- metadata +2 -5
- data/lib/fig/geo_tree.pdf +0 -0
- data/lib/fig/multi_tree.pdf +0 -0
    
        data/lib/geotree/multitree.rb
    CHANGED
    
    | @@ -16,7 +16,7 @@ module GeoTreeModule | |
| 16 16 | 
             
              # When querying a MultiTree, the user must specify which level of detail (i.e.,
         | 
| 17 17 | 
             
              # which of the contained trees) is to be examined.   
         | 
| 18 18 | 
             
              #
         | 
| 19 | 
            -
              # | 
| 19 | 
            +
              # {An animation of a MultiTree in action.}[link:http://www.cs.ubc.ca/~jpsember/multi_tree.ps]   
         | 
| 20 20 | 
             
              #
         | 
| 21 21 | 
             
              class MultiTree
         | 
| 22 22 |  | 
| @@ -123,9 +123,7 @@ module GeoTreeModule | |
| 123 123 | 
             
                end
         | 
| 124 124 |  | 
| 125 125 | 
             
                def add_buffered_point(data_point)
         | 
| 126 | 
            -
                   | 
| 127 | 
            -
                  #      db = true
         | 
| 128 | 
            -
             | 
| 126 | 
            +
                  
         | 
| 129 127 | 
             
                  # Determine which is the lowest detail level at which
         | 
| 130 128 | 
             
                  # this point is to be found
         | 
| 131 129 |  | 
| @@ -137,8 +135,6 @@ module GeoTreeModule | |
| 137 135 |  | 
| 138 136 | 
             
                  randval = (wt + stretch*rf) / MAX_POINT_WEIGHT
         | 
| 139 137 |  | 
| 140 | 
            -
                  !db || pr("add pt#%4d  wt%2d  rf=%6.3f rand=%6.3f:  ",data_point.name,wt,rf,randval)
         | 
| 141 | 
            -
             | 
| 142 138 | 
             
                  num_trees.times do |ti|
         | 
| 143 139 | 
             
                    di = num_trees - 1 - ti
         | 
| 144 140 |  | 
| @@ -146,10 +142,8 @@ module GeoTreeModule | |
| 146 142 | 
             
                      break
         | 
| 147 143 | 
             
                    end
         | 
| 148 144 |  | 
| 149 | 
            -
                    !db || pr("  ++ #{di}  ")
         | 
| 150 145 | 
             
                    tree(di).add_buffered_point(data_point)
         | 
| 151 146 | 
             
                  end
         | 
| 152 | 
            -
                  !db || pr("\n")
         | 
| 153 147 | 
             
                end
         | 
| 154 148 |  | 
| 155 149 | 
             
                private
         | 
| @@ -177,16 +171,3 @@ module GeoTreeModule | |
| 177 171 | 
             
              end
         | 
| 178 172 | 
             
            end
         | 
| 179 173 |  | 
| 180 | 
            -
            if main?(__FILE__)
         | 
| 181 | 
            -
              include GeoTreeModule
         | 
| 182 | 
            -
              newdir = File.join(File.dirname(__FILE__),"../../test/workdir")
         | 
| 183 | 
            -
              assert!(File.directory?(newdir))
         | 
| 184 | 
            -
              Dir.chdir(newdir)
         | 
| 185 | 
            -
              remove_file_or_dir("_multitree_")
         | 
| 186 | 
            -
             | 
| 187 | 
            -
              mt = MultiTree.new("_multitree_",3)
         | 
| 188 | 
            -
             | 
| 189 | 
            -
              pts = DataPoint.rnd_many(100)
         | 
| 190 | 
            -
              pts.each{|x| mt.add(x)}
         | 
| 191 | 
            -
             | 
| 192 | 
            -
            end
         | 
    
        data/lib/geotree/pswriter.rb
    CHANGED
    
    | @@ -1,6 +1,22 @@ | |
| 1 1 | 
             
            require_relative 'tools'
         | 
| 2 2 |  | 
| 3 3 | 
             
            module PS_Private
         | 
| 4 | 
            +
              LT_SOLID_ = 1900
         | 
| 5 | 
            +
              LT_DASHED_ = 1901
         | 
| 6 | 
            +
              LT_DOTTED_ = 1902
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              LINEWIDTH_FACTOR_ = 3.0
         | 
| 9 | 
            +
              LINETYPE_ = 1
         | 
| 10 | 
            +
              LINEWIDTH_ = 2
         | 
| 11 | 
            +
              TRANS_ = 3
         | 
| 12 | 
            +
              RGB_ = 4
         | 
| 13 | 
            +
              FONTHEIGHT_ = 5
         | 
| 14 | 
            +
              SCALE_ = 6
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              S_START_ = 0
         | 
| 17 | 
            +
              S_OPEN_ = 1
         | 
| 18 | 
            +
              S_CLOSED_ = 2
         | 
| 19 | 
            +
              
         | 
| 4 20 | 
             
              class SOper
         | 
| 5 21 | 
             
                attr_reader :type
         | 
| 6 22 | 
             
                def self.null
         | 
| @@ -24,35 +40,40 @@ module PS_Private | |
| 24 40 | 
             
              end
         | 
| 25 41 | 
             
            end
         | 
| 26 42 |  | 
| 27 | 
            -
            # A debugging / demonstration utility class that | 
| 43 | 
            +
            # A debugging / demonstration utility class that
         | 
| 28 44 | 
             
            # generates postscript images
         | 
| 29 45 | 
             
            #
         | 
| 30 46 | 
             
            class PSWriter
         | 
| 31 47 | 
             
              include PS_Private
         | 
| 32 48 |  | 
| 33 | 
            -
              LT_SOLID = 1900
         | 
| 34 | 
            -
              LT_DASHED = 1901
         | 
| 35 | 
            -
              LT_DOTTED = 1902
         | 
| 36 | 
            -
             | 
| 37 | 
            -
              LINEWIDTH_FACTOR = 3.0
         | 
| 38 | 
            -
              LINETYPE = 1
         | 
| 39 | 
            -
              LINEWIDTH = 2
         | 
| 40 | 
            -
              TRANS = 3
         | 
| 41 | 
            -
              RGB = 4
         | 
| 42 | 
            -
              FONTHEIGHT = 5
         | 
| 43 | 
            -
              SCALE = 6
         | 
| 44 | 
            -
             | 
| 45 | 
            -
              S_START = 0
         | 
| 46 | 
            -
              S_OPEN = 1
         | 
| 47 | 
            -
              S_CLOSED = 2
         | 
| 48 49 | 
             
              # @param path path of file to write (e.g. xxx.ps)
         | 
| 49 50 | 
             
              def initialize(path)
         | 
| 50 51 | 
             
                @path = path
         | 
| 51 52 | 
             
                @line_width = -1
         | 
| 52 53 | 
             
                @rgb = [-1,0,0]
         | 
| 53 54 | 
             
                @phys_size = [612,792]
         | 
| 54 | 
            -
                @state =  | 
| 55 | 
            +
                @state = S_START_
         | 
| 55 56 | 
             
                @stack = []
         | 
| 57 | 
            +
                @buffer_stack = []
         | 
| 58 | 
            +
                @dict = {}
         | 
| 59 | 
            +
                @dict_keys = []
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                de("A","{arc} bind")
         | 
| 62 | 
            +
                de("CP","{closepath} bind")
         | 
| 63 | 
            +
                de('F','{fill} bind')
         | 
| 64 | 
            +
                de('I','{index} bind')
         | 
| 65 | 
            +
                de("L","{lineto} bind")
         | 
| 66 | 
            +
                de("M","{moveto} bind")
         | 
| 67 | 
            +
                de("NP","{newpath} bind")
         | 
| 68 | 
            +
                de('SRGB','{setrgbcolor} bind')
         | 
| 69 | 
            +
                de('SLW','{setlinewidth} bind')
         | 
| 70 | 
            +
                de('P','{pop} bind')
         | 
| 71 | 
            +
                de("R","{rmoveto} bind")
         | 
| 72 | 
            +
                de("S","{stroke} bind")
         | 
| 73 | 
            +
                de('SCL','{scale} bind')
         | 
| 74 | 
            +
                de('TR','{translate} bind')
         | 
| 75 | 
            +
                de("V","{rlineto} bind")
         | 
| 76 | 
            +
                de("DSH","{setdash} bind")
         | 
| 56 77 |  | 
| 57 78 | 
             
                set_logical_page_size(1000,1200)
         | 
| 58 79 |  | 
| @@ -65,22 +86,45 @@ class PSWriter | |
| 65 86 | 
             
                @s = ''
         | 
| 66 87 | 
             
              end
         | 
| 67 88 |  | 
| 89 | 
            +
              def start_buffer
         | 
| 90 | 
            +
                raise IllegalStateException if !@buffer_stack.empty?
         | 
| 91 | 
            +
                @buffer_stack << @s
         | 
| 92 | 
            +
                @s = ''
         | 
| 93 | 
            +
              end
         | 
| 94 | 
            +
              
         | 
| 95 | 
            +
              def stop_buffer
         | 
| 96 | 
            +
                raise IllegalStateException if @buffer_stack.empty?
         | 
| 97 | 
            +
                ret = @s
         | 
| 98 | 
            +
                @s = @buffer_stack.pop
         | 
| 99 | 
            +
                ret
         | 
| 100 | 
            +
              end
         | 
| 101 | 
            +
              
         | 
| 102 | 
            +
                
         | 
| 68 103 | 
             
              # Close document and write to disk
         | 
| 69 104 | 
             
              def close
         | 
| 70 | 
            -
                if @state <  | 
| 105 | 
            +
                if @state < S_CLOSED_
         | 
| 71 106 | 
             
                  if @stack.size != 0
         | 
| 72 107 | 
             
                    warn("state stack nonempty for #{@path}")
         | 
| 73 108 | 
             
                  end
         | 
| 109 | 
            +
             | 
| 74 110 | 
             
                  flush_page
         | 
| 75 | 
            -
             | 
| 76 | 
            -
                   | 
| 111 | 
            +
             | 
| 112 | 
            +
                  # Construct file by combining header, dictionary, and
         | 
| 113 | 
            +
                  # the user text
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                  s = get_doc_header
         | 
| 116 | 
            +
                  s << get_doc_dictionary
         | 
| 117 | 
            +
                  s << @s
         | 
| 118 | 
            +
                  set_state(S_CLOSED_)
         | 
| 119 | 
            +
             | 
| 120 | 
            +
                  write_text_file(@path, s)
         | 
| 77 121 | 
             
                end
         | 
| 78 122 | 
             
              end
         | 
| 79 123 |  | 
| 80 124 | 
             
              # Set logical page size.  Subsequent drawing operations will be scaled
         | 
| 81 125 | 
             
              # appropriately.  Default logical page size is 1000 x 1200 units.
         | 
| 82 126 | 
             
              def set_logical_page_size( width,  height)
         | 
| 83 | 
            -
                raise IllegalStateException if @state !=  | 
| 127 | 
            +
                raise IllegalStateException if @state != S_START_
         | 
| 84 128 | 
             
                @document_size = [width,height]
         | 
| 85 129 | 
             
              end
         | 
| 86 130 |  | 
| @@ -91,83 +135,103 @@ class PSWriter | |
| 91 135 | 
             
              # Draw a rectangle
         | 
| 92 136 | 
             
              # @param inset distance to inset rectangle boundary (positive: shrink; negative:expand)
         | 
| 93 137 | 
             
              def draw_rect(x,y,w,h,inset = 0)
         | 
| 138 | 
            +
                de("RC","{3 I 3 I M 1 I 0 V 0 1 I V 1 I neg 0 V P P P P CP S }")
         | 
| 94 139 | 
             
                a(x + inset)
         | 
| 95 140 | 
             
                a(y + inset)
         | 
| 96 141 | 
             
                a(w - 2 * inset);
         | 
| 97 142 | 
             
                a(h - 2 * inset);
         | 
| 98 | 
            -
                a(" | 
| 143 | 
            +
                a("RC");
         | 
| 144 | 
            +
                cr
         | 
| 99 145 | 
             
              end
         | 
| 100 146 |  | 
| 101 147 | 
             
              def set_font_size(height)
         | 
| 102 | 
            -
                raise IllegalStateException if @state !=  | 
| 148 | 
            +
                raise IllegalStateException if @state != S_OPEN_
         | 
| 103 149 |  | 
| 104 150 | 
             
                ret = SOper.null
         | 
| 105 151 |  | 
| 106 | 
            -
                if | 
| 107 | 
            -
                  ret = SOper.new( | 
| 152 | 
            +
                if @font_height != height
         | 
| 153 | 
            +
                  ret = SOper.new(FONTHEIGHT_, @font_height)
         | 
| 108 154 | 
             
                  @font_height = height;
         | 
| 109 155 | 
             
                  @scaled_font_height = height / @scale;
         | 
| 110 156 | 
             
                  a("/Monaco findfont ");
         | 
| 111 157 | 
             
                  a(@scaled_font_height);
         | 
| 112 158 | 
             
                  a("scalefont setfont\n");
         | 
| 159 | 
            +
                  cr
         | 
| 113 160 | 
             
                end
         | 
| 114 161 | 
             
                ret
         | 
| 115 162 | 
             
              end
         | 
| 116 163 |  | 
| 117 164 | 
             
              def draw_string(string, x, y)
         | 
| 165 | 
            +
                if @font_height == 0
         | 
| 166 | 
            +
                  set_font_size(28)
         | 
| 167 | 
            +
                end
         | 
| 168 | 
            +
             | 
| 169 | 
            +
                #    /TEXTL { currentpoint S M 0 0 R show } def
         | 
| 170 | 
            +
                #    % Right-justified text
         | 
| 171 | 
            +
                #    /TEXTR { currentpoint S M dup stringwidth pop neg 0 R show } def
         | 
| 172 | 
            +
                #    % Centered text
         | 
| 173 | 
            +
                de("TX", "{currentpoint S M dup stringwidth pop -2 div 0 R show }")
         | 
| 174 | 
            +
             | 
| 118 175 | 
             
                a(x)
         | 
| 119 176 | 
             
                a(y - @scaled_font_height / 2);
         | 
| 120 | 
            -
                a("M | 
| 177 | 
            +
                a("M")
         | 
| 121 178 | 
             
                work = make_eps_safe(string)
         | 
| 122 179 | 
             
                a(work)
         | 
| 123 | 
            -
                a(" | 
| 180 | 
            +
                a("TX")
         | 
| 181 | 
            +
                cr
         | 
| 124 182 | 
             
              end
         | 
| 125 183 |  | 
| 126 | 
            -
              def draw_disc(cx, | 
| 127 | 
            -
                 | 
| 184 | 
            +
              def draw_disc(cx,cy,radius)
         | 
| 185 | 
            +
                de("CF", "{NP 0 360 A CP F}")
         | 
| 128 186 | 
             
                a(cx);
         | 
| 129 187 | 
             
                a(cy);
         | 
| 130 188 | 
             
                a(radius);
         | 
| 131 | 
            -
                a(" | 
| 189 | 
            +
                a("CF")
         | 
| 190 | 
            +
                cr
         | 
| 132 191 | 
             
              end
         | 
| 133 192 |  | 
| 134 193 | 
             
              def draw_circle(cx, cy, radius)
         | 
| 194 | 
            +
                de("CH", "{NP 0 360 A CP S}")
         | 
| 135 195 | 
             
                a("NP");
         | 
| 136 196 | 
             
                a(cx);
         | 
| 137 197 | 
             
                a(cy);
         | 
| 138 198 | 
             
                a(radius);
         | 
| 139 | 
            -
                a(" | 
| 199 | 
            +
                a("CH");
         | 
| 200 | 
            +
                cr
         | 
| 140 201 | 
             
              end
         | 
| 141 202 |  | 
| 142 203 | 
             
              def draw_line(x1,y1,x2,y2)
         | 
| 143 | 
            -
                 | 
| 204 | 
            +
                de("LN", "{NP 4 2 roll M L CP S}")
         | 
| 205 | 
            +
             | 
| 206 | 
            +
                #    a("NP");
         | 
| 144 207 | 
             
                a(x1);
         | 
| 145 208 | 
             
                a(y1);
         | 
| 146 | 
            -
                a(" | 
| 209 | 
            +
                #    a("M");
         | 
| 147 210 | 
             
                a(x2);
         | 
| 148 211 | 
             
                a(y2);
         | 
| 149 | 
            -
                a(" | 
| 212 | 
            +
                a("LN");
         | 
| 213 | 
            +
                cr
         | 
| 150 214 | 
             
              end
         | 
| 151 215 |  | 
| 152 216 | 
             
              def set_line_solid
         | 
| 153 | 
            -
                set_line_type( | 
| 217 | 
            +
                set_line_type(LT_SOLID_)
         | 
| 154 218 | 
             
              end
         | 
| 155 219 |  | 
| 156 220 | 
             
              def set_line_dashed
         | 
| 157 | 
            -
                set_line_type( | 
| 221 | 
            +
                set_line_type(LT_DASHED_)
         | 
| 158 222 | 
             
              end
         | 
| 159 223 |  | 
| 160 224 | 
             
              def set_line_dotted
         | 
| 161 | 
            -
                set_line_type( | 
| 225 | 
            +
                set_line_type(LT_DOTTED_)
         | 
| 162 226 | 
             
              end
         | 
| 163 227 |  | 
| 164 228 | 
             
              def set_scale(f)
         | 
| 165 229 | 
             
                ret = SOper.null
         | 
| 166 230 | 
             
                if   f != 1
         | 
| 167 | 
            -
                  ret = SOper.new( | 
| 231 | 
            +
                  ret = SOper.new(SCALE_, 1.0 / f)
         | 
| 168 232 | 
             
                  a(f);
         | 
| 169 233 | 
             
                  a(f);
         | 
| 170 | 
            -
                  a(" | 
| 234 | 
            +
                  a("SCL");
         | 
| 171 235 | 
             
                end
         | 
| 172 236 | 
             
                ret
         | 
| 173 237 | 
             
              end
         | 
| @@ -175,24 +239,24 @@ class PSWriter | |
| 175 239 | 
             
              def set_line_type(type)
         | 
| 176 240 | 
             
                ret = SOper.null
         | 
| 177 241 | 
             
                if  @line_type != type
         | 
| 178 | 
            -
                  ret = SOper.new( | 
| 242 | 
            +
                  ret = SOper.new(LINETYPE_, @line_type)
         | 
| 179 243 | 
             
                  @line_type = type
         | 
| 180 244 | 
             
                  case type
         | 
| 181 | 
            -
                  when  | 
| 245 | 
            +
                  when LT_DASHED_
         | 
| 182 246 | 
             
                    n =    (@scale * 30).to_i
         | 
| 183 247 | 
             
                    a("[");
         | 
| 184 248 | 
             
                    a(n);
         | 
| 185 249 | 
             
                    a(n);
         | 
| 186 | 
            -
                    a("] 0  | 
| 187 | 
            -
                  when  | 
| 250 | 
            +
                    a("] 0 DSH");
         | 
| 251 | 
            +
                  when LT_DOTTED_
         | 
| 188 252 | 
             
                    int n =    (@scale * 30).to_i
         | 
| 189 253 | 
             
                    n2 = n / 4
         | 
| 190 254 | 
             
                    a("[");
         | 
| 191 255 | 
             
                    a(n2);
         | 
| 192 256 | 
             
                    a(n);
         | 
| 193 | 
            -
                    a("] 0  | 
| 194 | 
            -
                  else #  | 
| 195 | 
            -
                    a("[] 0  | 
| 257 | 
            +
                    a("] 0 DSH");
         | 
| 258 | 
            +
                  else # LT_SOLID_
         | 
| 259 | 
            +
                    a("[] 0 DSH");
         | 
| 196 260 | 
             
                  end
         | 
| 197 261 | 
             
                end
         | 
| 198 262 | 
             
                ret
         | 
| @@ -203,38 +267,39 @@ class PSWriter | |
| 203 267 | 
             
              # @param x translation to apply to coordinates
         | 
| 204 268 | 
             
              # @param y
         | 
| 205 269 | 
             
              def draw_polygon(polygon, x, y)
         | 
| 270 | 
            +
             | 
| 206 271 | 
             
                push(translate(x, y))
         | 
| 207 | 
            -
                a("NP | 
| 272 | 
            +
                a("NP")
         | 
| 208 273 | 
             
                i = 0
         | 
| 209 274 | 
             
                while i < polygon.size
         | 
| 210 275 | 
             
                  a(polygon[i])
         | 
| 211 | 
            -
                  a(' ');
         | 
| 212 276 | 
             
                  a((polygon[i + 1]))
         | 
| 213 277 | 
             
                  if (i == 0)
         | 
| 214 | 
            -
                    a(" | 
| 278 | 
            +
                    a("M");
         | 
| 215 279 | 
             
                  else
         | 
| 216 | 
            -
                    a(" | 
| 280 | 
            +
                    a("L");
         | 
| 217 281 | 
             
                  end
         | 
| 218 282 | 
             
                  i += 2
         | 
| 219 283 | 
             
                end
         | 
| 220 | 
            -
             | 
| 221 | 
            -
                 | 
| 284 | 
            +
                a("CP S")
         | 
| 285 | 
            +
                cr
         | 
| 222 286 | 
             
                pop()
         | 
| 223 287 | 
             
              end
         | 
| 224 288 |  | 
| 225 289 | 
             
              # Translate subsequent drawing operations
         | 
| 226 290 | 
             
              def translate(tx,ty,neg=false)
         | 
| 291 | 
            +
             | 
| 227 292 | 
             
                ret = SOper.null
         | 
| 228 293 | 
             
                if (neg)
         | 
| 229 294 | 
             
                  tx = -tx;
         | 
| 230 295 | 
             
                  ty = -ty;
         | 
| 231 296 | 
             
                end
         | 
| 232 297 | 
             
                if (tx != 0 || ty != 0)
         | 
| 233 | 
            -
                  ret = SOper.new( | 
| 298 | 
            +
                  ret = SOper.new(TRANS_, -tx, -ty)
         | 
| 234 299 |  | 
| 235 300 | 
             
                  a(tx);
         | 
| 236 301 | 
             
                  a(ty);
         | 
| 237 | 
            -
                  a("TR | 
| 302 | 
            +
                  a("TR");
         | 
| 238 303 | 
             
                end
         | 
| 239 304 | 
             
                ret
         | 
| 240 305 | 
             
              end
         | 
| @@ -242,10 +307,11 @@ class PSWriter | |
| 242 307 | 
             
              def set_line_width(w)
         | 
| 243 308 | 
             
                ret = SOper.null
         | 
| 244 309 | 
             
                if @line_width != w
         | 
| 245 | 
            -
             | 
| 310 | 
            +
             | 
| 311 | 
            +
                  ret = SOper.new(LINEWIDTH_, @line_width)
         | 
| 246 312 | 
             
                  @line_width = w
         | 
| 247 | 
            -
                  a( | 
| 248 | 
            -
                  a("SLW | 
| 313 | 
            +
                  a(LINEWIDTH_FACTOR_ * @scale   * @line_width)
         | 
| 314 | 
            +
                  a("SLW");
         | 
| 249 315 | 
             
                end
         | 
| 250 316 | 
             
                ret
         | 
| 251 317 | 
             
              end
         | 
| @@ -253,12 +319,13 @@ class PSWriter | |
| 253 319 | 
             
              def set_rgb(r,g,b)
         | 
| 254 320 | 
             
                ret = SOper.null
         | 
| 255 321 | 
             
                if (r != @rgb[0] || g != @rgb[1] || b != @rgb[2])
         | 
| 256 | 
            -
             | 
| 322 | 
            +
             | 
| 323 | 
            +
                  ret = SOper.new(RGB_, @rgb[0], @rgb[1], @rgb[2])
         | 
| 257 324 | 
             
                  a(r)
         | 
| 258 325 | 
             
                  a(g)
         | 
| 259 326 | 
             
                  a(b)
         | 
| 260 327 | 
             
                  @rgb = [r,g,b]
         | 
| 261 | 
            -
                  a("SRGB | 
| 328 | 
            +
                  a("SRGB");
         | 
| 262 329 | 
             
                end
         | 
| 263 330 | 
             
                ret
         | 
| 264 331 | 
             
              end
         | 
| @@ -270,11 +337,11 @@ class PSWriter | |
| 270 337 | 
             
              def set_state(  s)
         | 
| 271 338 | 
             
                if (@state != s)
         | 
| 272 339 | 
             
                  case s
         | 
| 273 | 
            -
                  when  | 
| 274 | 
            -
                    raise IllegalStateException if @state !=  | 
| 340 | 
            +
                  when S_OPEN_
         | 
| 341 | 
            +
                    raise IllegalStateException if @state != S_START_
         | 
| 275 342 | 
             
                    @state = s
         | 
| 276 | 
            -
                    print_document_header
         | 
| 277 | 
            -
                  when  | 
| 343 | 
            +
                    #        print_document_header
         | 
| 344 | 
            +
                  when S_START_
         | 
| 278 345 | 
             
                    raise IllegalStateException
         | 
| 279 346 | 
             
                  end
         | 
| 280 347 | 
             
                  @state = s
         | 
| @@ -284,7 +351,7 @@ class PSWriter | |
| 284 351 | 
             
              # Start a new page
         | 
| 285 352 | 
             
              # @param page_title title of new page
         | 
| 286 353 | 
             
              def new_page(page_title)
         | 
| 287 | 
            -
                set_state( | 
| 354 | 
            +
                set_state(S_OPEN_);
         | 
| 288 355 | 
             
                flush_page
         | 
| 289 356 |  | 
| 290 357 | 
             
                print_page_header(page_title);
         | 
| @@ -303,39 +370,82 @@ class PSWriter | |
| 303 370 | 
             
                  n = @stack.size   - 1
         | 
| 304 371 | 
             
                  op = @stack.pop
         | 
| 305 372 | 
             
                  case op.type
         | 
| 306 | 
            -
                  when  | 
| 373 | 
            +
                  when RGB_
         | 
| 307 374 | 
             
                    set_rgb(op.arg(0),op.arg(1),op.arg(2))
         | 
| 308 | 
            -
                  when  | 
| 375 | 
            +
                  when LINETYPE_
         | 
| 309 376 | 
             
                    set_line_type(op.arg(0))
         | 
| 310 | 
            -
                  when  | 
| 377 | 
            +
                  when LINEWIDTH_
         | 
| 311 378 | 
             
                    set_line_width(op.arg(0))
         | 
| 312 | 
            -
                  when  | 
| 379 | 
            +
                  when TRANS_
         | 
| 313 380 | 
             
                    translate(op.arg(0),op.arg(1))
         | 
| 314 | 
            -
                  when  | 
| 381 | 
            +
                  when FONTHEIGHT_
         | 
| 315 382 | 
             
                    set_font_size(op.arg(0))
         | 
| 316 | 
            -
                  when  | 
| 383 | 
            +
                  when SCALE_
         | 
| 317 384 | 
             
                    set_scale(op.arg(0))
         | 
| 318 385 | 
             
                  end
         | 
| 319 386 | 
             
                end
         | 
| 320 387 | 
             
              end
         | 
| 321 388 |  | 
| 389 | 
            +
              # Define an element by placing it in the dictionary
         | 
| 390 | 
            +
              def add_element(key,val)
         | 
| 391 | 
            +
                de(key,'{'+val+'}')
         | 
| 392 | 
            +
              end
         | 
| 393 | 
            +
              
         | 
| 394 | 
            +
              def draw_element(key)
         | 
| 395 | 
            +
                val = @dict[key]
         | 
| 396 | 
            +
                raise ArgumentError if !@dict.member?(key)
         | 
| 397 | 
            +
                a(key)
         | 
| 398 | 
            +
              end
         | 
| 399 | 
            +
              
         | 
| 322 400 | 
             
              private
         | 
| 323 401 |  | 
| 402 | 
            +
              def cr
         | 
| 403 | 
            +
                if true
         | 
| 404 | 
            +
                  if @sp_req
         | 
| 405 | 
            +
                    @s << ' '
         | 
| 406 | 
            +
                    @sp_req = false
         | 
| 407 | 
            +
                  end
         | 
| 408 | 
            +
                else
         | 
| 409 | 
            +
                  @sp_req = false
         | 
| 410 | 
            +
                  @s << "\n"
         | 
| 411 | 
            +
                end
         | 
| 412 | 
            +
              end
         | 
| 413 | 
            +
             | 
| 324 414 | 
             
              def a(obj)
         | 
| 415 | 
            +
                if @sp_req
         | 
| 416 | 
            +
                  @s << ' '
         | 
| 417 | 
            +
                end
         | 
| 325 418 | 
             
                if obj.is_a? Numeric
         | 
| 326 419 | 
             
                  if obj.is_a? Float
         | 
| 327 | 
            -
                    w = sprintf(" | 
| 328 | 
            -
                     | 
| 420 | 
            +
                    w = sprintf("%.2f",obj)
         | 
| 421 | 
            +
                    # Trim extraneous leading/trailing zeros
         | 
| 422 | 
            +
             | 
| 423 | 
            +
                    if w[0,2] == '0.'
         | 
| 424 | 
            +
                      w = w[1.. -1]
         | 
| 425 | 
            +
                    elsif w[0,3] == '-0.'
         | 
| 426 | 
            +
                      w[1,1] = ''
         | 
| 427 | 
            +
                    end
         | 
| 428 | 
            +
             | 
| 429 | 
            +
                    j = w.index('.')
         | 
| 430 | 
            +
                    if j
         | 
| 431 | 
            +
                      while w[-1] == '0'
         | 
| 432 | 
            +
                        w = w[0..-2]
         | 
| 433 | 
            +
                      end
         | 
| 434 | 
            +
                      if w[-1] == '.'
         | 
| 435 | 
            +
                        w = w[0..-2]
         | 
| 436 | 
            +
                      end
         | 
| 437 | 
            +
                    end
         | 
| 438 | 
            +
                    @s <<    w
         | 
| 329 439 | 
             
                  else
         | 
| 330 | 
            -
                    @s <<  | 
| 440 | 
            +
                    @s << obj.to_s
         | 
| 331 441 | 
             
                  end
         | 
| 332 442 | 
             
                else
         | 
| 333 | 
            -
                  @s << | 
| 443 | 
            +
                  @s <<   obj
         | 
| 334 444 | 
             
                end
         | 
| 445 | 
            +
                @sp_req = true
         | 
| 335 446 | 
             
              end
         | 
| 336 447 |  | 
| 337 448 | 
             
              def print_page_header(page_title)
         | 
| 338 | 
            -
             | 
| 339 449 | 
             
                # set up transformation
         | 
| 340 450 | 
             
                lMargin = @phys_size[0] * 0.07
         | 
| 341 451 | 
             
                lWorkX = @phys_size[0] - 2 * lMargin
         | 
| @@ -348,10 +458,10 @@ class PSWriter | |
| 348 458 |  | 
| 349 459 | 
             
                a(lcx)
         | 
| 350 460 | 
             
                a(lcy)
         | 
| 351 | 
            -
                a("TR | 
| 461 | 
            +
                a("TR");
         | 
| 352 462 | 
             
                a(scl);
         | 
| 353 463 | 
             
                a(scl);
         | 
| 354 | 
            -
                a("SCL | 
| 464 | 
            +
                a("SCL");
         | 
| 355 465 | 
             
                set_line_width(1);
         | 
| 356 466 | 
             
                set_gray(0);
         | 
| 357 467 |  | 
| @@ -366,46 +476,40 @@ class PSWriter | |
| 366 476 | 
             
                end
         | 
| 367 477 | 
             
              end
         | 
| 368 478 |  | 
| 369 | 
            -
              def  | 
| 370 | 
            -
             | 
| 371 | 
            -
             | 
| 372 | 
            -
             | 
| 373 | 
            -
             | 
| 374 | 
            -
                 | 
| 375 | 
            -
             | 
| 376 | 
            -
             | 
| 377 | 
            -
             | 
| 378 | 
            -
            / | 
| 379 | 
            -
             | 
| 380 | 
            -
            / | 
| 381 | 
            -
             | 
| 382 | 
            -
             | 
| 383 | 
            -
             | 
| 384 | 
            -
            /M {moveto} bind def
         | 
| 385 | 
            -
            /L {lineto} bind def
         | 
| 386 | 
            -
            /R {rmoveto} bind def
         | 
| 387 | 
            -
            /V {rlineto} bind def
         | 
| 388 | 
            -
            % Left-justified text
         | 
| 389 | 
            -
            /TEXTL { currentpoint S M 0 0 R show } def
         | 
| 390 | 
            -
            % Right-justified text
         | 
| 391 | 
            -
            /TEXTR { currentpoint S M dup stringwidth pop neg 0 R show } def
         | 
| 392 | 
            -
            % Centered text
         | 
| 393 | 
            -
            /TEXTC { currentpoint S M dup stringwidth pop -2 div 0 R show } def
         | 
| 394 | 
            -
              
         | 
| 395 | 
            -
            % Plot rectangle at x,y,w,h
         | 
| 396 | 
            -
            /RECT {  3 index 3 index M
         | 
| 397 | 
            -
             1 index 0 V
         | 
| 398 | 
            -
             0 1 index V
         | 
| 399 | 
            -
             1 index neg 0 V
         | 
| 400 | 
            -
             pop pop pop pop CP
         | 
| 401 | 
            -
             S } def
         | 
| 402 | 
            -
            TXT
         | 
| 403 | 
            -
                )
         | 
| 479 | 
            +
              def get_doc_header
         | 
| 480 | 
            +
                h = "%!PS\n"
         | 
| 481 | 
            +
              end
         | 
| 482 | 
            +
             | 
| 483 | 
            +
              def get_doc_dictionary
         | 
| 484 | 
            +
                s = ''
         | 
| 485 | 
            +
                @dict_keys.each do |k|
         | 
| 486 | 
            +
                  v = @dict[k]
         | 
| 487 | 
            +
                  if v.size
         | 
| 488 | 
            +
                    s << '/' << k << ' ' << v << " def\n"
         | 
| 489 | 
            +
                  else
         | 
| 490 | 
            +
                    s2 << '/' << k << "\n"
         | 
| 491 | 
            +
                  end
         | 
| 492 | 
            +
                end
         | 
| 493 | 
            +
                s
         | 
| 404 494 | 
             
              end
         | 
| 405 495 |  | 
| 496 | 
            +
              def de(key,val)
         | 
| 497 | 
            +
                if !@dict.member? key
         | 
| 498 | 
            +
                  @dict_keys << key
         | 
| 499 | 
            +
                  @dict[key] = val
         | 
| 500 | 
            +
                else
         | 
| 501 | 
            +
                  vexist = @dict[key]
         | 
| 502 | 
            +
                  if vexist != val
         | 
| 503 | 
            +
                    raise ArgumentError,"Attempt to change value for key #{key} to #{val}, was #{vexist}"
         | 
| 504 | 
            +
                  end
         | 
| 505 | 
            +
             | 
| 506 | 
            +
                end
         | 
| 507 | 
            +
              end
         | 
| 508 | 
            +
             | 
| 509 | 
            +
             | 
| 406 510 | 
             
              def flush_page
         | 
| 407 511 | 
             
                if @page_used
         | 
| 408 | 
            -
                   | 
| 512 | 
            +
                  a("showpage")
         | 
| 409 513 | 
             
                  @page_used = false
         | 
| 410 514 | 
             
                end
         | 
| 411 515 | 
             
              end
         | 
| @@ -432,40 +536,3 @@ TXT | |
| 432 536 |  | 
| 433 537 | 
             
            end
         | 
| 434 538 |  | 
| 435 | 
            -
            if __FILE__ == $0
         | 
| 436 | 
            -
             | 
| 437 | 
            -
              poly  = [ 0, 0, 50, 30, 30, 80]
         | 
| 438 | 
            -
             | 
| 439 | 
            -
              w = PSWriter.new("_jeff_.ps")
         | 
| 440 | 
            -
             | 
| 441 | 
            -
              w.set_logical_page_size(1000, 1000)
         | 
| 442 | 
            -
              10.times do |i|
         | 
| 443 | 
            -
             | 
| 444 | 
            -
                w.new_page("example page #{i}" )
         | 
| 445 | 
            -
             | 
| 446 | 
            -
                w.draw_disc(200, 700, 200 - i * 18)
         | 
| 447 | 
            -
                w.draw_circle(700, 220, 10 + i * 5);
         | 
| 448 | 
            -
             | 
| 449 | 
            -
                w.push(w.set_gray(0.8));
         | 
| 450 | 
            -
                w.draw_disc(500, 500, 30 + i * 10);
         | 
| 451 | 
            -
                w.pop();
         | 
| 452 | 
            -
                w.push(w.set_line_width(3));
         | 
| 453 | 
            -
                w.push(w.set_line_dashed());
         | 
| 454 | 
            -
                w.draw_circle(500, 500, 30 + i * 10);
         | 
| 455 | 
            -
                w.pop(2);
         | 
| 456 | 
            -
             | 
| 457 | 
            -
                w.draw_line(20 + i * 10, 20, 980, 500 + i * 48);
         | 
| 458 | 
            -
                w.push(w.set_line_width(1.2   + 0.3   * i));
         | 
| 459 | 
            -
                w.push(w.translate(500 - i * 40, 500 - i * 40));
         | 
| 460 | 
            -
                w.push(w.set_scale(1 + i * 0.7));
         | 
| 461 | 
            -
                w.draw_polygon(poly, 0, 0);
         | 
| 462 | 
            -
                w.pop(3);
         | 
| 463 | 
            -
             | 
| 464 | 
            -
                w.push(w.set_rgb(1, 0.2, 0.2));
         | 
| 465 | 
            -
                w.push(w.set_font_size(10 + i * 3));
         | 
| 466 | 
            -
                w.draw_string("Hello", 10 + i * 30, 900 - i * 40);
         | 
| 467 | 
            -
                w.pop();
         | 
| 468 | 
            -
                w.pop();
         | 
| 469 | 
            -
              end
         | 
| 470 | 
            -
              w.close();
         | 
| 471 | 
            -
            end
         |