metapost

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Next revisionBoth sides next revision
metapost [2019/06/09 09:25] – [Scalebars] Add Scalebar 3 brucemuttonmetapost [2019/11/30 08:05] – Better anchor point tarquinwj
Line 297: Line 297:
   enddef;   enddef;
  
-===P-hangers that face the right way===+===P-hangers that face the right way, and other anchor designs===
  
 The default "anchor" symbol takes up a lot of space. It also resists rotation. This produces a P-hanger icon instead. It respects rotation, so that if the "orientation" arrow points to the right, the P-hanger will point in the chosen direction. In addition, it selects the correct direction to face, so that the loop of the hanger always points down the page. It intentionally has a thinner line pointing into the rock, so that it appears to pierce the wall of the cave (just like a real P-hanger). The default "anchor" symbol takes up a lot of space. It also resists rotation. This produces a P-hanger icon instead. It respects rotation, so that if the "orientation" arrow points to the right, the P-hanger will point in the chosen direction. In addition, it selects the correct direction to face, so that the loop of the hanger always points down the page. It intentionally has a thinner line pointing into the rock, so that it appears to pierce the wall of the cave (just like a real P-hanger).
 +
 +In elevation view, by default it switches to being a filled circle, a standard symbol for a fixed position hanger, which can be placed on the linepoints of a basic rope line.
 +
 +By using the "-attr type" option, you can control which type of anchor it will show:
 +* "-attr type auto" (default) shows a P-hanger (like "p") in plan view, and a filled circle in elevation view.
 +* "-attr type p" shows a P-hanger in either plan or elevation view - the control point is at the place where a P-hanger meets the wall, not where the rope meets the hanger.
 +* "-attr type ropedp" the same as "p" but the control point is at the place where the hanger meets the rope - this can be more useful for showing it with ropes attached.
 +* "-attr type fixed" shows a filled circle in either plan or elevation view.
 +* "-attr type natural" shows an empty circle in either plan or elevation view, a common symbol for "natural belay" - note that this circle is filled with the scrap background colour in order to obscure any ropes, though this may look odd if placed outside the cave.
  
 <code> <code>
 code metapost code metapost
-  % a P-hanger+ 
 +  % store the original clean_legend_box 
 +  boolean p_anchor_MY_inlegend; 
 +  p_anchor_MY_inlegend:=false; 
 +  let p_anchor_MY_legend_box = clean_legend_box; 
 +  % redefine clean_legend_box to store the flag, then run the original 
 +  def clean_legend_box = 
 +    p_anchor_MY_inlegend:=true; 
 +    p_anchor_MY_legend_box; 
 +  enddef; 
 + 
 +  % a P-hanger, fixed point or natural circle
   def p_anchor_MY (expr P,R,S,A)=   def p_anchor_MY (expr P,R,S,A)=
