I'd like to draw an arc segment:
(90° here, but I want different arcs, for something like Fan Chart)
I can draw the arc (the yellow segment) fine with an a/A path segment, however, as soon as I want to round the corners, the arc (blue segment) isn't actually a full (circular) arc any longer, but is "flattened". Is there still any way to draw this part of the path with the a/A primitives, or should I just draw them in a separate path that allows me to set the center point correctly?
This must be explained with a bit of trigonometry. Consider the following three paths:
The first has the path definition (center of the arc at 0, 100).
d="M 0,100 H 80 A 80,80 0 0 0 0,20 z"
In the second one, the corners have been rounded with a radius of 15. To keep the connection of the small corner arcs with the larger arc smooth, the larger radius is reduced from 80 to 65. As you can see, the arc sits wide outside its original position.
d="M 0,100 H 65 A 15,15 0 0 0 80,85 65,65 0 0 0 15,20 15,15 0 0 0 0,35 Z"
In the third one, the connection is ignored and the radius kept at 80. Still, the position of the arc is too wide.
d="M 0,100 H 65 A 15,15 0 0 0 80,85 80,80 0 0 0 15,20 15,15 0 0 0 0,35 Z"
That is because the small corner arc is too far from the center of the large arc. For a visual construction, you would draw a circle with radius 15 inside the pie, and move it towards the corner until it meets both the straight line and the arc in a tangent. See the green circle:
It is meeting the arc to the right of the upper corner, and a bit lower. How much lower, you have to compute.
Suppose you want to round the corner with a radius of d=15. Then, the center of the circle sits at the intersection of the vertical line at x = d = 15 and the reduced arc with r₂ = r₁ - d = 65.
The angle α of a line from the inner corner to that point computes to
α = arcsin(d / r₂) = arcsin(15 / 65) = 13.342364°
The end point of the large arc then is at
x = cx + r₁ × sin(α) = 80 × sin(13.342364°) = 18.4615
y = cy - r₁ × cos(α) = 100 - 80 × cos(13.342364°) = 22.1593
The point where the rounded corner begins is at
x = cx = 0
y = cy - r₂ × cos(α) = 100 - 65 × cos(13.342364°) = 36.7544
After doing the same computation for the lower right corner, the final path computes to
d="M 0,100 H 63.25 A 15,15 0 0 0 77.85,81.54 80,80 0 0 0 18.46,22.15 15,15 0 0 0 0,36.75 Z"
I've been trying to figure this one out for a few days, the material icons are a bit too thick, so I downloaded one and have been trying to change the stroke weight / thickness. But just using the stroke-width property doesn't change anything, and if I add a 'stroke' it also adds a border around the element.
For example, here is the 'public' icon from google / material icons
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
<path d="M0 0h24v24H0V0z" fill="none"/>
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM4 12c0-.61.08-1.21.21-1.78L8.99 15v1c0 1.1.9 2 2 2v1.93C7.06 19.43 4 16.07 4 12zm13.89 5.4c-.26-.81-1-1.4-1.9-1.4h-1v-3c0-.55-.45-1-1-1h-6v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41C17.92 5.77 20 8.65 20 12c0 2.08-.81 3.98-2.11 5.4z"/>
</svg>
How would I go about making this thinner or thicker? Is there a minimum font weight? ( I want some pretty thin strokes for this)
The design of the icon is your problem
Paste the path in https://yqnn.github.io/svg-path-editor/
If you want more detail you need to edit the (filled) path.
Disclaimer: I am new to Gnuplot, and I need to plot some "simple" things for my studies.
I want to plot a part of a polygon with some names and vectors added.
The picutre below was created with Euklid Dynageo, and I am now trying to create this with Gnuplot.
The biggest problem I am facing right now is the labeling u,v,w and adding the angles to the plot. I think I would use vectors and lines.
Do you now a 'simple' way to create this plot?
If you really need to use Gnuplot for this, you have to make it all manually by placing various objects, labels and arrows (keep in mind that complex plots will be cumbersome). A minimal example for two arrows and alpha_1, similar like in your example, could like like this:
# two arrows:
set arrow 1 from 0,0 to sqrt(2)/2,sqrt(2)/2
set arrow 2 from 0,0 to 1,0
# the alpha_1 symbol:
set label 1 '{/Symbol a}_1' at 0.2,0.1 front
# the filled yellow arc (from 0 to 45deg):
set style fill solid 1.0 border
set object 1 circle at 0,0 radius 0.2 arc[0:45] fc rgb "yellow"
# proper ratio, range, and plot 'something':
set xrange[-0.1:1.1]
set yrange[-0.1:1.1]
set size ratio 1
plot 1/0
Lookup the manual for possible object properties.
gnuplot is a very versatile plotting tool, but certainly not optimized for such tasks. For this type of drawing maybe Inkscape or others tools might be better choices, especially for interactive drawing by clicking, dragging and snapping.
And as #JackGlasshard already mentioned, of course you can do such graphs with gnuplot which will be rather time consuming if you do it manually.
Alternatively, you can facilitate the work if you use a "template".
Creating such a template probably only makes sense if you need to create more than one drawing.
Just for fun and feasibility, I tried to create such a template for general use to make such graphs easier.
For the input data you need 3 datablocks (without headers)
$Points: # no., x, y, label, xoff, yoff, pt, ps, color
you define: point number, x-coordinate, y-coordinate, point label, x-offset, y-offset, pointtype, pointsize, point color
$Vectors: # p1, p2, label, arrow, lw, dt, xoff, yoff, color
you define: first point number, second point number, label, arrowsstyle (-1=backhead, 0=nohead, 1=head, 2=heads), linewidth, dashtype, x-offset, y-offset, vector color
$Angles: # p1, p2, p3, r, label, aoff, roff, color
you define: 1st point number, 2nd point number (=angle center point), 3rd point number, radius, label, angular label offset, radial label offset, color
Now, you only have to change the data part of the script for your custom graph. In case you want to insert "invisible" vector starting or end points, simply set pointsize to 0 in $Points. The plotting of the variable arrowheads is a bit cumbersome because of the issue mentioned in this question.
For sure, more features and more flexibility can be added to the template. No warranty that the script is free of bugs. There is certainly room for improvements.
Update: (linewidth and dashtype added)
Since there is no variable linewidth (lw var) and no variable dashtype (dt var)
you have to plot each line separately in a for loop and every ::n::n.
Furthermore, I noticed that the order of variable pointsize (ps var) and and variable pointtype (pt var) apparently has changed from gnuplot 5.2 to 5.4. Not sure whether this intentional or a "bug".
The version below has the order for gnuplot 5.4.
Script:
### drawing sketch with points, vectors and angles
reset session
# no., x, y, label, xoff, yoff, pt, ps, color
$Points <<EOD
1 1 1 "" 0 0 5 1 0xff0000
2 10 2 V_{i-1} 0 0 5 1 0xff0000
3 15 10 V_i 0 0 5 1 0xff0000
4 4 12 X -1.5 0 5 1 0xff0000
5 14 16 V_{i+1} 0 0 5 1 0xff0000
6 5 20 "" 0 0 5 1 0xff0000
EOD
# p1, p2, label, arrow, lw, dt, xoff, yoff, color
# arrows: -1=backhead, 0=nohead, 1=head, 2=heads
$Vectors <<EOD
1 2 "" 0 1.0 1 0 0 0xff0000
2 3 "" 0 2.0 1 0 0 0x000000
3 5 "" 0 1.5 3 0 0 0x000000
4 2 w 1 1.0 1 1.0 0 0x000000
4 3 v 1 1.0 1 0 0.7 0x0000ff
4 5 u 1 1.0 1 0 0.7 0x000000
5 6 "" 0 1.0 1 0 0 0x000000
EOD
# p1, p2, p3, r, label, aoff, roff, color
# p2=angle center point
$Angles <<EOD
2 4 3 4.0 α_{i-1} 7.0 0.5 0xffcccc
3 4 5 4.5 α_i 3.0 0.7 0xffffcc
EOD
### end of data input
### start of template
# point/vector coordinates
px(n,m) = real(word($Points[int(word($Vectors[n],m))],2)) # x coordinate of point n
py(n,m) = real(word($Points[int(word($Vectors[n],m))],3)) # y coordinate of point n
vxd(n) = px(n,2)-px(n,1) # vector delta x
vyd(n) = py(n,2)-py(n,1) # vector delta y
vxc(n) = (px(n,2)+px(n,1))/2. # vector center x
vyc(n) = (py(n,2)+py(n,1))/2. # vector center y
lw(n) = real(word($Vectors[n],5))
dt(n) = int(word($Vectors[n],6))
# angles
as(n) = int(column(5)+2) # arrow style
ax(n) = real(word($Points[int(word($Angles[int(column(0)+1)],n))],2)) # angle center x
ay(n) = real(word($Points[int(word($Angles[int(column(0)+1)],n))],3)) # angle center y
set angle degrees
Angle(x0,y0,x1,y1) = (_dx=x1-x0, _dy=y1-y0, _L=sqrt(_dx**2 + _dy**2), _L==0 ? NaN : \
(_dy>=0 ? acos(_dx/_L) : -acos(_dx/_L) ))
a1(m) = Angle(ax(2),ay(2),ax(1),ay(1)) # starting angle
a2(m) = Angle(ax(2),ay(2),ax(3),ay(3)) # end angle
set style arrow 1 backhead filled # -1
set style arrow 2 nohead filled # 0
set style arrow 3 head filled # 1
set style arrow 4 heads filled # 2
set size ratio -1 # ensure same x- and y-ratio
set key noautotitle
set xrange [0:22]
set yrange [0:22]
set mxtics 5
set mytics 5
set grid x,y,mx,my
set style fill solid 0.5 border lc "black"
plot $Angles u (ax(2)):(ay(2)):4:(a1(0)):(a2(0)):8 w circles lc rgb var, \
'' u (ax(2)+($4*0.5+$7)*cos(0.5*(a1(0)+a2(0))+$6)): \
(ay(2)+($4*0.5+$7)*sin(0.5*(a1(0)+a2(0))+$6)):5 w labels font "Times New Roman,13" center, \
for [i=1:|$Vectors|] $Vectors \
u (px(i,1)):(py(i,1)):(vxd(i)):($4==-1?vyd(i):NaN):9 every ::i-1::i-1 w vectors lc rgb var lw lw(i) dt dt(i) filled backhead, \
for [i=1:|$Vectors|] '' \
u (px(i,1)):(py(i,1)):(vxd(i)):($4== 0?vyd(i):NaN):9 every ::i-1::i-1 w vectors lc rgb var lw lw(i) dt dt(i) filled nohead, \
for [i=1:|$Vectors|] '' \
u (px(i,1)):(py(i,1)):(vxd(i)):($4== 1?vyd(i):NaN):9 every ::i-1::i-1 w vectors lc rgb var lw lw(i) dt dt(i) filled head, \
for [i=1:|$Vectors|] '' \
u (px(i,1)):(py(i,1)):(vxd(i)):($4== 2?vyd(i):NaN):9 every ::i-1::i-1 w vectors lc rgb var lw lw(i) dt dt(i) filled heads, \
for [i=1:|$Vectors|] '' \
u (vxc(i)+$7):(vyc(i)+$8):3:9 every ::i-1::i-1 w labels font ",12" tc rgb var, \
$Points u 2:3:7:8:9 w p ps var pt var lc rgb var, \
'' u ($2+$5):($3+$6):4:9 w labels tc rgb var font ",12" left offset 1,0
### end of script
Result:
I need to create a block with specific borders around it:
I want to have this block scalable, that is why I try doing it with svg.
Here is what I've done:
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none slice" viewBox="0 0 300 400">
<path stroke-width="1" stroke="#7DD37D" fill="red" d="
M20 0h260
m20 20v360
m-20 20H20
m-20 -20V20
M0 20a20 20 0 0 0 20 -20
M300 20a20 20 0 0 1 -20 -20
M300 380a20 20 0 0 0 -20 20
M0 380a20 20 0 0 1 20 20" id="path"/>
</svg>
Demo on codepen
The border was created as path from lines and arcs.
The problem is, that I can't make svg to fill the area inside this path. It fills some space inside arcs instead of rectangle. What I'm doing wrong?
When I do something similar with Inkscape, the resulting path is combined from lines and Cubic Bezier curves. Can it be done with simple arcs instead of Bezier curves?
Each time you use a move ('m' or 'M') path command, it creates a new subpath. Each subpath gets filled, not the whole thing.
If you want the whole thing filled, it has to be a continuous path. In other words, in this case, it should be a move followed by a line, then an arc, then another line, and arc, and so on until you have completed all four sides of the shape.
I have a data set that uses the x-scale:
0.1 0.4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
But I need the tics to line up evenly, not have 0.1 and 0.4 scrunched up into the corner. I currently use,
set xtics 1
set xtics add (0.1)(0.4)
But that spaces 0.1 and 0.4 respective to the rest of the scale. I've attached a link to a tinypic I uploaded of my dummy data set with my current problem.
http://tinypic.com/r/2zfolxf/7
Current State
As far as I know, you can do the following in gnuplot with tics (at least what is relevant to your question):
You can specify the start, increment and end of the tics displayed.
This would make sense to you, if you wish to simply set the tics after the value of 2 like
set xtics 2, 1
The other thing you can do, is add explicit tic labels to certain values like
set xtics add ("0.1" 0, "0.4" 1)
This would introduce the labels 0.1, and 0.4 to the x scale where the actual values are 0 and 1
However you cannot modify the actual plotting of the graph. If in you data it states
0.1 100
0.4 150
1 200
2 300
then gunplot will plot it correspondingly.
Possible workaround
A workaround could look like this:
Plot the normal graph from 2 upwards.
Do some hackery stuff to the first two values with this:
plot "Data.dat" every 1::2 w l, "" every 1::1::2 using ($1<magic>):($2)
magic specifies some algebraic operation you want to do with the first column.
Everything is allowed and if your values are constant you can specify a polynomial that goes through the points 0, 1 and 2 with the inputs 0.1, 0.4 and 1 like this polynomial:
y = -1.85*x^2 + 4.26*x - 1.4
Example
Suppose you have this data file:
0.1 0.41
0.4 0.03
1 0.97
2 0.74
3 0.05
4 0.15
5 0.11
6 0.60
7 0.76
8 0.25
Then you can "rearrange" the first two entries to the x-positions -1 and 0 like this:
plot "Data.dat" every 1::2 w l, \
"" every 1::0::2 using (-1.85*$1**2 + 4.26*$1 - 1.4):($2) w l
With some tic-labeling and line style settings it should look exactly like what you are after.
I hope I understood what you are after and that you can make some use of my suggestions.
Cherio
Woltan