Hiding small objects at large scales
I have just noticed Thomas Holders metapost sample for hiding small rocks at large scale reductions. http://therion.speleo.sk/wiki/doku.php?id=metapost def l_rockborder (expr p) = if abs(llcorner p - urcorner p) > u: l_rockborder_UIS(p); fi; enddef; I'm guessing the same approach could be used to hide any type of line or area object dependant on the scale, and it looks as though it might be trivially easy to implement, even for someone like me who knows next to nothing about meta post. What would be the chances of this working in the form presented above for point objects? Or for labels as below? def p_label (expr txt,pos,rot,mode) = if abs(llcorner p - urcorner p) > u: p_label_UIS(txt,pos,rot,mode); fi; enddef; Or modified to show or hide point objects depending on the value of the -scale property? Has anyone tried something like this? Bruce
On Wed, Feb 3, 2010 at 10:43 AM, Bruce <dangle@tomo.co.nz> wrote:
I have just noticed Thomas Holders metapost sample for hiding small rocks at large scale reductions.
def l_rockborder (expr p) =
if abs(llcorner p - urcorner p) > u:
l_rockborder_UIS(p);
fi;
enddef;
What would be the chances of this working in the form presented above for point objects?
You would need to use something like if abs(U) > 3pt: p_symbol_UIS(p); fi; where abs(U) means (approximate) distance from the centre of the point symbol to the upper-right corner. The U variable is defined for all (or almost all) point symbols directly in the symbol definition. It means that you would need to implement the test after the U is defined (so you need to change the definition of the original symbol; it would be not enough just to define wrapper symbol like in l_rockborder example). Another possibility is create wrapper symbol which 1) draws the desired symbol in the temporary picture 2) measures the dimensions of temporary picture 3) decides whether to draw the symbol. But this would be quite slow.
Or for labels as below?
The easiest way would be to enhance p_label symbol itself: vardef p_label@#(expr txt,pos,rot,mode) = if (mode=1) or (mode=7): interim labeloffset:=(u/8) fi; lab:=thelabel@#(txt, pos); if abs(llcorner bbox lab - urcorner bbox lab) > u: % here is the size test if mode>1: pickup PenD fi; if mode=1: pickup pencircle scaled (u/6); drawdot(pos); process_label(pos,0); elseif mode=2: process_uplabel; elseif mode=3: process_downlabel; elseif mode=4: process_updownlabel; elseif mode=5: process_circledlabel; elseif mode=6: process_boxedlabel; elseif mode=7: process_label(pos,rot); % station name elseif mode=8: process_filledlabel(pos, rot); else: process_label(pos,rot); fi; fi; % end of size test enddef;
Or modified to show or hide point objects depending on the value of the –scale property?
You can test even for user-defined attributes. martin
Thanks Martin I guess I should try some of these out now. For the p_label example you gave, I can see how the -scale property test would go in the same place as the %size test. Could you give an example of the syntax for the test to print only normal, large and extra large sized labels? Something like... if and(size <> xs, size <> s) [standard label metapost code] fi; Thanks Bruce
The hide small rocks layout really works. Quite nice. Thomas Holders scalebar1 is also very nice, although I can only get it to work at 1:1000. Get error cp-02 for larger and smaller scales.... Not quite sure why, Mostly I'm ensuring the 'as plotted' length of the scalebar is 100mm so it shouldn't be a formatting problem. Still haven't cracked the syntax for label size. Are you going to make me lookup the metapost references :)
if and(size <> xs, size <> s) [standard label metapost code] fi;
Bruce
Hi Bruce,
Thomas Holders scalebar1 is also very nice, although I can only get it to work at 1:1000. Get error cp-02 for larger and smaller scales....
that's strange, it should work at any scale. What is error cp-02 ?
Still haven't cracked the syntax for label size. Are you going to make me lookup the metapost references :)
if and(size <> xs, size <> s) [standard label metapost code] fi;
the label size is not passed to metapost but is controlled with tex macros like \thlargesize. You might achieve what you want like this: code metapost % set xs and s to 1pt verbatimtex \def\thsmallsize{\size[1]} \def\thtinysize{\size[1]} etex % label with minimum text height condition vardef p_label@#(expr txt,pos,rot,mode) = if abs(llcorner txt - ulcorner txt) > 5pt: p_label_orig@#(txt,pos,rot,mode) fi; enddef; % original therion label definition vardef p_label_orig@#(expr txt,pos,rot,mode) = if (mode=1) or (mode=7): interim labeloffset:=(u/8) fi; lab:=thelabel@#(txt, pos); if mode>1: pickup PenD fi; if mode=1: pickup pencircle scaled (u/6); drawdot(pos); process_label(pos,0); elseif mode=2: process_uplabel; elseif mode=3: process_downlabel; elseif mode=4: process_updownlabel; elseif mode=5: process_circledlabel; elseif mode=6: process_boxedlabel; elseif mode=7: process_label(pos,rot); % station name elseif mode=8: process_filledlabel(pos, rot); else: process_label(pos,rot); fi; enddef; endcode It's not very nice and may fail for multiline labels. Cheers, Thomas
% label with minimum text height condition vardef p_label@#(expr txt,pos,rot,mode) = if abs(llcorner txt - ulcorner txt) > 5pt: p_label_orig@#(txt,pos,rot,mode) fi; enddef; Thomas The above does not seem to work. It seems likely to me that the third to last line is missing a ; although adding it does not seem to help that much. The definition p_label_orig does not seem familiar to me. The data.mp file produced by Therion does not contain one of that name, only a p_label. In the above code I changed p_label_orig to p_label (assuming recursive definitions might be OK), but I get an error,
p_label_orig.lft ! Isolated expression.
culminating in "can't open file" and no pdf output. The differences between what you posted and what I have been using are... code metapost fonts_setup(6,8,10,12,16) instead of... % set xs and s to 1pt verbatimtex \def\thsmallsize{\size[1]} \def\thtinysize{\size[1]} etex (first trials are to get it to work when its not hiding any text) I did not define my own p_label_orig (because I assumed the default must already be defined somewhere). If I do define as per your entire example I get different, and perhaps less serious errors, "can't open file" and still no output... [20] [21] [22] [23] [24] [25] (./mptextmp.mp) (./mptextmp.mp) (./mptextmp.mp) (./mptextmp.mp) (./mptextmp.mp) (./mptextmp.mp) (./mptextmp.mp) [26] (Actually these probably are not errors, when I remove this metapost code altogether, they are still logged, and I get a perfect output.) If I run therion in debug mode I get an output with most of the text removed. I'm not sure that it is producing all of the text that should be plotted however. Therion does give a warning condition on exit, and the cavern log file has a red hyperlink suggesting an error has occurred (10> in the following list) 8> 127 numeric registers used out of 32768 9> 10> [1] ) 11> Here is how much of TeX's memory you used: 12> 314 strings out of 95622 13> 3125 string characters out of 1... So, the best I can get is a truncated pdf output if I run Therion in debug mode, regardless of whether any text should be hidden or not. (Actually my data contains wall altitude points - perhaps these are always smaller than 6 points?) Any ideas? Bruce (sorry for the long rambling post)
Hi Bruce,
% label with minimum text height condition vardef p_label@#(expr txt,pos,rot,mode) = if abs(llcorner txt - ulcorner txt) > 5pt: p_label_orig@#(txt,pos,rot,mode) fi; enddef;
Thomas The above does not seem to work. It seems likely to me that the third to last line is missing a ; although adding it does not seem to help that much.
no, the semicolon is not necessary here.
The definition p_label_orig does not seem familiar to me. The data.mp file produced by Therion does not contain one of that name, only a p_label. In the above code I changed p_label_orig to p_label (assuming recursive definitions might be OK), but I get an error,
p_label_orig.lft ! Isolated expression.
recursion on the original p_label definition is not possible, it just gets overwritten. So you need to carry the complete label code when overwriting it, what I did with introducing p_label_orig (you could put it all in the p_label definition, but I tried to separate new code from existing one for clarity).
culminating in "can't open file" and no pdf output.
uhm, now it gets crude. I haven't looked in detail into the code, but a quick inspection led me to this hack: vardef p_label@#(expr txt,pos,rot,mode) = if abs(llcorner txt - ulcorner txt) > 5pt: p_label_orig@#(txt,pos,rot,mode) else: last_write := charcode fi; enddef; Has to do with the temporary file written by write_circ_bbox, which might not be created if the label gets skipped.
The differences between what you posted and what I have been using are...
code metapost fonts_setup(6,8,10,12,16)
instead of... % set xs and s to 1pt verbatimtex \def\thsmallsize{\size[1]} \def\thtinysize{\size[1]} etex
looks good, I just forgot that there was a fonts_setup method ;-)
I did not define my own p_label_orig (because I assumed the default must already be defined somewhere). If I do define as per your entire example I get different, and perhaps less serious errors, "can't open file" and still no output...
see above. In any case you need the p_label_orig. Cheers, Thomas
Thomas
uhm, now it gets crude. I haven't looked in detail into the code, but a quick inspection led me to this hack:
vardef p_label@#(expr txt,pos,rot,mode) = if abs(llcorner txt - ulcorner txt) > 5pt: p_label_orig@#(txt,pos,rot,mode) else: last_write := charcode fi; enddef;
Has to do with the temporary file written by write_circ_bbox, which might not be created if the label gets skipped.
Thanks for those comments. They make sense. Since modifying the code as above I have no errors, but predicting which labels will be hidden becomes harder to predict. For example, considering only single line labels, if ... if abs(llcorner txt - ulcorner txt ) > 3pt: then labels with fonts of 5pt are printed, but not 4.5pt, 3pt or less. This at least is fairly constant, so I imagined there could be a linear scale factor affecting the behaviour. If I use scale 1 2000 and base-scale 1 1000 then the output is less predictable on the basis of font pts alone. All my samples were lower case. If ... if abs(llcorner txt - ulcorner txt ) > 3pt: then labels with fonts of 9pt are always printed, labels with fonts of 8pt are generally printed, labels with fonts of 7 are printed in some cases, and labels with fonts of 6pt are never printed. I am guessing it relates to the specific character size and shape within the label text. Ie p, q, g, ( push the boundaries of the label further than some other characters. So my tentative conclusion is that the test above may hide text smaller than size = 3pt * 1.5 * scale / base-scale, And is certain to hide text with font size = 3pt * scale / base-scale or less. So one needs to set the test limit and font sizes to avoid having too many labels in this 'ambiguous' zone. Rather crude, but it does enable setting up layouts that give fairly automatic text visibility based on scale of the output. Bruce
we should make a dedicated wiki page for scale dependant hiding of objects, including a summary of this email thread. What do you think? Cheers, Thomas
participants (3)
-
Bruce -
Martin Budaj -
Thomas Holder