Get line width and inner sep of a TikZ node - tikz

Is it possible to retrieve a node's inner sep and line width using the key tree? My exact use case is below.
I want to find the coordinates of the red marks in the image below, but not using the method I've used below. Basically I want what would be the north east anchor (or some other anchor on a rectangle) if it were to sit in the middle of the border line instead of the outer edge, as well as if it were to lie on the node's contents before inner sep is added. I don't want to use duplicate "phantom" nodes as I have below because in my use case the node's contents might be messy.
I also realize I can just save the line width and inner sep globally by using \pgfmathsetlength{}{}, applying them to the node and using the same macros to navigate relative to north east, or in similar fashion by defining custom keys. But I'd really like to ask the node directly, as though these values were specified as literals in the node's options like \node [inner sep=1.2em] {};.
Image:
Code:
\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\node [draw, line width=5pt, inner sep=8pt] (A) {foo};
\node [draw=cyan, line width=2pt, inner sep=8pt] (B) {\phantom{foo}};
\node [line width=0pt, inner sep=0pt] (C) {\phantom{foo}};
\node [line width=0pt, inner sep=8pt] (D) {\phantom{foo}};
% Basically I don't want to use nodes C and D, I want everything relative to A
\draw [red] plot [mark=x] coordinates { (C.north east) };
\draw [red] plot [mark=x] coordinates { (D.north east) };
\draw [green] plot [mark=x] coordinates { (A.north east) };
\end{tikzpicture}
\end{document}

Related

Increase the BBOX size but keep the ratio (Lon/Lat)

I have a Bbox that is defined by the following values:
xmin: 11.555333537980914
ymin: 47.76067947037518
xmax: 11.995692579075694
ymax: 48.281587762758136
I would like to increase the size of this Bbox but keep the ratio.
One approach I tried is to calculate the middle point of the Bbox and calculate a new Bbox with the value of radius increased by 50%.
The problem: the ratio gets lost.
How could I increase the size of Bbox to 50% but keep the ratio.
Perhaps ST_Expand is what you're looking for. You could first calculate the area of the input bbox using ST_Area and then use the output as a unit to expand the bbox.
SELECT -- here you can play with different sizes
ST_Expand(geom, ST_Area(geom)/2)
FROM yourtable;
Example:
WITH j (geom) AS (
SELECT ST_MakeEnvelope(11.555333537980914,
47.76067947037518,
11.995692579075694,
48.281587762758136,4326)
)
SELECT
ST_Expand(geom,ST_Area(geom)/2)
FROM j;
The image below represents the result set. The inner bbox is the one you provided and the outer one was created with ST_Expand.
Demo: db<>fiddle
The answer provided by #Jim Jones works perfectly. Is there something PostGIS can not do? :)
I did not wanted to be dependend on PostGIS
so I tried to solve the problem with R. My approach:
I prolong each diagonal of the bbox and calculate the bearing for that diagonal. Based on that data I calculate new edge points of the bbox. It kind of works but the left side of the bbox looks a bit small. I think there is a misstake somwhere but i dont know yet where.
xmin<- 11.555333537980914
ymin<- 47.76067947037518
xmax<- 11.995692579075694
ymax<- 48.281587762758136
###calculate bearing clockwise of diagonal for each corner of the BBOX
######## right bottom, left und top
######## left and bottom, right and top
######## left and top and right and bottom
######## right and top, left and bottom
##bearing(p1, p2, a=6378137, f=1/298.257223563)
bearing1 <- geosphere::bearingRhumb(c(xmax,ymin),c(xmin,ymax))
bearing2 <- geosphere::bearingRhumb(c(xmin,ymin),c(xmax,ymax))
bearing3 <- geosphere::bearingRhumb(c(xmin,ymin),c(xmax,ymin))
bearing4 <- geosphere::bearingRhumb(c(xmax,ymax),c(xmin,ymin))
#new bbox points
########################## left und top
########################## right und top
########################## right und bottom
########################## left und bottom
p1<- geosphere::destPointRhumb(c(xmin,ymax), bearing1, 10000, r = 6378137)
p2<- geosphere::destPointRhumb(c(xmax,ymax), bearing2, 10000, r = 6378137)
p3<- geosphere::destPointRhumb(c(xmax,ymin), bearing3, 10000, r = 6378137)
p4<- geosphere::destPointRhumb(c(xmin,ymin), bearing4, 10000, r = 6378137)
data<-rbind.data.frame(p1,p2,p3,p4)
xmin<-min(data$lon)
ymin<-min(data$lat)
xmax<-max(data$lon)
ymax<-max(data$lat)
cat(xmin,",",ymin,",",xmax,",",ymax)
One solution would be to translate the box so that its center is at the origin, multiply everything with 1.5, and then translate back. This should be possible with a single ST_Affine(), but I'm too lazy to work out the details. :)

