Mapsui: Point position : A to B with degrees

Created on 25 Sep 2018  ·  15Comments  ·  Source: Mapsui/Mapsui

Hi,

I need to find position of the point B from the point A, where I know what the distance between them (meter) is, and the point B is from the point A in specific direction (degrees-clockwise).
obraz

With analytic geometry (coordinate geometry) I'm trying to do:

Point positionA = new Point(12, 34);
Point positionB = null;//?
float distanceM = 2;//2m
int angle = 30;//30°

double distance1 = Math.Abs(Math.Sqrt(Math.Pow(positionB.X - positionA.X, 2) + Math.Pow(positionB.Y - positionA.Y, 2)));//Mapsui.Geometries.Utilities.Algorithms.Distance(positionA, positionB);
double angle1 = Math.Atan2((positionB.Y - positionA.Y) , (positionB.X - positionA.X)) * (180 / Math.PI);
//agle == agle1

tbc

How can I do it in Mapsui 1.4 (without too many of own calculations), any method/s?

I see this
Mapsui.Geometries.Utilities.Algorithms.RotateClockwiseDegrees but I'm not sure how (and if) I can use it. (and some calculations in GeoHelper)

Many Thanks,
Łukasz

question

All 15 comments

obraz

Pow(2) = Pow(Yb - 34)+Pow(Xb - 12); Tan(30) = (Yb - 34) / (Xb - 12); Atan(30) = (Xb - 12) / (Yb - 34) ... in this case is 30 so from my (on paper) calculation:
Xb = Sqrt(3) + 12; Yb = 35; B(14,35)
but is it correct and how calc it if will be different degrees?

I know maybe it's not Mapsui issue but will be nice to have some solution in Mapsui methods/algorithms.

Perhaps this could help you. See second answer.

Yes, I've looked at the answer and... no idea what I'm doing here wrong, but it doesn't work:

            var startPoint = SphericalMercator.FromLonLat(19, 55);

            var pointA = new Feature { Geometry = startPoint };
            pointLayer.Add(pointA);

            var DegreesToRadians = Math.PI / 180;//0.01745329251994329576923690768489;//SphericalMercator.D2R
            var EarthRadius = 6378137.0;//SphericalMercator.Radius
            var TwoPi = Math.PI * 2;

            var rangeMeters = 2000;//2km
            var angle = 10;

            //var sp = SphericalMercator.ToLonLat(startPoint.X, startPoint.Y);
            var sp = startPoint.Clone();

            double lonA = sp.X;// * DegreesToRadians;
            double latA = sp.Y;// * DegreesToRadians;
            double angularDistance = rangeMeters / EarthRadius;
            double trueCourse = angle * DegreesToRadians;

            double lat = Math.Asin(
                Math.Sin(latA) * Math.Cos(angularDistance) +
                Math.Cos(latA) * Math.Sin(angularDistance) * Math.Cos(trueCourse));

            double dlon = Math.Atan2(
                Math.Sin(trueCourse) * Math.Sin(angularDistance) * Math.Cos(latA),
                Math.Cos(angularDistance) - Math.Sin(latA) * Math.Sin(lat));

            double lon = ((lonA + dlon + Math.PI) % TwoPi) - Math.PI;

            //var endPoint = SphericalMercator.FromLonLat(lon, lat);
            var endPoint = new Point(lon, lat);

            var pointB = new Feature { Geometry = endPoint };
            pointLayer.Add(pointB);

