This commit is contained in:
Rustam Zaitov 2014-09-19 21:31:49 +04:00
Родитель b3ab014ff5
Коммит 16d7083640
45 изменённых файлов: 1008 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,32 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Footprint", "Footprint\Footprint.csproj", "{F8FE1176-70FB-428C-A099-2032DC7C585C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|iPhoneSimulator = Debug|iPhoneSimulator
Release|iPhoneSimulator = Release|iPhoneSimulator
Debug|iPhone = Debug|iPhone
Release|iPhone = Release|iPhone
Ad-Hoc|iPhone = Ad-Hoc|iPhone
AppStore|iPhone = AppStore|iPhone
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F8FE1176-70FB-428C-A099-2032DC7C585C}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone
{F8FE1176-70FB-428C-A099-2032DC7C585C}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone
{F8FE1176-70FB-428C-A099-2032DC7C585C}.AppStore|iPhone.ActiveCfg = AppStore|iPhone
{F8FE1176-70FB-428C-A099-2032DC7C585C}.AppStore|iPhone.Build.0 = AppStore|iPhone
{F8FE1176-70FB-428C-A099-2032DC7C585C}.Debug|iPhone.ActiveCfg = Debug|iPhone
{F8FE1176-70FB-428C-A099-2032DC7C585C}.Debug|iPhone.Build.0 = Debug|iPhone
{F8FE1176-70FB-428C-A099-2032DC7C585C}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{F8FE1176-70FB-428C-A099-2032DC7C585C}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{F8FE1176-70FB-428C-A099-2032DC7C585C}.Release|iPhone.ActiveCfg = Release|iPhone
{F8FE1176-70FB-428C-A099-2032DC7C585C}.Release|iPhone.Build.0 = Release|iPhone
{F8FE1176-70FB-428C-A099-2032DC7C585C}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{F8FE1176-70FB-428C-A099-2032DC7C585C}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
StartupItem = Footprint\Footprint.csproj
EndGlobalSection
EndGlobal