How to find all circles that have their center in their intercection a main circle

Is there a clean way to find all the circles that are not only intersection with a main circle but also have their center inside the intersection with that main circle.
Sure it's simple. You need to use ## or center to get the center point and then #> to use contains.
SELECT
x AS r_value,
circle('0,0', x) #> ## circle('2,3', 1) AS contains
FROM generate_series(1,5) AS gs(x);
-or-
SELECT
x AS r_value,
circle('0,0', x) #> center(circle('2,3', 1)) AS contains
FROM generate_series(1,5) AS gs(x);
This brute-force tests circles with the center at the origin, with a radius of [1,5] whether they contain the center of circle('2,3',1).
See the docs on geometry functions for more info.
select * from circles a , circles b
where st_intersects(a.geom,st_centroid(b.geom))
Also, you can filter the results by adding condition in where clause. I am assuming main circle name.
select * from circles a , circles b
where st_intersects(a.geom,st_centroid(b.geom)) and a.circle_name = 'Main Circle';

Plotting intersection of planar surfaces in matlab

I am looking to plot the intersection of two surfaces(patches) lying the same plane in MATLAB.
As you can see in the above picture the green circle intersects four red rectangles.I want to plot out(or patch) only the four intersections.How do I proceed?
I tried to plot points on the circular patch which lies outside the intersection of one rectangle and circle using conditional statements.But MATLAB throws an error.Here is the code snippet.
[p,q] = size(points);
for s=1:1:q;
t = points(1,s);
if (points(1,s) >= Pa3(1,1)) && (points(1,s) <= Pa2(1,1)) && (points(2,s) >= Pa3(1,2)) && (points(2,s) <= Pa4(1,2))
points(1,s) = 0;points(2,s) = 0;
end
end
fill3(points(1,:), points(2,:), points(3,:), 'g');
The above code throws an error at if statement.Basically in the code "points" represent all the points in the green circle.Pa1,Pa2,Pa3,Pa4 represent the vertices of the left top corner rectangle with Pa1 being the left corner top vertex and Pa2,Pa3,Pa4 following in clockwise manner.
Thanks
Patches are defined by polygons, and what you are looking for is the intersection of two polygons which itself is a polygon.
If you have the Mapping Toolbox, you can use polybool to compute the intersection and other logical operations on polygons.
If not, have a look at the submission Polygon_Intersection on the Matlab File Exchange.
See also intersection and union of polygons.

draw vertical lines at regular intervals in a rectangle in matlab

