0

I have an application where the user draws a line, then automatically the software should create a rectangle where the line intersects the midpoint of two adjacent sides of a right angled rectangle. See below, the red line is user drawn and the purple rectangle is calculated. My algorithm almost works, in some directions the rectangles aren't right angled. I want to know why, there is a fair amount of approximation in my code, which should be fine based on the scales I use (a few km). I shouldn't have to worry about the curvature of the earth.

Anybody know how I can improve my code? Here are my references: calculate points lat and long to meters

Map rectange

        public static MapRectangle CreatMapRectangle(BalingZone zone, double thickness)
    {
        MapsCoordinate rectpoint2;
        MapsCoordinate rectPoint1 ;
        MapsCoordinate rectPoint3 ;
        MapsCoordinate rectPoint4 ;

        var point1 = zone.Coordinates[0];
        var point2 = zone.Coordinates[1];

        var latitudeDiff = LatitudeDiffToMeters(point2.Latitude - point1.Latitude);
        var longitudeDiff = LongitudeDiffToMeters(point1.Longitude - point2.Longitude, point1.Latitude);
        var slopeB = longitudeDiff / latitudeDiff;

        double latOffset = thickness * (slopeB / Math.Sqrt(1 + slopeB * slopeB));
        double longOffset = thickness * (1 / Math.Sqrt(1 + slopeB * slopeB));


        double p3Lat = CalculateLatitude(point1.Latitude, latOffset);
        double p3Long = CalculateLongitude( point1.Longitude, p3Lat , longOffset);
        rectPoint1 = new MapsCoordinate(p3Lat, p3Long);


        double p4Lat = CalculateLatitude(point1.Latitude, -latOffset);
        double p4Long = CalculateLongitude(point1.Longitude, p4Lat, -longOffset);
        rectpoint2 = new MapsCoordinate(p4Lat, p4Long);


        double p5Lat = CalculateLatitude(point2.Latitude, latOffset);
        double p5Long = CalculateLongitude( point2.Longitude, p5Lat , longOffset);
        rectPoint4 = new MapsCoordinate(p5Lat, p5Long);

        double p6Lat = CalculateLatitude(point2.Latitude, -latOffset);
        double p6Long = CalculateLongitude( point2.Longitude, p6Lat , -longOffset);
        rectPoint3 = new MapsCoordinate(p6Lat, p6Long);

        return new MapRectangle(rectPoint4, rectPoint3, rectPoint1, rectpoint2, thickness);
    }

    //use the quick and dirty estimate that 111,111 meters (111.111 km) in the y direction is 1 degree (of latitude)
    // and 111,111 * cos(latitude) meters in the x direction is 1 degree (of longitude).

    private static double LatitudeDiffToMeters(double latitudeDiff)
    {
        return 111111.0 * latitudeDiff;
    }

    private static double LongitudeDiffToMeters(double longitudeDiff, double latitude)
    {
        return 111111.0*Math.Cos(latitude)*longitudeDiff;
    }


    private static double CalculateLatitude(double latitude, double offset)
    {
        return latitude + offset/111111.0;
    }

    private static double CalculateLongitude(double longitude, double latitude, double offset)
    {
        return longitude + offset/(111111.0*Math.Cos(latitude));
    }
}
pogorman
  • 101
  • 2

2 Answers2

0

The pseudocode that works for me (cannot find reference on internet, sorry):

  1. dX=X2-X1; dY=(Y2-Y1); L=SQRT(dX * dX+dY * dY)
  2. xC= - dY * h/L; yC=dX * h/L where h is half length of perpendicular line

Coordinates of point to the left of the line start:

xL=X1+xC; yL=Y1+yC

Coordinates of point to the right of the line start:

xL=X1-xC; yL=Y1-yC

I hope naming is self-explanatory and you can figure out how to find 2 points at the line end.

Found it on net

FelixIP
  • 22,922
  • 3
  • 29
  • 61
  • Thanks, I tried this implementation, but it made the rectangles slightly worse. It worked great for lines in the N-S or E-W directions, but with NW-SE and SW-NE directions the rectangles really lost their shape. Maybe my approximation to meters is not good enough – pogorman Sep 09 '15 at 19:56
0

There was an error in my code, i was using degrees instead of radians in the math functions. I also updated the calculations to assume a spherical earth.

private static double LatitudeDiffToMeters(double latitudeDiff)
    {
        return (R*latitudeDiff*Math.PI)/180;
    }

    private static double LongitudeDiffToMeters(double longitudeDiff, double latitude)
    {
        return (longitudeDiff*Math.PI* R * Math.Cos (Math.PI * latitude / 180))/180;
    }


    private static double CalculateLatitude(double latitude, double offset)
    {
        return latitude + ((offset/R) * (180/Math.PI));
    }

    private static double CalculateLongitude(double longitude, double latitude, double offset)
    {
        return longitude + offset / (R * Math.Cos (Math.PI * latitude / 180)) * (180 / Math.PI);
    }
pogorman
  • 101
  • 2