-    U:=(.25u,.4u); +    if p_anchor_MY_inlegend
-    T:=identity aligned A rotated R scaled S shifted P+      % this is the legend - make sure the function works normally again 
-    thick part sticking out of the rock +      p_anchor_MY_inlegend:=false
-    thdraw (0,0)--(0,.4uwithpen PenB withcolor black+      draw a pretty legend - show all possibilities 
-    % thin part in the rock +      string ATTR_type; 
-    thdraw (0,-.2u)--(0,0) withpen PenC withcolor black+      ATTR_type:="p"; 
-    % the loop should hang down the "page", based on the rotation +      p_anchor_MY((.2,.57inscale,270,1,(0,0)); 
-    if (R > 0) and (R < 180)+      ATTR_type:="fixed"; 
-      Facing:=-1+      p_anchor_MY((.5,.5inscale,0,1,(0,0))
 +      ATTR_type:="natural"; 
 +      p_anchor_MY((.7,.5inscale,0,1,(0,0));
     else:     else:
-      Facing:=1+      begingroup; 
 +        save type, facing; 
 +        T:=identity aligned A rotated R scaled S shifted P; 
 +        string type; 
 +        if known ATTR_type: 
 +          type:=ATTR_type; 
 +        else: 
 +          type:="auto"; 
 +        fi; 
 +        if (type = "natural"): 
 +          U:=(.2u,.2u); 
 +          PenCThick:=(0.5u/10S); % thickness of PenC - pen thicknesses do not scale with S 
 +          % fill with background colour, to remove any rope lines going through the point 
 +          % this does not respect opacity, but there is no other way to remove lines from other objects 
 +          % clipping currentpicture does not work, since ropes are always drawn last, then layered beneath point symbols 
 +          thunfill fullcircle scaled (0.4u-PenCThick); 
 +          thdraw fullcircle scaled (0.4u-PenCThick) withpen PenC; 
 +        else: 
 +          if (type = "fixed") or (ATTR__elevation and (type = "auto")): 
 +            U:=(.2u,.2u); 
 +            thfill fullcircle scaled 0.4u; 
 +          else: 
 +            if (R > 0) and (R < 180): 
 +              facing:=-1 
 +            else: 
 +              facing:=1 
 +            fi; 
 +            if (type = "ropedp"): 
 +              T:=identity shifted (facing*-0.25u,-0.25u) aligned A rotated R scaled S shifted P; 
 +            fi; 
 +            U:=(.25u,.4u); 
 +            % thick part sticking out of the rock 
 +            thdraw (0,0)--(0,.4u) withpen PenB; 
 +            % thin part in the rock 
 +            thdraw (0,-.2u)--(0,0) withpen PenC; 
 +            % the loop should hang down the "page", based on the rotation 
 +            % stubs to hold the semicircle 
 +            thdraw (0,.1u)--(facing*.1u,.1u) withpen PenB; 
 +            thdraw (0,.4u)--(facing*.1u,.4u) withpen PenB; 
 +            % semicircle 
 +            thdraw halfcircle scaled .3u rotated (facing*-90) shifted (facing*.1u,.25u) withpen PenB; 
 +          fi; 
 +        fi; 
 +      endgroup;
     fi;     fi;
-    % stubs to hold the semicircle 
-    thdraw (0,.1u)--(Facing*.1u,.1u) withpen PenB withcolor black; 
-    thdraw (0,.4u)--(Facing*.1u,.4u) withpen PenB withcolor black; 
-    % semicircle 
-    thdraw halfcircle scaled .3u rotated (Facing*-90) shifted (Facing*.1u,.25u) withpen PenB withcolor black; 
   enddef;   enddef;
   initsymbol("p_anchor_MY");   initsymbol("p_anchor_MY");
Line 1050: Line 1110:
 Blocks shown as produced by default settings, at about half scale. Blocks shown as produced by default settings, at about half scale.
  
-Various things could be improved, the drawing of the different sided boulders, and calling of thclean qq; three times to stop transparency cannot be the best way.+The grid is made of horizontal and vertical grids, but due to the way the starting regular polygon is derived the starting point is always top middle, this makes no randomness makes the squares come out at 45°
  
-**Code for blocks, Variables can be amended at the start** +Various things could be improved. 
-    initsymbol("a_blocks_BCA"); + 
-     +The settings can no be overridden by using <code>-attr</code> 
-    def a_blocks_BCA (expr p) = +on each area, therefore having different types and density of blocks in different areas. 
-  T:=identity; + 
-  symbol_distance:=0.7; % Distance between the blocks as set out in a rectangular grid +overlap <''true|false''>\\ 
-  block_randomisation:=0.7; % Max each point of the base block can be moved. Too big and they can intersect themselves +Do the blocks overlap the borderif false an attempt is made to shink the block until it is inside or out\\ 
-  base_rotation:= 0; % Rotation from 0 of base block, can be used to set all blocks to the same angle +Default false\\ 
-  random_rotation:= 360; % Rotation either side of base rotation eg 20 will be plus or minus 10 each side + 
-  min_scale_factor:=0.7; % Minimum multiplier used for the base shape +separation <''number''>\\ 
-  add_scale_factor:= 0.6; % Added to the minimum multiplier to get the maximum scale +Proportion to the size of separation of centres of the blocks as set out in a rectangular grid\\ 
-  block_rectangle:=1.5; % How much longer the block is than it is wide, before randomising +Default 0.7\\ 
-  shift_randomisation:=0.75; % Max random amount block can be moved from the original grid + 
-  %Now set the proportions of different sided block +block_random <''number''>\\ 
-  b_tri:=1; +Max each point of the base block can be moved. Too big and they can intersect themselves\\ 
-  b_quad:=3; +Default 0.7\ 
-  b_pent:=4; + 
-  b_hex:=2; +base_rotation <''number''>
-  pickup PenC; +Rotation from 0 of base block, can be used to set all blocks to the same angle, not relavant if random rotation is set to 360\\ 
- path q, regular, qq; q = bbox p; +Default 0\\ 
- pair outside; + 
- outside:= ulcorner q + up; +random_rotation <''number''>\\ 
- picture tmp_pic;  +Rotation either side of base rotation eg 20 will be plus or minus 10 each side\\ 
- uu := max(u, (xpart urcorner q - xpart llcorner q)/100, (ypart urcorner q - ypart     llcorner q)/100); +Default 360\\ 
- iu := uu * block_rectangle+ 
- blocks := b_tri+b_quad + b_pent + b_hex; +min_scale <''number''>\\ 
- tmp_pic := image( +Minimum multiplier used for the base shape\\ 
-    for i = xpart llcorner q step symbol_distance block_rectangle * uu until xpart urcorner q: +Default 0.7\\ 
-       for j = ypart llcorner q step symbol_distance*uu until ypart urcorner q: + 
-         pick_sides := uniformdeviate(blocks); +max_scale <''number''>\\ 
-         if pick_sides < b_tri: +Added to the minimum multiplier to get the maximum scale\\ 
-         sides:=3; +Default 0.6\\ 
-         elseif pick_sides < b_tri + b_quad: + 
-         sides:=4+aspect <''number''>\\ 
-         elseif pick_sides < b_tri + b_quad +b_pent: +How much longer the block is than it is wide, before randomising\\ 
-         sides:=5; +Default 1.5\\ 
-         else: + 
-         sides:=6 +shift_random <''number''>\\ 
-         fi; +Max random amount block can be moved from the original grid\\ 
-   +Deafult 0.75\\ 
-           qq :=  for n:=0 upto sides-1: + 
-                   ((cosd(360*n/sides))*iu/2,(sind(360*n/sides))*uu/2) --  +shapes <''number,number,number,number''>\\ 
-                             endfor cycle%radius is 0.5 divide by 2 +Set the ratio of different sided block, triangle, square, pentagon, hexagon. Must be single digits\\ 
-           qq := punked ((qq)  +Default 1,3,4,2 
-           randomized (block_randomisation * uu)) + 
-           scaled (uniformdeviate(add_scale_factor)+min_scale_factor) + 
-           rotated (base_rotation + random_rotation / 2 - uniformdeviate(random_rotation) ) +**Code for blocks** 
-           shifted ((i,j) randomized (shift_randomisation * uu)); +<code> 
-           +initsymbol ("a_blocks_BCA"); 
-           + 
-           forever: % Repeatedly reduces the size of the image, as this is done round zero it also moves it to the zero location, until it fits in the area +def a_blocks_BCA (expr p) = 
-            exitif xpart (p intersectiontimes qq) < 0; + T:=identity; 
-            qq:= qq scaled (0.99 ); + 
-           endfor; +%Derived from one of the built in blocks symbols 
-             if pointinside((i,j),p,outside): % Cleans lines on border, assumably ones outside with jut an edge touching +%No error checking on the attr so can break badly 
-                thclean qq; +% Andrew Atkinson 2019 
-                thclean qq; + 
-                thclean qq; +%Do the blocks overlap the border, if false an attempt is made to shink the block until it is inside or out 
-                thclean qq; +boolean overlap; 
-                thdraw qq; +overlap:= 
-             fi; +if known ATTR_overlap: scantokens(ATTR_overlap) 
-       endfor;   +else: false fi; 
-    endfor; + 
- ); +Proportion to the size of separation of centres of the blocks as set out in a rectangular grid 
-  clip tmp_pic to p; +%FIXME: Really need to check if it is number and not zero in for some cases 
-  drawoptions(); +separation:=  
-  draw tmp_pic; +if known ATTR_separation: scantokens(ATTR_separation) 
- enddef;+else: 0.7 fi; 
 + 
 +% Max each point of the base block can be moved. Too big and they can intersect themselves 
 +block_random:= 
 +if known ATTR_block_random: scantokens(ATTR_block_random); 
 +else: 0.7 
 +fi; 
 + 
 +% Rotation from 0 of base block, can be used to set all blocks to the same angle 
 +base_rotation:= 
 +if known ATTR_base_rotation: scantokens(ATTR_base_rotation) 
 +else: 0 
 +fi; 
 + 
 +% Rotation either side of base rotation eg 20 will be plus or minus 10 each side 
 + 
 +random_rotation:= 
 +if known ATTR_random_rotation: scantokens(ATTR_random_rotation) 
 +else: 360 
 +fi; 
 + 
 +% Minimum multiplier used for the base shape 
 + 
 +min_scale_factor:= 
 +if known ATTR_min_size: scantokens(ATTR_min_size) 
 +else: 0.
 +fi; 
 + 
 +% Added to the minimum multiplier to get the maximum scale 
 +add_scale_factor:= 
 +if known ATTR_max_size: scantokens(ATTR_max_size) 
 +else: 0.
 +fi; 
 + 
 +% How much longer the block is than it is wide, before randomising 
 +aspect:= 
 +if known ATTR_aspect: scantokens(ATTR_aspect) 
 +else: 1.
 +fi; 
 + 
 +% Max random amount block can be moved from the original grid 
 +shift_random:
 +if known ATTR_shift_random: scantokens(ATTR_shift_random) 
 +else: 0.75 
 +fi; 
 + 
 +Set the propotions of different sided block 
 +if known ATTR_shapes: 
 +b_tri:=scantokens substring (0,1) of ATTR_shapes; 
 +b_quad:=scantokens substring (2,3) of ATTR_shapes; 
 +b_pent:=scantokens substring (4,5) of ATTR_shapes; 
 +b_hex:=scantokens substring (6,7) of ATTR_shapes; 
 +else: 
 +b_tri:=1; 
 +b_quad:=3; 
 +b_pent:=4; 
 +b_hex:=2; 
 +fi; 
 + 
 +pickup PenC; 
 +path q, qq; q = bbox p; 
 +pair outside; 
 +outside:= ulcorner q + up; 
 +picture tmp_pic;  
 +uu := max(u, (xpart urcorner q - xpart llcorner q)/100, (ypart urcorner q - ypart     llcorner q)/100); 
 +iu := uu * aspect
 +blocks := b_tri+b_quad + b_pent + b_hex; 
 +tmp_pic := image( 
 +   for i = xpart llcorner q step separation aspect * uu until xpart urcorner q: 
 +      for j = ypart llcorner q step separation*uu until ypart urcorner q: 
 +        pick_sides := uniformdeviate(blocks); 
 + 
 +% This is probably a better way to impliment the different sided blocks calculates the vertices of polygons 
 +%for (i = 0; i < n; i++) { 
 +% printf("%f %f\n",x + r * Math.cos(2 * Math.PI * i / n), y + r * Math.sin(2 * Math.PI * i / n)); 
 +%} 
 + 
 +        if pick_sides < b_tri: 
 +          qq := punked (((.5iu,0)--(-0.25iu,.43uu)--(-.25iu,-0.43uu)--cycle)  
 +          randomized (block_random * uu)) 
 +          scaled (uniformdeviate(add_scale_factor)+min_scale_factor) 
 +         rotated (base_rotation + random_rotation / 2 - uniformdeviate(random_rotation) ) 
 +          shifted ((i,j) randomized (shift_random * uu)); 
 +        elseif pick_sides < b_tri + b_quad: 
 +                    qq := punked (((0.5iu,0)--(0,0.5uu)--(-0.5iu,0)--(0,-0.5uu)--cycle)  
 +          randomized (block_random * uu)) 
 +          scaled (uniformdeviate(add_scale_factor)+min_scale_factor) 
 +         rotated (base_rotation + random_rotation / 2 - uniformdeviate(random_rotation) ) 
 +          shifted ((i,j) randomized (shift_random * uu))
 +         elseif pick_sides < b_tri + b_quad + b_pent: 
 +                    qq := punked (((0.5iu,0)--(.15iu,0.48uu)--(-0.4iu,0.29uu)--(-0.4iu,-0.29uu)--(0.15iu,-0.48uu)--cycle 
 +          randomized (block_random * uu)) 
 +          scaled (uniformdeviate(add_scale_factor)+min_scale_factor) 
 +         rotated (base_rotation + random_rotation / 2 - uniformdeviate(random_rotation) ) 
 +          shifted ((i,j) randomized (shift_random * uu))
 +          else: 
 +          qq := punked (((0.5iu,0)--(0.25iu,0.43uu)--(-0.25iu,0.43uu)--(-0.5iu,0)--(-0.25iu,-0.43uu)--(0.25iu,-0.43uu)--cycle)  
 +          randomized (block_random * uu)) 
 +          scaled (uniformdeviate(add_scale_factor)+min_scale_factor) 
 +          rotated (base_rotation + random_rotation / 2 - uniformdeviate(random_rotation) ) 
 +          shifted ((i,j) randomized (shift_random * uu)); 
 +         fi; 
 +       if not overlap:  
 +          forever: % Repeatedly reduces the size of the image, as this is done round zero it also moves it to the zero location, until it fits in the area 
 +           exitif xpart (p intersectiontimes qq) < 0; 
 +           qq:= qq scaled (0.99 ); 
 +          endfor; 
 +        fi 
 +            if pointinside((i,j),p,outside): 
 +               thclean qq; 
 +               thdraw qq; 
 +             fi; 
 +      endfor;   
 +   endfor; 
 +); 
 + clip tmp_pic to p; %this appears not to be needed as the pointinside removes any outside the area 
 + drawoptions(); % no idea what this does! 
 + draw tmp_pic; 
 +enddef; 
 +</code>
  
 The base_rotation is an attempt to produce bedding plane breakdown, it could do with more time but this is possible The base_rotation is an attempt to produce bedding plane breakdown, it could do with more time but this is possible
Line 1126: Line 1305:
  
 using the settings using the settings
- +<code> 
-  symbol_distance:=0.5; % Distance between the blocks as set out in a rectangular grid +area blocks -attr shapes 1,2,4,7 -attr seperation 0.5 -attr block_random 0.7  -attr base_rotation 20 -attr random_rotation 5 -attr min_scale 0.5 -attr aspect 
-  block_randomisation:=0.7; % Max each point of the base block can be moved. Too big and they can intersect themselves +</code>
-  base_rotation:= 20; % Rotation from 0 of base block, can be used to set all blocks to the same angle +
-  random_rotation:= 5; % Rotation either side of base rotation eg 20 will be plus or minus 10 each side +
-  min_scale_factor:=0.5; % Minimum multiplier used for the base shape +
-  add_scale_factor:= 0.6; % Added to the minimum multiplier to get the maximum scale +
-  block_rectangle:=7; % How much longer the block is than it is wide, before randomising +
-  shift_randomisation:=0.75; % Max random amount block can be moved from the original grid +
-  %Now set the propotions of different sided block +
-  b_tri:=1; +
-  b_quad:=2; +
-  b_pent:=4; +
-  b_hex:=7;+
  
  
  • metapost.txt
  • Last modified: 22 months ago
  • by tarquinwj