I need to draw vertical lines at regular intervals in a rectangular box. this is what i have used so far:
xmin=000;
xmax=70000;
ymin=0;
ymax=1000;
line1Val=900;
line2Val=600;
line3Val=300;
xlim([xmin xmax])
ylim([ymin ymax])
xl=get(gca,'XLim');
line(xl,[line1Val line1Val],'Color','y');
line(xl,[line2Val line2Val],'Color','y');
line(xl,[line3Val line3Val],'Color','y');
hold on ;
rectangle('Position',[120000,900,(280000-120000),37],'faceColor','k')
so the width of the rectangle is 160000 units i want to divide this into 4 , where the vertical line is of a different color(say red) and the height of the line is 37 units.
any ideas on how i can draw this without drawing 4 rectangles whose edges are red and are filled with black color.
You could use the parameters xstart,ystart,width and height for drawing your rectangle:
rectangle('Position',[xstart,ystart,width,height],'faceColor','k');
After that, you could determine the line positions in a loop and simply draw these lines:
for i = 1:3
x = xstart+i*width/4;
line([x x],[ystart ystart+height],'Color','r');
end
If you want a red line at the start and end of the rectangle, let i = 0:4.

Objective-C: How do I calculate the x/y coordinates of a given distance on 2 different circle sizes, inside one another?

iPhone SDK and Objective-C
Goal:
I'm trying to calculate the 'x' and 'y' coordinates of 2 circles. I have the inner circle dimensions and want to calculate what the 'x' and 'y' coordinates of the larger outer circle circumference would be to match the same width (distance) along the edge of the larger circle as it does with the inner circle.
In the end, I just need to figure out what the edge x/y points would be for the large circles edge. So that it matches the same as the inner smaller circle. If the width is 10 high on the inner circle, I need to know the x/y points to make it 10 high to the larger circle. To make a rectangle that will extend. Perpendicular lines.
Example:
I'm using the following to calculate the first 2 sets of x/y for the arc on the inner circle to plot points:
- (CGPoint)coordinatePoints:(CGFloat)radius angleDegrees:(CGFloat)degrees xAxis:(CGFloat)x yAxis:(CGFloat)y {
CGFloat pointX = (CGFloat) ((radius * cos((degrees * M_PI) / 180.0f)) + x);
CGFloat pointY = (CGFloat) ((radius * sin((degrees * M_PI) / 180.0f)) + y);
CGPoint points = CGPointMake(pointX, pointY);
return points;
}
I call it for the first 2 positions on the inner circle. I need to figure out how to make it have the distance on the outer circle as well.
CGPoint innerPoints1 = [self coordinatePoints:innerRadius angleDegrees:startingPoint xAxis:x yAxis:y];
CGPoint innerPoints2 = [self coordinatePoints:innerRadius angleDegrees:endingPoint xAxis:x yAxis:y];
If the inner circle radius is 200, and the outer circle radius is 500, I want it to still be the same thickness from the inner circle to the larger outer circle when I plot the points.
// I have these calculated.
CGContextMoveToPoint(context, innerPoints1.x, innerPoints1.y);
CGContextAddLineToPoint(context, innerPoints2.x, innerPoints2.y);
// I need to find the solution for making innerPoints3 and innerPoints4 correctly.
CGContextAddLineToPoint(context, innerPoints3.x, innerPoints3.y);
CGContextAddLineToPoint(context, innerPoints4.x, innerPoints4.y);
I have the coordinates for the inner circle lines for spaced out x/y points. I need to find the proper way to get the same width plotted for the larger circle locations. Circle sizes will always change. Lengths of the lines will be dynamic. As I'm trying to create a polygon, I need to find 2 coordinates on the larger circles, for each segment.
Any help with this would be greatly appreciated.
Information graphics: a comprehensive illustrated reference
Page 74: In the section "Circular Column Graph", my end goal is to be able to produce the same result as displayed in the 3 images.
If the spokes are not too thick, then the arc length is a good approximation of the spoke width:
So first you construct your 2 inner points, with 2 angles (a1 and a2) centered around a main spoke angle (a).
Then you calculate the distance D between these points (or you approximate it by R1*(a2-a1))
Then you take the points on the outer circle with angle values centered around the same main spoke angle: a-0.5*D/R2 and a+0.5*D/R2. These points will be D apart (measured on the arc)