Просмотреть файл

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Foundation;
using UIKit;
namespace Footprint
{
[Register ("AppDelegate")]
public partial class AppDelegate : UIApplicationDelegate
{
public override UIWindow Window { get; set; }
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
</dict>
</plist>

Просмотреть файл

@ -0,0 +1,150 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform>
<ProjectTypeGuids>{FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<ProjectGuid>{F8FE1176-70FB-428C-A099-2032DC7C585C}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>Footprint</RootNamespace>
<IPhoneResourcePrefix>Resources</IPhoneResourcePrefix>
<AssemblyName>Footprint</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\iPhoneSimulator\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
<MtouchArch>i386, x86_64</MtouchArch>
<MtouchLink>None</MtouchLink>
<MtouchDebug>true</MtouchDebug>
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhoneSimulator' ">
<DebugType>full</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\iPhoneSimulator\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<MtouchLink>None</MtouchLink>
<MtouchArch>i386, x86_64</MtouchArch>
<ConsolePause>false</ConsolePause>
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\iPhone\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
<MtouchArch>ARMv7, ARM64</MtouchArch>
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
<CodesignKey>iPhone Developer</CodesignKey>
<MtouchDebug>true</MtouchDebug>
<MtouchI18n>
</MtouchI18n>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' ">
<DebugType>full</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\iPhone\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
<MtouchArch>ARMv7, ARM64</MtouchArch>
<ConsolePause>false</ConsolePause>
<CodesignKey>iPhone Developer</CodesignKey>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Ad-Hoc|iPhone' ">
<DebugType>full</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\iPhone\Ad-Hoc</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
<MtouchArch>ARMv7, ARM64</MtouchArch>
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
<BuildIpa>true</BuildIpa>
<CodesignProvision>Automatic:AdHoc</CodesignProvision>
<CodesignKey>iPhone Distribution</CodesignKey>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'AppStore|iPhone' ">
<DebugType>full</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\iPhone\AppStore</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
<MtouchArch>ARMv7, ARM64</MtouchArch>
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
<CodesignProvision>Automatic:AppStore</CodesignProvision>
<CodesignKey>iPhone Distribution</CodesignKey>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Xml" />
<Reference Include="System.Core" />
<Reference Include="Xamarin.iOS" />
</ItemGroup>
<ItemGroup>
<None Include="Info.plist" />
<None Include="Entitlements.plist" />
</ItemGroup>
<ItemGroup>
<Compile Include="Main.cs" />
<Compile Include="AppDelegate.cs" />
<Compile Include="MainViewController.cs" />
<Compile Include="Math\CoordinateConverter.cs" />
<Compile Include="Math\EastSouthDistance.cs" />
<Compile Include="Math\GeoAnchor.cs" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
<ItemGroup>
<InterfaceDefinition Include="Main.storyboard" />
</ItemGroup>
<ItemGroup>
<Folder Include="Resources\Images.xcassets\" />
<Folder Include="Resources\Images.xcassets\AppIcon.appiconset\" />
<Folder Include="Resources\Images.xcassets\LaunchImage.launchimage\" />
<Folder Include="Math\" />
</ItemGroup>
<ItemGroup>
<ImageAsset Include="Resources\Images.xcassets\FLOORPLAN_IMAGE_LANDSCAPE.imageset\Contents.json" />
<ImageAsset Include="Resources\Images.xcassets\FLOORPLAN_IMAGE_LANDSCAPE.imageset\FLOORPLAN_IMAGE_LANDSCAPE.png" />
<ImageAsset Include="Resources\Images.xcassets\FLOORPLAN_IMAGE_PORTRAIT.imageset\Contents.json" />
<ImageAsset Include="Resources\Images.xcassets\FLOORPLAN_IMAGE_PORTRAIT.imageset\FLOORPLAN_IMAGE_PORTRAIT.png" />
<ImageAsset Include="Resources\Images.xcassets\pin.imageset\Contents.json" />
<ImageAsset Include="Resources\Images.xcassets\pin.imageset\pin.png" />
<ImageAsset Include="Resources\Images.xcassets\radius.imageset\Contents.json" />
<ImageAsset Include="Resources\Images.xcassets\radius.imageset\radius.png" />
<ImageAsset Include="Resources\Images.xcassets\AppIcon.appiconset\Contents.json" />
<ImageAsset Include="Resources\Images.xcassets\AppIcon.appiconset\Icon-60%402x.png" />
<ImageAsset Include="Resources\Images.xcassets\AppIcon.appiconset\Icon-72.png" />
<ImageAsset Include="Resources\Images.xcassets\AppIcon.appiconset\Icon-72%402x.png" />
<ImageAsset Include="Resources\Images.xcassets\AppIcon.appiconset\Icon-76.png" />
<ImageAsset Include="Resources\Images.xcassets\AppIcon.appiconset\Icon-76%402x.png" />
<ImageAsset Include="Resources\Images.xcassets\AppIcon.appiconset\Icon-Small-50.png" />
<ImageAsset Include="Resources\Images.xcassets\AppIcon.appiconset\Icon-Small-50%402x.png" />
<ImageAsset Include="Resources\Images.xcassets\AppIcon.appiconset\Icon-Small.png" />
<ImageAsset Include="Resources\Images.xcassets\AppIcon.appiconset\Icon-Small%402x.png" />
<ImageAsset Include="Resources\Images.xcassets\AppIcon.appiconset\Icon-Spotlight-40.png" />
<ImageAsset Include="Resources\Images.xcassets\AppIcon.appiconset\Icon-Spotlight-40%402x.png" />
<ImageAsset Include="Resources\Images.xcassets\AppIcon.appiconset\Icon.png" />
<ImageAsset Include="Resources\Images.xcassets\AppIcon.appiconset\Icon%402x.png" />
<ImageAsset Include="Resources\Images.xcassets\LaunchImage.launchimage\Contents.json" />
<ImageAsset Include="Resources\Images.xcassets\LaunchImage.launchimage\Default-568h%402x.png" />
<ImageAsset Include="Resources\Images.xcassets\LaunchImage.launchimage\Default-Landscape%402x~ipad.png" />
<ImageAsset Include="Resources\Images.xcassets\LaunchImage.launchimage\Default-Landscape~ipad.png" />
<ImageAsset Include="Resources\Images.xcassets\LaunchImage.launchimage\Default-Portrait%402x~ipad.png" />
<ImageAsset Include="Resources\Images.xcassets\LaunchImage.launchimage\Default-Portrait~ipad.png" />
<ImageAsset Include="Resources\Images.xcassets\LaunchImage.launchimage\Default.png" />
<ImageAsset Include="Resources\Images.xcassets\LaunchImage.launchimage\Default%402x.png" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDisplayName</key>
<string>Footprint</string>
<key>CFBundleIdentifier</key>
<string>com.your-company.Footprint</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>MinimumOSVersion</key>
<string>8.0</string>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Your location is used to show you how to use CoreLocation!</string>
<key>UIBackgroundModes</key>
<array>
<string>location</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>XSAppIconAssets</key>
<string>Resources/Images.xcassets/AppIcon.appiconset</string>
<key>XSLaunchImageAssets</key>
<string>Resources/Images.xcassets/LaunchImage.launchimage</string>
</dict>
</plist>

Просмотреть файл

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Foundation;
using UIKit;
namespace Footprint
{
public class Application
{
static void Main (string[] args)
{
UIApplication.Main (args, null, "AppDelegate");
}
}
}

Просмотреть файл

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6154.21" systemVersion="13E28" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="vXZ-lx-hvc">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6153.13"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="ufC-wZ-h7g">
<objects>
<viewController id="vXZ-lx-hvc" customClass="MainViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="wKM-50-wav"/>
<viewControllerLayoutGuide type="bottom" id="BSO-b2-nar"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="JIg-XY-Nu0">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="FLOORPLAN_IMAGE_PORTRAIT" translatesAutoresizingMaskIntoConstraints="NO" id="Gk1-8e-5tu">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
</imageView>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="radius" translatesAutoresizingMaskIntoConstraints="NO" id="avJ-F8-Gai">
<rect key="frame" x="6" y="7" width="62" height="62"/>
</imageView>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="pin" translatesAutoresizingMaskIntoConstraints="NO" id="5yS-V7-hCw">
<rect key="frame" x="0.0" y="0.0" width="75" height="75"/>
</imageView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="Gk1-8e-5tu" secondAttribute="trailing" id="Vsq-QW-AQq"/>
<constraint firstAttribute="bottom" secondItem="Gk1-8e-5tu" secondAttribute="bottom" id="hUg-xj-j3X"/>
<constraint firstItem="Gk1-8e-5tu" firstAttribute="top" secondItem="JIg-XY-Nu0" secondAttribute="top" id="jKG-tp-kaQ"/>
<constraint firstItem="Gk1-8e-5tu" firstAttribute="leading" secondItem="JIg-XY-Nu0" secondAttribute="leading" id="pWb-Vu-ztm"/>
</constraints>
</view>
<connections>
<outlet property="imageView" destination="Gk1-8e-5tu" id="5Dx-Mk-i07"/>
<outlet property="pinView" destination="5yS-V7-hCw" id="RQB-Ze-6Dq"/>
<outlet property="radiusView" destination="avJ-F8-Gai" id="FW6-82-6cM"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="x5A-6p-PRh" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="245" y="691"/>
</scene>
</scenes>
<resources>
<image name="FLOORPLAN_IMAGE_PORTRAIT" width="510" height="826"/>
<image name="pin" width="150" height="150"/>
<image name="radius" width="62" height="62"/>
</resources>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar"/>
<simulatedOrientationMetrics key="orientation"/>
<simulatedScreenMetrics key="destination" type="retina4"/>
</simulatedMetricsContainer>
</document>

Просмотреть файл

@ -0,0 +1,162 @@
using System;
using Foundation;
using UIKit;
using MapKit;
using CoreGraphics;
using CoreLocation;
namespace Footprint
{
[Register ("MainViewController")]
public class MainViewController : UIViewController
{
[Outlet ("imageView")]
UIImageView ImageView { get; set; }
[Outlet ("pinView")]
UIImageView PinView { get; set; }
[Outlet ("radiusView")]
UIImageView RadiusView { get; set; }
CLLocationManager locationManager;
Tuple<GeoAnchor, GeoAnchor> anchorPair;
CoordinateConverter coordinateConverter;
nfloat displayScale;
CGPoint displayOffset;
public MainViewController (IntPtr handle)
: base (handle)
{
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
locationManager = new CLLocationManager ();
locationManager.AuthorizationChanged += OnAuthorizationChanged;
locationManager.LocationsUpdated += OnLocationsUpdated;
locationManager.DesiredAccuracy = CLLocation.AccuracyBest;
locationManager.ActivityType = CLActivityType.Other;
// We setup a pair of anchors that will define how the floorplan image, maps to geographic co-ordinates
var anchor1 = new GeoAnchor {
LatitudeLongitude = new CLLocationCoordinate2D (37.770511, -122.465810),
Pixel = new CGPoint (12, 18)
};
var anchor2 = new GeoAnchor {
LatitudeLongitude = new CLLocationCoordinate2D (37.769125, -122.466356),
Pixel = new CGPoint (481, 815)
};
anchorPair = new Tuple<GeoAnchor, GeoAnchor> (anchor1, anchor2);
// Initialize the coordinate system converter with two anchor points.
coordinateConverter = new CoordinateConverter (anchorPair);
}
public override void ViewDidAppear (bool animated)
{
base.ViewDidAppear (animated);
SetScaleAndOffset ();
StartTrackingLocation ();
}
void SetScaleAndOffset ()
{
CGSize imageViewFrameSize = ImageView.Frame.Size;
CGSize imageSize = ImageView.Image.Size;
// Calculate how much we'll be scaling the image to fit on screen.
nfloat wRatio = imageViewFrameSize.Width / imageSize.Width;
nfloat hRatio = imageViewFrameSize.Height / imageSize.Height;
displayScale = NMath.Min (wRatio, hRatio);
Console.WriteLine ("Scale Factor: {0}", displayScale);
// Depending on whether we're constrained by width or height,
// figure out how much our floorplan pixels need to be offset to adjust for the image being centered
if (wRatio < hRatio) {
Console.WriteLine ("Constrained by width");
displayOffset = new CGPoint (0, (imageViewFrameSize.Height - imageSize.Height * displayScale) / 2);
} else {
Console.WriteLine ("Constrained by height");
displayOffset = new CGPoint ((imageViewFrameSize.Width - imageSize.Width * displayScale) / 2, 0);
}
Console.WriteLine ("Offset: x={0}, y={1}", displayOffset.X, displayOffset.Y);
}
void StartTrackingLocation ()
{
CLAuthorizationStatus status = CLLocationManager.Status;
if (status == CLAuthorizationStatus.NotDetermined) {
locationManager.RequestWhenInUseAuthorization ();
} else if (status == CLAuthorizationStatus.AuthorizedWhenInUse || status == CLAuthorizationStatus.AuthorizedAlways) {
locationManager.StartUpdatingLocation ();
}
}
void OnAuthorizationChanged (object sender, CLAuthorizationChangedEventArgs e)
{
switch (e.Status) {
case CLAuthorizationStatus.AuthorizedAlways:
case CLAuthorizationStatus.AuthorizedWhenInUse:
Console.WriteLine ("Got authorization, start tracking location");
StartTrackingLocation ();
break;
case CLAuthorizationStatus.NotDetermined:
locationManager.RequestWhenInUseAuthorization ();
break;
default:
break;
}
}
void OnLocationsUpdated (object sender, CLLocationsUpdatedEventArgs e)
{
// Pass location updates to the map view.
foreach (var l in e.Locations) {
Console.WriteLine ("Location (Floor {0}): {1}", l.Floor, l);
UpdateViewWithLocation (l);
}
}
void UpdateViewWithLocation (CLLocation location)
{
// We animate transition from one position to the next, this makes the dot move smoothly over the map
UIView.Animate (0.75, () => {
// Call the converter to find these coordinates on our floorplan.
CGPoint pointOnImage = coordinateConverter.Convert (location.Coordinate);
// These coordinates need to be scaled based on how much the image has been scaled
var x = pointOnImage.X * displayScale + displayOffset.X;
var y = pointOnImage.Y * displayScale + displayOffset.Y;
var scaledPoint = new CGPoint (x, y);
// Calculate and set the size of the radius
nfloat radiusFrameSize = (nfloat)location.HorizontalAccuracy * coordinateConverter.PixelsPerMeter * 2;
RadiusView.Frame = new CGRect (0, 0, radiusFrameSize, radiusFrameSize);
// Move the pin and radius to the user's location
PinView.Center = scaledPoint;
RadiusView.Center = scaledPoint;
});
}
public override void WillAnimateRotation (UIInterfaceOrientation toInterfaceOrientation, double duration)
{
base.WillAnimateRotation (toInterfaceOrientation, duration);
SetScaleAndOffset ();
}
}
}

Просмотреть файл

@ -0,0 +1,128 @@
using System;
using MapKit;
using CoreGraphics;
using CoreLocation;
namespace Footprint
{
public class CoordinateConverter
{
// We pick one of the anchors on the floorplan as an origin point that we will compute distance relative to.
MKMapPoint fromAnchorMKPoint;
CGPoint fromAnchorFloorplanPoint;
public nfloat PixelsPerMeter { get; private set; }
nfloat radiansRotated;
// This will anchor image to geographic coordinates
public CoordinateConverter (CLLocationCoordinate2D topLeft, CLLocationCoordinate2D bottomRight, CGSize imageSize)
{
var topLeftAnchor = new GeoAnchor {
LatitudeLongitude = topLeft,
Pixel = new CGPoint (0, 0)
};
var bottomRightAnchor = new GeoAnchor {
LatitudeLongitude = bottomRight,
Pixel = new CGPoint (imageSize.Width, imageSize.Height)
};
var anchorPair = new Tuple<GeoAnchor, GeoAnchor> (topLeftAnchor, bottomRightAnchor);
Init (anchorPair);
}
public CoordinateConverter (Tuple<GeoAnchor, GeoAnchor> anchors)
{
Init (anchors);
}
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;
}
// Convert the specified geographic coordinate to floorplan point
public CGPoint Convert (CLLocationCoordinate2D coordinate)
{
// Get the distance east & south with respect to the first anchor point in meters
EastSouthDistance rect = FetchRect (fromAnchorMKPoint, MKMapPoint.FromCoordinate (coordinate));
// Convert the east-south anchor point distance to pixels (still in east-south)
// TODO: https://trello.com/c/aL7pN9yI
var scaleTransform = CGAffineTransform.MakeScale (PixelsPerMeter, PixelsPerMeter);
CGPoint pixelsXYInEastSouth = ApplyTransform (new CGPoint (rect.East, rect.South), scaleTransform);
// Rotate the east-south distance to be relative to floorplan horizontal
// This gives us an xy distance in pixels from the anchor point.
var rotateTransform = CGAffineTransform.MakeRotation (radiansRotated);
CGPoint xy = ApplyTransform (pixelsXYInEastSouth, rotateTransform);
// From Anchor point may not be top letf corner.
// however, we need the pixels from the (0, 0) of the floorplan
// so we adjust by the position of the anchor point in the floorplan
xy.X += fromAnchorFloorplanPoint.X;
xy.Y += fromAnchorFloorplanPoint.Y;
return xy;
}
// 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;
}
static nfloat Hypot (nfloat x, nfloat y)
{
return NMath.Sqrt (x * x + y * y);
}
static CGPoint ApplyTransform (CGPoint point, CGAffineTransform t)
{
CGPoint p = new CGPoint ();
p.X = t.xx * point.X + t.xy * point.Y + t.x0;
p.Y = t.yx * point.X + t.yy * point.Y + t.y0;
return p;
}
}
}

Просмотреть файл

@ -0,0 +1,17 @@
using System;
using CoreLocation;
namespace Footprint
{
// Struct that contains a point in meters (east and south) with respect to an origin point (in geographic space)
// We use East & South because when drawing on an image, origin (0,0) is on the top-left.
// So +eastMeters corresponds to +x and +southMeters corresponds to +y
public struct EastSouthDistance
{
public nfloat East { get; set; }
public nfloat South { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,14 @@
using System;
using CoreLocation;
using CoreGraphics;
namespace Footprint
{
public struct GeoAnchor
{
public CLLocationCoordinate2D LatitudeLongitude { get; set; }
public CGPoint Pixel { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,104 @@
{
"images": [
{
"filename": "Icon-Small.png",
"size": "29x29",
"scale": "1x",
"idiom": "iphone"
},
{
"filename": "Icon-Small@2x.png",
"size": "29x29",
"scale": "2x",
"idiom": "iphone"
},
{
"filename": "Icon-Spotlight-40@2x.png",
"size": "40x40",
"scale": "2x",
"idiom": "iphone"
},
{
"filename": "Icon.png",
"size": "57x57",
"scale": "1x",
"idiom": "iphone"
},
{
"filename": "Icon@2x.png",
"size": "57x57",
"scale": "2x",
"idiom": "iphone"
},
{
"filename": "Icon-60@2x.png",
"size": "60x60",
"scale": "2x",
"idiom": "iphone"
},
{
"filename": "Icon-Small.png",
"size": "29x29",
"scale": "1x",
"idiom": "ipad"
},
{
"filename": "Icon-Small@2x.png",
"size": "29x29",
"scale": "2x",
"idiom": "ipad"
},
{
"filename": "Icon-Spotlight-40.png",
"size": "40x40",
"scale": "1x",
"idiom": "ipad"
},
{
"filename": "Icon-Spotlight-40@2x.png",
"size": "40x40",
"scale": "2x",
"idiom": "ipad"
},
{
"filename": "Icon-Small-50.png",
"size": "50x50",
"scale": "1x",
"idiom": "ipad"
},
{
"filename": "Icon-Small-50@2x.png",
"size": "50x50",
"scale": "2x",
"idiom": "ipad"
},
{
"filename": "Icon-72.png",
"size": "72x72",
"scale": "1x",
"idiom": "ipad"
},
{
"filename": "Icon-72@2x.png",
"size": "72x72",
"scale": "2x",
"idiom": "ipad"
},
{
"filename": "Icon-76.png",
"size": "76x76",
"scale": "1x",
"idiom": "ipad"
},
{
"filename": "Icon-76@2x.png",
"size": "76x76",
"scale": "2x",
"idiom": "ipad"
}
],
"info": {
"version": 1,
"author": "xcode"
}
}

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 7.0 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 5.4 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 8.0 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 5.5 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 8.2 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 4.4 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 6.3 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 3.6 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 4.7 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 4.0 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 5.5 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 4.7 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 6.8 KiB

Просмотреть файл

@ -0,0 +1,13 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "FLOORPLAN_IMAGE_LANDSCAPE.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 268 KiB

Просмотреть файл

@ -0,0 +1,13 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "FLOORPLAN_IMAGE_PORTRAIT.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 279 KiB

Просмотреть файл

@ -0,0 +1,148 @@
{
"images": [
{
"minimum-system-version": "7.0",
"orientation": "portrait",
"extent": "full-screen",
"filename": "Default@2x.png",
"size": "640x960",
"scale": "2x",
"idiom": "iphone"
},
{
"minimum-system-version": "7.0",
"orientation": "portrait",
"extent": "full-screen",
"filename": "Default-568h@2x.png",
"size": "640x1136",
"subtype": "retina4",
"scale": "2x",
"idiom": "iphone"
},
{
"minimum-system-version": "7.0",
"orientation": "portrait",
"extent": "full-screen",
"filename": "Default-Portrait~ipad.png",
"size": "768x1024",
"scale": "1x",
"idiom": "ipad"
},
{
"minimum-system-version": "7.0",
"orientation": "portrait",
"extent": "full-screen",
"filename": "Default-Portrait@2x~ipad.png",
"size": "1536x2048",
"scale": "2x",
"idiom": "ipad"
},
{
"minimum-system-version": "7.0",
"orientation": "landscape",
"extent": "full-screen",
"filename": "Default-Landscape~ipad.png",
"size": "1024x768",
"scale": "1x",
"idiom": "ipad"
},
{
"minimum-system-version": "7.0",
"orientation": "landscape",
"extent": "full-screen",
"filename": "Default-Landscape@2x~ipad.png",
"size": "2048x1536",
"scale": "2x",
"idiom": "ipad"
},
{
"orientation": "portrait",
"extent": "full-screen",
"filename": "Default.png",
"size": "320x480",
"scale": "1x",
"idiom": "iphone"
},
{
"orientation": "portrait",
"extent": "full-screen",
"filename": "Default@2x.png",
"size": "640x960",
"scale": "2x",
"idiom": "iphone"
},
{
"orientation": "portrait",
"extent": "full-screen",
"filename": "Default-568h@2x.png",
"size": "640x1136",
"subtype": "retina4",
"scale": "2x",
"idiom": "iphone"
},
{
"orientation": "portrait",
"extent": "full-screen",
"filename": "Default-Portrait~ipad.png",
"size": "768x1024",
"scale": "1x",
"idiom": "ipad"
},
{
"orientation": "portrait",
"extent": "full-screen",
"filename": "Default-Portrait@2x~ipad.png",
"size": "1536x2048",
"scale": "2x",
"idiom": "ipad"
},
{
"orientation": "portrait",
"extent": "to-status-bar",
"size": "768x1004",
"scale": "1x",
"idiom": "ipad"
},
{
"orientation": "portrait",
"extent": "to-status-bar",
"size": "1536x2008",
"scale": "2x",
"idiom": "ipad"
},
{
"orientation": "landscape",
"extent": "full-screen",
"filename": "Default-Landscape~ipad.png",
"size": "1024x768",
"scale": "1x",
"idiom": "ipad"
},
{
"orientation": "landscape",
"extent": "full-screen",
"filename": "Default-Landscape@2x~ipad.png",
"size": "2048x1536",
"scale": "2x",
"idiom": "ipad"
},
{
"orientation": "landscape",
"extent": "to-status-bar",
"size": "1024x748",
"scale": "1x",
"idiom": "ipad"
},
{
"orientation": "landscape",
"extent": "to-status-bar",
"size": "2048x1496",
"scale": "2x",
"idiom": "ipad"
}
],
"info": {
"version": 1,
"author": "xcode"
}
}

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 61 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 22 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 28 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 21 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 42 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 14 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 38 KiB

Просмотреть файл

@ -0,0 +1,13 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "pin.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Двоичные данные
ios8/Footprint/Footprint/Resources/Images.xcassets/pin.imageset/pin.png поставляемый Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 7.5 KiB

Просмотреть файл

@ -0,0 +1,13 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "radius.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Двоичные данные
ios8/Footprint/Footprint/Resources/Images.xcassets/radius.imageset/radius.png поставляемый Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 4.1 KiB

Просмотреть файл

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8" ?>
<SampleMetadata>
<ID>4fbc7a89-cbc0-496a-85f5-5be69fcca74d</ID>
<IsFullApplication>false</IsFullApplication>
<Level>Beginning</Level>
<Tags>Device Features,Maps & Location, iOS8</Tags>
<SupportedPlatforms>iOS</SupportedPlatforms>
<Gallery>true</Gallery>
<MinimumLicenseRequirement>Starter</MinimumLicenseRequirement>
</SampleMetadata>

37
ios8/Footprint/README.md Normal file
Просмотреть файл

@ -0,0 +1,37 @@
Footprint
==============
Display device location on a floorplan image.
Using Core Location, we will take the position in Latitude/Longitude and project it onto a flat floorplan. We will demonstrate how to do the conversion from the Geographic coordinates system (Latitude/Longitude) to the floorplan's image coordinate system (x,y)
**Note:** For this sample to function, you must have a floorplan for a venue that is Indoor Positioning enabled. To see the the apporpriate position on the floorplan, the device will need to be in that venue. If you are not in a venue, you must emulate a position in the venue using "Custom Location" in the simulator.
Using Your Own Floorplan
------------------------
If you have a venue floorplan you would like to use, make the following changes:
* Replace the existing `FLOORPLAN_IMAGE` in the image Assets
* Set the two anchor points in `MainViewController`: These are two points on the floorplan in Latitude/Longitude, and Image x,y
Refs
----
https://developer.apple.com/videos/wwdc/2014/
* Taking Core Location Indoors (recomended)
* What's New in Core Location (optional)
Build Requirements
------------------
Building this sample requires Xcode 6.0 and iOS 8.0 SDK
Target
------
This sample runnable on iPhoneSimulator/iPadSimulator iPhone/iPad
Author
------
IOS:
Copyright (C) 2014 Apple Inc. All rights reserved.
Ported to Xamarin.iOS by Rustam Zaitov

Двоичные данные
ios8/Footprint/Screenshots/iPad/Footplan.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 740 KiB

Двоичные данные
ios8/Footprint/Screenshots/iPhone/Footplan.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 270 KiB