简体   繁体   中英

How to get the 4 coordinates of a rectangle from 3 coordinates?

I want to create a function that allows user to draw rectangle from 3 points (blue points):

  • The first two points will form an edge (width).
  • The third point will determine the height.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM