====== Source Code iOSEditionSample AnalyzeVisual.zip ====== ====AppDelegate.cs==== using Foundation; using UIKit; namespace AnalyzingVisualization { // The UIApplicationDelegate for the application. This class is responsible for launching the // User Interface of the application, as well as listening (and optionally responding) to // application events from iOS. [Register("AppDelegate")] public partial class AppDelegate : UIApplicationDelegate { // class-level declarations public override UIWindow Window { get; set; } // This method is invoked when the application is about to move from active to inactive state. // OpenGL applications should use this method to pause. public override void OnResignActivation(UIApplication application) { } // This method should be used to release shared resources and it should store the application state. // If your application supports background exection this method is called instead of WillTerminate // when the user quits. public override void DidEnterBackground(UIApplication application) { } // This method is called as part of the transiton from background to active state. public override void WillEnterForeground(UIApplication application) { } // This method is called when the application is about to terminate. Save data, if needed. public override void WillTerminate(UIApplication application) { } } } ====Main.cs==== using UIKit; namespace AnalyzingVisualization { public class Application { // This is the main entry point of the application. static void Main(string[] args) { // if you want to use a different Application Delegate class from "AppDelegate" // you can specify it here. UIApplication.Main(args, null, "AppDelegate"); } } } ====MainViewController.cs==== using MonoTouch.Dialog; using UIKit; using System; using System.Collections.ObjectModel; using System.Linq; using System.Reflection; using System.Xml.Linq; namespace AnalyzingVisualization { public partial class MainViewController : UIViewController { public MainViewController(IntPtr handle) : base(handle) { } public override void ViewDidLoad() { base.ViewDidLoad(); SliderViewController navigation = new SliderViewController(); navigation.Position = FlyOutPosition.Left; navigation.View.Frame = UIScreen.MainScreen.Bounds; View.AddSubview(navigation.View); AddChildViewController(navigation); XDocument xDoc = XDocument.Load("AppData/SampleList.xml"); Section section = new Section("Style List"); if (xDoc.Root != null) { Collection styleList = new Collection(); foreach (var element in xDoc.Root.Elements()) { string image = element.Attribute("Image").Value; string className = element.Attribute("Class").Value; string name = element.Attribute("Name").Value; UIImage icon = UIImage.FromBundle(image); BadgeElement iconItem = new BadgeElement(icon, name); section.Add(iconItem); DetailViewController rootController = (DetailViewController)Activator.CreateInstance(Assembly.GetExecutingAssembly().GetType("AnalyzingVisualization." + className)); rootController.DetailButtonClick = navigation.ToggleMenu; rootController.Title = name; UINavigationController mainController = new UINavigationController(rootController); styleList.Add(mainController); } navigation.ViewControllers = styleList.ToArray(); } navigation.NavigationRoot = new RootElement("Style List") { section }; } } } ====MainViewController.designer.cs==== // WARNING // // This file has been generated automatically by Xamarin Studio from the outlets and // actions declared in your storyboard file. // Manual changes to this file will not be maintained. // using System; using Foundation; using UIKit; using System.CodeDom.Compiler; namespace AnalyzingVisualization { [Register|("MainViewController")] partial class MainViewController { void ReleaseDesignerOutlets () { } } } ====DotDenstyStyleViewContoller.cs==== using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.iOSEdition; namespace AnalyzingVisualization { public class DotDenstyStyleViewContoller : DetailViewController { public DotDenstyStyleViewContoller() { } protected override void InitializeMap() { base.InitializeMap(); MapView.MapUnit = GeographyUnit.DecimalDegree; WorldMapKitOverlay worldOverlay = new WorldMapKitOverlay(); MapView.Overlays.Add(worldOverlay); ShapeFileFeatureLayer usLayer = new ShapeFileFeatureLayer("AppData/usStatesCensus2010.shp"); LayerOverlay layerOverlay = new LayerOverlay(); layerOverlay.Layers.Add(usLayer); MapView.Overlays.Add(layerOverlay); usLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Clear(); usLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(20, GeoColor.FromHtml("#00e6fe")), GeoColor.StandardColors.Gray)); usLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(GetDotDensityStyle()); usLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; MapView.ZoomTo(new PointShape(-96.8150, 39.6948), MapView.ZoomLevelSet.ZoomLevel05.Scale); } private static DotDensityStyle GetDotDensityStyle() { double pointToValueRatio = 0.0000094778167166538189; PointStyle pointStyle = PointStyles.CreateSimpleCircleStyle(GeoColor.StandardColors.Black, 7); DotDensityStyle dotDensityStyle = new DotDensityStyle("Population", pointToValueRatio, pointStyle); dotDensityStyle.CustomPointStyle = PointStyles.CreateSimpleCircleStyle(GeoColor.FromHtml("#a57431"), 5); return dotDensityStyle; } } } ====HeatStyleViewContoller.cs==== using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.iOSEdition; namespace AnalyzingVisualization { public class HeatStyleViewContoller : DetailViewController { public HeatStyleViewContoller() { } protected override void InitializeMap() { MapView.MapUnit = GeographyUnit.DecimalDegree; MapView.CurrentExtent = new RectangleShape(-124.097208477811, 48.9471097666172, -110.242106301448, 28.7359794668483); WorldMapKitOverlay worldOverlay = new WorldMapKitOverlay(); MapView.Overlays.Add(worldOverlay); ShapeFileFeatureLayer usEarthquakeLayer = new ShapeFileFeatureLayer("AppData/usEarthquake_Simplified.shp"); MapView.Overlays.Add(new LayerOverlay(new Layer[] { usEarthquakeLayer })); usEarthquakeLayer.DrawingMarginPercentage = 100; usEarthquakeLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Clear(); usEarthquakeLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(new HeatStyle(10, 150, "MAGNITUDE", 0, 12, 100, DistanceUnit.Kilometer)); usEarthquakeLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; MapView.Refresh(); } } } ====IconStyleViewController.cs==== using System.Globalization; using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.iOSEdition; namespace AnalyzingVisualization { public class IconStyleViewController : DetailViewController { public IconStyleViewController() { } protected override void InitializeMap() { MapView.MapUnit = GeographyUnit.DecimalDegree; View.AddSubview(MapView); WorldMapKitOverlay worldOverlay = new WorldMapKitOverlay(); MapView.Overlays.Add(worldOverlay); ShapeFileFeatureLayer iconStyleFeatureLayer = new ShapeFileFeatureLayer("AppData/Vehicles.shp"); LayerOverlay layerOverlay = new LayerOverlay(); layerOverlay.TileType = TileType.SingleTile; layerOverlay.Layers.Add(iconStyleFeatureLayer); MapView.Overlays.Add(layerOverlay); iconStyleFeatureLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Clear(); iconStyleFeatureLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(GetIconStyle("AppData/Images/vehicle")); iconStyleFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; MapView.ZoomTo(new PointShape(-96.7689, 33.1620), MapView.ZoomLevelSet.ZoomLevel14.Scale); } private static ValueStyle GetIconStyle(string imagePath) { ValueStyle valueStyle = new ValueStyle(); valueStyle.ColumnName = "TYPE"; GeoFont font = new GeoFont("Arial", 12, DrawingFontStyles.Bold); GeoSolidBrush brush = new GeoSolidBrush(GeoColor.StandardColors.Black); for (int i = 1; i <= 7; i++) { IconStyle iconStyle = new IconStyle(imagePath + i + ".png", "Type", font, brush); iconStyle.HaloPen = new GeoPen(GeoColor.SimpleColors.White); ValueItem valueItem = new ValueItem(i.ToString(CultureInfo.InvariantCulture), iconStyle); valueStyle.ValueItems.Add(valueItem); } return valueStyle; } } } ====DetailViewController.cs==== using CoreGraphics; using Foundation; using System; using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.iOSEdition; using UIKit; namespace AnalyzingVisualization { [Register("DetailViewController")] public class DetailViewController : UIViewController { private UIView settingContainerView; private UIBarButtonItem settingButton; protected MapView MapView; public Action SettingButtonClick; public Action DetailButtonClick; public DetailViewController() { } protected UIView SettingContainerView { get { return settingContainerView; } } protected UIBarButtonItem SettingButton { get { return settingButton; } } protected float SettingContainerHeight { get; set; } public override void ViewDidLoad() { base.ViewDidLoad(); View.BackgroundColor = UIColor.Red; View.AutoresizingMask = UIViewAutoresizing.FlexibleHeight | UIViewAutoresizing.FlexibleWidth; MapView = new MapView(View.Frame); MapView.BackgroundColor = UIColor.FromRGB(244, 242, 238); MapView.MapTools.ZoomMapTool.Center = new CGPoint(MapView.MapTools.ZoomMapTool.Center.X + 10, MapView.MapTools.ZoomMapTool.Center.Y + 55); View.Add(MapView); InitializeMap(); InitializeToolbar(); InitializeSettingView(); } public override void WillAnimateRotation(UIInterfaceOrientation toInterfaceOrientation, double duration) { base.WillAnimateRotation(toInterfaceOrientation, duration); double resolution = Math.Max(MapView.CurrentExtent.Width / MapView.Frame.Width, MapView.CurrentExtent.Height / MapView.Frame.Height); MapView.Frame = View.Bounds; MapView.CurrentExtent = GetExtentRetainScale(MapView.CurrentExtent.GetCenterPoint(), MapView.Frame, resolution); MapView.Refresh(); } /// /// This method customizes the map for a specific sample. /// We could add overlays, layers, styles inside of this method. /// protected virtual void InitializeMap() { } /// /// Gets the extent retain scale. /// /// The current location in mecator. /// The frame. /// The resolution. /// RectangleShape. private static RectangleShape GetExtentRetainScale(PointShape currentLocationInMecator, CGRect frame, double resolution) { double left = currentLocationInMecator.X - resolution * frame.Width * .5; double right = currentLocationInMecator.X + resolution * frame.Width * .5; double top = currentLocationInMecator.Y + resolution * frame.Height * .5; double bottom = currentLocationInMecator.Y - resolution * frame.Height * .5; return new RectangleShape(left, top, right, bottom); } private void InitializeToolbar() { UIBarButtonItem detailButton = new UIBarButtonItem(UIImage.FromBundle("detail40"), UIBarButtonItemStyle.Plain, OnDetailButtonClick); detailButton.TintColor = UIColor.Black; NavigationItem.SetLeftBarButtonItem(detailButton, true); settingButton = new UIBarButtonItem(UIImage.FromBundle("settings40"), UIBarButtonItemStyle.Plain, OnSettingButtonClick); settingButton.TintColor = UIColor.Black; settingButton.Enabled = false; NavigationItem.SetRightBarButtonItems(new[] { settingButton }, true); } private void InitializeSettingView() { if (settingContainerView == null) { settingContainerView = new UIView(); settingContainerView.TranslatesAutoresizingMaskIntoConstraints = false; NSLayoutConstraint[] settingViewConstraints = { NSLayoutConstraint.Create(settingContainerView, NSLayoutAttribute.Left, NSLayoutRelation.Equal, View, NSLayoutAttribute.Left, 1, 0), NSLayoutConstraint.Create(settingContainerView, NSLayoutAttribute.Right, NSLayoutRelation.Equal, View, NSLayoutAttribute.Right, 1, 0), NSLayoutConstraint.Create(settingContainerView, NSLayoutAttribute.Height, NSLayoutRelation.Equal, null, NSLayoutAttribute.NoAttribute, 1, SettingContainerHeight), NSLayoutConstraint.Create(settingContainerView, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, View, NSLayoutAttribute.Bottom, 1, 0) }; View.Add(settingContainerView); View.AddConstraints(settingViewConstraints); } } private void OnSettingButtonClick(object sender, EventArgs e) { if (SettingButtonClick != null) SettingButtonClick(); } private void OnDetailButtonClick(object sender, EventArgs e) { if (DetailButtonClick != null) DetailButtonClick(); } } } ====InstructionView.cs==== using CoreGraphics; using System; using UIKit; namespace AnalyzingVisualization { internal class InstructionView : UIView { private Action InstructionViewTopChanged; private Action ResetChildrenLayout; public InstructionView(Action initializeChildrenContent, Action instructionViewTopChanged) { ResetChildrenLayout = initializeChildrenContent; InstructionViewTopChanged = instructionViewTopChanged; InitializeComponentLayout(); } private static int DescriptionMarginLeft { get { return iOSCapabilityHelper.IsOnIPhone ? 10 : 20; } } private void CollapseButtonTouchDown(object sender, EventArgs e) { if (InstructionViewTopChanged != null) InstructionViewTopChanged(); } private void InitializeComponentLayout() { float titleHeight = 40; Alpha = 0.9f; BackgroundColor = UIColor.FromRGBA(126, 124, 129, 255); UIView topLine = new UIView(new CGRect(0, 0, Frame.Width, 2)); topLine.BackgroundColor = UIColor.DarkGray; topLine.Layer.CornerRadius = 4; topLine.Layer.ShadowRadius = 3; topLine.Layer.ShadowOpacity = .8f; topLine.Layer.ShadowColor = UIColor.Black.CGColor; topLine.Layer.ShadowOffset = new CGSize(1, 0); topLine.TranslatesAutoresizingMaskIntoConstraints = false; Add(topLine); UIButton titleView = new UIButton(); titleView.BackgroundColor = UIColor.FromRGBA(126, 124, 129, 255); titleView.TouchUpInside += CollapseButtonTouchDown; titleView.TranslatesAutoresizingMaskIntoConstraints = false; Add(titleView); UILabel instructionLable = new UILabel(); instructionLable.BackgroundColor = BackgroundColor; instructionLable.Text = "Setting"; instructionLable.Font = UIFont.FromName("Helvetica-Bold", 20); instructionLable.TextColor = UIColor.White; instructionLable.ShadowColor = UIColor.Gray; instructionLable.ShadowOffset = new CGSize(1, 1); instructionLable.TextAlignment = UITextAlignment.Left; instructionLable.TranslatesAutoresizingMaskIntoConstraints = false; titleView.Add(instructionLable); UIButton collapseButton = UIButton.FromType(UIButtonType.RoundedRect); collapseButton.SetImage(UIImage.FromBundle("More"), UIControlState.Normal); collapseButton.TintColor = UIColor.White; collapseButton.TouchUpInside += CollapseButtonTouchDown; collapseButton.TranslatesAutoresizingMaskIntoConstraints = false; titleView.Add(collapseButton); float contentViewTop = titleHeight + 5; UIView contentView = new UIView(); contentView.TranslatesAutoresizingMaskIntoConstraints = false; Add(contentView); NSLayoutConstraint[] instructionViewConstraints = new[] { NSLayoutConstraint.Create(topLine, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this, NSLayoutAttribute.Left, 1, 0), NSLayoutConstraint.Create(topLine, NSLayoutAttribute.Right, NSLayoutRelation.Equal, this, NSLayoutAttribute.Right, 1, 0), NSLayoutConstraint.Create(topLine, NSLayoutAttribute.Top, NSLayoutRelation.Equal, this, NSLayoutAttribute.Top, 1, 0), NSLayoutConstraint.Create(topLine, NSLayoutAttribute.Height, NSLayoutRelation.Equal, null, NSLayoutAttribute.NoAttribute, 1, 2), NSLayoutConstraint.Create(collapseButton, NSLayoutAttribute.Width, NSLayoutRelation.Equal, null, NSLayoutAttribute.NoAttribute, 1, 55), NSLayoutConstraint.Create(collapseButton, NSLayoutAttribute.Right, NSLayoutRelation.Equal, this, NSLayoutAttribute.Right, 1, 5), NSLayoutConstraint.Create(collapseButton, NSLayoutAttribute.Top, NSLayoutRelation.Equal, this, NSLayoutAttribute.Top, 1, 10), NSLayoutConstraint.Create(collapseButton, NSLayoutAttribute.Height, NSLayoutRelation.Equal, null, NSLayoutAttribute.NoAttribute, 1, 30), NSLayoutConstraint.Create(instructionLable, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this, NSLayoutAttribute.Left, 1, DescriptionMarginLeft), NSLayoutConstraint.Create(instructionLable, NSLayoutAttribute.Right, NSLayoutRelation.Equal, this, NSLayoutAttribute.Right, 1, 0), NSLayoutConstraint.Create(instructionLable, NSLayoutAttribute.Top, NSLayoutRelation.Equal, this, NSLayoutAttribute.Top, 1, 0), NSLayoutConstraint.Create(instructionLable, NSLayoutAttribute.Height, NSLayoutRelation.Equal, null, NSLayoutAttribute.NoAttribute, 1, titleHeight), NSLayoutConstraint.Create(titleView, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this, NSLayoutAttribute.Left, 1, 0), NSLayoutConstraint.Create(titleView, NSLayoutAttribute.Right, NSLayoutRelation.Equal, this, NSLayoutAttribute.Right, 1, 0), NSLayoutConstraint.Create(titleView, NSLayoutAttribute.Top, NSLayoutRelation.Equal, this, NSLayoutAttribute.Top, 1, 0), NSLayoutConstraint.Create(titleView, NSLayoutAttribute.Height, NSLayoutRelation.Equal, null, NSLayoutAttribute.NoAttribute, 1, titleHeight), NSLayoutConstraint.Create(contentView, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this, NSLayoutAttribute.Left, 1, DescriptionMarginLeft), NSLayoutConstraint.Create(contentView, NSLayoutAttribute.Right, NSLayoutRelation.Equal, this, NSLayoutAttribute.Right, 1, DescriptionMarginLeft), NSLayoutConstraint.Create(contentView, NSLayoutAttribute.Top, NSLayoutRelation.Equal, this, NSLayoutAttribute.Top, 1, contentViewTop), NSLayoutConstraint.Create(contentView, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, this, NSLayoutAttribute.Bottom, 1, 0), }; AddConstraints(instructionViewConstraints); if (ResetChildrenLayout != null) ResetChildrenLayout(contentView); } } } ====SliderViewController.cs==== using CoreGraphics; using Foundation; using MediaPlayer; using MonoTouch.Dialog; using ObjCRuntime; using System; using System.Drawing; using UIKit; namespace AnalyzingVisualization { public enum FlyOutPosition { Left = 0, // default Right }; [Register("SilderViewController")] public class SliderViewController : UIViewController { private const float sidebarFlickVelocity = 1000.0f; private const int menuWidth = 240; private bool hideShadow; private UIButton closeButton; private FlyOutPosition position; private DialogViewController leftNavigation; private int selectedIndex; private UIView shadowView; private nfloat startX; private UIView statusImage; private UIViewController[] viewControllers; private bool isIos7; private bool isOpen; public event UITouchEventArgs ShouldReceiveTouch; public Action SelectedIndexChanged; public SliderViewController(IntPtr handle) : base(handle) { Initialize(); } public SliderViewController(UITableViewStyle navigationStyle = UITableViewStyle.Plain) { Initialize(navigationStyle); } public FlyOutPosition Position { get { return position; } set { position = value; shadowView.Layer.ShadowOffset = new CGSize(Position == FlyOutPosition.Left ? -5 : 5, -1); } } public bool AlwaysShowLandscapeMenu { get; set; } public bool ForceMenuOpen { get; set; } public bool HideShadow { get { return hideShadow; } set { if (value == hideShadow) return; hideShadow = value; if (hideShadow) { if (mainView != null) View.InsertSubviewBelow(shadowView, mainView); } else { shadowView.RemoveFromSuperview(); } } } public UIColor ShadowViewColor { get { return shadowView.BackgroundColor; } set { shadowView.BackgroundColor = value; } } public UIViewController CurrentViewController { get; set; } public UIView mainView { get { if (CurrentViewController == null) return null; return CurrentViewController.View; } } public RootElement NavigationRoot { get { return leftNavigation.Root; } set { EnsureInvokedOnMainThread(delegate { leftNavigation.Root = value; }); } } public UITableView NavigationTableView { get { return leftNavigation.TableView; } } public UIViewController[] ViewControllers { get { return viewControllers; } set { EnsureInvokedOnMainThread(delegate { viewControllers = value; NavigationItemSelected(GetIndexPath(SelectedIndex)); }); } } public bool IsOpen { get { if (Position == FlyOutPosition.Left) { return mainView.Frame.X == menuWidth; } else { return mainView.Frame.X == -menuWidth; } } set { isOpen = value; if (value) HideMenu(); else ShowMenu(); } } public bool ShouldStayOpen { get { if (ForceMenuOpen || (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad && AlwaysShowLandscapeMenu && (InterfaceOrientation == UIInterfaceOrientation.LandscapeLeft || InterfaceOrientation == UIInterfaceOrientation.LandscapeRight))) return true; return false; } } public int SelectedIndex { get { return selectedIndex; } set { if (selectedIndex == value) return; selectedIndex = value; EnsureInvokedOnMainThread(delegate { NavigationItemSelected(value); }); } } public bool DisableRotation { get; set; } public override bool ShouldAutorotateToInterfaceOrientation(UIInterfaceOrientation toInterfaceOrientation) { if (DisableRotation) return toInterfaceOrientation == InterfaceOrientation; bool theReturn = CurrentViewController == null ? true : CurrentViewController.ShouldAutorotateToInterfaceOrientation(toInterfaceOrientation); return theReturn; } public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations() { if (CurrentViewController != null) return CurrentViewController.GetSupportedInterfaceOrientations(); return UIInterfaceOrientationMask.All; } public override void ViewDidLayoutSubviews() { base.ViewDidLayoutSubviews(); CGRect navFrame = View.Bounds; // navFrame.Y += UIApplication.SharedApplication.StatusBarFrame.Height; // navFrame.Height -= navFrame.Y; //this.statusbar navFrame.Width = menuWidth; if (Position == FlyOutPosition.Right) navFrame.X = mainView.Frame.Width - menuWidth; if (leftNavigation.View.Frame != navFrame) leftNavigation.View.Frame = navFrame; } public override void ViewWillAppear(bool animated) { CGRect navFrame = leftNavigation.View.Frame; navFrame.Width = menuWidth; if (Position == FlyOutPosition.Right) navFrame.X = mainView.Frame.Width - menuWidth; navFrame.Location = PointF.Empty; leftNavigation.View.Frame = navFrame; View.BackgroundColor = NavigationTableView.BackgroundColor; var frame = mainView.Frame; setViewSize(); SetLocation(frame); base.ViewWillAppear(animated); } private void Initialize(UITableViewStyle navigationStyle = UITableViewStyle.Plain) { DisableStatusBarMoving = true; statusImage = new UIView { ClipsToBounds = true }.SetAccessibilityId("statusbar"); leftNavigation = new DialogViewController(navigationStyle, null); leftNavigation.OnSelection += NavigationItemSelected; CGRect navFrame = leftNavigation.View.Frame; navFrame.Width = menuWidth; if (Position == FlyOutPosition.Right) navFrame.X = mainView.Frame.Width - menuWidth; leftNavigation.View.Frame = navFrame; View.AddSubview(leftNavigation.View); var version = new Version(UIDevice.CurrentDevice.SystemVersion); isIos7 = version.Major >= 7; if (isIos7) { leftNavigation.TableView.TableHeaderView = new UIView(new CGRect(0, 0, 320, 22)) { BackgroundColor = UIColor.Clear }; leftNavigation.TableView.SectionHeaderHeight = 50; } leftNavigation.TableView.TableFooterView = new UIView(new CGRect(0, 0, 100, 100)) { BackgroundColor = UIColor.Clear }; leftNavigation.TableView.ScrollsToTop = false; shadowView = new UIView(); shadowView.BackgroundColor = UIColor.White; shadowView.Layer.ShadowOffset = new CGSize(Position == FlyOutPosition.Left ? -5 : 5, -1); shadowView.Layer.ShadowColor = UIColor.Black.CGColor; shadowView.Layer.ShadowOpacity = .75f; closeButton = new UIButton(); closeButton.TouchUpInside += delegate { HideMenu(); }; AlwaysShowLandscapeMenu = true; View.AddGestureRecognizer(new OpenMenuGestureRecognizer(DragContentView, shouldReceiveTouch)); UIButton moreButton = UIButton.FromType(UIButtonType.System); moreButton.SetImage(UIImage.FromBundle("more40"), UIControlState.Normal); moreButton.TintColor = UIColor.Black; moreButton.TranslatesAutoresizingMaskIntoConstraints = false; moreButton.TouchUpInside += (sender, args) => UIApplication.SharedApplication.OpenUrl(new NSUrl("http://www.thinkgeo.com/")); NSLayoutConstraint[] moreButtonConstraints = new[] { NSLayoutConstraint.Create(moreButton, NSLayoutAttribute.Left, NSLayoutRelation.Equal, View, NSLayoutAttribute.Left, 1, 7), NSLayoutConstraint.Create(moreButton, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, View, NSLayoutAttribute.Bottom, 1, -7), NSLayoutConstraint.Create(moreButton, NSLayoutAttribute.Width, NSLayoutRelation.Equal, null, NSLayoutAttribute.NoAttribute, 1, 44), NSLayoutConstraint.Create(moreButton, NSLayoutAttribute.Height, NSLayoutRelation.Equal, null, NSLayoutAttribute.NoAttribute, 1, 44), }; View.Add(moreButton); View.AddConstraints(moreButtonConstraints); } private void DragContentView(UIPanGestureRecognizer panGesture) { //if (ShouldStayOpen || mainView == null) if (mainView == null) return; if (!HideShadow) View.InsertSubviewBelow(shadowView, mainView); leftNavigation.View.Hidden = false; CGRect frame = mainView.Frame; shadowView.Frame = frame; nfloat translation = panGesture.TranslationInView(View).X; if (panGesture.State == UIGestureRecognizerState.Began) { startX = frame.X; } else if (panGesture.State == UIGestureRecognizerState.Changed) { frame.X = translation + startX; if (Position == FlyOutPosition.Left) { if (frame.X < 0) frame.X = 0; else if (frame.X > menuWidth) frame.X = menuWidth; } else { if (frame.X > 0) frame.X = 0; else if (frame.X < -menuWidth) frame.X = -menuWidth; } SetLocation(frame); } else if (panGesture.State == UIGestureRecognizerState.Ended) { nfloat velocity = panGesture.VelocityInView(View).X; nfloat newX = translation + startX; bool show = Math.Abs(velocity) > sidebarFlickVelocity ? velocity > 0 : newX > (menuWidth / 2); if (Position == FlyOutPosition.Right) { show = Math.Abs(velocity) > sidebarFlickVelocity ? velocity < 0 : newX < -(menuWidth / 2); } if (show) { ShowMenu(); } else { HideMenu(); } } } private bool shouldReceiveTouch(UIGestureRecognizer gesture, UITouch touch) { if (ShouldReceiveTouch != null) return ShouldReceiveTouch(gesture, touch); return true; } private void NavigationItemSelected(NSIndexPath indexPath) { int index = GetIndex(indexPath); NavigationItemSelected(index); } private void NavigationItemSelected(int index) { if (selectedIndex == index && CurrentViewController != null) { HideMenu(); return; } selectedIndex = index; if (viewControllers == null || viewControllers.Length <= index || index < 0) { if (SelectedIndexChanged != null) SelectedIndexChanged(); return; } if (ViewControllers[index] == null) { if (SelectedIndexChanged != null) SelectedIndexChanged(); return; } if (!DisableStatusBarMoving) //if (!DisableStatusBarMoving && !ShouldStayOpen) UIApplication.SharedApplication.SetStatusBarHidden(false, UIStatusBarAnimation.Fade); //bool isOpen = false; //if (mainView != null) //{ // mainView.RemoveFromSuperview(); // isOpen = IsOpen; //} //isOpen = false; CurrentViewController = ViewControllers[SelectedIndex]; CGRect frame = View.Bounds; //if (isOpen || ShouldStayOpen) if (isOpen) { frame.X = Position == FlyOutPosition.Left ? menuWidth : -menuWidth; frame.Width = frame.Width - frame.X; } //setViewSize(); SetLocation(frame); View.AddSubview(mainView); AddChildViewController(CurrentViewController); //if (!ShouldStayOpen) HideMenu(); if (SelectedIndexChanged != null) SelectedIndexChanged(); } //bool isOpen {get{ return mainView.Frame.X == menuWidth; }} private void ShowMenu() { if (mainView == null) return; EnsureInvokedOnMainThread(delegate { //navigation.ReloadData (); //isOpen = true; leftNavigation.View.Hidden = false; closeButton.Frame = mainView.Frame; shadowView.Frame = mainView.Frame; var statusFrame = statusImage.Frame; statusFrame.X = mainView.Frame.X; statusImage.Frame = statusFrame; //if (!ShouldStayOpen) View.AddSubview(closeButton); if (!HideShadow) View.InsertSubviewBelow(shadowView, mainView); UIView.BeginAnimations("slideMenu"); UIView.SetAnimationCurve(UIViewAnimationCurve.EaseIn); UIView.SetAnimationDuration(.3); setViewSize(); CGRect frame = mainView.Frame; frame.X = Position == FlyOutPosition.Left ? menuWidth : -menuWidth; SetLocation(frame); setViewSize(); frame = mainView.Frame; shadowView.Frame = frame; closeButton.Frame = frame; statusFrame.X = mainView.Frame.X; statusImage.Frame = statusFrame; UIView.CommitAnimations(); isOpen = true; }); } private void setViewSize() { CGRect frame = View.Bounds; //frame.Location = PointF.Empty; //if (ShouldStayOpen) if (isOpen) frame.Width -= menuWidth; if (mainView.Bounds == frame) return; mainView.Bounds = frame; } private void SetLocation(CGRect frame) { mainView.Layer.AnchorPoint = new CGPoint(.5f, .5f); frame.Y = 0; if (mainView.Frame.Location == frame.Location) return; frame.Size = mainView.Frame.Size; var center = new CGPoint(frame.Left + frame.Width / 2, frame.Top + frame.Height / 2); mainView.Center = center; shadowView.Center = center; if (Math.Abs(frame.X - 0) > float.Epsilon) { getStatus(); var statusFrame = statusImage.Frame; statusFrame.X = mainView.Frame.X; statusImage.Frame = statusFrame; } } private bool DisableStatusBarMoving { get; set; } private void getStatus() { //if (DisableStatusBarMoving || !isIos7 || statusImage.Superview != null || ShouldStayOpen) if (DisableStatusBarMoving || !isIos7 || statusImage.Superview != null) return; var image = captureStatusBarImage(); if (image == null) return; this.View.AddSubview(statusImage); foreach (var view in statusImage.Subviews) view.RemoveFromSuperview(); statusImage.AddSubview(image); statusImage.Frame = UIApplication.SharedApplication.StatusBarFrame; UIApplication.SharedApplication.StatusBarHidden = true; } private UIView captureStatusBarImage() { try { UIView screenShot = UIScreen.MainScreen.SnapshotView(false); return screenShot; } catch (Exception ex) { return null; } } private void hideStatus() { if (!isIos7) return; statusImage.RemoveFromSuperview(); UIApplication.SharedApplication.StatusBarHidden = false; } private void HideMenu() { //if (mainView == null || mainView.Frame.X == 0) if (mainView == null) return; EnsureInvokedOnMainThread(delegate { isOpen = false; leftNavigation.FinishSearch(); closeButton.RemoveFromSuperview(); shadowView.Frame = mainView.Frame; var statusFrame = statusImage.Frame; statusFrame.X = mainView.Frame.X; statusImage.Frame = statusFrame; UIView.Animate(.5, () => { UIView.SetAnimationCurve(UIViewAnimationCurve.EaseInOut); CGRect frame = View.Bounds; frame.X = 0; setViewSize(); SetLocation(frame); shadowView.Frame = frame; statusFrame.X = 0; statusImage.Frame = statusFrame; }, hideComplete); }); } [Export("animationEnded")] private void hideComplete() { hideStatus(); shadowView.RemoveFromSuperview(); leftNavigation.View.Hidden = true; } private void ResignFirstResponders(UIView view) { if (view.Subviews == null) return; foreach (UIView subview in view.Subviews) { if (subview.IsFirstResponder) subview.ResignFirstResponder(); ResignFirstResponders(subview); } } public void ToggleMenu() { EnsureInvokedOnMainThread(delegate { if (!IsOpen && CurrentViewController != null && CurrentViewController.IsViewLoaded) ResignFirstResponders(CurrentViewController.View); if (IsOpen) HideMenu(); else ShowMenu(); }); } private int GetIndex(NSIndexPath indexPath) { int section = 0; int rowCount = 0; while (section < indexPath.Section) { rowCount += leftNavigation.Root[section].Count; section++; } return rowCount + indexPath.Row; } private NSIndexPath GetIndexPath(int index) { if (leftNavigation.Root == null) return NSIndexPath.FromRowSection(0, 0); int currentCount = 0; int section = 0; foreach (Section element in leftNavigation.Root) { if (element.Count + currentCount > index) break; currentCount += element.Count; section++; } int row = index - currentCount; return NSIndexPath.FromRowSection(row, section); } //public override void DidRotate(UIInterfaceOrientation fromInterfaceOrientation) //{ // base.DidRotate(fromInterfaceOrientation); // if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone) // return; // switch (InterfaceOrientation) // { // case UIInterfaceOrientation.LandscapeLeft: // case UIInterfaceOrientation.LandscapeRight: // ShowMenu(); // break; // default: // HideMenu(); // break; // } //} private void EnsureInvokedOnMainThread(Action action) { if (NSThread.Current.IsMainThread) { action(); return; } BeginInvokeOnMainThread(() => action() ); } } internal static class Helpers { static readonly IntPtr selAccessibilityIdentifier_Handle = Selector.GetHandle("accessibilityIdentifier"); public static UIView SetAccessibilityId(this UIView view, string id) { var nsId = NSString.CreateNative(id); //Messaging.void_objc_msgSend_IntPtr(view.Handle, selAccessibilityIdentifier_Handle, nsId); return view; } } internal class OpenMenuGestureRecognizer : UIPanGestureRecognizer { public OpenMenuGestureRecognizer(Action callback, Func shouldReceiveTouch) : base(callback) { ShouldReceiveTouch += (sender, touch) => { //Ugly hack to ignore touches that are on a cell that is moving... bool isMovingCell = touch.View.ToString().IndexOf("UITableViewCellReorderControl", StringComparison.InvariantCultureIgnoreCase) > -1; if (touch.View is UISlider || touch.View is MPVolumeView || isMovingCell) return false; return shouldReceiveTouch(sender, touch); }; } } } ====ClassBreakChartView.cs==== using CoreAnimation; using CoreGraphics; using Foundation; using System; using System.Linq; using ThinkGeo.MapSuite.Core; using UIKit; namespace AnalyzingVisualization { public class ClassBreakChartView : UIView { public ClassBreakChartView(CGPoint lowerLeftPoint, ClassBreakStyle classBreakStyle) { InitializeClassBreakChartView(lowerLeftPoint, classBreakStyle); } private void InitializeClassBreakChartView(CGPoint lowerLeftPoint, ClassBreakStyle classBreakStyle) { ClassBreakChartLayer chartLayer = new ClassBreakChartLayer(classBreakStyle); chartLayer.Opacity = .9f; chartLayer.SetNeedsDisplay(); Layer.AddSublayer(chartLayer); Frame = new CGRect(new CGPoint(lowerLeftPoint.X, lowerLeftPoint.Y - chartLayer.Frame.Height), chartLayer.Frame.Size); } private class ClassBreakChartLayer : CALayer { private static readonly UIFont font = UIFont.FromName("Arial", 12); private ClassBreakStyle classBreakStyle; private float paddingTop; private float paddingLeft; private float segmentWidth; private float segmentHeight; private float textMargin; public ClassBreakChartLayer(ClassBreakStyle classBreakStyle) { this.classBreakStyle = classBreakStyle; float paddingRight = 2; float paddingBottom = 5; paddingTop = 2; paddingLeft = 5; segmentWidth = 24; segmentHeight = 20; textMargin = 4; nfloat maxTextWidth = classBreakStyle.ClassBreaks.Select(c => new NSString(c.Value.ToString("R0")).StringSize(font).Width).Max(); Frame = new CGRect(0, 0, paddingLeft + segmentWidth + textMargin + maxTextWidth + paddingRight, paddingTop + paddingBottom + segmentHeight * classBreakStyle.ClassBreaks.Count); } public override void DrawInContext(CGContext ctx) { base.DrawInContext(ctx); ctx.SetFillColor(UIColor.White.CGColor); ctx.FillRect(new CGRect(paddingLeft - 2, paddingTop - 2, segmentWidth + 4, segmentHeight * classBreakStyle.ClassBreaks.Count + 4)); for (int i = 0; i < classBreakStyle.ClassBreaks.Count; i++) { int currentIndex = classBreakStyle.ClassBreaks.Count - i - 1; float barLeft = paddingLeft; float barTop = paddingTop + i * segmentHeight; ctx.SetFillColor(GetCGColor(classBreakStyle.ClassBreaks[currentIndex])); ctx.FillRect(new CGRect(barLeft, barTop, segmentWidth, segmentHeight)); NSString text = new NSString(classBreakStyle.ClassBreaks[currentIndex].Value.ToString("R0")); CGSize textSize = text.StringSize(font); nfloat textTop = barTop + segmentHeight - textSize.Height; nfloat textLeft = barLeft + segmentWidth + textMargin; ctx.SetTextDrawingMode(CGTextDrawingMode.Stroke); ctx.SetFillColor(UIColor.White.CGColor); ctx.SetLineWidth(1); UIGraphics.PushContext(ctx); text.DrawString(new CGPoint(textLeft, textTop), font); UIGraphics.PopContext(); ctx.SetTextDrawingMode(CGTextDrawingMode.Fill); ctx.SetFillColor(UIColor.Black.CGColor); UIGraphics.PushContext(ctx); text.DrawString(new CGPoint(textLeft, textTop), font); UIGraphics.PopContext(); } } private static CGColor GetCGColor(ClassBreak classBreak) { GeoColor color = classBreak.DefaultAreaStyle.FillSolidBrush.Color; return UIColor.FromRGBA(color.RedComponent, color.GreenComponent, color.BlueComponent, color.AlphaComponent).CGColor; } } } } ====ClassBreakStyleViewController.cs==== using CoreGraphics; using System.Collections.ObjectModel; using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.iOSEdition; namespace AnalyzingVisualization { public class ClassBreakStyleViewController : DetailViewController { public ClassBreakStyleViewController() { } protected override void InitializeMap() { MapView.MapUnit = GeographyUnit.DecimalDegree; WorldMapKitOverlay worldOverlay = new WorldMapKitOverlay(); worldOverlay.TileType = TileType.MultiTile; MapView.Overlays.Add(worldOverlay); ClassBreakStyle classBreakStyle = GetClassBreakStyle(); ShapeFileFeatureLayer usLayer = new ShapeFileFeatureLayer("AppData/usStatesCensus2010.shp"); usLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Clear(); usLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(classBreakStyle); usLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; LayerOverlay layerOverlay = new LayerOverlay(); layerOverlay.Layers.Add(usLayer); MapView.Overlays.Add(layerOverlay); MapView.ZoomTo(new PointShape(-96.8150, 39.6948), MapView.ZoomLevelSet.ZoomLevel05.Scale); ClassBreakChartView chartView = new ClassBreakChartView(new CGPoint(5, View.Frame.Height - 5), classBreakStyle); View.AddSubview(chartView); } private static ClassBreakStyle GetClassBreakStyle() { double[] classBreakValues = { 0, 814180.0, 1328361.0, 2059179.0, 2967297.0, 4339367.0, 5303925.0, 6392017.0, 8791894.0 }; GeoColor fromColor = GeoColor.FromArgb(255, 116, 160, 255); GeoColor toColor = GeoColor.FromArgb(255, 220, 52, 56); Collection familyColors = GeoColor.GetColorsInQualityFamily(fromColor, toColor, 10, ColorWheelDirection.CounterClockwise); ClassBreakStyle classBreakStyle = new ClassBreakStyle("Population", BreakValueInclusion.IncludeValue); GeoColor outlineColor = GeoColor.FromHtml("#f05133"); for (int i = 0; i < classBreakValues.Length; i++) { GeoColor fillColor = new GeoColor(200, familyColors[i]); AreaStyle areaStyle = AreaStyles.CreateSimpleAreaStyle(fillColor, outlineColor, 1); classBreakStyle.ClassBreaks.Add(new ClassBreak(classBreakValues[i], areaStyle)); } return classBreakStyle; } } } ====ClassBreakClusterPointStyle.cs==== using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; using System.Linq; using System.Reflection; using ThinkGeo.MapSuite.Core; namespace AnalyzingVisualization { [Serializable] public class ClassBreakClusterPointStyle : Style { [Obfuscation(Exclude|= true)] private Dictionary classBreakPoint; [Obfuscation(Exclude|= true)] private int cellSize = 100; [Obfuscation(Exclude|= true)] private TextStyle textSytle = new TextStyle(); public ClassBreakClusterPointStyle() : base() { classBreakPoint = new Dictionary(); } public Dictionary ClassBreakPoint { get { return classBreakPoint; } } public TextStyle TextStyle { get { return textSytle; } set { textSytle = value; } } public int CellSize { get { return cellSize; } set { cellSize = value; } } protected override void DrawCore(IEnumerable features, GeoCanvas canvas, Collection labelsInThisLayer, Collection labelsInAllLayers) { double scale = ExtentHelper.GetScale(canvas.CurrentWorldExtent, canvas.Width, canvas.MapUnit); MapSuiteTileMatrix mapSuiteTileMatrix = new MapSuiteTileMatrix(scale, cellSize, cellSize, canvas.MapUnit); IEnumerable tileMatricCells = mapSuiteTileMatrix.GetContainedCells(canvas.CurrentWorldExtent); Dictionary unusedFeatures = new Dictionary(); foreach (Feature feature in features) { if (feature.GetWellKnownType() != WellKnownType.Point && feature.GetWellKnownType() != WellKnownType.Multipoint) { continue; } unusedFeatures.Add(feature.Id, feature.Id); } foreach (TileMatrixCell cell in tileMatricCells) { int featureCount = 0; MultipointShape tempMultiPointShape = new MultipointShape(); foreach (Feature feature in features) { // Make sure the feature has not been used in another cluster if (unusedFeatures.ContainsKey(feature.Id)) { // Check if the cell contains the feature if (cell.BoundingBox.Contains(feature.GetBoundingBox())) { featureCount++; unusedFeatures.Remove(feature.Id); if (feature.GetWellKnownType() == WellKnownType.Multipoint) { MultipointShape multipointShape = feature.GetShape() as MultipointShape; foreach (var item in multipointShape.Points) { tempMultiPointShape.Points.Add(item); } } else { tempMultiPointShape.Points.Add(feature.GetShape() as PointShape); } } } } if (featureCount > 0) { // Add the feature count to the new feature we created. The feature will be placed // at the center of gravity of all the clustered features of the cell we created. Dictionary featureValues = new Dictionary(); featureValues.Add("FeatureCount", featureCount.ToString(CultureInfo.InvariantCulture)); bool isMatch = false; for (int i = 0; i < classBreakPoint.Count - 1; i++) { var startItem = classBreakPoint.ElementAt(i); var endItem = classBreakPoint.ElementAt(i + 1); if (featureCount >= startItem.Key && featureCount < endItem.Key) { //Draw the point shape startItem.Value.Draw(new Feature[] { new Feature(tempMultiPointShape.GetCenterPoint(), featureValues) }, canvas, labelsInThisLayer, labelsInAllLayers); isMatch = true; break; } } if (!isMatch && featureCount >= classBreakPoint.LastOrDefault().Key) { classBreakPoint.LastOrDefault().Value.Draw(new Feature[] { new Feature(tempMultiPointShape.GetCenterPoint(), featureValues) }, canvas, labelsInThisLayer, labelsInAllLayers); } if (featureCount != 1) { // Draw the text style to show how many feaures are consolidated in the cluster textSytle.Draw(new Feature[] { new Feature(tempMultiPointShape.GetCenterPoint(), featureValues) }, canvas, labelsInThisLayer, labelsInAllLayers); } } } } } } ====ClusterPointStyleViewController.cs==== using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.iOSEdition; namespace AnalyzingVisualization { public class ClusterPointStyleViewController : DetailViewController { public ClusterPointStyleViewController() { } protected override void InitializeMap() { MapView.MapUnit = GeographyUnit.DecimalDegree; WorldMapKitOverlay worldOverlay = new WorldMapKitOverlay(); MapView.Overlays.Add(worldOverlay); ShapeFileFeatureLayer usEarthquakeLayer = new ShapeFileFeatureLayer("AppData/usEarthquake.shp"); usEarthquakeLayer.DrawingMarginPercentage = 100; usEarthquakeLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Clear(); usEarthquakeLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(GetClusterPointStyle()); usEarthquakeLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; LayerOverlay layerOverlay = new LayerOverlay(); layerOverlay.Layers.Add(usEarthquakeLayer); MapView.Overlays.Add(layerOverlay); MapView.ZoomTo(new PointShape(-96.8150, 39.6948), MapView.ZoomLevelSet.ZoomLevel05.Scale); } private static ClassBreakClusterPointStyle GetClusterPointStyle() { ClassBreakClusterPointStyle clusterPointStyle = new ClassBreakClusterPointStyle(); clusterPointStyle.CellSize = 65; PointStyle pointStyle1 = new PointStyle(PointSymbolType.Circle, new GeoSolidBrush(GeoColor.FromArgb(250, 222, 226, 153)), new GeoPen(GeoColor.FromArgb(100, 222, 226, 153), 5), 8); PointStyle pointStyle2 = new PointStyle(PointSymbolType.Circle, new GeoSolidBrush(GeoColor.FromArgb(250, 222, 226, 153)), new GeoPen(GeoColor.FromArgb(100, 222, 226, 153), 8), 15); PointStyle pointStyle3 = new PointStyle(PointSymbolType.Circle, new GeoSolidBrush(GeoColor.FromArgb(250, 255, 183, 76)), new GeoPen(GeoColor.FromArgb(100, 255, 183, 76), 10), 25); PointStyle pointStyle4 = new PointStyle(PointSymbolType.Circle, new GeoSolidBrush(GeoColor.FromArgb(250, 243, 193, 26)), new GeoPen(GeoColor.FromArgb(100, 243, 193, 26), 15), 35); PointStyle pointStyle5 = new PointStyle(PointSymbolType.Circle, new GeoSolidBrush(GeoColor.FromArgb(250, 245, 7, 10)), new GeoPen(GeoColor.FromArgb(100, 245, 7, 10), 15), 40); PointStyle pointStyle6 = new PointStyle(PointSymbolType.Circle, new GeoSolidBrush(GeoColor.FromArgb(250, 245, 7, 10)), new GeoPen(GeoColor.FromArgb(100, 245, 7, 10), 20), 50); clusterPointStyle.ClassBreakPoint.Add(1, pointStyle1); clusterPointStyle.ClassBreakPoint.Add(2, pointStyle2); clusterPointStyle.ClassBreakPoint.Add(50, pointStyle3); clusterPointStyle.ClassBreakPoint.Add(150, pointStyle4); clusterPointStyle.ClassBreakPoint.Add(350, pointStyle5); clusterPointStyle.ClassBreakPoint.Add(500, pointStyle6); clusterPointStyle.TextStyle = TextStyles.CreateSimpleTextStyle("FeatureCount", "Arail", 10, DrawingFontStyles.Regular, GeoColor.SimpleColors.Black); clusterPointStyle.TextStyle.PointPlacement = PointPlacement.Center; return clusterPointStyle; } } } ====CustomGeoImageLineStyle.cs==== using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using ThinkGeo.MapSuite.Core; namespace AnalyzingVisualization { public class CustomGeoImageLineStyle : LineStyle { private Collection geoImages; private int spacing; private LineStyle lineStyle; private SymbolSide side; public CustomGeoImageLineStyle(LineStyle lineStyle, GeoImage geoImage, int spacing, SymbolSide side) : this(lineStyle, new Collection { geoImage }, spacing, side) { } public CustomGeoImageLineStyle(LineStyle lineStyle, IEnumerable geoImages, int spacing, SymbolSide side) { this.side = side; this.spacing = spacing; this.lineStyle = lineStyle; this.geoImages = new Collection(); foreach (var geoImage in geoImages) { this.geoImages.Add(geoImage); } } protected override void DrawCore(IEnumerable features, GeoCanvas canvas, Collection labelsInThisLayer, Collection labelsInAllLayers) { PointStyle[] pointStyles = geoImages.Select(geoImage => new PointStyle(geoImage) { DrawingLevel = DrawingLevel.LevelThree }).ToArray(); foreach (Feature feature in features) { LineShape lineShape = (LineShape)feature.GetShape(); lineStyle.Draw(new BaseShape[] { lineShape }, canvas, labelsInThisLayer, labelsInAllLayers); int index = 0; double totalDist = 0; for (int i = 0; i < lineShape.Vertices.Count - 1; i++) { PointShape pointShape1 = new PointShape(lineShape.Vertices[i]); PointShape pointShape2 = new PointShape(lineShape.Vertices[i|+ 1]); LineShape tempLineShape = new LineShape(); tempLineShape.Vertices.Add(lineShape.Vertices[i]); tempLineShape.Vertices.Add(lineShape.Vertices[i|+ 1]); double angle = GetAngleFromTwoVertices(lineShape.Vertices[i], lineShape.Vertices[i|+ 1]); //Left side if (side == SymbolSide.Left) { if (angle >= 270) { angle = angle - 180; } } //Right side else { if (angle <= 90) { angle = angle + 180; } } //pointStyle.RotationAngle = (float)angle; foreach (var pointStyle in pointStyles) pointStyle.RotationAngle = (float)angle; float screenDist = ExtentHelper.GetScreenDistanceBetweenTwoWorldPoints(canvas.CurrentWorldExtent, pointShape1, pointShape2, canvas.Width, canvas.Height); double currentDist = Math.Round(pointShape1.GetDistanceTo(pointShape2, canvas.MapUnit, DistanceUnit.Meter), 2); double worldInterval = (currentDist * spacing) / screenDist; while (totalDist <= currentDist) { PointStyle pointStyle = pointStyles[index|% pointStyles.Length]; PointShape tempPointShape = tempLineShape.GetPointOnALine(StartingPoint.FirstPoint, totalDist, canvas.MapUnit, DistanceUnit.Meter); pointStyle.Draw(new BaseShape[] { tempPointShape }, canvas, labelsInThisLayer, labelsInAllLayers); totalDist = totalDist + worldInterval; index++; } totalDist = totalDist - currentDist; } } } private static double GetAngleFromTwoVertices(Vertex b, Vertex c) { double alpha = 0; double tangentAlpha = (c.Y - b.Y) / (c.X - b.X); double Peta = Math.Atan(tangentAlpha); if (c.X > b.X) { alpha = 90 + (Peta * (180 / Math.PI)); } else if (c.X < b.X) { alpha = 270 + (Peta * (180 / Math.PI)); } else { if (c.Y > b.Y) alpha = 0; if (c.Y < b.Y) alpha = 180; } double offset; if (b.X > c.X) { offset = 90; } else { offset = -90; } return alpha + offset; } public enum SymbolSide { Right = 0, Left = 1 } } } ====CustomStyleViewContoller.cs==== using System; using System.Collections.ObjectModel; using System.Globalization; using System.IO; using System.Linq; using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.iOSEdition; namespace AnalyzingVisualization { public class CustomStyleViewContoller : DetailViewController { public CustomStyleViewContoller() { } protected override void InitializeMap() { MapView.MapUnit = GeographyUnit.Meter; MapView.CurrentExtent = new RectangleShape(-13886070, 6660597, -8906057, 3382985); LineStyle lineStyle = LineStyles.CreateSimpleLineStyle(GeoColor.FromArgb(255, 50, 0, 249), 4, false); //Cold Front CustomGeoImageLineStyle coldFrontLineStyle = GetCustomLineStyle(lineStyle, 19, "offset_circle_red_bl.png", "offset_triangle_blue_revert.png"); InMemoryFeatureLayer coldFrontLineLayer = new InMemoryFeatureLayer(); coldFrontLineLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(coldFrontLineStyle); coldFrontLineLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; coldFrontLineLayer.InternalFeatures.Add(new Feature(File.ReadAllText(@"AppData/CustomStyles/ColdFront2.txt"))); coldFrontLineLayer.InternalFeatures.Add(new Feature(File.ReadAllText(@"AppData/CustomStyles/ColdFront3.txt"))); //Warm Front CustomGeoImageLineStyle warmFrontLineStyle = GetCustomLineStyle(lineStyle, 30, "offset_circle_blue.png"); InMemoryFeatureLayer warmFrontLineLayer = new InMemoryFeatureLayer(); warmFrontLineLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(warmFrontLineStyle); warmFrontLineLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; warmFrontLineLayer.InternalFeatures.Add(new Feature(File.ReadAllText(@"AppData/CustomStyles/WarmFront5.txt"))); warmFrontLineLayer.InternalFeatures.Add(new Feature(File.ReadAllText(@"AppData/CustomStyles/WarmFront6.txt"))); warmFrontLineLayer.InternalFeatures.Add(new Feature(File.ReadAllText(@"AppData/CustomStyles/WarmFront7.txt"))); warmFrontLineLayer.InternalFeatures.Add(new Feature(File.ReadAllText(@"AppData/CustomStyles/WarmFront8.txt"))); //Occluded Front CustomGeoImageLineStyle occludedFrontLineStyle = GetCustomLineStyle(lineStyle, 45, "offset_triangle_and_circle_blue.png", "offset_triangle_and_circle_red.png"); InMemoryFeatureLayer occludedFrontLineLayer = new InMemoryFeatureLayer(); occludedFrontLineLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(occludedFrontLineStyle); occludedFrontLineLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; occludedFrontLineLayer.InternalFeatures.Add(new Feature(File.ReadAllText(@"AppData/CustomStyles/OccludedFront9.txt"))); occludedFrontLineLayer.InternalFeatures.Add(new Feature(File.ReadAllText(@"AppData/CustomStyles/OccludedFront10.txt"))); occludedFrontLineLayer.InternalFeatures.Add(new Feature(File.ReadAllText(@"AppData/CustomStyles/OccludedFront11.txt"))); PressureValueStyle pressureValueStyle = new PressureValueStyle(); pressureValueStyle.ColumnName = "Pressure"; InMemoryFeatureLayer pressureFeatureLayer = new InMemoryFeatureLayer(); pressureFeatureLayer.Open(); pressureFeatureLayer.Columns.Add(new FeatureSourceColumn("Pressure")); pressureFeatureLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(pressureValueStyle); pressureFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; pressureFeatureLayer.InternalFeatures.Add(new Feature(MapView.CurrentExtent.GetCenterPoint())); Random random = new Random(); string[] pressures = { "H", "L" }; for (int i = 0; i < 20; i++) { Feature pressurePoint = new Feature(random.Next(-13886070, -8906057), random.Next(3382985, 6660597)); pressurePoint.ColumnValues["Pressure"] = pressures[random.Next(0,|2)]; pressureFeatureLayer.InternalFeatures.Add(pressurePoint); } WindPointStyle windStyle1 = new WindPointStyle("TEXT", "LEVEL", "ANGLE", GeoColor.FromHtml("#0AF8F8")); WindPointStyle windStyle2 = new WindPointStyle("TEXT", "LEVEL", "ANGLE", GeoColor.FromHtml("#0FF5B0")); WindPointStyle windStyle3 = new WindPointStyle("TEXT", "LEVEL", "ANGLE", GeoColor.FromHtml("#F7F70D")); WindPointStyle windStyle4 = new WindPointStyle("TEXT", "LEVEL", "ANGLE", GeoColor.FromHtml("#FBE306")); ClassBreakStyle windClassBreakStyle = new ClassBreakStyle(); windClassBreakStyle.ColumnName = "TEXT"; windClassBreakStyle.ClassBreaks.Add(new ClassBreak(10, new Collection