I want to set my XSL:FO to show a border.
What I want to do is to have a dashed style border with 4 dashes: _ _ _ _ (ex1. style dashed; width 1pt ; length 1pt) and set the width to 1 mm without changing the length of the dash
<fo:table-cell
border-before-style="dashed"
border-before-width="1mm"
border-before-width.length="1pt" >
When I use the code above I get (same distance as in example ex1.) - - - - - - - - - - - -
I get smaler dashes in height but also I get more of them!!!!!
We had 4 dashes width 1pt length 1 pt, now when we used the code above and
We have 12 dashes(bad) with width 1mm (which is good) but the length magically changes to 0.1pt as well.
Do you have some ideas?
Related
I am trying to convert the X/Y coordinates from the ^FO command to the equivalent ^FT coordinates in such a way that the position of text in the label does not change for rotated text.
The solution that I am looking for was already addressed partially in a question that I previously asked [link added here] (Is it possible to find equivalent X/Y coordinates in order to print some text at the same position using both ^FO as well as ^FT command using ZPL 2)
I am able to find some equations for different rotations (as stated below for font 0) but I am unsure about the exact formula to be used for converting corresponding Y coordinate for 270 rotation or equivalently X coordinate for 180 rotation:
For 0 rotation:
FOx = FTx and
FOy = FTy - (0.75 * height)
For 90 rotation:
FOx = FTx - (0.25 * height) and
FOy = FTy
For 180 rotation:
FOx = Not found yet and
FOy = FTy - (height * 0.25)
For 270 rotation:
FOx = FTx - (height * 0.75) and
FOy = Not yet found
I guess those missing equations depend on the number of characters in the text to be printed as well as the width of the text but I am not able to find the exact equation.
Any thoughts or suggestions on the finding the same would be greatly appreciated.
The calculation for FOx (180 rotation) would be:
FOx = FTx - text length
and for FOy (270 rotation) would be:
FOy = FTy - text length
Text length for non-monospaced font (font 0) is difficult to calculate since width will vary for different characters.
For monospaced font, the length of text in dots would be calculated for different fonts as per Table 26 (Page #: 1413) in the ZPL Programming guide.
Another useful answer on how to calculate length is answered below:
How to Calculate Zebra Font 0 text width?
I have a dc.js heatmap working:
But I want to add grid lines to it, like so:
You can see that the lines to not match up with the bottom edges of the rects. Inserting the lines themselves is easy, you just start at zero and add 11 lines based on the height of the rects, which in this case will always be 11 / chart.effectiveHeight().
The reason they do not match up, seems to be that the top rect row does not always start at 0, instead, there seems to be a random(?) y position that the chart starts at, this will change with the height of the chart container, eg this y position starts at 5:
If it was consistent, then I could just start appending lines from that number instead of 0, but it is not. I have tried a couple of hacky work arounds, however I am unsure as to how to get the y position of all the rects after they are available in the DOM.
Interestingly the demo heatmap does not have this issue:
Here is the code for the heatmap:
const heat_map = dc.heatMap('#heatmap');
heat_map
.width(0)
.height(0)
.margins(margins)
.dimension(hm_dim)
.group(hm_group)
.keyAccessor(function(d) { return +d.key[0]; })
.valueAccessor(function(d) { return +d.key[1]; })
.colorAccessor(function(d) { return +d.value; })
.colors(color_scale)
.calculateColorDomain()
.yBorderRadius(0)
.xBorderRadius(0)
heat_map.render();
Is there a way to force the rects to begin at 0? Or get the random y position for the top rows? I did have a look at the source code but got a bit lost. Also I thought about creating a false group that would include each rect in the grid, and the grid lines could then be rect borders, but I thought that was a bit heavy handed.
Outlining the cells using CSS
It's easy to outline the cells using CSS:
rect.heat-box {
stroke-width: 1;
stroke: black;
}
Example fiddle.
However, as you point out, this only works if all the cells have values; crossfilter will not create the empty ones and I agree it would be absurd fill them in using a fake group just for some lines.
So, to answer your original question...
Why is there a gap at the top of the chart?
The heatmap calculates an integer size for the cells, and there may be space left over (since the space doesn't divide perfectly).
It's kind of nasty but the heatmap example avoids having extra space by calculating the width and height for the chart using the count of cells in each dimension:
chart
.width(45 * 20 + 80)
.height(45 * 5 + 40)
The default margins are {top: 10, right: 50, bottom: 30, left: 30} so this allocates 45x45 pixels for each cell and adds on the margins to get the right chart size.
Since the heatmap in this example draws 20 columns by 5 rows, it will calculate the cell width and height as 45.
Alternative Answer for Responsive/Resizable Charts
I am revisiting this question after rewriting my heatmap chart to be responsive - using the "ResizeObserver" method outlined in the dc.js resizing examples and Gordon's answer to this question
While specifying the chart width and height for the heatmap in Gordon's answer still works, it does not combine well with the resizing method because resized charts will have their .width and .height set to 'null'. Which means that this rounding issue will reoccur and the heat boxes will be again be offset by a random integer x or y value of anywhere between 0 and 5 (unless you want to write a custom resizing function for heatmaps).
The alternative answer is relatively simple and can be determined by selecting just one heat-box element in the heatmap.
The vertical offset value for the heat boxes is the remainder value when the heat-box y attribute is divided by the heat-box height attribute.
const heatbox_y = heat_map.select('.heat-box').attr('y);
const heatbox_height = heat_map.select('.heat-box').attr('height')
const vertical_offset = heatbox_y % heatbox_height
The modulus % will return the remainder.
The horizontal offset can be determined in the same way.
Thus you can append lines to the chart at regular intervals determined by the heatbox_height + the vertical_offset values.
This will work if you pick any heat-box in the chart, and so it is suitable for instances like this where you cannot guarantee that there will be a heat-box at each x or y level. And it means that you are free to set your chart height and width to 'null' if needed.
I am following this post to make a pie chart using Gnuplot. The only problem with the approach is that I can't align my percentage labels. What am I missing here?
DATA FILE:
"Others" 1.085117e-01 3.904323e-02
"D_o" 2.894902e-01 6.145359e-01
"{/Symbol b}_o" 5.760601e-01 3.760299e-01
"O_h" 5.393108e-01 1.000000e+00
"D_p" 6.743313e-01 2.284404e-01
"{/Symbol a}_p" 1.000000e+00 1.271822e-01
"{/Symbol b}_f" 4.020115e-01 2.233656e-01
"D_m" 2.389996e-01 8.577689e-02
"{/Symbol a}_m" 3.601146e-01 1.033153e-01
"{/Symbol b}_m" 5.596836e-01 1.947165e-01
CODE:
#!/usr/bin/gnuplot
# Terminal & Encoding
set terminal epscairo enhanced color dashed rounded size 8.5, 4.5
set output 'mu_piechart.eps'
set termoption enhanced
set encoding utf8
# Get Status
filename = './datafile.dat'
stats filename u 2 noout
# Get Angles & Percentages
ANG(x)=x*360.0/STATS_sum
PER(x)=x*100.0/STATS_sum
# Square Canvas
set size square
set xrange [-1:1.5]
set yrange [-1.25:1.25]
set style fill solid 1
# Remove Base Properties (Titles, Tics, Axis, Palette)
unset key
unset tics
unset border
unset colorbox
# Initial Angle, Mid Angle, Initial Color
A = 0.0; M = 0.0; i = 0;
# Palette
set palette defined (1 1 0.788 0.055, 2 0.090 0.161 0.659)
# Plot
plot for [i=0:STATS_records-1] filename u (0):(0):(1):(A):(A=A+ANG($2)):(i) every ::i::i with circle linecolor palette,\
filename u (M=A+ANG($2), A=2*M-A, M=M*pi/360.0, -0.5*cos(M)):(-0.5*sin(M)):(PER($2) > 8.00 ? sprintf('%.1f\%', PER($2)) : " ") every ::1 w labels center font ',10',\
for [i=0:STATS_records-1] filename u (1.45):(i*0.25)-1.11:($1) every ::i::i with labels left,\
for [i=0:STATS_records-1] '+' u (1.3):(i*0.25)-1.11:(i) pt 5 ps 4 lc palette
exit
OUTPUT:
The percentages positions are not correct in the figure generated by the script.
Your labels are at wrong positions, because your label plot starts at 1, i.e. you skip the first entry.
Also, what I don't understand is, why you plot the pie parts counterclockwise, and the labels clockwise.
Here is a working version of you script, without some parts which are superfluous for demonstration. Both labels and pie parts are plotted starting at an angle of A = 0 (note the second initialization between the two plots):
reset
# Get Status
filename = './datafile.dat'
stats filename u 2 noout
# Get Angles & Percentages
ANG(x)=x*360.0/STATS_sum
PER(x)=x*100.0/STATS_sum
# Y position of key point and label
YLBL(row) = 2.0 * (row - 0.5*(STATS_records - 1))/(STATS_records - 1)
# Square Canvas
set size square
set xrange [-1:1.5]
set yrange [-1.25:1.25]
set style fill solid 1
# Remove Base Properties (Titles, Tics, Axis, Palette)
unset key
unset tics
unset border
unset colorbox
# Palette
set palette defined (1 1 0.788 0.055, 2 0.090 0.161 0.659)
# Plot
A = 0.0
plot filename u (0):(0):(1):(A):(A=A+ANG($2)):0 with circle linecolor palette,\
A = 0,\
filename u (M=A+ANG($2), A=2*M-A, M=M*pi/360.0, 0.5*cos(M)):(0.5*sin(M)):(PER($2) > 8.0 ? sprintf('%.1f\%', PER($2)) : "" ) w labels center,\
filename u (1.3):(YLBL($0)):1 with labels offset char 3 left ,\
filename u (1.3):(YLBL($0)):0 pt 5 ps 4 lc palette
The script contains some other improvements:
You don't need to iterate over STATS_records
The text and point for the key are plotted at the same position, the label is shifted with the offset parameter by three character units (offset char 3). That makes fine-tuning easier.
Here is provided an example of line breaking in a plot drawn with Gnuplot.
Using arrows, as suggested in the link above, the results depend by the axis, i.e. I can't handle the angle of the arrow with simplicity. The following figure shows an example of an ugly line breaking obtained by the example in the link above.
To obtain that ugly arrows, I did something like:
x1 = 32
yb = 0
yt = 100
tiny=2
set arrow 1 from x1-tiny, yb-tiny to x1+tiny, yb+tiny nohead
set arrow 2 from x1-tiny, yt-tiny to x1+tiny, yt+tiny nohead
for the first plot and:
x2 = 33
set arrow 1 from x2-tiny, yb-tiny to x2+tiny, yb+tiny nohead
set arrow 2 from x2-tiny, yt-tiny to x2+tiny, yt+tiny nohead
for the second.
Hence, instead of using arrows, I wish to use a symbol to be put at the end of the axis. A symbol is in pt and doesn't change with the axis length. I think it should be done by putting a label centered into a specific point.
Which is the code to do that in Gnuplot?
Try the following lines for the first and the latter plot, respectively:
set label "/" at x1, yb center font "Symbol,24"
set label "/" at x1, yt center font "Symbol,24"
set label "/" at x2, yb center font "Symbol,24"
set label "/" at x2, yt center font "Symbol,24"
This should work!
the trick to specifying your arrows at fixed angles is to work in graph coordinates.
(Note my split axis approach does not work right with the postscipt driver..not sure why)
set terminal png
set yrange [0:20]
set multiplot
set ytics nomirror
set xrange [0:10]
set border 7 #left,top,bottom
set key left
dy = .025 #height of slash in graph coordinates
dx = dy/tan(10*pi/180) # 10 degree angle
set arrow nohead lt -1 from graph 1-dx,-dy to graph 1+dx,dy
set origin 0,0
set size .5,.8
set xtics (0,4,8)
plot sqrt(x)
set origin .5,0
set xrange [100:200]
set border 13 #right,top,bottom
unset ytics
set nokey
unset arrow
set arrow nohead lt -1 from graph -dx,-dy to graph dx,dy
set xtics (125,150,175,200)
plot sqrt(x)
Note this will work just fine if you have log scales..
oops forgot the top, for that you just do
set arrow nohead lt -1 from graph 1-dx,-dy+1 to graph 1+dx,dy+1
I'm working on a radial menu (for a game) and I'm having some trouble with getting text along paths to behave exactly how I'd like it to. Here's an example of the menu at the moment:
I want all the text to be aligned to the center of the node it's in, and for the fontSize to be sufficiently small for the text to fit into the available space. This is achieved fairly trivially for the straight text by scalingthe font and measuring the width until it fits:
var fontSize = 19;
var titleText = new Kinetic.Text({
text: title,
fontSize: fontSize ,
fontFamily: 'Calibri',
fill: 'white',
rotationDeg: rotation
});
while (titleText.getWidth() > availableSpace)
titleText.setFontSize(--fontSize);
However, this approach can't be applied to the curved text because (as far as I can see) there's no way to measure how long a string is when placed along a path.
How should I achieve centering and scaling of text when it is placed along a path?
Here is a hack in terms of centering, but you get the idea:
http://jsfiddle.net/ysaLp/2/
basically when you have each item in your list, you want to add blank spaces to the beginning, dependent on total space in the arc.
you can do (again, inside a loop):
textPathObjectName.setText(' ' + textPathObjectName.getText()); //dependent on the length of the width of text ( .getTextWidth() )
In terms of resizing you get : http://jsfiddle.net/ysaLp/5/
for (var i = 1; i < 5 && titleText.getTextWidth() > circumference ; i++)
titleText.setFontSize(titleText.getFontSize()-i);
which lowers your font until it "fits" into your wedge's circumference
It also helps to start your font at a lower value, since you are calculating the path data right after, set the font size at 15 first.