I've tried this and looks better but still distance and angle are wrong```

        var Longitude = 19;
        var Latitude = 54;

        var startPoint = SphericalMercator.FromLonLat(Longitude, Latitude);

        var pointA = new Feature { Geometry = startPoint };
        pointLayer.Add(pointA);

        var DegreesToRadians = Math.PI / 180;//0.01745329251994329576923690768489;//SphericalMercator.D2R
        var EarthRadius = 6378137.0;//SphericalMercator.Radius
        var TwoPi = Math.PI * 2;

        var rangeMeters = 200;
        var angle = 45;

        double lonA = Longitude * DegreesToRadians;
        double latA = Latitude * DegreesToRadians;
        double angularDistance = rangeMeters / EarthRadius;
        double trueCourse = angle * DegreesToRadians;

        double lat = Math.Asin(
            Math.Sin(latA) * Math.Cos(angularDistance) +
            Math.Cos(latA) * Math.Sin(angularDistance) * Math.Cos(trueCourse));

        double dlon = Math.Atan2(
            Math.Sin(trueCourse) * Math.Sin(angularDistance) * Math.Cos(latA),
            Math.Cos(angularDistance) - Math.Sin(latA) * Math.Sin(lat));

        double lon = ((lonA + dlon + Math.PI) % TwoPi) - Math.PI;

        var endPoint = SphericalMercator.FromLonLat(Longitude+lon, Latitude+lat);

        var pointB = new Feature { Geometry = endPoint };
        pointLayer.Add(pointB);

