I want to create a function that allows user to draw rectangle from 3 points (blue points):
I need this custom draw function in leaflet, however leaflet's default rectangle is created with 2 diagonal points: https://leafletjs.com/reference-1.5.0.html#rectangle .
I need to calculate one of the green points but my small brain can't seem to figure it out :P
PS/EDIT: The rectangle might be angled, this is what makes it challenging
Leaflet's default rectangle is created with 2 diagonal points
[...]
The rectangle might be angled, this is what makes it challenging
Be aware that Leaflet's L.Rectangle
is created from a L.LatLngBounds
, a bounding box in which the edges are implicitly aligned to the coordinate grid . Don't use bounding boxes, and rely on L.Polygon
instead, providing all four points.
Let A and B be the points of the base of the rectangle, and C be the point on the top. Assuming all points are Javascript structures of the form {x: Number, y: Number}
, and assuming that you're working in an euclidean plane (ie not on the surface of a geoid),
First, calculate the distance from a point to a line defined by the other two points , ie the distance from C to the line defined by AB. Let that be distance
(note that it's equal to "height" in your diagram):
var distance = Math.abs(
(A.y - B.y) * C.x - (A.x - B-x) * C.y + B.x * A.y - B.y * A.x )
) / Math.sqrt(
Math.pow(B.y - A.y, 2) + Math.pow(B.x - A.x, 2)
);
Then, let AB be the vector from A to B
var AB = { x: B.x - A.x, y: B.y - A.y };
(Note that the length of AB is equal to "width" in your diagram)
Calculate a unit vector perpendicular to AB:
var perpendicular = {x: -AB.y, y: AB.x}
var perpendicularSize = Math.sqrt(AB.x * AB.x + AB.y * AB.y);
var unit = {x: perpendicular.x / perpendicularSize, y: perpendicular.y / perpendicularSize};
Multiply that unit vector by the distance from C to AB to get the vectors for the "sides" of your rectangle:
var sideVector = { x: unit.x * distance, y: unit.y * distance };
...and create new points D and E by offsetting A and B by the vector for the sides of the rectangle:
var D = { x: A.x + sideVector.x, y: A.y + sideVector.y };
var E = { x: B.x + sideVector.x, y: B.y + sideVector.y };
...And your rectangle is now defined by the points ABDE. Note that C is in the line defined by points DE.
Assuming coordinates of those 3 dots are provided, - 2, 5 (first point) - 5, 5 (second point) - x, 8 (third point)
the first green will take x from one of the first two point let's say from the first one => 2, and y from the third point => 8 so the first green point is at 2,8
the second will take x from the second point => 5, and y from the third point => 8 so the second green point is at 5,8
I'm not sure if I understand the answer correctly tho.
assuming edge1 = [x1,y1] , edge2 = [x2,y2]
def calculate_edges (edge1,edge2,height)
edge3 [0] = edge1[0] //x3
edge3 [1] = edge1[1] + height //y3
edge4 [0] = edge2[0] //x4
edge4 [1] = edge2[1] + height //y4
return edge3,edge4
For Python:
#Given three points fit a rectangle
import math
a,b,c=[1,4],[3,4],[3,10] #Sample numbers
#Distance from dot C to line AB (https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line#Line_defined_by_two_points)
distance= abs((b[1]-a[1])*c[0] - (b[0]-a[0])*c[1] + b[0]*a[1] - b[1]*a[0] ) / math.sqrt((b[1]-a[1])**2 + (b[0]-a[0])**2)
print(distance)
#let AB be the vector from A to B
ab=[b[0]-a[0],b[1]-a[1]]
#unit vector perpendicular to AB (https://en.wikipedia.org/wiki/Unit_vector)
perpendicularSize = math.sqrt(ab[0]**2+ab[1]**2)
unit = [-ab[1]/perpendicularSize ,ab[0]/perpendicularSize]
#Multiply that unit vector by the distance from C to AB to get the vectors for the "sides" of your rectangle
sideVector = [unit[0]*distance,unit[1]*distance]
#create new points D and E by offsetting A and B by the vector for the sides of the rectangle
d=[a[0]+sideVector[0],a[1]+sideVector[1]]
e=[b[0]+sideVector[0],b[1]+sideVector[1]]
print(e,d) #[3.0, 10.0] [1.0, 10.0]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.