Ejemplo n.º 1
0
        void Init(Tuple <GeoAnchor, GeoAnchor> anchors)
        {
            // To compute the distance between two geographical co-ordinates, we first need to
            // convert to MapKit co-ordinates
            fromAnchorFloorplanPoint = anchors.Item1.Pixel;
            fromAnchorMKPoint        = MKMapPoint.FromCoordinate(anchors.Item1.LatitudeLongitude);
            MKMapPoint toAnchorMKPoint = MKMapPoint.FromCoordinate(anchors.Item2.LatitudeLongitude);

            // So that we can use MapKit's helper function to compute distance.
            // this helper function takes into account the curvature of the earth.
            var distanceBetweenPointsMeters = (nfloat)MKGeometry.MetersBetweenMapPoints(fromAnchorMKPoint, toAnchorMKPoint);

            var dx = anchors.Item1.Pixel.X - anchors.Item2.Pixel.X;
            var dy = anchors.Item1.Pixel.Y - anchors.Item2.Pixel.Y;

            // Distance between two points in pixels (on the floorplan image)
            var distanceBetweenPointsPixels = Hypot(dx, dy);

            // This gives us pixels/meter
            PixelsPerMeter = distanceBetweenPointsPixels / distanceBetweenPointsMeters;

            // Get the 2nd anchor's eastward/southward distance in meters from the first anchor point.
            var hyp = FetchRect(fromAnchorMKPoint, toAnchorMKPoint);

            // Angle of diagonal to east (in geographic)
            nfloat angleFromEastAndHypo = NMath.Atan2(hyp.South, hyp.East);

            // Angle of diagonal to horizontal (in floorplan)
            nfloat angleFromXAndHypo = NMath.Atan2(dy, dx);

            // Rotation amount from the geographic anchor line segment
            // to the floorplan anchor line segment
            // This is angle between X axis and East direction. This angle shows how you floor plan exists in real world
            radiansRotated = angleFromXAndHypo - angleFromEastAndHypo;
        }
Ejemplo n.º 2
0
        // MapKit alternative
        public static double MKGetDistanceBetween(Airport airport1, Airport airport2)
        {
            CLLocationCoordinate2D loc1   = new CLLocationCoordinate2D(airport1.Latitude, airport1.Longitude);
            CLLocationCoordinate2D loc2   = new CLLocationCoordinate2D(airport2.Latitude, airport2.Longitude);
            MKMapPoint             point1 = MKMapPoint.FromCoordinate(loc1);
            MKMapPoint             point2 = MKMapPoint.FromCoordinate(loc2);

            return(MKGeometry.MetersBetweenMapPoints(point1, point2) / MetersPerNauticalMile);
        }
Ejemplo n.º 3
0
        // Two points in rectangular co-ordinate system create a rectange
        static EastSouthDistance FetchRect(MKMapPoint fromAnchorMKPoint, MKMapPoint toPoint)
        {
            double latitude          = MKMapPoint.ToCoordinate(fromAnchorMKPoint).Latitude;
            nfloat metersPerMapPoint = (nfloat)MKGeometry.MetersPerMapPointAtLatitude(latitude);

            var eastSouthDistance = new EastSouthDistance {
                East  = (nfloat)(toPoint.X - fromAnchorMKPoint.X) * metersPerMapPoint,
                South = (nfloat)(toPoint.Y - fromAnchorMKPoint.Y) * metersPerMapPoint
            };

            return(eastSouthDistance);
        }
Ejemplo n.º 4
0
        public void MetersPerMapPointAtLatitude()
        {
            Assert.That(MKGeometry.MetersPerMapPointAtLatitude(0), Is.EqualTo(0.148).Within(0.001), "0");

            Assert.That(MKGeometry.MetersPerMapPointAtLatitude(90), Is.EqualTo(0.254).Within(0.001), "90");
            Assert.That(MKGeometry.MetersPerMapPointAtLatitude(91), Is.EqualTo(Double.PositiveInfinity), "91");

            Assert.That(MKGeometry.MetersPerMapPointAtLatitude(-90), Is.EqualTo(0.000416).Within(0.000001), "-90");
            Assert.That(MKGeometry.MetersPerMapPointAtLatitude(-91), Is.EqualTo(Double.PositiveInfinity), "-91");

            Assert.That(MKGeometry.MetersPerMapPointAtLatitude(Double.NaN), Is.NaN, "NaN");
            Assert.That(MKGeometry.MetersPerMapPointAtLatitude(Double.NegativeInfinity), Is.NaN, "NegativeInfinity");
            Assert.That(MKGeometry.MetersPerMapPointAtLatitude(Double.PositiveInfinity), Is.NaN, "PositiveInfinity");
        }
