├── .gitattributes ├── .gitignore ├── App.config ├── ExampleDb ├── SimpleMapDb.Designer.cs ├── SimpleMapDb.cs ├── SimpleMapDb.resx ├── SimpleMapDb.xsc ├── SimpleMapDb.xsd └── SimpleMapDb.xss ├── ExampleExe ├── Screenshot.png ├── SimpleMap.exe └── SimpleMap.exe.config ├── ExampleForms ├── Controls │ ├── ButtonPanelCtl.Designer.cs │ ├── ButtonPanelCtl.cs │ ├── ButtonPanelCtl.resx │ ├── MapCtl.cs │ ├── MapCtl.designer.cs │ └── MapCtl.resx ├── FrmMapDownloader.Designer.cs ├── FrmMapDownloader.cs ├── FrmMapDownloader.resx ├── FrmOpticMap.Designer.cs ├── FrmOpticMap.cs ├── FrmOpticMap.resx └── Miscellaneous.cs ├── Framework ├── ExternalHelpers.cs ├── GraphicLayer.cs └── WorkerThread │ ├── Types │ ├── EventPriorityType.cs │ ├── EventPriorityTypeConverter.cs │ ├── MainThreadEventArgs.cs │ └── WorkerEventType.cs │ ├── WorkerEvent.cs │ └── WorkerMessageThread.cs ├── Layers ├── MapLayer.cs ├── MapObjects │ ├── BuildingTree.cs │ ├── CableTree.cs │ ├── TreeNodes │ │ ├── BuildingNode.cs │ │ ├── CableNode.cs │ │ └── VertexNode.cs │ └── VertexTree.cs └── NetLayer.cs ├── Map ├── Coordinate.cs ├── CoordinatePoligon.cs ├── CoordinateRectangle.cs ├── EarthUtilities.cs ├── Google │ ├── GoogleBlock.cs │ ├── GoogleCoordinate.cs │ ├── GoogleMapUtilities.cs │ └── GoogleRectangle.cs ├── Indexer │ └── CoordinateIndexer.cs ├── Spatial │ ├── Indexer │ │ ├── SpatialContentIndexer.cs │ │ ├── SpatialLevelPowerIndexer.cs │ │ └── SpatialSheetIndexer.cs │ ├── SpatialQueryIterator.cs │ ├── SpatialSheet.cs │ ├── SpatialSheetBase.cs │ ├── SpatialTree.cs │ └── Types │ │ ├── SpatialSheetPowerTypes.cs │ │ ├── SpatialTreeNode.cs │ │ └── SpatialTreeNodeTypes.cs └── Types │ └── InterseptResult.cs ├── Program.cs ├── Properties ├── AssemblyInfo.cs ├── Resources.Designer.cs ├── Resources.resx ├── Settings.Designer.cs ├── Settings.settings └── app.manifest ├── README.md ├── Resources ├── centermap_24.png ├── print_24.png ├── program_24.png ├── refresh_16.png ├── save 2_16x16.png ├── vertex_16.png ├── vertex_24.png └── vertex_8.png ├── Settings.cs ├── SimpleMap.csproj ├── SimpleMap.csproj.user ├── SimpleMap.sln └── default.ico /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | *.suo 49 | bin/ 50 | obj/ 51 | -------------------------------------------------------------------------------- /App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | SimpleMap\ 18 | 19 | 20 | 12 21 | 22 | 23 | 17 24 | 25 | 26 | 5 27 | 28 | 29 | 37.24468 30 | 31 | 32 | 55.9469 33 | 34 | 35 | 38.00891 36 | 37 | 38 | 55.5601 39 | 40 | 41 | 42 | 43 | 44 | 45 | http://mt1.google.com/vt/lyrs=m@146&hl=en&x={0}&y={1}&z={2} 46 | 47 | 48 | 1.3.8.5 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /ExampleDb/SimpleMapDb.cs: -------------------------------------------------------------------------------- 1 | using System.Data; 2 | using System.Windows.Forms; 3 | 4 | namespace ProgramMain.ExampleDb 5 | { 6 | 7 | public partial class SimpleMapDb 8 | { 9 | 10 | public static BindingSource CreateDataSource(DataTable table) 11 | { 12 | var bindingSource = new BindingSource {DataSource = table.DataSet, DataMember = table.TableName}; 13 | 14 | return bindingSource; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ExampleDb/SimpleMapDb.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | False 122 | 123 | -------------------------------------------------------------------------------- /ExampleDb/SimpleMapDb.xsc: -------------------------------------------------------------------------------- 1 |  2 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ExampleDb/SimpleMapDb.xsd: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /ExampleDb/SimpleMapDb.xss: -------------------------------------------------------------------------------- 1 |  2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /ExampleExe/Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agafonoff2000/SimpleMap/7893f78f2ac8a5c070a7b98c993dd168aff16b83/ExampleExe/Screenshot.png -------------------------------------------------------------------------------- /ExampleExe/SimpleMap.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agafonoff2000/SimpleMap/7893f78f2ac8a5c070a7b98c993dd168aff16b83/ExampleExe/SimpleMap.exe -------------------------------------------------------------------------------- /ExampleExe/SimpleMap.exe.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | SimpleMap\ 18 | 19 | 20 | 12 21 | 22 | 23 | 17 24 | 25 | 26 | 5 27 | 28 | 29 | 37.24468 30 | 31 | 32 | 55.9469 33 | 34 | 35 | 38.00891 36 | 37 | 38 | 55.5601 39 | 40 | 41 | 42 | 43 | 44 | 45 | http://mt1.google.com/vt/lyrs=m@146&hl=en&x={0}&y={1}&z={2} 46 | 47 | 48 | 1.3.8.5 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /ExampleForms/Controls/ButtonPanelCtl.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace ProgramMain.ExampleForms.Controls 2 | { 3 | partial class ButtonPanelCtl 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.components = new System.ComponentModel.Container(); 32 | this.labelControl1 = new System.Windows.Forms.Label(); 33 | this.btnRefreshMap = new System.Windows.Forms.Button(); 34 | this.btnPrint = new System.Windows.Forms.Button(); 35 | this.zoomLevel = new System.Windows.Forms.TrackBar(); 36 | this.btnCenterMap = new System.Windows.Forms.Button(); 37 | this.btnCacheAllMap = new System.Windows.Forms.Button(); 38 | this.btnSaveMapAsImage = new System.Windows.Forms.Button(); 39 | this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); 40 | ((System.ComponentModel.ISupportInitialize)(this.zoomLevel)).BeginInit(); 41 | this.SuspendLayout(); 42 | // 43 | // labelControl1 44 | // 45 | this.labelControl1.Location = new System.Drawing.Point(105, 13); 46 | this.labelControl1.Name = "labelControl1"; 47 | this.labelControl1.Size = new System.Drawing.Size(40, 13); 48 | this.labelControl1.TabIndex = 3; 49 | this.labelControl1.Text = "Zoom:"; 50 | // 51 | // btnRefreshMap 52 | // 53 | this.btnRefreshMap.Image = global::ProgramMain.Properties.Resources.refresh_16; 54 | this.btnRefreshMap.Location = new System.Drawing.Point(3, 3); 55 | this.btnRefreshMap.Name = "btnRefreshMap"; 56 | this.btnRefreshMap.Size = new System.Drawing.Size(33, 32); 57 | this.btnRefreshMap.TabIndex = 8; 58 | this.toolTip1.SetToolTip(this.btnRefreshMap, "Refresh Sample Tree"); 59 | this.btnRefreshMap.UseCompatibleTextRendering = true; 60 | this.btnRefreshMap.UseVisualStyleBackColor = true; 61 | this.btnRefreshMap.Click += new System.EventHandler(this.btnRefreshMap_Click); 62 | // 63 | // btnPrint 64 | // 65 | this.btnPrint.Image = global::ProgramMain.Properties.Resources.print_24; 66 | this.btnPrint.Location = new System.Drawing.Point(42, 3); 67 | this.btnPrint.Name = "btnPrint"; 68 | this.btnPrint.Size = new System.Drawing.Size(33, 32); 69 | this.btnPrint.TabIndex = 9; 70 | this.toolTip1.SetToolTip(this.btnPrint, "Print Map"); 71 | this.btnPrint.UseVisualStyleBackColor = true; 72 | this.btnPrint.Click += new System.EventHandler(this.btnPrint_Click); 73 | // 74 | // zoomLevel 75 | // 76 | this.zoomLevel.LargeChange = 2; 77 | this.zoomLevel.Location = new System.Drawing.Point(151, 0); 78 | this.zoomLevel.Maximum = 20; 79 | this.zoomLevel.Minimum = 10; 80 | this.zoomLevel.Name = "zoomLevel"; 81 | this.zoomLevel.Size = new System.Drawing.Size(226, 45); 82 | this.zoomLevel.TabIndex = 10; 83 | this.toolTip1.SetToolTip(this.zoomLevel, "Change map zoom level"); 84 | this.zoomLevel.Value = 12; 85 | this.zoomLevel.ValueChanged += new System.EventHandler(this.zoomLevel_ValueChanged); 86 | // 87 | // btnCenterMap 88 | // 89 | this.btnCenterMap.Image = global::ProgramMain.Properties.Resources.centermap_24; 90 | this.btnCenterMap.Location = new System.Drawing.Point(383, 3); 91 | this.btnCenterMap.Name = "btnCenterMap"; 92 | this.btnCenterMap.Size = new System.Drawing.Size(33, 32); 93 | this.btnCenterMap.TabIndex = 11; 94 | this.toolTip1.SetToolTip(this.btnCenterMap, "Center map"); 95 | this.btnCenterMap.UseVisualStyleBackColor = true; 96 | this.btnCenterMap.Click += new System.EventHandler(this.btnCenterMap_Click); 97 | // 98 | // btnCacheAllMap 99 | // 100 | this.btnCacheAllMap.Image = global::ProgramMain.Properties.Resources.save_2_16x16; 101 | this.btnCacheAllMap.Location = new System.Drawing.Point(422, 3); 102 | this.btnCacheAllMap.Name = "btnCacheAllMap"; 103 | this.btnCacheAllMap.Size = new System.Drawing.Size(33, 32); 104 | this.btnCacheAllMap.TabIndex = 12; 105 | this.toolTip1.SetToolTip(this.btnCacheAllMap, "Download whole map to local disk cache"); 106 | this.btnCacheAllMap.UseVisualStyleBackColor = true; 107 | this.btnCacheAllMap.Click += new System.EventHandler(this.btnCacheAllMap_Click); 108 | // 109 | // btnSaveMapAsImage 110 | // 111 | this.btnSaveMapAsImage.Image = global::ProgramMain.Properties.Resources.program_24; 112 | this.btnSaveMapAsImage.Location = new System.Drawing.Point(461, 3); 113 | this.btnSaveMapAsImage.Name = "btnSaveMapAsImage"; 114 | this.btnSaveMapAsImage.Size = new System.Drawing.Size(33, 32); 115 | this.btnSaveMapAsImage.TabIndex = 13; 116 | this.toolTip1.SetToolTip(this.btnSaveMapAsImage, "Save map as image to file"); 117 | this.btnSaveMapAsImage.UseVisualStyleBackColor = true; 118 | this.btnSaveMapAsImage.Click += new System.EventHandler(this.btnSaveMapAsImage_Click); 119 | // 120 | // ButtonPanelCtl 121 | // 122 | this.Controls.Add(this.btnSaveMapAsImage); 123 | this.Controls.Add(this.btnCacheAllMap); 124 | this.Controls.Add(this.btnCenterMap); 125 | this.Controls.Add(this.zoomLevel); 126 | this.Controls.Add(this.btnPrint); 127 | this.Controls.Add(this.btnRefreshMap); 128 | this.Controls.Add(this.labelControl1); 129 | this.MaximumSize = new System.Drawing.Size(20000, 38); 130 | this.MinimumSize = new System.Drawing.Size(325, 38); 131 | this.Name = "ButtonPanelCtl"; 132 | this.Size = new System.Drawing.Size(600, 38); 133 | this.Load += new System.EventHandler(this.FrmDesignPanel_Load); 134 | ((System.ComponentModel.ISupportInitialize)(this.zoomLevel)).EndInit(); 135 | this.ResumeLayout(false); 136 | this.PerformLayout(); 137 | 138 | } 139 | 140 | #endregion 141 | 142 | private System.Windows.Forms.Label labelControl1; 143 | private System.Windows.Forms.Button btnCenterMap; 144 | private System.Windows.Forms.TrackBar zoomLevel; 145 | private System.Windows.Forms.Button btnPrint; 146 | private System.Windows.Forms.Button btnRefreshMap; 147 | private System.Windows.Forms.Button btnCacheAllMap; 148 | private System.Windows.Forms.Button btnSaveMapAsImage; 149 | private System.Windows.Forms.ToolTip toolTip1; 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /ExampleForms/Controls/ButtonPanelCtl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace ProgramMain.ExampleForms.Controls 5 | { 6 | public partial class ButtonPanelCtl : UserControl 7 | { 8 | public ButtonPanelCtl() 9 | { 10 | InitializeComponent(); 11 | } 12 | 13 | public int Level 14 | { 15 | get 16 | { 17 | return zoomLevel.Value; 18 | } 19 | set 20 | { 21 | zoomLevel.Value = value; 22 | } 23 | } 24 | 25 | public class LevelValueArgs : EventArgs 26 | { 27 | public int Level { get; private set; } 28 | 29 | public LevelValueArgs(int level) 30 | { 31 | Level = level; 32 | } 33 | } 34 | public event EventHandler LevelValueChanged; 35 | 36 | public event EventHandler CenterMapClicked; 37 | 38 | public event EventHandler PrintMapClicked; 39 | 40 | public event EventHandler RefreshMapClicked; 41 | 42 | public event EventHandler SaveAllMapClicked; 43 | 44 | public event EventHandler SaveMapAsImageClicked; 45 | 46 | private void FrmDesignPanel_Load(object sender, EventArgs e) 47 | { 48 | zoomLevel.Maximum = Properties.Settings.Default.MaxZoomLevel; 49 | zoomLevel.Minimum = Properties.Settings.Default.MinZoomLevel; 50 | zoomLevel.Value = Properties.Settings.Default.StartZoomLevel; 51 | } 52 | 53 | private void zoomLevel_ValueChanged(object sender, EventArgs e) 54 | { 55 | if (LevelValueChanged != null && zoomLevel.Value >= Properties.Settings.Default.MinZoomLevel 56 | && zoomLevel.Value <= Properties.Settings.Default.MaxZoomLevel) 57 | { 58 | LevelValueChanged(this, new LevelValueArgs(zoomLevel.Value)); 59 | } 60 | } 61 | 62 | private void btnCenterMap_Click(object sender, EventArgs e) 63 | { 64 | if (CenterMapClicked != null) CenterMapClicked(this, e); 65 | } 66 | 67 | private void btnRefreshMap_Click(object sender, EventArgs e) 68 | { 69 | if (RefreshMapClicked != null) RefreshMapClicked(this, e); 70 | } 71 | 72 | private void btnPrint_Click(object sender, EventArgs e) 73 | { 74 | if (PrintMapClicked != null) PrintMapClicked(this, EventArgs.Empty); 75 | } 76 | 77 | private void btnCacheAllMap_Click(object sender, EventArgs e) 78 | { 79 | if (SaveAllMapClicked != null) SaveAllMapClicked(this, EventArgs.Empty); 80 | } 81 | 82 | private void btnSaveMapAsImage_Click(object sender, EventArgs e) 83 | { 84 | if (SaveMapAsImageClicked != null) SaveMapAsImageClicked(this, EventArgs.Empty); 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /ExampleForms/Controls/ButtonPanelCtl.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 17, 17 122 | 123 | -------------------------------------------------------------------------------- /ExampleForms/Controls/MapCtl.designer.cs: -------------------------------------------------------------------------------- 1 | namespace ProgramMain.ExampleForms.Controls 2 | { 3 | partial class MapCtl 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.components = new System.ComponentModel.Container(); 32 | this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); 33 | this.SuspendLayout(); 34 | // 35 | // MapCtl 36 | // 37 | this.Name = "MapCtl"; 38 | this.Paint += new System.Windows.Forms.PaintEventHandler(this.MapCtl_Paint); 39 | this.DoubleClick += new System.EventHandler(this.MapCtl_DoubleClick); 40 | this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.MapCtl_KeyDown); 41 | this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.MapCtl_KeyUp); 42 | this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.MapCtl_MouseDown); 43 | this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.MapCtl_MouseMove); 44 | this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.MapCtl_MouseUp); 45 | this.Resize += new System.EventHandler(this.MapCtl_Resize); 46 | this.ResumeLayout(false); 47 | 48 | } 49 | 50 | #endregion 51 | 52 | private System.Windows.Forms.ToolTip toolTip1; 53 | 54 | 55 | 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /ExampleForms/Controls/MapCtl.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 17, 17 122 | 123 | -------------------------------------------------------------------------------- /ExampleForms/FrmMapDownloader.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace ProgramMain.ExampleForms 2 | { 3 | partial class FrmMapDownloader 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.labelInfo = new System.Windows.Forms.Label(); 32 | this.progressBar1 = new System.Windows.Forms.ProgressBar(); 33 | this.btnCancel = new System.Windows.Forms.Button(); 34 | this.label2 = new System.Windows.Forms.Label(); 35 | this.labProceed = new System.Windows.Forms.Label(); 36 | this.label3 = new System.Windows.Forms.Label(); 37 | this.labTotal = new System.Windows.Forms.Label(); 38 | this.saveFileDialog1 = new System.Windows.Forms.SaveFileDialog(); 39 | this.SuspendLayout(); 40 | // 41 | // labelInfo 42 | // 43 | this.labelInfo.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 44 | | System.Windows.Forms.AnchorStyles.Right))); 45 | this.labelInfo.Location = new System.Drawing.Point(12, 13); 46 | this.labelInfo.Name = "labelInfo"; 47 | this.labelInfo.Size = new System.Drawing.Size(487, 23); 48 | this.labelInfo.TabIndex = 0; 49 | this.labelInfo.Text = "Cache all map on local disk"; 50 | // 51 | // progressBar1 52 | // 53 | this.progressBar1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 54 | | System.Windows.Forms.AnchorStyles.Right))); 55 | this.progressBar1.Location = new System.Drawing.Point(12, 39); 56 | this.progressBar1.Name = "progressBar1"; 57 | this.progressBar1.Size = new System.Drawing.Size(487, 23); 58 | this.progressBar1.TabIndex = 1; 59 | this.progressBar1.Value = 20; 60 | // 61 | // btnCancel 62 | // 63 | this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 64 | | System.Windows.Forms.AnchorStyles.Right))); 65 | this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; 66 | this.btnCancel.Location = new System.Drawing.Point(423, 102); 67 | this.btnCancel.Name = "btnCancel"; 68 | this.btnCancel.Size = new System.Drawing.Size(75, 23); 69 | this.btnCancel.TabIndex = 2; 70 | this.btnCancel.Text = "Cancel"; 71 | this.btnCancel.UseVisualStyleBackColor = true; 72 | // 73 | // label2 74 | // 75 | this.label2.AutoSize = true; 76 | this.label2.Location = new System.Drawing.Point(12, 69); 77 | this.label2.Name = "label2"; 78 | this.label2.Size = new System.Drawing.Size(120, 13); 79 | this.label2.TabIndex = 3; 80 | this.label2.Text = "Proceed Block Number:"; 81 | // 82 | // labProceed 83 | // 84 | this.labProceed.AutoSize = true; 85 | this.labProceed.Location = new System.Drawing.Point(139, 69); 86 | this.labProceed.Name = "labProceed"; 87 | this.labProceed.Size = new System.Drawing.Size(14, 13); 88 | this.labProceed.TabIndex = 4; 89 | this.labProceed.Text = "~"; 90 | // 91 | // label3 92 | // 93 | this.label3.AutoSize = true; 94 | this.label3.Location = new System.Drawing.Point(12, 94); 95 | this.label3.Name = "label3"; 96 | this.label3.Size = new System.Drawing.Size(69, 13); 97 | this.label3.TabIndex = 5; 98 | this.label3.Text = "Total Blocks:"; 99 | // 100 | // labTotal 101 | // 102 | this.labTotal.AutoSize = true; 103 | this.labTotal.Location = new System.Drawing.Point(139, 94); 104 | this.labTotal.Name = "labTotal"; 105 | this.labTotal.Size = new System.Drawing.Size(14, 13); 106 | this.labTotal.TabIndex = 6; 107 | this.labTotal.Text = "~"; 108 | // 109 | // saveFileDialog1 110 | // 111 | this.saveFileDialog1.DefaultExt = "PNG file (*.png)|*.png"; 112 | this.saveFileDialog1.FileName = "SimpleMap.png"; 113 | // 114 | // FrmMapDownloader 115 | // 116 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 117 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 118 | this.CancelButton = this.btnCancel; 119 | this.ClientSize = new System.Drawing.Size(511, 143); 120 | this.Controls.Add(this.labTotal); 121 | this.Controls.Add(this.label3); 122 | this.Controls.Add(this.labProceed); 123 | this.Controls.Add(this.label2); 124 | this.Controls.Add(this.btnCancel); 125 | this.Controls.Add(this.progressBar1); 126 | this.Controls.Add(this.labelInfo); 127 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 128 | this.MaximizeBox = false; 129 | this.MinimizeBox = false; 130 | this.Name = "FrmMapDownloader"; 131 | this.Text = "Map Downloader"; 132 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FrmMapDownloader_FormClosing); 133 | this.Load += new System.EventHandler(this.FrmMapDownloader_Load); 134 | this.ResumeLayout(false); 135 | this.PerformLayout(); 136 | 137 | } 138 | 139 | #endregion 140 | 141 | private System.Windows.Forms.Label labelInfo; 142 | private System.Windows.Forms.ProgressBar progressBar1; 143 | private System.Windows.Forms.Button btnCancel; 144 | private System.Windows.Forms.Label label2; 145 | private System.Windows.Forms.Label labProceed; 146 | private System.Windows.Forms.Label label3; 147 | private System.Windows.Forms.Label labTotal; 148 | private System.Windows.Forms.SaveFileDialog saveFileDialog1; 149 | } 150 | } -------------------------------------------------------------------------------- /ExampleForms/FrmMapDownloader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Drawing.Imaging; 4 | using System.Globalization; 5 | using System.IO; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | using System.Windows.Forms; 9 | using ProgramMain.Layers; 10 | using ProgramMain.Map; 11 | using ProgramMain.Map.Google; 12 | using ProgramMain.Framework; 13 | using PixelFormat = System.Drawing.Imaging.PixelFormat; 14 | 15 | namespace ProgramMain.ExampleForms 16 | { 17 | public partial class FrmMapDownloader : Form 18 | { 19 | private readonly CancellationTokenSource _tokenSource; 20 | private Task _mapTask; 21 | 22 | protected delegate void ProgressEventDelegate(int progress, int mapBlockNumber, int mapBlockCount); 23 | 24 | protected event ProgressEventDelegate ProgressEvent; 25 | 26 | protected delegate void SaveMapEventDelegate(Bitmap image); 27 | 28 | protected event SaveMapEventDelegate SaveMapEvent; 29 | 30 | private enum WorkMode 31 | { 32 | Download, 33 | SaveToImageFile 34 | }; 35 | 36 | private WorkMode _workMode; 37 | 38 | private PixelFormat _mapPiFormat; 39 | private int _mapLevel; 40 | 41 | public static void DownloadMap() 42 | { 43 | var frm = new FrmMapDownloader 44 | { 45 | _workMode = WorkMode.Download, 46 | Text = @"Download Map", 47 | labelInfo = {Text = @"Cache all map on local disk"}, 48 | }; 49 | frm.ShowDialog(); 50 | } 51 | 52 | public static void SaveMapAsImage(PixelFormat mapPiFormat, int mapLevel) 53 | { 54 | var frm = new FrmMapDownloader 55 | { 56 | _workMode = WorkMode.SaveToImageFile, 57 | _mapPiFormat = mapPiFormat, 58 | _mapLevel = mapLevel, 59 | Text = @"Save Map As Image", 60 | labelInfo = {Text = @"Save big map as one image"} 61 | }; 62 | 63 | frm.ShowDialog(); 64 | } 65 | 66 | private FrmMapDownloader() 67 | { 68 | InitializeComponent(); 69 | 70 | _tokenSource = new CancellationTokenSource(); 71 | ProgressEvent += OnProgress; 72 | SaveMapEvent += OnSaveMap; 73 | } 74 | 75 | private void FrmMapDownloader_Load(object sender, EventArgs e) 76 | { 77 | var token = _tokenSource.Token; 78 | switch (_workMode) 79 | { 80 | case WorkMode.Download: 81 | _mapTask = Task.Factory.StartNew(() => DownloadThread(token), token); 82 | break; 83 | case WorkMode.SaveToImageFile: 84 | _mapTask = Task.Factory.StartNew(() => GetFullMapThread(token), token); 85 | break; 86 | } 87 | } 88 | 89 | private void FrmMapDownloader_FormClosing(object sender, FormClosingEventArgs e) 90 | { 91 | _tokenSource.Cancel(); 92 | Task.WaitAll(_mapTask); 93 | e.Cancel = false; 94 | } 95 | 96 | protected void OnProgress(int progress, int mapBlockNumber, int mapBlockCount) 97 | { 98 | if (progress > 100) 99 | { 100 | Close(); 101 | return; 102 | } 103 | if (mapBlockNumber % 10 == 0 || progress >= 100) 104 | { 105 | progressBar1.Value = progress; 106 | labProceed.Text = mapBlockNumber.ToString(CultureInfo.InvariantCulture); 107 | labTotal.Text = mapBlockCount.ToString(CultureInfo.InvariantCulture); 108 | } 109 | } 110 | 111 | protected void OnSaveMap(Bitmap image) 112 | { 113 | try 114 | { 115 | if (saveFileDialog1.ShowDialog(this) == DialogResult.OK) 116 | { 117 | /*var palette = BitmapPalettes.Halftone256; 118 | 119 | var idxImage = new RenderTargetBitmap( 120 | image.Width, 121 | image.Height, 122 | Screen.PrimaryScreen.BitsPerPixel, 123 | Screen.PrimaryScreen.BitsPerPixel, 124 | PixelFormats.Indexed8); 125 | var visual = new DrawingVisual(); 126 | var context = visual.RenderOpen(); 127 | context.DrawImage(image, ); 128 | idxImage.Render(); 129 | Graphics.FromImage(idxImage); 130 | 131 | */ 132 | { 133 | image.Save(saveFileDialog1.FileName, ImageFormat.Png); 134 | } 135 | } 136 | } 137 | finally 138 | { 139 | Close(); 140 | } 141 | } 142 | 143 | private void DownloadThread(CancellationToken ct) 144 | { 145 | var leftBound = new Coordinate(Properties.Settings.Default.LeftMapBound, Properties.Settings.Default.TopMapBound); 146 | var rightBound = new Coordinate(Properties.Settings.Default.RightMapBound, Properties.Settings.Default.BottomMapBound); 147 | 148 | var rectBound = new CoordinateRectangle(leftBound, rightBound); 149 | 150 | var mapBlockCount = 0; 151 | for (var mapLevel = Properties.Settings.Default.MinZoomLevel; mapLevel <= Properties.Settings.Default.MaxZoomLevel; mapLevel++) 152 | { 153 | var mapWidth = Convert.ToInt32((new GoogleCoordinate(rectBound.RightTop, mapLevel)).X - (new GoogleCoordinate(rectBound.LeftTop, mapLevel)).X) + 2 * GoogleBlock.BlockSize; 154 | var mapHeight = Convert.ToInt32((new GoogleCoordinate(rectBound.LeftBottom, mapLevel)).Y - (new GoogleCoordinate(rectBound.LeftTop, mapLevel)).Y) + 2 * GoogleBlock.BlockSize; 155 | 156 | var viewBound = rectBound.LineMiddlePoint.GetScreenViewFromCenter(mapWidth, mapHeight, mapLevel); 157 | var blockView = viewBound.BlockView; 158 | mapBlockCount += (blockView.Right - blockView.Left + 1) * (blockView.Bottom - blockView.Top + 1); 159 | } 160 | 161 | var mapBlockNumber = 0; 162 | BeginInvoke(ProgressEvent, new Object[] {mapBlockNumber * 100 / mapBlockCount, mapBlockNumber, mapBlockCount}); 163 | 164 | for (var mapLevel = Properties.Settings.Default.MinZoomLevel; mapLevel <= Properties.Settings.Default.MaxZoomLevel; mapLevel++) 165 | { 166 | var mapWidth = Convert.ToInt32((new GoogleCoordinate(rectBound.RightTop, mapLevel)).X - (new GoogleCoordinate(rectBound.LeftTop, mapLevel)).X) + 2 * GoogleBlock.BlockSize; 167 | var mapHeight = Convert.ToInt32((new GoogleCoordinate(rectBound.LeftBottom, mapLevel)).Y - (new GoogleCoordinate(rectBound.LeftTop, mapLevel)).Y) + 2 * GoogleBlock.BlockSize; 168 | 169 | var viewBound = rectBound.LineMiddlePoint.GetScreenViewFromCenter(mapWidth, mapHeight, mapLevel); 170 | var blockView = viewBound.BlockView; 171 | 172 | for (var x = blockView.Left; x <= blockView.Right; x++) 173 | { 174 | for (var y = blockView.Top; y <= blockView.Bottom; y++) 175 | { 176 | var block = new GoogleBlock(x, y, mapLevel); 177 | 178 | var fileName = Properties.Settings.GetMapFileName(block); 179 | if (!File.Exists(fileName)) 180 | MapLayer.DownloadImageFromGoogle(block, false); 181 | 182 | mapBlockNumber++; 183 | 184 | BeginInvoke(ProgressEvent, new Object[] {mapBlockNumber * 100 / mapBlockCount, mapBlockNumber, mapBlockCount}); 185 | 186 | if (ct.IsCancellationRequested) 187 | return; 188 | } 189 | } 190 | } 191 | BeginInvoke(ProgressEvent, new Object[] {101, mapBlockNumber, mapBlockCount}); 192 | } 193 | 194 | private void GetFullMapThread(CancellationToken ct) 195 | { 196 | var leftBound = new Coordinate(Properties.Settings.Default.LeftMapBound, Properties.Settings.Default.TopMapBound); 197 | var rightBound = new Coordinate(Properties.Settings.Default.RightMapBound, Properties.Settings.Default.BottomMapBound); 198 | 199 | var rectBound = new CoordinateRectangle(leftBound, rightBound); 200 | 201 | try 202 | { 203 | var mapWidth = Convert.ToInt32((new GoogleCoordinate(rectBound.RightTop, _mapLevel)).X - (new GoogleCoordinate(rectBound.LeftTop, _mapLevel)).X) + 2 * GoogleBlock.BlockSize; 204 | var mapHeight = Convert.ToInt32((new GoogleCoordinate(rectBound.LeftBottom, _mapLevel)).Y - (new GoogleCoordinate(rectBound.LeftTop, _mapLevel)).Y) + 2 * GoogleBlock.BlockSize; 205 | 206 | var image = GraphicLayer.CreateCompatibleBitmap(null, mapWidth, mapHeight, _mapPiFormat); 207 | var graphics = Graphics.FromImage(image); 208 | 209 | var viewBound = rectBound.LineMiddlePoint.GetScreenViewFromCenter(mapWidth, mapHeight, _mapLevel); 210 | var blockView = viewBound.BlockView; 211 | var mapBlockCount = (blockView.Right - blockView.Left + 1) * (blockView.Bottom - blockView.Top + 1); 212 | var mapBlockNumber = 0; 213 | 214 | BeginInvoke(ProgressEvent, new Object[] {mapBlockNumber * 100 / mapBlockCount, mapBlockNumber, mapBlockCount}); 215 | 216 | for (var x = blockView.Left; x <= blockView.Right; x++) 217 | { 218 | for (var y = blockView.Top; y <= blockView.Bottom; y++) 219 | { 220 | var block = new GoogleBlock(x, y, _mapLevel); 221 | var bmp = GraphicLayer.CreateCompatibleBitmap( 222 | MapLayer.DownloadImageFromFile(block) ?? MapLayer.DownloadImageFromGoogle(block, true), 223 | GoogleBlock.BlockSize, GoogleBlock.BlockSize, _mapPiFormat); 224 | 225 | var rect = ((GoogleRectangle) block).GetScreenRect(viewBound); 226 | graphics.DrawImageUnscaled(bmp, rect.Location.X, rect.Location.Y); 227 | 228 | mapBlockNumber++; 229 | 230 | BeginInvoke(ProgressEvent, new Object[]{mapBlockNumber * 100 / mapBlockCount, mapBlockNumber, mapBlockCount}); 231 | 232 | if (ct.IsCancellationRequested) 233 | return; 234 | } 235 | } 236 | 237 | BeginInvoke(SaveMapEvent, new Object[] {image}); 238 | } 239 | catch (Exception e) 240 | { 241 | BeginInvoke(ProgressEvent, new Object[] { 101, 0, 0 }); 242 | MessageBox.Show(e.Message, @"Error!", MessageBoxButtons.OK, MessageBoxIcon.Error); 243 | } 244 | } 245 | } 246 | } 247 | -------------------------------------------------------------------------------- /ExampleForms/FrmMapDownloader.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 17, 17 122 | 123 | -------------------------------------------------------------------------------- /ExampleForms/FrmOpticMap.Designer.cs: -------------------------------------------------------------------------------- 1 | using ProgramMain.ExampleForms.Controls; 2 | 3 | namespace ProgramMain.ExampleForms 4 | { 5 | partial class FrmOpticMap 6 | { 7 | /// 8 | /// Required designer variable. 9 | /// 10 | private System.ComponentModel.IContainer components = null; 11 | 12 | /// 13 | /// Clean up any resources being used. 14 | /// 15 | /// true if managed resources should be disposed; otherwise, false. 16 | protected override void Dispose(bool disposing) 17 | { 18 | if (disposing && (components != null)) 19 | { 20 | components.Dispose(); 21 | } 22 | base.Dispose(disposing); 23 | } 24 | 25 | #region Windows Form Designer generated code 26 | 27 | /// 28 | /// Required method for Designer support - do not modify 29 | /// the contents of this method with the code editor. 30 | /// 31 | private void InitializeComponent() 32 | { 33 | this.printDocument1 = new System.Drawing.Printing.PrintDocument(); 34 | this.printDialog1 = new System.Windows.Forms.PrintDialog(); 35 | this.mapCtl1 = new MapCtl(); 36 | this.buttonPanelCtl1 = new ButtonPanelCtl(); 37 | this.SuspendLayout(); 38 | // 39 | // printDocument1 40 | // 41 | this.printDocument1.DocumentName = "Simple Map"; 42 | this.printDocument1.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(this.Document_PrintPage); 43 | // 44 | // printDialog1 45 | // 46 | this.printDialog1.Document = this.printDocument1; 47 | this.printDialog1.UseEXDialog = true; 48 | // 49 | // mapCtl1 50 | // 51 | this.mapCtl1.AllowDrop = true; 52 | this.mapCtl1.Dock = System.Windows.Forms.DockStyle.Fill; 53 | this.mapCtl1.Level = 13; 54 | this.mapCtl1.Location = new System.Drawing.Point(0, 38); 55 | this.mapCtl1.Name = "mapCtl1"; 56 | this.mapCtl1.Size = new System.Drawing.Size(680, 426); 57 | this.mapCtl1.TabIndex = 0; 58 | this.mapCtl1.LevelValueChanged += new System.EventHandler(this.mapCtl1_LevelValueChanged); 59 | // 60 | // buttonPanelCtl1 61 | // 62 | this.buttonPanelCtl1.Dock = System.Windows.Forms.DockStyle.Top; 63 | this.buttonPanelCtl1.Level = 12; 64 | this.buttonPanelCtl1.Location = new System.Drawing.Point(0, 0); 65 | this.buttonPanelCtl1.MaximumSize = new System.Drawing.Size(2000, 38); 66 | this.buttonPanelCtl1.MinimumSize = new System.Drawing.Size(350, 38); 67 | this.buttonPanelCtl1.Name = "buttonPanelCtl1"; 68 | this.buttonPanelCtl1.Size = new System.Drawing.Size(680, 38); 69 | this.buttonPanelCtl1.TabIndex = 1; 70 | this.buttonPanelCtl1.LevelValueChanged += new System.EventHandler(this.buttonPanelCtl1_LevelValueChanged); 71 | this.buttonPanelCtl1.CenterMapClicked += new System.EventHandler(this.buttonPanelCtl1_CenterMapClicked); 72 | this.buttonPanelCtl1.PrintMapClicked += new System.EventHandler(this.buttonPanelCtl1_PrintMapClicked); 73 | this.buttonPanelCtl1.RefreshMapClicked += new System.EventHandler(this.buttonPanelCtl1_RefreshMapClicked); 74 | this.buttonPanelCtl1.SaveAllMapClicked += new System.EventHandler(this.buttonPanelCtl1_SaveAllMapClicked); 75 | this.buttonPanelCtl1.SaveMapAsImageClicked += new System.EventHandler(this.buttonPanelCtl1_SaveMapAsImageClicked); 76 | // 77 | // FrmOpticMap 78 | // 79 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 80 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 81 | this.ClientSize = new System.Drawing.Size(680, 464); 82 | this.Controls.Add(this.mapCtl1); 83 | this.Controls.Add(this.buttonPanelCtl1); 84 | this.DoubleBuffered = true; 85 | this.Name = "FrmOpticMap"; 86 | this.Text = "Map"; 87 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FrmOpticMap_FormClosing); 88 | this.Load += new System.EventHandler(this.FrmOpticMap_Load); 89 | this.ResumeLayout(false); 90 | 91 | } 92 | 93 | #endregion 94 | 95 | private MapCtl mapCtl1; 96 | private ButtonPanelCtl buttonPanelCtl1; 97 | private System.Drawing.Printing.PrintDocument printDocument1; 98 | private System.Windows.Forms.PrintDialog printDialog1; 99 | } 100 | } -------------------------------------------------------------------------------- /ExampleForms/FrmOpticMap.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Drawing.Drawing2D; 4 | using System.Windows.Forms; 5 | using ProgramMain.ExampleForms.Controls; 6 | 7 | namespace ProgramMain.ExampleForms 8 | { 9 | public partial class FrmOpticMap : Form 10 | { 11 | public FrmOpticMap() 12 | { 13 | InitializeComponent(); 14 | 15 | Icon = Miscellaneous.DefaultIcon(); 16 | } 17 | 18 | //protected override CreateParams CreateParams 19 | //{ 20 | // get 21 | // { 22 | // var handleParam = base.CreateParams; 23 | // handleParam.ExStyle |= 0x02000000; // WS_EX_COMPOSITED 24 | // return handleParam; 25 | // } 26 | //} 27 | 28 | protected override void OnResizeBegin(EventArgs e) 29 | { 30 | SuspendLayout(); 31 | base.OnResizeBegin(e); 32 | } 33 | 34 | protected override void OnResizeEnd(EventArgs e) 35 | { 36 | ResumeLayout(); 37 | base.OnResizeEnd(e); 38 | } 39 | 40 | private void FrmOpticMap_Load(object sender, EventArgs e) 41 | { 42 | Text = Miscellaneous.GetAssemblyTitle(); 43 | } 44 | 45 | private void FrmOpticMap_FormClosing(object sender, FormClosingEventArgs e) 46 | { 47 | mapCtl1.ControlClosing(); 48 | } 49 | 50 | public void RefreshForm() 51 | { 52 | mapCtl1.RefreshControl(); 53 | } 54 | 55 | public void SetCenterMapObject(decimal longitude, decimal latitude) 56 | { 57 | mapCtl1.MoveCenterMapObject(longitude, latitude); 58 | } 59 | 60 | private void buttonPanelCtl1_RefreshMapClicked(object sender, EventArgs e) 61 | { 62 | RefreshForm(); 63 | } 64 | 65 | private void buttonPanelCtl1_LevelValueChanged(object sender, ButtonPanelCtl.LevelValueArgs e) 66 | { 67 | mapCtl1.Level = e.Level; 68 | } 69 | 70 | private void buttonPanelCtl1_CenterMapClicked(object sender, EventArgs e) 71 | { 72 | mapCtl1.SetCenterMap(); 73 | } 74 | 75 | public int Level 76 | { 77 | set { buttonPanelCtl1.Level = value; } 78 | } 79 | 80 | private void mapCtl1_LevelValueChanged(object sender, ButtonPanelCtl.LevelValueArgs e) 81 | { 82 | buttonPanelCtl1.Level = e.Level; 83 | } 84 | 85 | 86 | private void buttonPanelCtl1_PrintMapClicked(object sender, EventArgs e) 87 | { 88 | if (printDialog1.ShowDialog() == DialogResult.OK) 89 | printDocument1.Print(); 90 | } 91 | 92 | void Document_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) 93 | { 94 | e.HasMorePages = false; 95 | e.Graphics.InterpolationMode = InterpolationMode.HighQualityBilinear; 96 | try 97 | { 98 | var imageMap = mapCtl1.GetMapImageForPrint(); 99 | var printSize = e.PageBounds.Size; 100 | var k1 = (double)imageMap.Width / printSize.Width; 101 | var k2 = (double)imageMap.Height / printSize.Height; 102 | var k = (k1 > k2) ? k1 : k2; 103 | var newSize = new Size((int)(imageMap.Size.Width / k), (int)(imageMap.Size.Height / k)); 104 | 105 | var screnCenter = new Point(printSize.Width / 2, printSize.Height / 2); 106 | var mapCenter = new Point(newSize.Width / 2, newSize.Height / 2); 107 | var shift = new Size(screnCenter.X - mapCenter.X, screnCenter.Y - mapCenter.Y); 108 | var p = new Point(0, 0) + shift; 109 | 110 | var rectangle = new Rectangle(p, newSize); 111 | e.Graphics.DrawImage(imageMap, rectangle); 112 | } 113 | catch (Exception ex) 114 | { 115 | //do nothing 116 | System.Diagnostics.Trace.WriteLine(ex.Message); 117 | } 118 | } 119 | 120 | private void buttonPanelCtl1_SaveAllMapClicked(object sender, EventArgs e) 121 | { 122 | FrmMapDownloader.DownloadMap(); 123 | } 124 | 125 | private void buttonPanelCtl1_SaveMapAsImageClicked(object sender, EventArgs e) 126 | { 127 | FrmMapDownloader.SaveMapAsImage(mapCtl1.PiFormat, mapCtl1.Level); 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /ExampleForms/FrmOpticMap.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 17, 17 122 | 123 | 124 | 158, 17 125 | 126 | -------------------------------------------------------------------------------- /ExampleForms/Miscellaneous.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace ProgramMain.ExampleForms 4 | { 5 | public static class Miscellaneous 6 | { 7 | public static System.Drawing.Icon DefaultIcon() 8 | { 9 | return System.Drawing.Icon.ExtractAssociatedIcon(Application.ExecutablePath); 10 | } 11 | 12 | public static string GetAssemblyTitle() 13 | { 14 | var aTitle = @"Simple Map"; 15 | var thisAssembly = Program.MainForm.GetType().Assembly; 16 | var attributes = thisAssembly.GetCustomAttributes(typeof(System.Reflection.AssemblyTitleAttribute), false); 17 | if (attributes.Length == 1) 18 | { 19 | aTitle = ((System.Reflection.AssemblyTitleAttribute) attributes[0]).Title; 20 | } 21 | return aTitle; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Framework/ExternalHelpers.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | 3 | namespace ProgramMain.Framework 4 | { 5 | public static class ExternalHelpers 6 | { 7 | 8 | public static object Clone(this Rectangle src) 9 | { 10 | return new Rectangle(src.Location, src.Size); 11 | } 12 | 13 | public static bool Contains(this Point pt, Rectangle rect) 14 | { 15 | return pt.X >= rect.Left && pt.X <= rect.Right 16 | && pt.Y >= rect.Top && pt.Y <= rect.Bottom; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Framework/WorkerThread/Types/EventPriorityType.cs: -------------------------------------------------------------------------------- 1 | namespace ProgramMain.Framework.WorkerThread.Types 2 | { 3 | public enum EventPriorityType { Idle = 0, Low = 1, BelowNormal = 2, Normal = 3, AboveNormal = 4, High = 5, Critical = 6 }; 4 | } -------------------------------------------------------------------------------- /Framework/WorkerThread/Types/EventPriorityTypeConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ProgramMain.Framework.WorkerThread.Types 4 | { 5 | public static class EventPriorityTypeConverter 6 | { 7 | public static Array EventPriorityValues = null; 8 | public static Array EventPriorityEnum 9 | { 10 | get 11 | { 12 | return EventPriorityValues ?? (EventPriorityValues = Enum.GetValues(typeof (EventPriorityType))); 13 | } 14 | } 15 | 16 | public static int Length 17 | { 18 | get 19 | { 20 | return EventPriorityEnum.Length; 21 | } 22 | } 23 | 24 | public static EventPriorityType ToEventPriorityType(this Int32 i) 25 | { 26 | if (i >= 0 && i < EventPriorityEnum.Length) 27 | return (EventPriorityType)Convert.ChangeType(EventPriorityEnum.GetValue(i), typeof(EventPriorityType)); 28 | 29 | return EventPriorityType.Idle; 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Framework/WorkerThread/Types/MainThreadEventArgs.cs: -------------------------------------------------------------------------------- 1 | namespace ProgramMain.Framework.WorkerThread.Types 2 | { 3 | public class MainThreadEventArgs 4 | { 5 | // Summary: 6 | // Represents an event with no event data. 7 | public static readonly MainThreadEventArgs Empty = new MainThreadEventArgs(); 8 | 9 | public delegate void MainThreadEventHandler(object sender, T e) where T : MainThreadEventArgs; 10 | 11 | public delegate void DelegateToMainThread(T eventParams) where T : MainThreadEventArgs; 12 | } 13 | } -------------------------------------------------------------------------------- /Framework/WorkerThread/Types/WorkerEventType.cs: -------------------------------------------------------------------------------- 1 | namespace ProgramMain.Framework.WorkerThread.Types 2 | { 3 | public enum WorkerEventType { None, RedrawLayer, DownloadImage, DrawImage, ReloadData, AddDbObject }; 4 | } -------------------------------------------------------------------------------- /Framework/WorkerThread/WorkerEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using ProgramMain.Framework.WorkerThread.Types; 3 | 4 | namespace ProgramMain.Framework.WorkerThread 5 | { 6 | public class WorkerEvent : IComparable 7 | { 8 | // Summary: 9 | // Represents an event with no event data. 10 | public static readonly WorkerEvent Empty = new WorkerEvent(); 11 | 12 | private readonly WorkerEventType _eventType = WorkerEventType.None; 13 | public WorkerEventType EventType 14 | { 15 | get 16 | { 17 | return _eventType; 18 | } 19 | } 20 | 21 | private readonly EventPriorityType _eventPriority = EventPriorityType.Normal; 22 | public EventPriorityType EventPriority 23 | { 24 | get 25 | { 26 | return _eventPriority; 27 | } 28 | } 29 | 30 | private readonly bool _collapsible; 31 | public bool IsCollapsible 32 | { 33 | get 34 | { 35 | return _collapsible; 36 | } 37 | } 38 | 39 | private WorkerEvent() 40 | { 41 | _collapsible = false; 42 | } 43 | 44 | public WorkerEvent(WorkerEventType pEventType) 45 | { 46 | _eventType = pEventType; 47 | _collapsible = false; 48 | _eventPriority = EventPriorityType.Normal; 49 | } 50 | 51 | public WorkerEvent(WorkerEventType pEventType, bool pIsCollapsible) 52 | { 53 | _eventType = pEventType; 54 | _collapsible = pIsCollapsible; 55 | _eventPriority = EventPriorityType.Normal; 56 | } 57 | 58 | public WorkerEvent(WorkerEventType pEventType, bool pIsCollapsible, EventPriorityType pPriorityType) 59 | { 60 | _eventType = pEventType; 61 | _collapsible = pIsCollapsible; 62 | _eventPriority = pPriorityType; 63 | } 64 | 65 | virtual public int CompareTo(object obj) 66 | { 67 | if (obj != null) 68 | { 69 | if (((WorkerEvent)obj)._eventType > EventType) 70 | return 1; 71 | if (((WorkerEvent)obj)._eventType < EventType) 72 | return -1; 73 | 74 | return 0; 75 | } 76 | return -1; 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /Framework/WorkerThread/WorkerMessageThread.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agafonoff2000/SimpleMap/7893f78f2ac8a5c070a7b98c993dd168aff16b83/Framework/WorkerThread/WorkerMessageThread.cs -------------------------------------------------------------------------------- /Layers/MapLayer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Net; 5 | using System.Drawing; 6 | using ProgramMain.Framework; 7 | using ProgramMain.Framework.WorkerThread; 8 | using ProgramMain.Framework.WorkerThread.Types; 9 | using ProgramMain.Map; 10 | using ProgramMain.Map.Google; 11 | 12 | namespace ProgramMain.Layers 13 | { 14 | public class MapLayer : GraphicLayer 15 | { 16 | private const int MaxCacheSize = 240; 17 | 18 | private Rectangle _blockView; 19 | private readonly Bitmap _emptyBlock; 20 | 21 | protected class MapWorkerEvent : WorkerEvent 22 | { 23 | public GoogleBlock Block; 24 | 25 | public MapWorkerEvent(WorkerEventType eventType, GoogleBlock block, EventPriorityType priorityType) 26 | : base(eventType, true, priorityType) 27 | { 28 | Block = block; 29 | } 30 | 31 | override public int CompareTo(object obj) 32 | { 33 | var res = base.CompareTo(obj); 34 | if (res == 0) 35 | { 36 | if (obj != null) 37 | { 38 | res = ((MapWorkerEvent) obj).Block.CompareTo(Block); 39 | } 40 | else 41 | { 42 | res = -1; 43 | } 44 | } 45 | return res; 46 | } 47 | } 48 | 49 | private struct MapCacheItem 50 | { 51 | public long Timestamp; 52 | public Bitmap Bmp; 53 | }; 54 | 55 | private static readonly SortedDictionary MapCache = new SortedDictionary(); 56 | 57 | public MapLayer(int width, int height, Coordinate centerCoordinate, int level) 58 | : base(width, height, centerCoordinate, level) 59 | { 60 | _emptyBlock = CreateCompatibleBitmap(null, GoogleBlock.BlockSize, GoogleBlock.BlockSize, PiFormat); 61 | } 62 | 63 | override protected void TranslateCoords() 64 | { 65 | base.TranslateCoords(); 66 | 67 | _blockView = ScreenView.BlockView; 68 | } 69 | 70 | private void PutMapThreadEvent(WorkerEventType eventType, GoogleBlock block, EventPriorityType priorityType) 71 | { 72 | PutWorkerThreadEvent(new MapWorkerEvent(eventType, block, priorityType)); 73 | } 74 | 75 | override protected void DrawLayer(Rectangle clipRectangle) 76 | { 77 | try 78 | { 79 | SwapDrawBuffer(); 80 | 81 | Rectangle localBlockView; 82 | GoogleRectangle localScreenView; 83 | do 84 | { 85 | DropWorkerThreadEvents(WorkerEventType.RedrawLayer); 86 | 87 | localBlockView = (Rectangle) _blockView.Clone(); 88 | localScreenView = (GoogleRectangle) ScreenView.Clone(); 89 | } 90 | while (DrawImages(localBlockView, localScreenView) == false); 91 | } 92 | finally 93 | { 94 | SwapDrawBuffer(); 95 | } 96 | FireIvalidateLayer(clipRectangle); 97 | } 98 | 99 | private bool DrawImages(Rectangle localBlockView, GoogleRectangle localScreenView) 100 | { 101 | for (var x = localBlockView.Left; x <= localBlockView.Right; x++) 102 | { 103 | for (var y = localBlockView.Top; y <= localBlockView.Bottom; y++) 104 | { 105 | var block = new GoogleBlock(x, y, Level); 106 | var pt = ((GoogleCoordinate)block).GetScreenPoint(localScreenView); 107 | 108 | var bmp = FindImage(block); 109 | if (bmp != null) 110 | { 111 | DrawBitmap(bmp, pt); 112 | } 113 | else 114 | { 115 | DrawBitmap(_emptyBlock, pt); 116 | PutMapThreadEvent(WorkerEventType.DownloadImage, block, EventPriorityType.Idle); 117 | } 118 | 119 | if (Terminating) return true; 120 | 121 | if (localScreenView.CompareTo(ScreenView) != 0) return false; 122 | } 123 | } 124 | return true; 125 | } 126 | 127 | private void DrawImage(GoogleBlock block) 128 | { 129 | if (Terminating) return; 130 | 131 | if (block.Level == Level && block.Pt.Contains(_blockView)) 132 | { 133 | var bmp = FindImage(block); 134 | if (bmp != null) 135 | { 136 | var rect = ((GoogleRectangle)block).GetScreenRect(ScreenView); 137 | DrawBitmap(bmp, rect.Location); 138 | 139 | FireIvalidateLayer(rect); 140 | } 141 | } 142 | } 143 | 144 | private static Bitmap FindImage(GoogleBlock block) 145 | { 146 | if (MapCache.ContainsKey(block)) 147 | { 148 | var dimg = MapCache[block]; 149 | dimg.Timestamp = DateTime.Now.Ticks; 150 | return dimg.Bmp; 151 | } 152 | return null; 153 | } 154 | 155 | protected override bool SetCenterCoordinate(Coordinate center, int level) 156 | { 157 | var res = base.SetCenterCoordinate(center, level); 158 | 159 | if (res) 160 | DropWorkerThreadEvents(WorkerEventType.DownloadImage); 161 | 162 | return res; 163 | } 164 | 165 | protected override bool DispatchThreadEvents(WorkerEvent workerEvent) 166 | { 167 | var res = base.DispatchThreadEvents(workerEvent); 168 | 169 | if (!res && workerEvent is MapWorkerEvent) 170 | { 171 | switch (workerEvent.EventType) 172 | { 173 | case WorkerEventType.DownloadImage: 174 | { 175 | DownloadImage(((MapWorkerEvent)workerEvent).Block); 176 | return true; 177 | } 178 | case WorkerEventType.DrawImage: 179 | { 180 | DrawImage(((MapWorkerEvent)workerEvent).Block); 181 | return true; 182 | } 183 | } 184 | } 185 | 186 | return res; 187 | } 188 | 189 | private void DownloadImage(GoogleBlock block) 190 | { 191 | if (MapCache.ContainsKey(block)) 192 | { 193 | var dimg = MapCache[block]; 194 | if (dimg.Bmp != null) //to turn off compile warning 195 | { 196 | dimg.Timestamp = DateTime.Now.Ticks; 197 | } 198 | } 199 | else 200 | { 201 | var bmp = DownloadImageFromFile(block) ?? DownloadImageFromGoogle(block, true); 202 | 203 | if (bmp != null) 204 | { 205 | bmp = CreateCompatibleBitmap(bmp, GoogleBlock.BlockSize, GoogleBlock.BlockSize, PiFormat); 206 | 207 | var dimg = new MapCacheItem { Timestamp = DateTime.Now.Ticks, Bmp = bmp }; 208 | MapCache[block] = dimg; 209 | 210 | TruncateImageCache(block); 211 | 212 | PutMapThreadEvent(WorkerEventType.DrawImage, block, EventPriorityType.Low); 213 | } 214 | } 215 | } 216 | 217 | private void TruncateImageCache(GoogleBlock newCacheItem) 218 | { 219 | while (MapCache.Count > MaxCacheSize) 220 | { 221 | var mt = GoogleBlock.Empty; 222 | var lTicks = DateTime.Now.Ticks; 223 | 224 | foreach (var lt in MapCache) 225 | { 226 | if (lt.Value.Timestamp < lTicks && lt.Key.CompareTo(newCacheItem) != 0) 227 | { 228 | mt = lt.Key; 229 | lTicks = lt.Value.Timestamp; 230 | } 231 | } 232 | 233 | if (mt != GoogleBlock.Empty) 234 | MapCache.Remove(mt); 235 | } 236 | } 237 | 238 | public static Bitmap DownloadImageFromGoogle(GoogleBlock block, bool getBitmap) 239 | { 240 | try 241 | { 242 | var oRequest = GoogleMapUtilities.CreateGoogleWebRequest(block); 243 | var oResponse = (HttpWebResponse) oRequest.GetResponse(); 244 | 245 | var bmpStream = new MemoryStream(); 246 | var oStream = oResponse.GetResponseStream(); 247 | if (oStream != null) oStream.CopyTo(bmpStream); 248 | oResponse.Close(); 249 | if (bmpStream.Length > 0) 250 | { 251 | WriteImageToFile(block, bmpStream); 252 | return getBitmap ? (Bitmap) Image.FromStream(bmpStream) : null; 253 | } 254 | } 255 | catch (Exception ex) 256 | { 257 | //do nothing 258 | System.Diagnostics.Trace.WriteLine(ex.Message); 259 | } 260 | return null; 261 | } 262 | 263 | public static Bitmap DownloadImageFromFile(GoogleBlock block) 264 | { 265 | try 266 | { 267 | var fileName = Properties.Settings.GetMapFileName(block); 268 | if (File.Exists(fileName)) 269 | { 270 | var bmp = (Bitmap)Image.FromFile(fileName); 271 | return bmp; 272 | } 273 | } 274 | catch (Exception ex) 275 | { 276 | //do nothing 277 | System.Diagnostics.Trace.WriteLine(ex.Message); 278 | } 279 | return null; 280 | } 281 | 282 | private static void WriteImageToFile(GoogleBlock block, Stream bmpStream) 283 | { 284 | var fileName = Properties.Settings.GetMapFileName(block); 285 | try 286 | { 287 | if (!File.Exists(fileName)) 288 | { 289 | var path = Path.GetDirectoryName(fileName) ?? ""; 290 | var destdir = new DirectoryInfo(path); 291 | if (!destdir.Exists) 292 | { 293 | destdir.Create(); 294 | } 295 | var fileStream = File.Create(fileName); 296 | try 297 | { 298 | bmpStream.Seek(0, SeekOrigin.Begin); 299 | bmpStream.CopyTo(fileStream); 300 | } 301 | finally 302 | { 303 | fileStream.Flush(); 304 | fileStream.Close(); 305 | } 306 | } 307 | } 308 | catch (Exception ex) 309 | { 310 | //do nothing 311 | System.Diagnostics.Trace.WriteLine(ex.Message); 312 | } 313 | } 314 | } 315 | } 316 | -------------------------------------------------------------------------------- /Layers/MapObjects/BuildingTree.cs: -------------------------------------------------------------------------------- 1 | using System.Data; 2 | using System.Threading.Tasks; 3 | using ProgramMain.ExampleDb; 4 | using ProgramMain.Layers.MapObjects.TreeNodes; 5 | using ProgramMain.Map.Spatial; 6 | using ProgramMain.Map.Spatial.Types; 7 | 8 | namespace ProgramMain.Layers.MapObjects 9 | { 10 | public class BuildingTree : SpatialTree 11 | { 12 | public SimpleMapDb.BuildingsDataTable BuildingDbRows { get; private set; } 13 | 14 | public BuildingTree() 15 | : base(SpatialSheetPowerTypes.Ultra, SpatialSheetPowerTypes.Extra, SpatialSheetPowerTypes.Medium, SpatialSheetPowerTypes.Low) 16 | { 17 | BuildingDbRows = new SimpleMapDb.BuildingsDataTable(); 18 | } 19 | 20 | protected void Insert(SimpleMapDb.BuildingsRow row) 21 | { 22 | base.Insert(row); 23 | } 24 | 25 | protected void Delete(SimpleMapDb.BuildingsRow row) 26 | { 27 | base.Delete(row); 28 | } 29 | 30 | public void LoadData() 31 | { 32 | Clear(); 33 | 34 | //read data from db here 35 | 36 | Parallel.ForEach(BuildingDbRows, Insert); 37 | } 38 | 39 | public void MergeData(SimpleMapDb.BuildingsDataTable buildings) 40 | { 41 | if (BuildingDbRows == null) return; 42 | 43 | BuildingDbRows.Merge(buildings, false, MissingSchemaAction.Error); 44 | 45 | Parallel.ForEach(buildings, row => 46 | { 47 | var newRow = BuildingDbRows.FindByID(row.ID); 48 | Insert(newRow); 49 | }); 50 | //apply changes to db here 51 | } 52 | 53 | public bool RemoveBuilding(int objectId) 54 | { 55 | var row = (BuildingDbRows == null) ? null : BuildingDbRows.FindByID(objectId); 56 | if (row != null) 57 | { 58 | Delete(row); 59 | 60 | BuildingDbRows.Rows.Remove(row); 61 | //apply changes to db here 62 | 63 | return true; 64 | } 65 | return false; 66 | } 67 | 68 | public SimpleMapDb.BuildingsRow GetBuilding(int objectId) 69 | { 70 | if (BuildingDbRows == null) return null; 71 | 72 | var row = BuildingDbRows.FindByID(objectId); 73 | if (row != null) 74 | { 75 | var dt = (SimpleMapDb.BuildingsDataTable)BuildingDbRows.Clone(); 76 | dt.ImportRow(row); 77 | return (SimpleMapDb.BuildingsRow)dt.Rows[0]; 78 | } 79 | return null; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Layers/MapObjects/CableTree.cs: -------------------------------------------------------------------------------- 1 | using System.Data; 2 | using System.Threading.Tasks; 3 | using ProgramMain.ExampleDb; 4 | using ProgramMain.Layers.MapObjects.TreeNodes; 5 | using ProgramMain.Map.Spatial; 6 | using ProgramMain.Map.Spatial.Types; 7 | 8 | namespace ProgramMain.Layers.MapObjects 9 | { 10 | public class CableTree : SpatialTree 11 | { 12 | public SimpleMapDb.CablesDataTable CableDbRows { get; private set; } 13 | 14 | public CableTree() 15 | : base(SpatialSheetPowerTypes.Ultra, SpatialSheetPowerTypes.High, SpatialSheetPowerTypes.Low, SpatialSheetPowerTypes.Low) 16 | { 17 | CableDbRows = new SimpleMapDb.CablesDataTable(); 18 | } 19 | 20 | protected void Insert(SimpleMapDb.CablesRow row) 21 | { 22 | base.Insert(row); 23 | } 24 | 25 | protected void Delete(SimpleMapDb.CablesRow row) 26 | { 27 | base.Delete(row); 28 | } 29 | 30 | public void LoadData() 31 | { 32 | Clear(); 33 | 34 | //read data from db here 35 | 36 | Parallel.ForEach(CableDbRows, Insert); 37 | } 38 | 39 | public void MergeData(SimpleMapDb.CablesDataTable cables) 40 | { 41 | if (CableDbRows == null) return; 42 | 43 | CableDbRows.Merge(cables, false, MissingSchemaAction.Error); 44 | 45 | Parallel.ForEach(cables, row => 46 | { 47 | var newRow = CableDbRows.FindByID(row.ID); 48 | Insert(newRow); 49 | }); 50 | 51 | //apply changes to db here 52 | } 53 | 54 | public bool RemoveCable(int objectId) 55 | { 56 | var row = (CableDbRows == null) ? null : CableDbRows.FindByID(objectId); 57 | if (row != null) 58 | { 59 | Delete(row); 60 | 61 | CableDbRows.Rows.Remove(row); 62 | //apply changes to db here 63 | 64 | return true; 65 | } 66 | return false; 67 | } 68 | 69 | public SimpleMapDb.CablesRow GetCable(int objectId) 70 | { 71 | if (CableDbRows == null) return null; 72 | 73 | var row = CableDbRows.FindByID(objectId); 74 | if (row != null) 75 | { 76 | var dt = (SimpleMapDb.CablesDataTable)CableDbRows.Clone(); 77 | dt.ImportRow(row); 78 | return (SimpleMapDb.CablesRow)dt.Rows[0]; 79 | } 80 | return null; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Layers/MapObjects/TreeNodes/BuildingNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | using ProgramMain.ExampleDb; 4 | using ProgramMain.Map; 5 | using ProgramMain.Map.Spatial.Types; 6 | 7 | namespace ProgramMain.Layers.MapObjects.TreeNodes 8 | { 9 | public class BuildingNode : ISpatialTreeNode 10 | { 11 | private readonly SimpleMapDb.BuildingsRow _row; 12 | 13 | public SpatialTreeNodeTypes NodeType 14 | { 15 | get { return SpatialTreeNodeTypes.Rectangle; } 16 | } 17 | 18 | public Coordinate Coordinate 19 | { 20 | get { throw new Exception(); } 21 | } 22 | 23 | public CoordinateRectangle Rectangle 24 | { 25 | get 26 | { 27 | return new CoordinateRectangle( 28 | _row.Longitude1, 29 | _row.Latitude1, 30 | _row.Longitude2, 31 | _row.Latitude2); 32 | } 33 | } 34 | 35 | public CoordinatePoligon Poligon 36 | { 37 | get { throw new Exception(); } 38 | } 39 | 40 | public int RowId 41 | { 42 | get { return _row.ID; } 43 | } 44 | 45 | internal BuildingNode(SimpleMapDb.BuildingsRow row) 46 | { 47 | _row = row; 48 | } 49 | 50 | public DataRow Row 51 | { 52 | get { return _row; } 53 | } 54 | 55 | public static implicit operator BuildingNode(SimpleMapDb.BuildingsRow row) 56 | { 57 | return new BuildingNode(row); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /Layers/MapObjects/TreeNodes/CableNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | using ProgramMain.ExampleDb; 4 | using ProgramMain.Map; 5 | using ProgramMain.Map.Spatial.Types; 6 | 7 | namespace ProgramMain.Layers.MapObjects.TreeNodes 8 | { 9 | public class CableNode : ISpatialTreeNode 10 | { 11 | private readonly SimpleMapDb.CablesRow _row; 12 | 13 | public SpatialTreeNodeTypes NodeType 14 | { 15 | get { return SpatialTreeNodeTypes.Line; } 16 | } 17 | 18 | public Coordinate Coordinate 19 | { 20 | get { throw new Exception(); } 21 | } 22 | 23 | public CoordinateRectangle Rectangle 24 | { 25 | get 26 | { 27 | return new CoordinateRectangle( 28 | _row.Longitude1, 29 | _row.Latitude1, 30 | _row.Longitude2, 31 | _row.Latitude2); 32 | } 33 | } 34 | 35 | public CoordinatePoligon Poligon 36 | { 37 | get { throw new Exception(); } 38 | } 39 | 40 | public int RowId 41 | { 42 | get { return _row.ID; } 43 | } 44 | 45 | internal CableNode(SimpleMapDb.CablesRow row) 46 | { 47 | _row = row; 48 | } 49 | 50 | public DataRow Row 51 | { 52 | get { return _row; } 53 | } 54 | 55 | public static implicit operator CableNode(SimpleMapDb.CablesRow row) 56 | { 57 | return new CableNode(row); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /Layers/MapObjects/TreeNodes/VertexNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | using ProgramMain.ExampleDb; 4 | using ProgramMain.Map; 5 | using ProgramMain.Map.Spatial.Types; 6 | 7 | namespace ProgramMain.Layers.MapObjects.TreeNodes 8 | { 9 | public class VertexNode : ISpatialTreeNode 10 | { 11 | private readonly SimpleMapDb.VertexesRow _row; 12 | 13 | public SpatialTreeNodeTypes NodeType 14 | { 15 | get { return SpatialTreeNodeTypes.Point; } 16 | } 17 | 18 | public Coordinate Coordinate 19 | { 20 | get { return new Coordinate(_row.Longitude, _row.Latitude); } 21 | } 22 | 23 | public CoordinateRectangle Rectangle 24 | { 25 | get { throw new Exception(); } 26 | } 27 | 28 | public CoordinatePoligon Poligon 29 | { 30 | get { throw new Exception(); } 31 | } 32 | 33 | public int RowId 34 | { 35 | get { return _row.ID; } 36 | } 37 | 38 | internal VertexNode(SimpleMapDb.VertexesRow row) 39 | { 40 | _row = row; 41 | } 42 | 43 | public DataRow Row 44 | { 45 | get { return _row; } 46 | } 47 | 48 | public static implicit operator VertexNode(SimpleMapDb.VertexesRow row) 49 | { 50 | return new VertexNode(row); 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /Layers/MapObjects/VertexTree.cs: -------------------------------------------------------------------------------- 1 | using System.Data; 2 | using System.Threading.Tasks; 3 | using ProgramMain.ExampleDb; 4 | using ProgramMain.Layers.MapObjects.TreeNodes; 5 | using ProgramMain.Map.Spatial; 6 | using ProgramMain.Map.Spatial.Types; 7 | 8 | namespace ProgramMain.Layers.MapObjects 9 | { 10 | public class VertexTree : SpatialTree 11 | { 12 | public SimpleMapDb.VertexesDataTable VertexDbRows { get; private set;} 13 | 14 | public VertexTree() 15 | : base(SpatialSheetPowerTypes.Ultra, SpatialSheetPowerTypes.Extra, SpatialSheetPowerTypes.Medium, SpatialSheetPowerTypes.Low) 16 | { 17 | VertexDbRows = new SimpleMapDb.VertexesDataTable(); 18 | } 19 | 20 | protected void Insert(SimpleMapDb.VertexesRow row) 21 | { 22 | base.Insert(row); 23 | } 24 | 25 | protected void Delete(SimpleMapDb.VertexesRow row) 26 | { 27 | base.Delete(row); 28 | } 29 | 30 | public void LoadData() 31 | { 32 | Clear(); 33 | 34 | //read data from db here 35 | 36 | Parallel.ForEach(VertexDbRows, Insert); 37 | } 38 | 39 | public void MergeData(SimpleMapDb.VertexesDataTable vertexes) 40 | { 41 | if (VertexDbRows == null) return; 42 | 43 | VertexDbRows.Merge(vertexes, false, MissingSchemaAction.Error); 44 | 45 | Parallel.ForEach(vertexes, row => 46 | { 47 | var newRow = VertexDbRows.FindByID(row.ID); 48 | Insert(newRow); 49 | }); 50 | 51 | //apply changes to db here 52 | } 53 | 54 | public bool RemoveVertex(int objectId) 55 | { 56 | var row = (VertexDbRows == null) ? null : VertexDbRows.FindByID(objectId); 57 | if (row != null) 58 | { 59 | Delete(row); 60 | 61 | VertexDbRows.Rows.Remove(row); 62 | //apply changes to db here 63 | 64 | return true; 65 | } 66 | return false; 67 | } 68 | 69 | public SimpleMapDb.VertexesRow GetVertex(int objectId) 70 | { 71 | if (VertexDbRows == null) return null; 72 | 73 | var row = VertexDbRows.FindByID(objectId); 74 | if (row != null) 75 | { 76 | var dt = (SimpleMapDb.VertexesDataTable)VertexDbRows.Clone(); 77 | dt.ImportRow(row); 78 | return (SimpleMapDb.VertexesRow)dt.Rows[0]; 79 | } 80 | return null; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Map/Coordinate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using ProgramMain.Map.Google; 4 | 5 | namespace ProgramMain.Map 6 | { 7 | public class Coordinate : IComparable, ICloneable 8 | { 9 | public static readonly Coordinate Empty = new Coordinate(); 10 | 11 | public double Longitude { get; set; } 12 | 13 | public double Latitude { get; set; } 14 | 15 | private Coordinate() 16 | { 17 | Latitude = 0; 18 | Longitude = 0; 19 | } 20 | 21 | public Coordinate(double pLongitude, double pLatitude) 22 | { 23 | Longitude = pLongitude; 24 | Latitude = pLatitude; 25 | } 26 | 27 | public Coordinate(decimal pLongitude, decimal pLatitude) 28 | { 29 | Longitude = (double)pLongitude; 30 | Latitude = (double)pLatitude; 31 | } 32 | 33 | #region ICloneable Members 34 | public object Clone() 35 | { 36 | return new Coordinate(Longitude, Latitude); 37 | } 38 | #endregion 39 | 40 | #region IComparable Members 41 | public int CompareTo(Object obj) 42 | { 43 | var coords = (Coordinate)obj; 44 | if (coords.Latitude < Latitude) 45 | return -1; 46 | if (coords.Latitude > Latitude) 47 | return 1; 48 | if (coords.Longitude < Longitude) 49 | return -1; 50 | if (coords.Longitude > Longitude) 51 | return 1; 52 | return 0; 53 | } 54 | #endregion 55 | 56 | 57 | public override string ToString() 58 | { 59 | return (String.Format("E{0:F5} N{1:F5}", Longitude, Latitude)); 60 | } 61 | 62 | public static Coordinate operator + (Coordinate coordinate, GoogleCoordinate addon) 63 | { 64 | return new GoogleCoordinate(coordinate, addon.Level) + addon; 65 | } 66 | 67 | private GoogleCoordinate GetLeftTopGoogle(int screenWidth, int screenHeight, int level) 68 | { 69 | return new GoogleCoordinate( 70 | GoogleMapUtilities.GetGoogleX(this, level) - ((screenWidth + 1) / 2 - 1), 71 | GoogleMapUtilities.GetGoogleY(this, level) - ((screenHeight + 1) / 2 - 1), 72 | level); 73 | } 74 | 75 | private GoogleCoordinate GetRightBottomGoogle(int screenWidth, int screenHeight, int level) 76 | { 77 | return new GoogleCoordinate( 78 | GoogleMapUtilities.GetGoogleX(this, level) + ((screenWidth - 1) / 2 + 1), 79 | GoogleMapUtilities.GetGoogleY(this, level) + ((screenHeight - 1) / 2 + 1), 80 | level); 81 | } 82 | 83 | public GoogleRectangle GetScreenViewFromCenter(int screenWidth, int screenHeight, int level) 84 | { 85 | return new GoogleRectangle(GetLeftTopGoogle(screenWidth, screenHeight, level), GetRightBottomGoogle(screenWidth, screenHeight, level)); 86 | } 87 | 88 | public Point GetScreenPoint(GoogleRectangle screenView) 89 | { 90 | return new GoogleCoordinate(this, screenView.Level).GetScreenPoint(screenView); 91 | } 92 | 93 | public static Coordinate GetCoordinateFromScreen(GoogleRectangle screenView, Point point) 94 | { 95 | return screenView.LeftTop + new GoogleCoordinate(point.X, point.Y, screenView.Level); 96 | } 97 | 98 | public GoogleBlock GetGoogleBlock(int level) 99 | { 100 | return new GoogleCoordinate(this, level); 101 | } 102 | 103 | public double Distance(Coordinate coordinate) 104 | { 105 | return EarthUtilities.GetLength(this, coordinate); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /Map/CoordinatePoligon.cs: -------------------------------------------------------------------------------- 1 | using ProgramMain.Map.Google; 2 | using ProgramMain.Map.Indexer; 3 | using ProgramMain.Map.Types; 4 | 5 | namespace ProgramMain.Map 6 | { 7 | public class CoordinatePoligon 8 | { 9 | public static readonly CoordinatePoligon Empty = new CoordinatePoligon(); 10 | 11 | public readonly CoordinateIndexer Coordinates; 12 | 13 | public Coordinate First 14 | { 15 | get { return Coordinates[0]; } 16 | } 17 | 18 | public Coordinate Last 19 | { 20 | get { return Coordinates[Coordinates.Count - 1]; } 21 | } 22 | 23 | public CoordinateRectangle this[int index] 24 | { 25 | get 26 | { 27 | if (index < 0 || index > Count - 1) 28 | return null; 29 | var leftTop = Coordinates[index]; 30 | var rightBottom = index == Count - 1 ? Coordinates[0] : Coordinates[index + 1]; 31 | return new CoordinateRectangle(leftTop, rightBottom); 32 | } 33 | } 34 | 35 | public int Count 36 | { 37 | get { return Coordinates.Count; } 38 | } 39 | 40 | public CoordinatePoligon() 41 | { 42 | Coordinates = new CoordinateIndexer(); 43 | } 44 | 45 | public bool Add(Coordinate coordinate) 46 | { 47 | if (Count > 2) 48 | { 49 | var line1 = new CoordinateRectangle(First, coordinate); 50 | var line2 = new CoordinateRectangle(Last, coordinate); 51 | for (var i = 0; i < Count - 1; i++) 52 | { 53 | if (GoogleMapUtilities.CheckLinesInterseption(this[i], line1) 54 | || GoogleMapUtilities.CheckLinesInterseption(this[i], line2)) 55 | return false; 56 | } 57 | } 58 | 59 | Coordinates.Add(coordinate); 60 | return true; 61 | } 62 | 63 | public double PoligonDistance(Coordinate coordinate) 64 | { 65 | double res = 0; 66 | 67 | for (var i = 0; i < Count; i++) 68 | { 69 | var distance = this[i].LineDistance(coordinate); 70 | if (i == 0 || distance < res) 71 | res = distance; 72 | } 73 | return res; 74 | } 75 | 76 | public bool IncludeTo(CoordinateRectangle rect) 77 | { 78 | for (var i = 0; i < Coordinates.Count; i++) 79 | { 80 | if (rect.PointContains(Coordinates[i]) != InterseptResult.Contains) 81 | return false; 82 | } 83 | return true; 84 | } 85 | 86 | public InterseptResult PointContains(Coordinate coordinate) 87 | { 88 | //to do 89 | 90 | return InterseptResult.None; 91 | } 92 | 93 | public InterseptResult LineContains(CoordinateRectangle coordinate) 94 | { 95 | //to do 96 | 97 | return InterseptResult.None; 98 | } 99 | 100 | public InterseptResult RectangleContains(CoordinateRectangle coordinate) 101 | { 102 | //to do 103 | 104 | return InterseptResult.None; 105 | } 106 | 107 | public InterseptResult PoligonContains(CoordinateRectangle coordinate) 108 | { 109 | //to do 110 | 111 | return InterseptResult.None; 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /Map/CoordinateRectangle.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using ProgramMain.Map.Google; 4 | using ProgramMain.Map.Types; 5 | 6 | namespace ProgramMain.Map 7 | { 8 | public class CoordinateRectangle : ICloneable 9 | { 10 | public static readonly CoordinateRectangle Empty = new CoordinateRectangle(); 11 | 12 | public Coordinate LeftTop 13 | { 14 | get 15 | { 16 | return new Coordinate(Left, Top); 17 | } 18 | } 19 | 20 | public Coordinate RightBottom 21 | { 22 | get 23 | { 24 | return new Coordinate(Right, Bottom); 25 | } 26 | } 27 | 28 | public Coordinate LeftBottom 29 | { 30 | get 31 | { 32 | return new Coordinate(Left, Bottom); 33 | } 34 | } 35 | 36 | public Coordinate RightTop 37 | { 38 | get 39 | { 40 | return new Coordinate(Right, Top); 41 | } 42 | } 43 | 44 | public double Width 45 | { 46 | get { return Right - Left; } 47 | } 48 | 49 | public double Height 50 | { 51 | get { return Bottom - Top; } 52 | } 53 | 54 | public double Left { get; private set; } 55 | 56 | public double Right { get; private set; } 57 | 58 | public double Top { get; private set; } 59 | 60 | public double Bottom { get; private set; } 61 | 62 | private CoordinateRectangle() 63 | { 64 | Bottom = 0; 65 | Top = 0; 66 | Right = 0; 67 | Left = 0; 68 | } 69 | 70 | public CoordinateRectangle(double left, double top, double right, double bottom) 71 | { 72 | Left = left; 73 | Top = top; 74 | Right = right; 75 | Bottom = bottom; 76 | } 77 | 78 | public CoordinateRectangle(decimal left, decimal top, decimal right, decimal bottom) 79 | { 80 | Left = (double)left; 81 | Top = (double)top; 82 | Right = (double)right; 83 | Bottom = (double)bottom; 84 | } 85 | 86 | public CoordinateRectangle(Coordinate pLeftTop, Coordinate pRightBottom) 87 | { 88 | Left = pLeftTop.Longitude; 89 | Top = pLeftTop.Latitude; 90 | Right = pRightBottom.Longitude; 91 | Bottom = pRightBottom.Latitude; 92 | } 93 | 94 | #region ICloneable Members 95 | public object Clone() 96 | { 97 | return new CoordinateRectangle(Left, Top, Right, Bottom); 98 | } 99 | #endregion 100 | 101 | 102 | public override string ToString() 103 | { 104 | return (String.Format("E{0:F5} N{1:F5} - E{2:F5} N{3:F5} : {4:n}m", Left, Top, Right, Bottom, LineLength)); 105 | } 106 | 107 | public Rectangle GetScreenRect(GoogleRectangle screenView) 108 | { 109 | return new GoogleRectangle(this, screenView.Level).GetScreenRect(screenView); 110 | } 111 | 112 | public InterseptResult PointContains(Coordinate point) 113 | { 114 | return (point.Longitude >= Left 115 | && point.Longitude <= Right 116 | && point.Latitude <= Top 117 | && point.Latitude >= Bottom) ? InterseptResult.Contains : InterseptResult.None; 118 | } 119 | 120 | public InterseptResult RectangleContains(CoordinateRectangle rectangle) 121 | { 122 | var iLeftTop = PointContains(rectangle.LeftTop) != InterseptResult.None; 123 | var iRightBottom = PointContains(rectangle.RightBottom) != InterseptResult.None; 124 | 125 | if (iLeftTop && iRightBottom) 126 | return InterseptResult.Contains; 127 | if (iLeftTop || iRightBottom) 128 | return InterseptResult.Intersepts; 129 | 130 | if (PointContains(rectangle.LeftBottom) != InterseptResult.None) 131 | return InterseptResult.Intersepts; 132 | if (PointContains(rectangle.RightTop) != InterseptResult.None) 133 | return InterseptResult.Intersepts; 134 | 135 | iLeftTop = rectangle.PointContains(LeftTop) != InterseptResult.None; 136 | iRightBottom = rectangle.PointContains(RightBottom) != InterseptResult.None; 137 | 138 | if (iLeftTop && iRightBottom) 139 | return InterseptResult.Supersets; 140 | if (iLeftTop || iRightBottom) 141 | return InterseptResult.Intersepts; 142 | 143 | if (rectangle.PointContains(LeftBottom) != InterseptResult.None) 144 | return InterseptResult.Intersepts; 145 | if (rectangle.PointContains(RightTop) != InterseptResult.None) 146 | return InterseptResult.Intersepts; 147 | 148 | if (GoogleMapUtilities.CheckLinesInterseption(new CoordinateRectangle(Left, Top, Left, Bottom), 149 | new CoordinateRectangle(rectangle.Left, rectangle.Top, rectangle.Right, rectangle.Top))) 150 | return InterseptResult.Intersepts; 151 | if (GoogleMapUtilities.CheckLinesInterseption(new CoordinateRectangle(Left, Top, Right, Top), 152 | new CoordinateRectangle(rectangle.Left, rectangle.Top, rectangle.Left, rectangle.Bottom))) 153 | return InterseptResult.Intersepts; 154 | 155 | return InterseptResult.None; 156 | } 157 | 158 | public InterseptResult LineContains(CoordinateRectangle line) 159 | { 160 | var iLeftTop = PointContains(line.LeftTop) != InterseptResult.None; 161 | var iRightBottom = PointContains(line.RightBottom) != InterseptResult.None; 162 | 163 | if (iLeftTop && iRightBottom) 164 | return InterseptResult.Contains; 165 | if (iLeftTop || iRightBottom) 166 | return InterseptResult.Intersepts; 167 | if (GoogleMapUtilities.CheckLinesInterseption(new CoordinateRectangle(Left, Top, Right, Top), line)) 168 | return InterseptResult.Intersepts; 169 | if (GoogleMapUtilities.CheckLinesInterseption(new CoordinateRectangle(Right, Top, Right, Bottom), line)) 170 | return InterseptResult.Intersepts; 171 | if (GoogleMapUtilities.CheckLinesInterseption(new CoordinateRectangle(Left, Bottom, Right, Bottom), line)) 172 | return InterseptResult.Intersepts; 173 | if (GoogleMapUtilities.CheckLinesInterseption(new CoordinateRectangle(Left, Top, Left, Bottom), line)) 174 | return InterseptResult.Intersepts; 175 | return InterseptResult.None; 176 | } 177 | 178 | public InterseptResult PoligonContains(CoordinatePoligon poligon) 179 | { 180 | if (poligon.IncludeTo(this)) 181 | return InterseptResult.Contains; 182 | 183 | for (var i = 0; i < poligon.Count; i++) 184 | { 185 | if (LineContains(poligon[i]) != InterseptResult.None) 186 | return InterseptResult.Intersepts; 187 | } 188 | 189 | if (poligon.PointContains(LeftTop) != InterseptResult.None 190 | && poligon.PointContains(RightTop) != InterseptResult.None 191 | && poligon.PointContains(RightBottom) != InterseptResult.None 192 | && poligon.PointContains(LeftBottom) != InterseptResult.None) 193 | return InterseptResult.Supersets; 194 | 195 | return InterseptResult.None; 196 | } 197 | 198 | public double RectangeDistance(Coordinate coordinate) 199 | { 200 | if (PointContains(coordinate) != InterseptResult.None) 201 | return 0; 202 | 203 | var min = EarthUtilities.GetDistance(new CoordinateRectangle(Left, Top, Right, Top), coordinate); 204 | var res = EarthUtilities.GetDistance(new CoordinateRectangle(Right, Top, Right, Bottom), coordinate); 205 | if (res < min) min = res; 206 | res = EarthUtilities.GetDistance(new CoordinateRectangle(Right, Bottom, Left, Bottom), coordinate); 207 | if (res < min) min = res; 208 | res = EarthUtilities.GetDistance(new CoordinateRectangle(Left, Bottom, Left, Top), coordinate); 209 | if (res < min) min = res; 210 | 211 | return min; 212 | } 213 | 214 | public double LineDistance(Coordinate coordinate) 215 | { 216 | return EarthUtilities.GetDistance(this, coordinate); 217 | } 218 | 219 | public Coordinate LineMiddlePoint 220 | { 221 | get { return GoogleMapUtilities.GetMiddlePoint(LeftTop, RightBottom); } 222 | } 223 | 224 | public double LineLength 225 | { 226 | get { return LeftTop.Distance(RightBottom); } 227 | } 228 | 229 | public double LineAngle 230 | { 231 | get { return Math.Atan2(Width, Height); } 232 | } 233 | 234 | public void LineGrow(double meter) 235 | { 236 | var len = LineLength; 237 | var ang = LineAngle; 238 | Right = Left + (len + meter) * Math.Cos(ang); 239 | Bottom = Top + (len + meter) * Math.Sin(ang); 240 | } 241 | 242 | public Coordinate GetNearestPoint(Coordinate pt) 243 | { 244 | return EarthUtilities.GetNearestPoint(this, pt); 245 | } 246 | } 247 | } -------------------------------------------------------------------------------- /Map/EarthUtilities.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ProgramMain.Map 4 | { 5 | internal class EarthUtilities 6 | { 7 | #region Вспомогательные функциии для расчета растояний для земного шара с допуском, что все объекты находятся на высоте 0 метров над уровнем моря 8 | 9 | /// 10 | /// Приблизительное растояние между двумя точками 11 | /// Передаваемые широта/долгота в градусах и сотых долях 12 | /// 13 | public static double GetLength(Coordinate c1, Coordinate c2) 14 | { 15 | // Константы, используемые для вычисления смещения и расстояния 16 | const double d2R = Math.PI / 180; // Константа для преобразования градусов в радианы 17 | const double a = 6378137.0; // Основные полуоси 18 | //const double b = 6356752.314245; // Неосновные полуоси 19 | const double e2 = 0.006739496742337; // Квадрат эксцентричности эллипсоида 20 | 21 | // Вычисляем разницу между двумя долготами и широтами и получаем среднюю широту 22 | var fdLambda = (c1.Longitude - c2.Longitude) * d2R; // Разница между двумя значениями долготы 23 | var fdPhi = (c1.Latitude - c2.Latitude) * d2R; // Разница между двумя значениями широты 24 | var fPhimean = ((c1.Latitude + c2.Latitude) / 2.0) * d2R; // Средняя широта 25 | 26 | // Меридианский радиус кривизны 27 | var fRho = (a * (1 - e2)) / Math.Pow(1 - e2 * (Math.Pow(Math.Sin(fPhimean), 2)), 1.5); 28 | // Поперечный радиус кривизны 29 | var fNu = a / (Math.Sqrt(1 - e2 * (Math.Sin(fPhimean) * Math.Sin(fPhimean)))); 30 | 31 | // Вычисляем угловое расстояние от центра сфероида 32 | var fz = 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(fdPhi / 2.0), 2) + Math.Cos(c2.Latitude * d2R) * Math.Cos(c1.Latitude * d2R) * Math.Pow(Math.Sin(fdLambda / 2.0), 2))); 33 | 34 | // Вычисляем смещение 35 | var fAlpha = Math.Asin(Math.Cos(c2.Latitude * d2R) * Math.Sin(fdLambda) * 1 / Math.Sin(fz)); 36 | // Вычисляем радиус Земли 37 | var fR = (fRho * fNu) / ((fRho * Math.Pow(Math.Sin(fAlpha), 2)) + (fNu * Math.Pow(Math.Cos(fAlpha), 2))); 38 | 39 | // Вычисленное расстояния в метрах 40 | var distance = fz * fR; 41 | 42 | return distance; 43 | } 44 | 45 | /// 46 | /// Приблизительное растояние от точки до отрезка прямой 47 | /// Передаваемые широта/долгота в градусах и сотых долях 48 | /// 49 | public static double GetDistance(CoordinateRectangle line, Coordinate pt) 50 | { 51 | const double r2D = 180 / Math.PI; // Константа для преобразования радиан в градусы 52 | 53 | var a = GetLength(line.LeftTop, line.RightBottom); 54 | 55 | var b = GetLength(line.LeftTop, pt); 56 | var c = GetLength(line.RightBottom, pt); 57 | if (a <= 0) 58 | return (b + c) / 2; 59 | 60 | var enB = Math.Acos((Math.Pow(a, 2) + Math.Pow(b, 2) - Math.Pow(c, 2)) / (2 * a * b)) * r2D; 61 | if (enB >= 90) 62 | return b; 63 | var enC = Math.Acos((Math.Pow(a, 2) + Math.Pow(c, 2) - Math.Pow(b, 2)) / (2 * a * c)) * r2D; 64 | if (enC >= 90) 65 | return c; 66 | 67 | var s = (a + b + c) / 2; 68 | var ar = Math.Sqrt(s * (s - a) * (s - b) * (s - c)); 69 | 70 | return ar * 2 / a; 71 | } 72 | 73 | public static Coordinate GetNearestPoint(CoordinateRectangle line, Coordinate pt) 74 | { 75 | 76 | const double r2D = 180 / Math.PI; // Константа для преобразования радиан в градусы 77 | 78 | var a = GetLength(line.LeftTop, line.RightBottom); 79 | if (a <= 0) 80 | return pt; 81 | 82 | var b = GetLength(line.LeftTop, pt); 83 | var c = GetLength(line.RightBottom, pt); 84 | 85 | var enB = Math.Acos((Math.Pow(a, 2) + Math.Pow(b, 2) - Math.Pow(c, 2)) / (2 * a * b)) * r2D; 86 | if (enB >= 90) 87 | return pt; 88 | var enC = Math.Acos((Math.Pow(a, 2) + Math.Pow(c, 2) - Math.Pow(b, 2)) / (2 * a * c)) * r2D; 89 | if (enC >= 90) 90 | return pt; 91 | 92 | 93 | var x = ((line.Right - line.Left) * (line.Bottom - line.Top) * (pt.Latitude - line.Top) + 94 | line.Left * Math.Pow(line.Bottom - line.Top, 2) + pt.Longitude*Math.Pow(line.Right - line.Left, 2)) / 95 | (Math.Pow(line.Bottom - line.Top, 2) + Math.Pow(line.Right - line.Left, 2)); 96 | var y = (line.Bottom - line.Top) * (x - line.Left) / (line.Right - line.Left) + line.Top; 97 | 98 | return new Coordinate(x,y); 99 | } 100 | 101 | #endregion 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Map/Google/GoogleBlock.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | 4 | namespace ProgramMain.Map.Google 5 | { 6 | public class GoogleBlock : IComparable, ICloneable 7 | { 8 | public static readonly GoogleBlock Empty = new GoogleBlock(); 9 | 10 | public const int BlockSize = 256; 11 | 12 | public Point Pt 13 | { 14 | get 15 | { 16 | return new Point(X, Y); 17 | } 18 | } 19 | 20 | public int X { get; private set; } 21 | 22 | public int Y { get; private set; } 23 | 24 | public int Level { get; private set; } 25 | 26 | private GoogleBlock() 27 | { 28 | Level = 0; 29 | Y = 0; 30 | X = 0; 31 | } 32 | 33 | public GoogleBlock(int pX, int pY, int pLevel) 34 | { 35 | X = pX; 36 | Y = pY; 37 | Level = pLevel; 38 | } 39 | 40 | public GoogleBlock(Point pt, int pLevel) 41 | { 42 | X = pt.X; 43 | Y = pt.Y; 44 | 45 | Level = pLevel; 46 | } 47 | 48 | #region ICloneable Members 49 | public object Clone() 50 | { 51 | return new GoogleBlock(X, Y, Level); 52 | } 53 | #endregion 54 | 55 | #region IComparable Members 56 | public int CompareTo(Object obj) 57 | { 58 | var coords = (GoogleBlock)obj; 59 | if (coords.Level < Level) 60 | return -1; 61 | if (coords.Level > Level) 62 | return 1; 63 | if (coords.Y < Y) 64 | return -1; 65 | if (coords.Y > Y) 66 | return 1; 67 | if (coords.X < X) 68 | return -1; 69 | if (coords.X > X) 70 | return 1; 71 | return 0; 72 | } 73 | #endregion 74 | 75 | public static implicit operator GoogleCoordinate(GoogleBlock block) 76 | { 77 | return new GoogleCoordinate(block.X * BlockSize, block.Y * BlockSize, block.Level); 78 | } 79 | 80 | public static implicit operator GoogleRectangle(GoogleBlock block) 81 | { 82 | return new GoogleRectangle( 83 | block.X * BlockSize, block.Y * BlockSize, 84 | (block.X + 1) * BlockSize, (block.Y + 1) * BlockSize, 85 | block.Level); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Map/Google/GoogleCoordinate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | 4 | namespace ProgramMain.Map.Google 5 | { 6 | public class GoogleCoordinate : IComparable, ICloneable 7 | { 8 | public static readonly GoogleCoordinate Empty = new GoogleCoordinate(); 9 | 10 | public long X { get; private set; } 11 | 12 | public long Y { get; private set; } 13 | 14 | public int Level { get; private set; } 15 | 16 | private GoogleCoordinate() 17 | { 18 | X = 0; 19 | Level = 0; 20 | Y = 0; 21 | } 22 | 23 | public GoogleCoordinate(long pX, long pY, int pLevel) 24 | { 25 | X = pX; 26 | Y = pY; 27 | Level = pLevel; 28 | } 29 | 30 | public GoogleCoordinate(Coordinate coordinate, int level) 31 | { 32 | X = GoogleMapUtilities.GetGoogleX(coordinate, level); 33 | Y = GoogleMapUtilities.GetGoogleY(coordinate, level); 34 | Level = level; 35 | } 36 | 37 | #region ICloneable Members 38 | public object Clone() 39 | { 40 | return new GoogleCoordinate(X, Y, Level); 41 | } 42 | #endregion 43 | 44 | #region IComparable Members 45 | public int CompareTo(Object obj) 46 | { 47 | var coords = (GoogleCoordinate)obj; 48 | if (coords.Level < Level) 49 | return -1; 50 | if (coords.Level > Level) 51 | return 1; 52 | if (coords.Y < Y) 53 | return -1; 54 | if (coords.Y > Y) 55 | return 1; 56 | if (coords.X < X) 57 | return -1; 58 | if (coords.X > X) 59 | return 1; 60 | return 0; 61 | } 62 | #endregion 63 | 64 | public static GoogleCoordinate operator + (GoogleCoordinate google, GoogleCoordinate addon) 65 | { 66 | if (google.Level != addon.Level) 67 | { 68 | addon = new GoogleCoordinate(addon, google.Level); 69 | } 70 | return new GoogleCoordinate(google.X + addon.X, google.Y + addon.Y, google.Level); 71 | } 72 | 73 | public static implicit operator Coordinate(GoogleCoordinate google) 74 | { 75 | return new Coordinate(GoogleMapUtilities.GetLongitude(google), GoogleMapUtilities.GetLatitude(google)); 76 | } 77 | 78 | public static implicit operator GoogleBlock(GoogleCoordinate google) 79 | { 80 | return new GoogleBlock( 81 | (int)(google.X / GoogleBlock.BlockSize), 82 | (int)(google.Y / GoogleBlock.BlockSize), 83 | google.Level); 84 | } 85 | 86 | public Point GetScreenPoint(GoogleRectangle screenView) 87 | { 88 | if (Level != screenView.Level) 89 | { 90 | screenView = new GoogleRectangle(new CoordinateRectangle(screenView.LeftTop, screenView.RightBottom), Level); 91 | } 92 | return new Point((int)(X - screenView.Left), (int)(Y - screenView.Top)); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /Map/Google/GoogleMapUtilities.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | 4 | namespace ProgramMain.Map.Google 5 | { 6 | internal class GoogleMapUtilities 7 | { 8 | #region Helpers to work with Google Coordinate system 9 | /// 10 | /// Block count on the side of google level 11 | /// 12 | /// 13 | /// 14 | public static long NumTiles(int level) 15 | { 16 | return Convert.ToInt64(Math.Pow(2, (level - 1))); 17 | } 18 | 19 | /// 20 | /// Block count on the google level 21 | /// 22 | /// 23 | /// 24 | public static long CountTiles(int level) 25 | { 26 | var numTiles = NumTiles(level); 27 | return numTiles * numTiles; 28 | } 29 | 30 | /// 31 | /// Translate block count to google level 32 | /// 33 | /// 34 | /// 35 | public static long NumLevel(int countTiles) 36 | { 37 | return Convert.ToInt64(Math.Log(Math.Sqrt(countTiles), 2)) + 1; 38 | } 39 | 40 | /// 41 | /// Pixel count on the side of google level bitmap 42 | /// 43 | /// 44 | /// 45 | public static long BitMapSize(int level) 46 | { 47 | return NumTiles(level) * GoogleBlock.BlockSize; 48 | } 49 | 50 | /// 51 | /// Pixel count on the google level bitmap 52 | /// 53 | /// 54 | /// 55 | public static long BitmapOrigo(int level) 56 | { 57 | return BitMapSize(level) / 2; 58 | } 59 | 60 | /// 61 | /// Pixel count per degree on the google level bitmap 62 | /// 63 | /// 64 | /// 65 | public static double PixelsPerDegree(int level) 66 | { 67 | return (double)BitMapSize(level) / 360; 68 | } 69 | 70 | /// 71 | /// Pixel count per radian on the google level bitmap 72 | /// 73 | /// 74 | /// 75 | public static double PixelsPerRadian(int level) 76 | { 77 | const double p2 = 2 * Math.PI; 78 | return BitMapSize(level) / p2; 79 | } 80 | 81 | /// 82 | /// Translate longitude to X coordinate of the google level bitmap 83 | /// 84 | public static long GetGoogleX(Coordinate coordinate, int level) 85 | { 86 | return (long)(Math.Floor(BitmapOrigo(level) + coordinate.Longitude * PixelsPerDegree(level))); 87 | } 88 | 89 | /// 90 | /// Translate latitude to Y coordinate of the google level bitmap 91 | /// 92 | public static long GetGoogleY(Coordinate coordinate, int level) 93 | { 94 | const double d2R = Math.PI / 180; 95 | var z = (1 + Math.Sin(coordinate.Latitude * d2R)) / (1 - Math.Sin(coordinate.Latitude * d2R)); 96 | return (long)(Math.Floor(BitmapOrigo(level) - 0.5 * Math.Log(z) * PixelsPerRadian(level))); 97 | } 98 | 99 | /// 100 | /// Translate X coordinate of the google level bitmap to longitude 101 | /// 102 | public static double GetLongitude(GoogleCoordinate google) 103 | { 104 | return Math.Round((google.X - BitmapOrigo(google.Level)) / PixelsPerDegree(google.Level), 5); 105 | } 106 | 107 | /// 108 | /// Translate Y coordinate of the google level bitmap to latitude 109 | /// 110 | public static double GetLatitude(GoogleCoordinate google) 111 | { 112 | const double r2D = 180 / Math.PI; 113 | const double p2 = Math.PI / 2; 114 | var z = (google.Y - BitmapOrigo(google.Level)) / (-1 * PixelsPerRadian(google.Level)); 115 | return Math.Round((2 * Math.Atan(Math.Exp(z)) - p2) * r2D, 5); 116 | } 117 | 118 | /// 119 | /// Get google bitmap block number X by longitude 120 | /// 121 | public static long GetNumBlockX(Coordinate coordinate, int level) 122 | { 123 | return (long)Math.Floor((double)GetGoogleX(coordinate, level) / GoogleBlock.BlockSize); 124 | } 125 | 126 | /// 127 | /// Get google bitmap block number Y by latitude 128 | /// 129 | public static long GetNumBlockY(Coordinate coordinate, int level) 130 | { 131 | return (long)Math.Floor((double)GetGoogleY(coordinate, level) / GoogleBlock.BlockSize); 132 | } 133 | #endregion 134 | 135 | /// 136 | /// Line cross 137 | /// 138 | public static bool CheckLinesInterseption(CoordinateRectangle line1, CoordinateRectangle line2) 139 | { 140 | double d = (line1.Left - line1.Right) * (line2.Bottom - line2.Top) - (line1.Top - line1.Bottom) * (line2.Right - line2.Left); 141 | 142 | if (Math.Abs(d) < 0.000000001) 143 | return false; 144 | 145 | double da = (line1.Left - line2.Left) * (line2.Bottom - line2.Top) - (line1.Top - line2.Top) * (line2.Right - line2.Left); 146 | double db = (line1.Left - line1.Right) * (line1.Top - line2.Top) - (line1.Top - line1.Bottom) * (line1.Left - line2.Left); 147 | 148 | double ta = da / d; 149 | double tb = db / d; 150 | 151 | return ((0 <= ta) && (ta <= 1) && (0 <= tb) && (tb <= 1)); 152 | } 153 | 154 | /// 155 | /// Line middle point 156 | /// 157 | public static Coordinate GetMiddlePoint(Coordinate c1, Coordinate c2) 158 | { 159 | const double d2R = Math.PI / 180; 160 | const double r2D = 180 / Math.PI; 161 | 162 | var dLon = d2R * (c2.Longitude - c1.Longitude); 163 | var c1Rlat = d2R * (c1.Latitude); 164 | var c2Rlat = d2R * (c2.Latitude); 165 | var bX = Math.Cos(c2Rlat) * Math.Cos(dLon); 166 | var bY = Math.Cos(c2Rlat) * Math.Sin(dLon); 167 | 168 | var longitude = Math.Round(c1.Longitude + r2D * (Math.Atan2(bY, Math.Cos(c1Rlat) + bX)), 5); 169 | var latitude = Math.Round(r2D * (Math.Atan2(Math.Sin(c1Rlat) + Math.Sin(c2Rlat), Math.Sqrt((Math.Cos(c1Rlat) + bX) * (Math.Cos(c1Rlat) + bX) + bY * bY))), 5); 170 | 171 | return new Coordinate(longitude, latitude); 172 | } 173 | 174 | /// 175 | /// Create Url to get bitmap block from google bitmap cache 176 | /// 177 | public static string CreateUrl(GoogleBlock block) 178 | { 179 | return String.Format(Properties.Settings.Default.GoogleUrl, block.X, block.Y, block.Level - 1); 180 | } 181 | 182 | /// 183 | /// Create web request to get bitmap block from google bitmap cache 184 | /// 185 | public static HttpWebRequest CreateGoogleWebRequest(GoogleBlock block) 186 | { 187 | var urlGoogle = CreateUrl(block); 188 | var oRequest = (HttpWebRequest)WebRequest.Create(urlGoogle); 189 | oRequest.UserAgent = "www.simplemap.ru"; //!!!must have to retrieve image from google 190 | return oRequest; 191 | } 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /Map/Google/GoogleRectangle.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using ProgramMain.Map.Types; 4 | 5 | namespace ProgramMain.Map.Google 6 | { 7 | public class GoogleRectangle : ICloneable, IComparable 8 | { 9 | public static readonly GoogleRectangle Empty = new GoogleRectangle(); 10 | 11 | public GoogleCoordinate LeftTop 12 | { 13 | get 14 | { 15 | return new GoogleCoordinate(Left, Top, Level); 16 | } 17 | } 18 | 19 | public GoogleCoordinate RightBottom 20 | { 21 | get 22 | { 23 | return new GoogleCoordinate(Right, Bottom, Level); 24 | } 25 | } 26 | 27 | public long Left { get; private set; } 28 | 29 | public long Right { get; private set; } 30 | 31 | public long Top { get; private set; } 32 | 33 | public long Bottom { get; private set; } 34 | 35 | public int Level { get; private set; } 36 | 37 | private GoogleRectangle() 38 | { 39 | Left = 0; 40 | Right = 0; 41 | Top = 0; 42 | Bottom = 0; 43 | Level = 0; 44 | } 45 | 46 | public GoogleRectangle(long left, long top, long right, long bottom, int level) 47 | { 48 | Left = left; 49 | Top = top; 50 | Right = right; 51 | Bottom = bottom; 52 | Level = level; 53 | } 54 | 55 | public GoogleRectangle(GoogleCoordinate pLeftTop, GoogleCoordinate pRightBottom) 56 | { 57 | if (pRightBottom.Level != pLeftTop.Level) 58 | { 59 | pRightBottom = new GoogleCoordinate(pRightBottom, pLeftTop.Level); 60 | } 61 | Left = pLeftTop.X; 62 | Top = pLeftTop.Y; 63 | Right = pRightBottom.X; 64 | Bottom = pRightBottom.Y; 65 | Level = pLeftTop.Level; 66 | } 67 | 68 | public GoogleRectangle(CoordinateRectangle coordinateRect, int level) 69 | { 70 | var pLeftTop = new GoogleCoordinate(coordinateRect.LeftTop, level); 71 | var pRightBottom = new GoogleCoordinate(coordinateRect.RightBottom, level); 72 | Left = pLeftTop.X; 73 | Top = pLeftTop.Y; 74 | Right = pRightBottom.X; 75 | Bottom = pRightBottom.Y; 76 | Level = level; 77 | } 78 | 79 | public GoogleRectangle(CoordinatePoligon coordinatePoligon, int level) 80 | { 81 | for (var i = 0; i < coordinatePoligon.Count; i++) 82 | { 83 | var pt = new GoogleCoordinate(coordinatePoligon.Coordinates[i], level); 84 | if (i == 0) 85 | { 86 | Left = pt.X; 87 | Right = pt.X; 88 | Top = pt.Y; 89 | Bottom = pt.Y; 90 | } 91 | else 92 | { 93 | if (pt.X < Left) Left = pt.X; 94 | if (pt.X > Right) Right = pt.X; 95 | if (pt.Y < Top) Top = pt.Y; 96 | if (pt.Y > Bottom) Bottom = pt.Y; 97 | } 98 | } 99 | 100 | Level = level; 101 | } 102 | 103 | #region ICloneable Members 104 | public object Clone() 105 | { 106 | return new GoogleRectangle(Left, Top, Right, Bottom, Level); 107 | } 108 | #endregion 109 | 110 | #region IComparable Members 111 | public int CompareTo(Object obj) 112 | { 113 | var rectangle = (GoogleRectangle)obj; 114 | var res = LeftTop.CompareTo(rectangle.LeftTop); 115 | if (res != 0) return res; 116 | return RightBottom.CompareTo(rectangle.RightBottom); 117 | } 118 | #endregion 119 | 120 | public static implicit operator CoordinateRectangle(GoogleRectangle google) 121 | { 122 | return new CoordinateRectangle(google.LeftTop, google.RightBottom); 123 | } 124 | 125 | /// 126 | /// Google bitmap block count for (X, Y) 127 | /// 128 | public Rectangle BlockView 129 | { 130 | get 131 | { 132 | return Rectangle.FromLTRB( 133 | (int) (Left / GoogleBlock.BlockSize), 134 | (int) (Top / GoogleBlock.BlockSize), 135 | (int) ((Right - GoogleBlock.BlockSize) / GoogleBlock.BlockSize) + 1, 136 | (int) ((Bottom - GoogleBlock.BlockSize) / GoogleBlock.BlockSize) + 1); 137 | } 138 | } 139 | 140 | public Rectangle GetScreenRect(GoogleRectangle screenView) 141 | { 142 | if (Level != screenView.Level) 143 | { 144 | screenView = new GoogleRectangle( 145 | new CoordinateRectangle(screenView.LeftTop, screenView.RightBottom), Level); 146 | } 147 | 148 | var pt1 = LeftTop.GetScreenPoint(screenView); 149 | var pt2 = RightBottom.GetScreenPoint(screenView); 150 | 151 | return Rectangle.FromLTRB(pt1.X, pt1.Y, pt2.X, pt2.Y); 152 | } 153 | 154 | public InterseptResult PointContains(Coordinate point) 155 | { 156 | return ((CoordinateRectangle)this).PointContains(point); 157 | } 158 | 159 | public InterseptResult RectangleContains(CoordinateRectangle rectangle) 160 | { 161 | return ((CoordinateRectangle)this).RectangleContains(rectangle); 162 | } 163 | 164 | public InterseptResult LineContains(CoordinateRectangle line) 165 | { 166 | return ((CoordinateRectangle)this).LineContains(line); 167 | } 168 | 169 | public InterseptResult PoligonContains(CoordinatePoligon poligon) 170 | { 171 | return ((CoordinateRectangle)this).PoligonContains(poligon); 172 | } 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /Map/Indexer/CoordinateIndexer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace ProgramMain.Map.Indexer 4 | { 5 | public class CoordinateIndexer 6 | { 7 | private List _values; 8 | 9 | public Coordinate this[int index] 10 | { 11 | get { return index >= 0 && index < _values.Count ? _values[index] : null; } 12 | } 13 | 14 | public int Count {get { return _values != null ? _values.Count : 0; }} 15 | 16 | public void Add(Coordinate coordinate) 17 | { 18 | if (_values == null) 19 | _values = new List(); 20 | _values.Add(coordinate); 21 | } 22 | 23 | public void Remove(Coordinate coordinate) 24 | { 25 | if (_values != null) 26 | { 27 | _values.Remove(coordinate); 28 | } 29 | } 30 | 31 | public void Destroy() 32 | { 33 | if (_values != null) 34 | { 35 | _values.Clear(); 36 | _values = null; 37 | } 38 | } 39 | 40 | public bool HasChilds 41 | { 42 | get { return _values != null && _values.Count > 0; } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Map/Spatial/Indexer/SpatialContentIndexer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using ProgramMain.Map.Spatial.Types; 3 | 4 | namespace ProgramMain.Map.Spatial.Indexer 5 | { 6 | internal class SpatialContentIndexer where TNode : ISpatialTreeNode 7 | { 8 | private SortedDictionary _content; 9 | 10 | public void Add(TNode node) 11 | { 12 | if (_content == null) 13 | _content = new SortedDictionary(); 14 | _content[node.RowId] = node; 15 | } 16 | 17 | public void Remove(TNode node) 18 | { 19 | if (_content != null) 20 | { 21 | _content.Remove(node.RowId); 22 | } 23 | } 24 | 25 | public SortedDictionary.ValueCollection Values 26 | { 27 | get { return _content != null ? _content.Values : null; } 28 | } 29 | 30 | public void Destroy() 31 | { 32 | if (_content != null) 33 | { 34 | _content.Clear(); 35 | _content = null; 36 | } 37 | } 38 | 39 | public bool HasChilds 40 | { 41 | get { return _content != null && _content.Count > 0; } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Map/Spatial/Indexer/SpatialLevelPowerIndexer.cs: -------------------------------------------------------------------------------- 1 | using ProgramMain.Map.Spatial.Types; 2 | 3 | namespace ProgramMain.Map.Spatial.Indexer 4 | { 5 | public class SpatialLevelPowerIndexer where TNode : ISpatialTreeNode 6 | { 7 | private readonly SpatialSheetPowerTypes[] _power; 8 | private readonly SpatialTree _tree; 9 | 10 | internal SpatialLevelPowerIndexer(SpatialTree tree) 11 | { 12 | _tree = tree; 13 | _power = new SpatialSheetPowerTypes[_tree.SpatialDepth]; 14 | } 15 | 16 | public SpatialSheetPowerTypes this[int level] 17 | { 18 | get 19 | { 20 | if (level > 0 && level <= _power.Length) 21 | return _power[level - 1]; 22 | return SpatialSheetPowerTypes.None; 23 | } 24 | set 25 | { 26 | if (_tree.NodeCount > 0) return; 27 | 28 | if (level > 0 && level <= _power.Length) 29 | _power[level - 1] = value; 30 | } 31 | } 32 | 33 | //Zero level is virtual and always "None" 34 | public int Length 35 | { 36 | get { return _power.Length + 1; } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Map/Spatial/Indexer/SpatialSheetIndexer.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agafonoff2000/SimpleMap/7893f78f2ac8a5c070a7b98c993dd168aff16b83/Map/Spatial/Indexer/SpatialSheetIndexer.cs -------------------------------------------------------------------------------- /Map/Spatial/SpatialQueryIterator.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | 3 | namespace ProgramMain.Map.Spatial 4 | { 5 | internal class SpatialQueryIterator 6 | { 7 | public int Value { get; private set; } 8 | 9 | private SpatialQueryIterator() 10 | { 11 | Value = 0; 12 | } 13 | 14 | public static SpatialQueryIterator Start() 15 | { 16 | return new SpatialQueryIterator(); 17 | } 18 | 19 | public void Next() 20 | { 21 | lock (this) 22 | { 23 | Value++; 24 | } 25 | } 26 | 27 | public override string ToString() 28 | { 29 | return Value.ToString(CultureInfo.InvariantCulture); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Map/Spatial/SpatialSheet.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using ProgramMain.Map.Google; 3 | using ProgramMain.Map.Spatial.Types; 4 | using ProgramMain.Map.Types; 5 | 6 | namespace ProgramMain.Map.Spatial 7 | { 8 | internal class SpatialSheet : SpatialSheetBase where TNode : ISpatialTreeNode 9 | { 10 | public CoordinateRectangle Rectangle { get; private set; } 11 | 12 | public SpatialSheet(SpatialTree tree, int level, int googleLevel, CoordinateRectangle rectangle) 13 | : base(tree, level, googleLevel) 14 | { 15 | Rectangle = rectangle; 16 | } 17 | 18 | public enum SheetActionType { Insert, Delete }; 19 | 20 | internal void SheetAction(TNode node, SheetActionType actionType) 21 | { 22 | //Insert node to spatial index or remove node from spatial index 23 | if (!IsBottomSheet) 24 | { 25 | switch (node.NodeType) 26 | { 27 | case SpatialTreeNodeTypes.Point: 28 | PointSheetAction(node, actionType); 29 | break; 30 | case SpatialTreeNodeTypes.Line: 31 | LineSheetAction(node, actionType); 32 | break; 33 | case SpatialTreeNodeTypes.Rectangle: 34 | RectangleSheetAction(node, actionType); 35 | break; 36 | case SpatialTreeNodeTypes.Poligon: 37 | PoligonSheetAction(node, actionType); 38 | break; 39 | } 40 | } 41 | else 42 | { 43 | //Just do it on bottom level 44 | lock (this) 45 | { 46 | switch (actionType) 47 | { 48 | case SheetActionType.Insert: 49 | Content.Add(node); 50 | break; 51 | case SheetActionType.Delete: 52 | Content.Remove(node); 53 | break; 54 | } 55 | } 56 | } 57 | } 58 | 59 | private void PointSheetAction(TNode node, SheetActionType actionType) 60 | { 61 | var block = node.Coordinate.GetGoogleBlock(NextGoogleLevel); 62 | lock (this) 63 | { 64 | //point search in daughter sheet 65 | var sheet = Sheets[block]; 66 | 67 | sheet.SheetAction(node, actionType); 68 | 69 | PostSheetAction(block, sheet, actionType); 70 | } 71 | } 72 | 73 | private void LineSheetAction(TNode node, SheetActionType actionType) 74 | { 75 | var blockViewLevel = NextGoogleLevel; 76 | 77 | var line = node.Rectangle; 78 | var rect = new GoogleRectangle(line, blockViewLevel).BlockView; 79 | 80 | var deltaX = (rect.Left <= rect.Right) ? 1 : -1; 81 | var deltaY = (rect.Top <= rect.Bottom) ? 1 : -1; 82 | 83 | //line search in daughter sheet 84 | for (var x = rect.Left; (deltaX == 1 && x <= rect.Right) || (deltaX == -1 && x >= rect.Right); x += deltaX) 85 | { 86 | for (var y = rect.Top; (deltaY == 1 && y <= rect.Bottom) || (deltaY == -1 && y >= rect.Bottom); y += deltaY) 87 | { 88 | var block = new GoogleBlock(x, y, blockViewLevel); 89 | var googleRect = (GoogleRectangle)block; 90 | 91 | if (googleRect.LineContains(line) != InterseptResult.None) 92 | { 93 | lock (this) 94 | { 95 | var sheet = Sheets[block]; 96 | 97 | sheet.SheetAction(node, actionType); 98 | 99 | PostSheetAction(block, sheet, actionType); 100 | } 101 | } 102 | } 103 | } 104 | } 105 | 106 | private void RectangleSheetAction(TNode node, SheetActionType actionType) 107 | { 108 | var blockViewLevel = NextGoogleLevel; 109 | 110 | var rect = new GoogleRectangle(node.Rectangle, blockViewLevel).BlockView; 111 | 112 | var deltaX = (rect.Left <= rect.Right) ? 1 : -1; 113 | var deltaY = (rect.Top <= rect.Bottom) ? 1 : -1; 114 | 115 | //rectangle search in daughter sheet 116 | for (var x = rect.Left; (deltaX == 1 && x <= rect.Right) || (deltaX == -1 && x >= rect.Right); x += deltaX) 117 | { 118 | for (var y = rect.Top; (deltaY == 1 && y <= rect.Bottom) || (deltaY == -1 && y >= rect.Bottom); y += deltaY) 119 | { 120 | var block = new GoogleBlock(x, y, blockViewLevel); 121 | lock (this) 122 | { 123 | var sheet = Sheets[block]; 124 | 125 | sheet.SheetAction(node, actionType); 126 | 127 | PostSheetAction(block, sheet, actionType); 128 | } 129 | } 130 | } 131 | } 132 | 133 | private void PoligonSheetAction(TNode node, SheetActionType actionType) 134 | { 135 | var blockViewLevel = NextGoogleLevel; 136 | 137 | var poligon = node.Poligon; 138 | var rect = new GoogleRectangle(poligon, blockViewLevel).BlockView; 139 | 140 | var deltaX = (rect.Left <= rect.Right) ? 1 : -1; 141 | var deltaY = (rect.Top <= rect.Bottom) ? 1 : -1; 142 | 143 | //poligon search in daughter sheet 144 | for (var x = rect.Left; (deltaX == 1 && x <= rect.Right) || (deltaX == -1 && x >= rect.Right); x += deltaX) 145 | { 146 | for (var y = rect.Top; (deltaY == 1 && y <= rect.Bottom) || (deltaY == -1 && y >= rect.Bottom); y += deltaY) 147 | { 148 | var block = new GoogleBlock(x, y, blockViewLevel); 149 | var googleRect = (GoogleRectangle)block; 150 | 151 | if (googleRect.PoligonContains(poligon) != InterseptResult.None) 152 | { 153 | lock (this) 154 | { 155 | var sheet = Sheets[block]; 156 | 157 | sheet.SheetAction(node, actionType); 158 | 159 | PostSheetAction(block, sheet, actionType); 160 | } 161 | } 162 | } 163 | } 164 | } 165 | 166 | private void PostSheetAction(GoogleBlock block, SpatialSheet sheet, SheetActionType actionType) 167 | { 168 | switch (actionType) 169 | { 170 | case SheetActionType.Delete: 171 | { 172 | //delete sheet from index without elements 173 | if (sheet.IsEmpty) 174 | Sheets.Remove(block); 175 | } break; 176 | } 177 | } 178 | 179 | public void Query(HashSet hashSet, CoordinateRectangle rectangle, InterseptResult parentResult, SpatialQueryIterator i) 180 | { 181 | //Query elements on the map by coordinate ractengle(indexed search) 182 | lock (this) 183 | { 184 | if (!IsBottomSheet) 185 | { 186 | if (Sheets.HasChilds) 187 | { 188 | foreach (var sheet in Sheets.Values) 189 | { 190 | var res = parentResult == InterseptResult.Supersets ? InterseptResult.Supersets : InterseptResult.None; 191 | 192 | if (res != InterseptResult.Supersets) 193 | { 194 | i.Next(); 195 | 196 | res = sheet.Rectangle.RectangleContains(rectangle); 197 | } 198 | if (res != InterseptResult.None) 199 | { 200 | sheet.Query(hashSet, rectangle, res, i); 201 | } 202 | if (res == InterseptResult.Contains) break; 203 | } 204 | } 205 | } 206 | else if (Content.HasChilds) 207 | { 208 | foreach (var node in Content.Values) 209 | { 210 | var res = parentResult == InterseptResult.Supersets ? InterseptResult.Supersets : InterseptResult.None; 211 | if (res != InterseptResult.Supersets) 212 | { 213 | i.Next(); 214 | 215 | switch (node.NodeType) 216 | { 217 | case SpatialTreeNodeTypes.Point: 218 | res = rectangle.PointContains(node.Coordinate); 219 | break; 220 | case SpatialTreeNodeTypes.Line: 221 | res = rectangle.LineContains(node.Rectangle); 222 | break; 223 | case SpatialTreeNodeTypes.Rectangle: 224 | res = rectangle.RectangleContains(node.Rectangle); 225 | break; 226 | case SpatialTreeNodeTypes.Poligon: 227 | res = rectangle.PoligonContains(node.Poligon); 228 | break; 229 | } 230 | } 231 | if (res != InterseptResult.None) 232 | { 233 | hashSet.Add(node); 234 | } 235 | } 236 | } 237 | } 238 | } 239 | 240 | public void Distance(HashSet hashSet, Coordinate coordinate, double variance, SpatialQueryIterator i) 241 | { 242 | //Query elements on the map close to coordinate (indexed search) 243 | lock (this) 244 | { 245 | if (!IsBottomSheet) 246 | { 247 | if (Sheets.HasChilds) 248 | { 249 | foreach (var sheet in Sheets.Values) 250 | { 251 | i.Next(); 252 | 253 | if (sheet.Rectangle.RectangeDistance(coordinate) <= variance) 254 | { 255 | sheet.Distance(hashSet, coordinate, variance, i); 256 | } 257 | } 258 | } 259 | } 260 | else if (Content.HasChilds) 261 | { 262 | foreach (var node in Content.Values) 263 | { 264 | i.Next(); 265 | 266 | double distance = -1; 267 | switch (node.NodeType) 268 | { 269 | case SpatialTreeNodeTypes.Point: 270 | distance = node.Coordinate.Distance(coordinate); 271 | break; 272 | case SpatialTreeNodeTypes.Line: 273 | distance = node.Rectangle.LineDistance(coordinate); 274 | break; 275 | case SpatialTreeNodeTypes.Rectangle: 276 | distance = node.Rectangle.RectangeDistance(coordinate); 277 | break; 278 | case SpatialTreeNodeTypes.Poligon: 279 | distance = node.Poligon.PoligonDistance(coordinate); 280 | break; 281 | } 282 | 283 | if (distance >= 0 && distance <= variance) 284 | { 285 | hashSet.Add(node); 286 | } 287 | } 288 | } 289 | } 290 | } 291 | } 292 | } -------------------------------------------------------------------------------- /Map/Spatial/SpatialSheetBase.cs: -------------------------------------------------------------------------------- 1 | using ProgramMain.Map.Google; 2 | using ProgramMain.Map.Spatial.Indexer; 3 | using ProgramMain.Map.Spatial.Types; 4 | 5 | namespace ProgramMain.Map.Spatial 6 | { 7 | internal class SpatialSheetBase where TNode : ISpatialTreeNode 8 | { 9 | public int Level { get; private set; } 10 | public int GoogleLevel { get; private set; } 11 | 12 | //Daughter index sheets 13 | public readonly SpatialSheetIndexer Sheets; 14 | 15 | //Content array of index elemets on bottom index sheets 16 | public readonly SpatialContentIndexer Content; 17 | 18 | public bool IsEmpty 19 | { 20 | get 21 | { 22 | return !Sheets.HasChilds && !Content.HasChilds; 23 | } 24 | } 25 | 26 | public bool IsBottomSheet 27 | { 28 | get { return Level >= Sheets.PowerLength; } 29 | } 30 | 31 | public SpatialSheetBase(SpatialTree tree, int level, int googleLevel) 32 | { 33 | Level = level; 34 | GoogleLevel = googleLevel; 35 | 36 | Sheets = new SpatialSheetIndexer(this, tree); 37 | Content = new SpatialContentIndexer(); 38 | } 39 | 40 | private int GoogleNumLevel(int level) 41 | { 42 | return (int)GoogleMapUtilities.NumLevel((int)Sheets.Power(level)); 43 | } 44 | 45 | private int GoogleNextLevelAddon() 46 | { 47 | return GoogleNumLevel(Level) - 1; 48 | } 49 | 50 | public int NextGoogleLevel 51 | { 52 | get { return GoogleLevel + GoogleNextLevelAddon(); } 53 | } 54 | 55 | public void Clear() 56 | { 57 | lock (this) 58 | { 59 | if (!IsBottomSheet) 60 | { 61 | if (Sheets.HasChilds) 62 | { 63 | foreach (var sheet in Sheets.Values) 64 | { 65 | sheet.Clear(); 66 | } 67 | Sheets.Destroy(); 68 | } 69 | } 70 | else 71 | { 72 | Content.Destroy(); 73 | } 74 | } 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /Map/Spatial/SpatialTree.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using ProgramMain.Map.Spatial.Indexer; 3 | using ProgramMain.Map.Spatial.Types; 4 | using ProgramMain.Map.Types; 5 | 6 | namespace ProgramMain.Map.Spatial 7 | { 8 | public class SpatialTree where TNode : ISpatialTreeNode 9 | { 10 | //Spatial index depth count, can be > 4 11 | internal readonly int SpatialDepth = 4; 12 | 13 | //Root spatial index sheet includes all daughter indexed sheets 14 | private SpatialSheet _root; 15 | public int NodeCount { get; private set; } 16 | public readonly SpatialLevelPowerIndexer Power; 17 | 18 | internal int[] NodeDimension = null; 19 | 20 | public SpatialTree() 21 | { 22 | NodeCount = 0; 23 | Power = new SpatialLevelPowerIndexer(this); 24 | 25 | SetLevels( 26 | SpatialSheetPowerTypes.Medium, 27 | SpatialSheetPowerTypes.Medium, 28 | SpatialSheetPowerTypes.Medium, 29 | SpatialSheetPowerTypes.Medium); 30 | } 31 | 32 | public SpatialTree(SpatialSheetPowerTypes level1, SpatialSheetPowerTypes level2, SpatialSheetPowerTypes level3, SpatialSheetPowerTypes level4) 33 | { 34 | NodeCount = 0; 35 | Power = new SpatialLevelPowerIndexer(this); 36 | 37 | SetLevels(level1, level2, level3, level4); 38 | } 39 | 40 | protected void SetLevels(SpatialSheetPowerTypes level1, SpatialSheetPowerTypes level2, SpatialSheetPowerTypes level3, SpatialSheetPowerTypes level4) 41 | { 42 | if (NodeCount > 0) return; 43 | 44 | Power[1] = level1; 45 | if (Power.Length > 2) Power[2] = level2; 46 | if (Power.Length > 3) Power[3] = level3; 47 | if (Power.Length > 4) Power[4] = level4; 48 | 49 | for (var i = 5; i < Power.Length; i++) 50 | { 51 | Power[i] = SpatialSheetPowerTypes.Low; 52 | } 53 | //Root spatial index sheet includes whole world 54 | _root = new SpatialSheet(this, 1, 1, CoordinateRectangle.Empty); 55 | 56 | //Array to grab index stats for tuning 57 | NodeDimension = new int[Power.Length - 1]; 58 | } 59 | 60 | protected void Insert(TNode value) 61 | { 62 | lock (this) 63 | { 64 | NodeCount++; 65 | } 66 | 67 | _root.SheetAction(value, SpatialSheet.SheetActionType.Insert); 68 | } 69 | 70 | protected void Delete(TNode value) 71 | { 72 | lock (this) 73 | { 74 | NodeCount--; 75 | } 76 | 77 | _root.SheetAction(value, SpatialSheet.SheetActionType.Delete); 78 | } 79 | 80 | public HashSet Query(CoordinateRectangle rectangle) 81 | { 82 | //for debug to see how many iterations used for a search 83 | var i = SpatialQueryIterator.Start(); 84 | 85 | var res = new HashSet(); 86 | _root.Query(res, rectangle, InterseptResult.None, i); 87 | 88 | //index turning 89 | System.Diagnostics.Trace.WriteLine(string.Format("{5} Level nodes {1} {2} {3} {4}, Query iterations - {0:d}", 90 | i.Value, NodeDimension[0], NodeDimension[1], NodeDimension[2], NodeDimension[3], typeof(TNode).Name)); 91 | 92 | return res; 93 | } 94 | 95 | public HashSet Distance(Coordinate coordinate, double variance) 96 | { 97 | //for debug to see how many iterations used for a search 98 | var i = SpatialQueryIterator.Start(); 99 | 100 | var res = new HashSet(); 101 | _root.Distance(res, coordinate, variance, i); 102 | 103 | //index turning 104 | System.Diagnostics.Trace.WriteLine(string.Format("{5} Level nodes {1} {2} {3} {4}, Distance iterations - {0:d}", 105 | i.Value, NodeDimension[0], NodeDimension[1], NodeDimension[2], NodeDimension[3], typeof(TNode).Name)); 106 | 107 | return res; 108 | } 109 | 110 | public void Clear() 111 | { 112 | NodeCount = 0; 113 | _root.Clear(); 114 | 115 | NodeDimension = new int[Power.Length - 1]; 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /Map/Spatial/Types/SpatialSheetPowerTypes.cs: -------------------------------------------------------------------------------- 1 | namespace ProgramMain.Map.Spatial.Types 2 | { 3 | public enum SpatialSheetPowerTypes 4 | { 5 | None = 1, 6 | Few = 4, 7 | Low = 16, 8 | Medium = 64, 9 | High = 256, 10 | Extra = 1024, 11 | Ultra = 4096, 12 | Micro = 16384, 13 | Nano = 262144, 14 | Pico = 1048576 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Map/Spatial/Types/SpatialTreeNode.cs: -------------------------------------------------------------------------------- 1 | using System.Data; 2 | 3 | namespace ProgramMain.Map.Spatial.Types 4 | { 5 | public interface ISpatialTreeNode 6 | { 7 | SpatialTreeNodeTypes NodeType { get; } 8 | Coordinate Coordinate { get; } 9 | CoordinateRectangle Rectangle { get; } 10 | CoordinatePoligon Poligon { get; } 11 | int RowId { get; } 12 | DataRow Row { get; } //!!!absolute 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Map/Spatial/Types/SpatialTreeNodeTypes.cs: -------------------------------------------------------------------------------- 1 | namespace ProgramMain.Map.Spatial.Types 2 | { 3 | public enum SpatialTreeNodeTypes {Point, Line, Rectangle, Poligon} 4 | } 5 | -------------------------------------------------------------------------------- /Map/Types/InterseptResult.cs: -------------------------------------------------------------------------------- 1 | namespace ProgramMain.Map.Types 2 | { 3 | public enum InterseptResult { None, Intersepts, Contains, Supersets }; 4 | } 5 | -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | using ProgramMain.ExampleForms; 4 | 5 | 6 | namespace ProgramMain 7 | { 8 | static class Program 9 | { 10 | static Program() 11 | { 12 | MainForm = null; 13 | } 14 | 15 | public static FrmOpticMap MainForm { get; private set; } 16 | 17 | [STAThread] 18 | static void Main() 19 | { 20 | Application.EnableVisualStyles(); 21 | 22 | MainForm = new FrmOpticMap(); 23 | Application.Run(MainForm); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | using System.Resources; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Simple Map")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Agafonoff")] 12 | [assembly: AssemblyProduct("Simple Map")] 13 | [assembly: AssemblyCopyright("Copyright © None 2010")] 14 | [assembly: AssemblyTrademark("Simple Map")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | 24 | [assembly: Guid("381aef28-6284-4d3f-bcdd-87cfc27deaaa")] 25 | 26 | // Version information for an assembly consists of the following four values: 27 | // 28 | // Major Version 29 | // Minor Version 30 | // Build Number 31 | // Revision 32 | // 33 | [assembly: AssemblyVersion("1.3.8.5")] 34 | [assembly: AssemblyFileVersion("1.3.8.5")] 35 | [assembly: NeutralResourcesLanguageAttribute("ru-RU")] 36 | -------------------------------------------------------------------------------- /Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace ProgramMain.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ProgramMain.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Bitmap. 65 | /// 66 | internal static System.Drawing.Bitmap centermap_24 { 67 | get { 68 | object obj = ResourceManager.GetObject("centermap_24", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | 73 | /// 74 | /// Looks up a localized resource of type System.Drawing.Bitmap. 75 | /// 76 | internal static System.Drawing.Bitmap print_24 { 77 | get { 78 | object obj = ResourceManager.GetObject("print_24", resourceCulture); 79 | return ((System.Drawing.Bitmap)(obj)); 80 | } 81 | } 82 | 83 | /// 84 | /// Looks up a localized resource of type System.Drawing.Bitmap. 85 | /// 86 | internal static System.Drawing.Bitmap program_24 { 87 | get { 88 | object obj = ResourceManager.GetObject("program_24", resourceCulture); 89 | return ((System.Drawing.Bitmap)(obj)); 90 | } 91 | } 92 | 93 | /// 94 | /// Looks up a localized resource of type System.Drawing.Bitmap. 95 | /// 96 | internal static System.Drawing.Bitmap refresh_16 { 97 | get { 98 | object obj = ResourceManager.GetObject("refresh_16", resourceCulture); 99 | return ((System.Drawing.Bitmap)(obj)); 100 | } 101 | } 102 | 103 | /// 104 | /// Looks up a localized resource of type System.Drawing.Bitmap. 105 | /// 106 | internal static System.Drawing.Bitmap save_2_16x16 { 107 | get { 108 | object obj = ResourceManager.GetObject("save_2_16x16", resourceCulture); 109 | return ((System.Drawing.Bitmap)(obj)); 110 | } 111 | } 112 | 113 | /// 114 | /// Looks up a localized resource of type System.Drawing.Bitmap. 115 | /// 116 | internal static System.Drawing.Bitmap vertex_16 { 117 | get { 118 | object obj = ResourceManager.GetObject("vertex_16", resourceCulture); 119 | return ((System.Drawing.Bitmap)(obj)); 120 | } 121 | } 122 | 123 | /// 124 | /// Looks up a localized resource of type System.Drawing.Bitmap. 125 | /// 126 | internal static System.Drawing.Bitmap vertex_24 { 127 | get { 128 | object obj = ResourceManager.GetObject("vertex_24", resourceCulture); 129 | return ((System.Drawing.Bitmap)(obj)); 130 | } 131 | } 132 | 133 | /// 134 | /// Looks up a localized resource of type System.Drawing.Bitmap. 135 | /// 136 | internal static System.Drawing.Bitmap vertex_8 { 137 | get { 138 | object obj = ResourceManager.GetObject("vertex_8", resourceCulture); 139 | return ((System.Drawing.Bitmap)(obj)); 140 | } 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | ..\Resources\refresh_16.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 123 | 124 | 125 | ..\Resources\print_24.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 126 | 127 | 128 | ..\Resources\vertex_16.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 129 | 130 | 131 | ..\Resources\vertex_8.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 132 | 133 | 134 | ..\Resources\centermap_24.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 135 | 136 | 137 | ..\Resources\vertex_24.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 138 | 139 | 140 | ..\Resources\program_24.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 141 | 142 | 143 | ..\Resources\save 2_16x16.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 144 | 145 | -------------------------------------------------------------------------------- /Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace ProgramMain.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | 26 | [global::System.Configuration.UserScopedSettingAttribute()] 27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 28 | [global::System.Configuration.DefaultSettingValueAttribute("SimpleMap\\")] 29 | public string MapCacheLocalPath { 30 | get { 31 | return ((string)(this["MapCacheLocalPath"])); 32 | } 33 | set { 34 | this["MapCacheLocalPath"] = value; 35 | } 36 | } 37 | 38 | [global::System.Configuration.UserScopedSettingAttribute()] 39 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 40 | [global::System.Configuration.DefaultSettingValueAttribute("12")] 41 | public int StartZoomLevel { 42 | get { 43 | return ((int)(this["StartZoomLevel"])); 44 | } 45 | set { 46 | this["StartZoomLevel"] = value; 47 | } 48 | } 49 | 50 | [global::System.Configuration.ApplicationScopedSettingAttribute()] 51 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 52 | [global::System.Configuration.DefaultSettingValueAttribute("http://mt1.google.com/vt/lyrs=m@146&hl=en&x={0}&y={1}&z={2}")] 53 | public string GoogleUrl { 54 | get { 55 | return ((string)(this["GoogleUrl"])); 56 | } 57 | } 58 | 59 | [global::System.Configuration.ApplicationScopedSettingAttribute()] 60 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 61 | [global::System.Configuration.DefaultSettingValueAttribute("1.3.8.5")] 62 | public string AppVersion { 63 | get { 64 | return ((string)(this["AppVersion"])); 65 | } 66 | } 67 | 68 | [global::System.Configuration.UserScopedSettingAttribute()] 69 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 70 | [global::System.Configuration.DefaultSettingValueAttribute("17")] 71 | public int MaxZoomLevel { 72 | get { 73 | return ((int)(this["MaxZoomLevel"])); 74 | } 75 | set { 76 | this["MaxZoomLevel"] = value; 77 | } 78 | } 79 | 80 | [global::System.Configuration.UserScopedSettingAttribute()] 81 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 82 | [global::System.Configuration.DefaultSettingValueAttribute("5")] 83 | public int MinZoomLevel { 84 | get { 85 | return ((int)(this["MinZoomLevel"])); 86 | } 87 | set { 88 | this["MinZoomLevel"] = value; 89 | } 90 | } 91 | 92 | [global::System.Configuration.UserScopedSettingAttribute()] 93 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 94 | [global::System.Configuration.DefaultSettingValueAttribute("37.24468")] 95 | public double LeftMapBound { 96 | get { 97 | return ((double)(this["LeftMapBound"])); 98 | } 99 | set { 100 | this["LeftMapBound"] = value; 101 | } 102 | } 103 | 104 | [global::System.Configuration.UserScopedSettingAttribute()] 105 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 106 | [global::System.Configuration.DefaultSettingValueAttribute("55.9469")] 107 | public double TopMapBound { 108 | get { 109 | return ((double)(this["TopMapBound"])); 110 | } 111 | set { 112 | this["TopMapBound"] = value; 113 | } 114 | } 115 | 116 | [global::System.Configuration.UserScopedSettingAttribute()] 117 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 118 | [global::System.Configuration.DefaultSettingValueAttribute("38.00891")] 119 | public double RightMapBound { 120 | get { 121 | return ((double)(this["RightMapBound"])); 122 | } 123 | set { 124 | this["RightMapBound"] = value; 125 | } 126 | } 127 | 128 | [global::System.Configuration.UserScopedSettingAttribute()] 129 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 130 | [global::System.Configuration.DefaultSettingValueAttribute("55.5601")] 131 | public double BottomMapBound { 132 | get { 133 | return ((double)(this["BottomMapBound"])); 134 | } 135 | set { 136 | this["BottomMapBound"] = value; 137 | } 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | SimpleMap\ 7 | 8 | 9 | 12 10 | 11 | 12 | http://mt1.google.com/vt/lyrs=m@146&hl=en&x={0}&y={1}&z={2} 13 | 14 | 15 | 1.3.8.5 16 | 17 | 18 | 17 19 | 20 | 21 | 5 22 | 23 | 24 | 37.24468 25 | 26 | 27 | 55.9469 28 | 29 | 30 | 38.00891 31 | 32 | 33 | 55.5601 34 | 35 | 36 | -------------------------------------------------------------------------------- /Properties/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SimpleMap 2 | 3 | This is fully workable sample project on C# for Visual Studio 2012 or above. 4 | You can download and run SimpleMap.exe. Or download and compile the source code. 5 | 6 | SimpleMap/ExampleForms/FrmMapDownloader.cs demonstrates how to download google map area as single image (GetFullMapThread function) or how to cache google map on local disk (DownloadThread function). 7 | 8 | SimpleMap/ExampleForms/Controls/MapCtl.cs demostrates how to draw cached google map images to screen with custom objects as lines, bitmaps etc. 9 | 10 | The problem, project solve: 11 | 12 | Fast image(gif,png,jpg) draw to screen trhough GDI+ written pure on C# without any direct mapping to WinApi. 13 | Double buffering technology, all image changes draw into memory buffer and then changes apply to the screen. 14 | Download map images from google. 15 | Support google map coordinate system through sub classes and operators. Translate google coordinates to longitude and latitude. Translate longitude and latitude to google coordinates. Math operators support to work with coordinates. 16 | Cache google map files on disk. 17 | Download google image file cache to local storage. 18 | Save google map as one image. 19 | Base classes to draw any map layers. 20 | Spatial in-memory index with fast search by coordinates based on google map coordinate system. 21 | Spatial index tuning. 22 | Spatial index supported objects are: Point, Line, Rectangle, Poligon(patially suppoted). 23 | Sample demonstrates how You can use maps in your projects. It is absolutely free for use. 24 | 25 | Thanx. 26 | -------------------------------------------------------------------------------- /Resources/centermap_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agafonoff2000/SimpleMap/7893f78f2ac8a5c070a7b98c993dd168aff16b83/Resources/centermap_24.png -------------------------------------------------------------------------------- /Resources/print_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agafonoff2000/SimpleMap/7893f78f2ac8a5c070a7b98c993dd168aff16b83/Resources/print_24.png -------------------------------------------------------------------------------- /Resources/program_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agafonoff2000/SimpleMap/7893f78f2ac8a5c070a7b98c993dd168aff16b83/Resources/program_24.png -------------------------------------------------------------------------------- /Resources/refresh_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agafonoff2000/SimpleMap/7893f78f2ac8a5c070a7b98c993dd168aff16b83/Resources/refresh_16.png -------------------------------------------------------------------------------- /Resources/save 2_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agafonoff2000/SimpleMap/7893f78f2ac8a5c070a7b98c993dd168aff16b83/Resources/save 2_16x16.png -------------------------------------------------------------------------------- /Resources/vertex_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agafonoff2000/SimpleMap/7893f78f2ac8a5c070a7b98c993dd168aff16b83/Resources/vertex_16.png -------------------------------------------------------------------------------- /Resources/vertex_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agafonoff2000/SimpleMap/7893f78f2ac8a5c070a7b98c993dd168aff16b83/Resources/vertex_24.png -------------------------------------------------------------------------------- /Resources/vertex_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agafonoff2000/SimpleMap/7893f78f2ac8a5c070a7b98c993dd168aff16b83/Resources/vertex_8.png -------------------------------------------------------------------------------- /Settings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using ProgramMain.Map; 4 | using ProgramMain.Map.Google; 5 | 6 | // ReSharper disable CheckNamespace 7 | namespace ProgramMain.Properties { 8 | // ReSharper restore CheckNamespace 9 | 10 | 11 | // This class allows you to handle specific events on the settings class: 12 | // The SettingChanging event is raised before a setting's value is changed. 13 | // The PropertyChanged event is raised after a setting's value is changed. 14 | // The SettingsLoaded event is raised after the setting values are loaded. 15 | // The SettingsSaving event is raised before the setting values are saved. 16 | internal sealed partial class Settings { 17 | 18 | // ReSharper disable EmptyConstructor 19 | public Settings() { 20 | // ReSharper restore EmptyConstructor 21 | // // To add event handlers for saving and changing settings, uncomment the lines below: 22 | // 23 | // this.SettingChanging += this.SettingChangingEventHandler; 24 | // 25 | // this.SettingsSaving += this.SettingsSavingEventHandler; 26 | // 27 | } 28 | 29 | // ReSharper disable UnusedMember.Local 30 | private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) { 31 | // Add code to handle the SettingChangingEvent event here. 32 | if (sender != null && e != null) 33 | { 34 | 35 | } 36 | } 37 | 38 | private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) { 39 | // Add code to handle the SettingsSaving event here. 40 | if (sender != null && e != null) 41 | { 42 | 43 | } 44 | } 45 | // ReSharper restore UnusedMember.Local 46 | 47 | public static string GetMapFileName(GoogleBlock block) 48 | { 49 | var mapPath = Default.MapCacheLocalPath; 50 | if (!Path.IsPathRooted(mapPath)) 51 | { 52 | mapPath = Path.Combine( 53 | Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), 54 | mapPath); 55 | } 56 | var fileName = Path.Combine(mapPath, block.Level + "\\" + (block.X / 100) + "_" + (block.Y / 100) + "\\" + block.Level + "_" + block.X + "_" + block.Y + ".png"); 57 | 58 | return fileName; 59 | } 60 | 61 | private static Coordinate _centerMapBound; 62 | 63 | public static Coordinate CenterMapBound 64 | { 65 | get 66 | { 67 | if (_centerMapBound == null) 68 | { 69 | var rectBound = new CoordinateRectangle(Default.LeftMapBound, Default.TopMapBound, Default.RightMapBound, Default.BottomMapBound); 70 | _centerMapBound = rectBound.LineMiddlePoint; 71 | } 72 | return _centerMapBound; 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /SimpleMap.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Publish\ 5 | http://install.simplemap.ru/ 6 | 7 | 8 | 9 | 10 | en-US 11 | false 12 | 13 | -------------------------------------------------------------------------------- /SimpleMap.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleMap", "SimpleMap.csproj", "{FE54D43D-1518-478D-94C1-42656E024E1D}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {FE54D43D-1518-478D-94C1-42656E024E1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {FE54D43D-1518-478D-94C1-42656E024E1D}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {FE54D43D-1518-478D-94C1-42656E024E1D}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {FE54D43D-1518-478D-94C1-42656E024E1D}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /default.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agafonoff2000/SimpleMap/7893f78f2ac8a5c070a7b98c993dd168aff16b83/default.ico --------------------------------------------------------------------------------