```

What means „wrong“? Be careful, it is a perhaps a problem same as the scale bar length.

I try be careful :)
I mean that the calculation (the distance and the direction) of the point B on the map are wrong (position B), should be like Point X (the image attached bellow).

Let me again explain using the initial example and analytic geometry (trigonometry).

Distance: (not meters)
Angle: 30° (where I understand that: 0° = N, 90° = E, 180° = S, 270° W)
A(12, 34)
B(Xb, Yb)

Flat coordinate system:

Pow(2) = Pow(Yb - 34)+Pow(Xb - 12);
Tan(30) = (Yb - 34) / (Xb - 12);
Atan(30) = (Xb - 12) / (Yb - 34);

the result

Xb = Sqrt(3) + 12;
Yb = 35;

But pointB from on the map has (14.8262636, 34.433599).

I'm worry that the problem could be in SphericalMercator (OSM) and calculations for flat coordinate system(WGS84?), but in this case (dist:2°) the values are too small to have some calc. problems (big differences in result).

So, in the code (this) is something wrong.

I was hoping the Mapsui would help me.

The image of the map (OSM) and the points:
obraz

Now, the code looks:

            var Longitude = 12;
            var Latitude = 34;

            var startPoint = SphericalMercator.FromLonLat(Longitude, Latitude);

            StyleCollection stylesA = new StyleCollection
            {
                new VectorStyle{ Fill = new Brush(Color.Red), Outline = new Pen(Color.Green, 4) },
                new LabelStyle{ Text = "A ("+Longitude.ToString().Replace(",",".")+", "+Latitude.ToString().Replace(",",".")+")", BackColor = new Brush(Color.Transparent), HorizontalAlignment = LabelStyle.HorizontalAlignmentEnum.Right, Offset = new Offset(0,25, false) }
            };
            var pointA = new Feature { Geometry = startPoint, Styles = stylesA };
            pointLayer.Add(pointA);

            var DegreesToRadians = Math.PI / 180;//0.01745329251994329576923690768489;//SphericalMercator.D2R
            var EarthRadius = 6378137.0;//SphericalMercator.Radius
            var TwoPi = Math.PI * 2;

            var rangeMeters = 222393.344;//meters
            var angle = 30;//degrees

            double lonA = Longitude * DegreesToRadians;
            double latA = Latitude * DegreesToRadians;
            double angularDistance = 2;//rangeMeters / EarthRadius;
            double angularDistance2 = rangeMeters / 111196.672;
            double trueCourse = angle * DegreesToRadians;

            double lat = Math.Asin(
                Math.Sin(latA) * Math.Cos(angularDistance) +
                Math.Cos(latA) * Math.Sin(angularDistance) * Math.Cos(trueCourse));

            double dlon = Math.Atan2(
                Math.Sin(trueCourse) * Math.Sin(angularDistance) * Math.Cos(latA),
                Math.Cos(angularDistance) - Math.Sin(latA) * Math.Sin(lat));

            double lon = ((lonA + dlon + Math.PI) % TwoPi) - Math.PI;

            var endPoint = SphericalMercator.FromLonLat(Longitude+lon, Latitude+lat);

            StyleCollection stylesB = new StyleCollection
            {
                new VectorStyle{ Fill = new Brush(Color.Green), Outline = new Pen(Color.Red, 4) },
                new LabelStyle{ Text = "B ("+(Longitude+lon).ToString().Replace(",",".")+", "+(Latitude+lat).ToString().Replace(",",".")+")", BackColor = new Brush(Color.Transparent), HorizontalAlignment = LabelStyle.HorizontalAlignmentEnum.Left, Offset = new Offset(0,-25, false) }
            };
            var pointB = new Feature { Geometry = endPoint, Styles = stylesB };
            pointLayer.Add(pointB);


            var line = new LineString(new []{startPoint, endPoint});
            var lineAB = new Feature { Geometry = line, Styles = new StyleCollection{ new VectorStyle{ Line = new Pen(Color.Black, 5) }, new LabelStyle{ Text = String.Concat(/*rangeMeters, "m , ",*/"dist:",2,"° / angle:", angle, "° "), BackColor = new Brush(Color.Gray) } } };
            pointLayer.Add(lineAB);


            var thePoint = SphericalMercator.FromLonLat(Math.Sqrt(3)+12, 35);
            StyleCollection stylesX = new StyleCollection
            {
                new VectorStyle{ Fill = new Brush(Color.Yellow), Outline = new Pen(Color.Blue, 4) },
                new LabelStyle{ Text = "X ("+(Math.Sqrt(3)+12).ToString().Replace(",",".")+", "+(35).ToString().Replace(",",".")+")", BackColor = new Brush(Color.Transparent), Offset = new Offset(0,30, false) }
            };
            var pointX = new Feature { Geometry = thePoint, Styles = stylesX };
            pointLayer.Add(pointX);

To calculate distance your have to transform to WGS84 (EPGS:4326) and then calculate distance with a method that takes the shape of the earth into account. Maybe this (did a quick google) https://stackoverflow.com/a/24712129/85325

I do I do but still can't get correct position of point B.
I'm checking at the provided link now, thanks.

Calculating the distance for lonlat points is a general thing. So there should be a lot of resources that can help you with that.

Yes, I look over some currently.
Please keep the issue open, I'll share the final solution, maybe it will be useful to someone and then I will close it.

What this RotateClockwiseDegrees(Double, Double, Double) is doing exactly?

"Rotates the specified point clockwise about the origin" - sorry, I don't get it. From algebra and linear function I thought that a point doesn't have any direction. (not as a line, which has a directional factor)
Am I wrong?

P1(12,34) -> RCD(12, 34, 90) = P2(34,-12)
P1(12,34) -> RCD(12, 34, 180) = P2(-12,-34)
P1(12,34) -> RCD(12, 34, 270) = P2(-34,12)
What's this for, when could it be useful?

P1(12,34) -> RCD(12, 34, 30) = P2(27.3923, 23.4448)
P1(12,34) -> RCD(12, 34, -30) = P2(-6.6076, 35.4448)

A point has no direction. The point is rotated relative to the origin. This logic is used when a geometry is rotated around it's center. Look at the Geomorpher. It is totally unrelated to calculating distance.

Did you try to the stackoverflow answer I pointed to?

@lukaszpitulski This is still open. Did you find the correct function? Are you still searching?

ooo yes, I've found the solution a few days after @pauldendulk post.
But if you have anything, any idea, please share it.

Unfortunately, till now I've not implemented this in the app.
I was very busy with others projects, which draws me away from that all the time.
If you wish I can share here what I have, or just close the issue.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

charlenni picture charlenni  ·  3Comments

willy40 picture willy40  ·  6Comments

TarasParashchuk picture TarasParashchuk  ·  4Comments

Wil69 picture Wil69  ·  5Comments

lukaszpitulski picture lukaszpitulski  ·  8Comments