Ejemplo n.º 5
0
        public void MapPointsPerMeterAtLatitude()
        {
            Assert.That(MKGeometry.MapPointsPerMeterAtLatitude(0), Is.EqualTo(6.743).Within(0.001), "0");

            Assert.That(MKGeometry.MapPointsPerMeterAtLatitude(90), Is.EqualTo(3.936).Within(0.001), "90");
            Assert.That(MKGeometry.MapPointsPerMeterAtLatitude(91), Is.EqualTo(0), "91");

            Assert.That(MKGeometry.MapPointsPerMeterAtLatitude(-90), Is.EqualTo(2399.37).Within(0.01), "-90");
            Assert.That(MKGeometry.MapPointsPerMeterAtLatitude(-91), Is.EqualTo(0), "-91");

            Assert.That(MKGeometry.MapPointsPerMeterAtLatitude(Double.NaN), Is.NaN, "NaN");
            Assert.That(MKGeometry.MapPointsPerMeterAtLatitude(Double.NegativeInfinity), Is.NaN, "NegativeInfinity");
            Assert.That(MKGeometry.MapPointsPerMeterAtLatitude(Double.PositiveInfinity), Is.NaN, "PositiveInfinity");
        }
Ejemplo n.º 6
0
        public void MetersBetweenMapPoints()
        {
            MKMapPoint a = new MKMapPoint();

            Assert.That(MKGeometry.MetersBetweenMapPoints(a, a), Is.EqualTo(0.0), "a-a");

            MKMapPoint b = new MKMapPoint(1000, 1000);

            Assert.That(MKGeometry.MetersBetweenMapPoints(b, b), Is.EqualTo(0.0), "b-b");

            Assert.That(MKGeometry.MetersBetweenMapPoints(a, b), Is.EqualTo(18.153).Within(0.001), "a-b");
            Assert.That(MKGeometry.MetersBetweenMapPoints(b, a), Is.EqualTo(18.153).Within(0.001), "b-a");

            MKMapPoint c = new MKMapPoint(Double.NaN, Double.NaN);

            Assert.That(MKGeometry.MetersBetweenMapPoints(a, c), Is.NaN, "NaN");
        }
Ejemplo n.º 7
0
        public MapCluster(List <MapPointAnnotation> annotations, int depth, MKMapRect mapRect, double gamma, string clusterTitle, bool showSubtitle)
        {
            Depth         = depth;
            _mapRect      = mapRect;
            _clusterTitle = clusterTitle;
            ShowSubtitle  = showSubtitle;

            switch (annotations.Count)
            {
            case 0:
                _leftChild        = null;
                _rightChild       = null;
                Annotation        = null;
                ClusterCoordinate = new CLLocationCoordinate2D(91, 181);    // Todo: Invalid, instead of constant.
                break;

            case 1:
                _leftChild        = null;
                _rightChild       = null;
                Annotation        = annotations.Last();
                ClusterCoordinate = Annotation.Annotation.Coordinate;
                break;

            default:
            {
                Annotation = null;

                // Principal Component Analysis
                // If cov(x,y) = ∑(x-x_mean) * (y-y_mean) != 0 (covariance different from zero), we are looking for the following principal vector:
                // a (aX)
                //   (aY)
                //
                // x_ = x - x_mean ; y_ = y - y_mean
                //
                // aX = cov(x_,y_)
                //
                //
                // aY = 0.5/n * ( ∑(x_^2) + ∑(y_^2) + sqrt( (∑(x_^2) + ∑(y_^2))^2 + 4 * cov(x_,y_)^2 ) )

                // compute the means of the coordinate
                var xSum = 0.0;
                var ySum = 0.0;

                foreach (var annotation in annotations)
                {
                    xSum += annotation.MapPoint.X;
                    ySum += annotation.MapPoint.Y;
                }

                var xMean = xSum / annotations.Count;
                var yMean = ySum / annotations.Count;

                if (gamma != 1.0)
                {
                    // take gamma weight into account
                    var gammaSumX   = 0.0;
                    var gammaSumY   = 0.0;
                    var maxDistance = 0.0;
                    var meanCenter  = new MKMapPoint(xMean, yMean);

                    foreach (var annotation in annotations)
                    {
                        var distance = MKGeometry.MetersBetweenMapPoints(annotation.MapPoint, meanCenter);
                        if (distance > maxDistance)
                        {
                            maxDistance = distance;
                        }
                    }

                    var totalWeight = 0.0;
                    foreach (var annotation in annotations)
                    {
                        var point              = annotation.MapPoint;
                        var distance           = MKGeometry.MetersBetweenMapPoints(point, meanCenter);
                        var normalizedDistance = maxDistance != 0.0 ? distance / maxDistance : 1.0;
                        var weight             = Math.Pow(normalizedDistance, gamma - 1.0);
                        gammaSumX   += point.X * weight;
                        gammaSumY   += point.Y * weight;
                        totalWeight += weight;
                    }

                    xMean = gammaSumX / totalWeight;
                    yMean = gammaSumY / totalWeight;
                }
                // compute coefficients

                var sumXsquared = 0.0;
                var sumYsquared = 0.0;
                var sumXy       = 0.0;

                foreach (var annotation in annotations)
                {
                    var x = annotation.MapPoint.X - xMean;
                    var y = annotation.MapPoint.Y - yMean;
                    sumXsquared += x * x;
                    sumYsquared += y * y;
                    sumXy       += x * y;
                }

                double aX;
                double aY;

                if (Math.Abs(sumXy) / annotations.Count > MapConstants.ClusterDiscriminationPrecision)
                {
                    aX = sumXy;
                    var lambda = 0.5 * ((sumXsquared + sumYsquared) + Math.Sqrt((sumXsquared + sumYsquared) * (sumXsquared + sumYsquared) + 4 * sumXy * sumXy));
                    aY = lambda - sumXsquared;
                }
                else
                {
                    aX = sumXsquared > sumYsquared ? 1.0 : 0.0;
                    aY = sumXsquared > sumYsquared ? 0.0 : 1.0;
                }

                List <MapPointAnnotation> leftAnnotations;
                List <MapPointAnnotation> rightAnnotations;

                if (Math.Abs(sumXsquared) / annotations.Count < MapConstants.ClusterDiscriminationPrecision || Math.Abs(sumYsquared) / annotations.Count < MapConstants.ClusterDiscriminationPrecision)
                {
                    // then every x equals XMean and we have to arbitrarily choose where to put the pivotIndex
                    var pivotIndex = annotations.Count / 2;
                    leftAnnotations  = annotations.GetRange(0, pivotIndex);
                    rightAnnotations = annotations.GetRange(pivotIndex, annotations.Count - pivotIndex);
                }
                else
                {
                    // compute scalar product between the vector of this regression line and the vector
                    // (x - x(mean))
                    // (y - y(mean))
                    // the sign of this scalar product determines which cluster the point belongs to
                    leftAnnotations  = new List <MapPointAnnotation>();
                    rightAnnotations = new List <MapPointAnnotation>();

                    foreach (var annotation in annotations)
                    {
                        var point = annotation.MapPoint;
                        var positivityConditionOfScalarProduct = true;

                        // TODO: Don't know why this is here... its there in the original code. Or is it a wrong Objective-C interpretation?
                        if (true)
                        {
                            positivityConditionOfScalarProduct = (point.X - xMean) * aX + (point.Y - yMean) * aY > 0.0;
                        }
                        else
                        {
                            positivityConditionOfScalarProduct = (point.Y - yMean) > 0.0;
                        }

                        if (positivityConditionOfScalarProduct)
                        {
                            leftAnnotations.Add(annotation);
                        }
                        else
                        {
                            rightAnnotations.Add(annotation);
                        }
                    }
                }

                // compute map rects
                double xMin = float.MaxValue, xMax = 0.0f, yMin = float.MaxValue, yMax = 0.0f;

                foreach (var point in leftAnnotations.Select(annotation => annotation.MapPoint))
                {
                    if (point.X > xMax)
                    {
                        xMax = point.X;
                    }
                    if (point.Y > yMax)
                    {
                        yMax = point.Y;
                    }
                    if (point.X < xMin)
                    {
                        xMin = point.X;
                    }
                    if (point.Y < yMin)
                    {
                        yMin = point.Y;
                    }
                }

                var leftMapRect = new MKMapRect(xMin, yMin, xMax - xMin, yMax - yMin);

                xMin = float.MaxValue;
                xMax = 0.0;
                yMin = float.MaxValue;
                yMax = 0.0;

                foreach (var point in rightAnnotations.Select(annotation => annotation.MapPoint))
                {
                    if (point.X > xMax)
                    {
                        xMax = point.X;
                    }
                    if (point.Y > yMax)
                    {
                        yMax = point.Y;
                    }
                    if (point.X < xMin)
                    {
                        xMin = point.X;
                    }
                    if (point.Y < yMin)
                    {
                        yMin = point.Y;
                    }
                }

                var rightMapRect = new MKMapRect(xMin, yMin, xMax - xMin, yMax - yMin);
                ClusterCoordinate = MKMapPoint.ToCoordinate(new MKMapPoint(xMean, yMean));
                _leftChild        = new MapCluster(leftAnnotations, depth + 1, leftMapRect, gamma, clusterTitle, showSubtitle);
                _rightChild       = new MapCluster(rightAnnotations, depth + 1, rightMapRect, gamma, clusterTitle, showSubtitle);
            }

            break;
            }
        }