diff --git a/.gitignore b/.gitignore
index d0eae807..321e5da0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -69,6 +69,8 @@ ipch/
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
+*.idea
+*.vs
# TeamCity is a build add-in
_TeamCity*
@@ -136,8 +138,7 @@ UpgradeLog*.htm
# SQL Server files
App_Data/*.mdf
-App_Data/*.ldf
-
+App_Data/*.ldf
#LightSwitch generated files
GeneratedArtifacts/
@@ -160,10 +161,22 @@ $RECYCLE.BIN/
# Mac desktop service store files
.DS_Store
+__MACOSX/
+
+# GDAL SDK
+support/GDAL_SDK/licenses/*.rtf
+support/GDAL_SDK/**/*.dll
+support/GDAL_SDK/**/*.exe
+support/GDAL_SDK/**/*.lib
+support/GDAL_SDK/**/*.h
+support/GDAL_SDK/**/*.hpp
+support/GDAL_SDK/**/*.c
+support/GDAL_SDK/**/*.inc
+support/GDAL_SDK/**/*.proto
+support/GDAL_SDK/**/*.pc
# Custom
*.dll
-support/GDAL_SDK/*
docs/output
demo/.nuget/
*.zip
@@ -172,11 +185,8 @@ unittests/MapWinGISTests/AkkerwebTests.cs
*.mwd
*.mwx
unittests/packages/
-unittests/.vs/unittests/v15/Server/sqlite3/storage.ide
-unittests/.vs/unittests/v15/Server/sqlite3/db.lock
-docs/.vs/MapWinGis Documentation/v15/Server/sqlite3/storage.ide-wal
-docs/.vs/MapWinGis Documentation/v15/Server/sqlite3/storage.ide-shm
-docs/.vs/MapWinGis Documentation/v15/Server/sqlite3/storage.ide
-docs/.vs/MapWinGis Documentation/v15/Server/sqlite3/db.lock
-src/MapWinGIS.vcxproj.filters
-unittests/.vs/
+*.VC.db
+*.VC.opendb
+docs/Assets/Syncfusion Logos/
+tmp/
+docs/OptimizedImages/
diff --git a/docs/AxInterop.MapWinGIS.XML b/docs/AxInterop.MapWinGIS.XML
index b4bd2478..b363c6bf 100644
--- a/docs/AxInterop.MapWinGIS.XML
+++ b/docs/AxInterop.MapWinGIS.XML
@@ -1042,7 +1042,9 @@
\addtogroup map_drawing_layers Drawing layers
- Here is a list of methods and properties to interact with the drawing layers of the map. This module is a part of the documentation of AxMap class.
+ Here is a list of methods and properties to interact with the drawing layers of the map.
+ The drawing layers are more transient that the standard layers, intended for fast drawing of temporary elements on top of the map.
+ This module is a part of the documentation of AxMap class.
\dot
digraph map_drawing_layers {
splines = true;
@@ -1071,18 +1073,21 @@
- Clears all the drawings on the drawing layer specified.
+ Clears all drawings on the specified drawing layer, and removes the drawing layer. The drawing handle will no longer be valid.
+ Call AxMap.NewDrawing again to create a new drawing layer to continue adding new elements.
- Drawing handle of the drawing layer for which all drawings are to be cleared.
+ Drawing handle of the drawing layer to be cleared (and removed).
- Clears all drawings on all drawing layers. This method is slower than using ClearDrawing on a specific layer
+ Clears all drawings on all drawing layers, and removes all drawing layers.
+ This method is slower than using ClearDrawing on a specific layer.
+ Call AxMap.NewDrawing again to create a new drawing layer to continue adding new elements.
- Draws a circle on the last drawing layer created by NewDrawing
+ Draws a circle on the last drawing layer created by AxMap.NewDrawing
Center x coordinate for the circle to be drawn.
Center y coordinate for the circle to be drawn.
@@ -1103,7 +1108,7 @@
- Draws a line on the last drawing layer created using NewDrawing.
+ Draws a line on the last drawing layer created using AxMap.NewDrawing.
X coordinate of the first point used to draw the line
Y coordinate of the first point used to draw the line.
@@ -1126,7 +1131,7 @@
- Draws a point on the last drawing layer created by NewDrawing.
+ Draws a point on the last drawing layer created by AxMap.NewDrawing.
The x coordinate of the point to draw
The y coordinate of the point to draw.
@@ -1145,7 +1150,7 @@
- Draws a polygon on the last drawing layer created using NewDrawing.
+ Draws a polygon on the last drawing layer created using AxMap.NewDrawing.
An array containing x-coordinates for each point in the polygon.
An array containing y-coordinates for each point in the polygon.
@@ -1166,7 +1171,7 @@
- Draws a circle with custom outline width on the last drawing layer created by NewDrawing.
+ Draws a circle with custom outline width on the last drawing layer created by AxMap.NewDrawing.
Center x coordinate for the circle to be drawn.
Center y coordinate for the circle to be drawn.
@@ -1189,7 +1194,7 @@
- Draws a polygon with custom width of outline on the last drawing layer created using NewDrawing.
+ Draws a polygon with custom width of outline on the last drawing layer created using AxMap.NewDrawing.
An array containing x-coordinates for each point in the polygon.
An array containing y-coordinates for each point in the polygon.
@@ -1200,7 +1205,7 @@
- Draws a polygon with custom width of outline on the last drawing layer created using NewDrawing.
+ Draws a polygon with custom width of outline on the last drawing layer created using AxMap.NewDrawing.
The handle of the drawing layer created with AxMap.NewDrawing call.
An array containing x-coordinates for each point in the polygon.
@@ -1214,8 +1219,8 @@
Creates a new drawing layer on the map returning its handle.
- Sets the coordinate system to use for the new drawing layer to be created. (ScreenReferenced
- uses pixels in screen coordinates. SpatiallyReferenced uses projected map units.)
+ Sets the coordinate system to use for the new drawing layer to be created. (tkDrawReferenceList.dlScreenReferencedList
+ uses pixels in screen coordinates. tkDrawReferenceList.dlSpatiallyReferencedList uses projected map units.)
The handle for the new drawing layer in the map.
diff --git a/docs/AxInterop.MapWinGIS/AxMap.cs b/docs/AxInterop.MapWinGIS/AxMap.cs
index 8081488f..9502aa41 100644
--- a/docs/AxInterop.MapWinGIS/AxMap.cs
+++ b/docs/AxInterop.MapWinGIS/AxMap.cs
@@ -1,4 +1,9 @@
-using System;
+// ReSharper disable ArrangeAccessorOwnerBody
+// ReSharper disable DelegateSubtraction
+// ReSharper disable PossibleInvalidCastExceptionInForeachLoop
+// ReSharper disable CheckNamespace
+
+using System;
using MapWinGIS;
#pragma warning disable 67 // Never used warning
@@ -1470,7 +1475,9 @@ public bool get_LayerVisibleAtCurrentScale(int layerHandle)
#region Drawing layer
/// \addtogroup map_drawing_layers Drawing layers
- /// Here is a list of methods and properties to interact with the drawing layers of the map. This module is a part of the documentation of AxMap class.
+ /// Here is a list of methods and properties to interact with the drawing layers of the map.
+ /// The drawing layers are more transient that the standard layers, intended for fast drawing of temporary elements on top of the map.
+ /// This module is a part of the documentation of AxMap class.
/// \dot
/// digraph map_drawing_layers {
/// splines = true;
@@ -1506,16 +1513,19 @@ public Labels get_DrawingLabels(int DrawingLayerIndex)
}
///
- /// Clears all the drawings on the drawing layer specified.
+ /// Clears all drawings on the specified drawing layer, and removes the drawing layer. The drawing handle will no longer be valid.
+ /// Call AxMap.NewDrawing again to create a new drawing layer to continue adding new elements.
///
- /// Drawing handle of the drawing layer for which all drawings are to be cleared.
+ /// Drawing handle of the drawing layer to be cleared (and removed).
public void ClearDrawing(int DrawHandle)
{
throw new NotImplementedException();
}
///
- /// Clears all drawings on all drawing layers. This method is slower than using ClearDrawing on a specific layer
+ /// Clears all drawings on all drawing layers, and removes all drawing layers.
+ /// This method is slower than using ClearDrawing on a specific layer.
+ /// Call AxMap.NewDrawing again to create a new drawing layer to continue adding new elements.
///
public void ClearDrawings()
{
@@ -1523,7 +1533,7 @@ public void ClearDrawings()
}
///
- /// Draws a circle on the last drawing layer created by NewDrawing
+ /// Draws a circle on the last drawing layer created by AxMap.NewDrawing
///
/// Center x coordinate for the circle to be drawn.
/// Center y coordinate for the circle to be drawn.
@@ -1550,7 +1560,7 @@ public void DrawCircleEx(int LayerHandle, double x, double y, double pixelRadius
}
///
- /// Draws a line on the last drawing layer created using NewDrawing.
+ /// Draws a line on the last drawing layer created using AxMap.NewDrawing.
///
/// X coordinate of the first point used to draw the line
/// Y coordinate of the first point used to draw the line.
@@ -1579,7 +1589,7 @@ public void DrawLineEx(int LayerHandle, double x1, double y1, double x2, double
}
///
- /// Draws a point on the last drawing layer created by NewDrawing.
+ /// Draws a point on the last drawing layer created by AxMap.NewDrawing.
///
/// The x coordinate of the point to draw
/// The y coordinate of the point to draw.
@@ -1604,7 +1614,7 @@ public void DrawPointEx(int LayerHandle, double x, double y, int pixelSize, uint
}
///
- /// Draws a polygon on the last drawing layer created using NewDrawing.
+ /// Draws a polygon on the last drawing layer created using AxMap.NewDrawing.
///
/// An array containing x-coordinates for each point in the polygon.
/// An array containing y-coordinates for each point in the polygon.
@@ -1631,7 +1641,7 @@ public void DrawPolygonEx(int LayerHandle, ref object xPoints, ref object yPoint
}
///
- /// Draws a circle with custom outline width on the last drawing layer created by NewDrawing.
+ /// Draws a circle with custom outline width on the last drawing layer created by AxMap.NewDrawing.
///
/// Center x coordinate for the circle to be drawn.
/// Center y coordinate for the circle to be drawn.
@@ -1660,7 +1670,7 @@ public void DrawWideCircleEx(int LayerHandle, double x, double y, double radius,
}
///
- /// Draws a polygon with custom width of outline on the last drawing layer created using NewDrawing.
+ /// Draws a polygon with custom width of outline on the last drawing layer created using AxMap.NewDrawing.
///
/// An array containing x-coordinates for each point in the polygon.
/// An array containing y-coordinates for each point in the polygon.
@@ -1674,7 +1684,7 @@ public void DrawWidePolygon(ref object xPoints, ref object yPoints, int numPoint
}
///
- /// Draws a polygon with custom width of outline on the last drawing layer created using NewDrawing.
+ /// Draws a polygon with custom width of outline on the last drawing layer created using AxMap.NewDrawing.
///
/// The handle of the drawing layer created with AxMap.NewDrawing call.
/// An array containing x-coordinates for each point in the polygon.
@@ -1691,10 +1701,10 @@ public void DrawWidePolygonEx(int LayerHandle, ref object xPoints, ref object yP
///
/// Creates a new drawing layer on the map returning its handle.
///
- /// Sets the coordinate system to use for the new drawing layer to be created. (ScreenReferenced
- /// uses pixels in screen coordinates. SpatiallyReferenced uses projected map units.)
+ /// Sets the coordinate system to use for the new drawing layer to be created. (tkDrawReferenceList.dlScreenReferencedList
+ /// uses pixels in screen coordinates. tkDrawReferenceList.dlSpatiallyReferencedList uses projected map units.)
/// The handle for the new drawing layer in the map.
- public int NewDrawing(MapWinGIS.tkDrawReferenceList Projection)
+ public int NewDrawing(tkDrawReferenceList projection)
{
throw new NotImplementedException();
}
diff --git a/docs/AxInterop.MapWinGIS/AxMap_Deprecated.cs b/docs/AxInterop.MapWinGIS/AxMap_Deprecated.cs
index d0092aa9..309777b6 100644
--- a/docs/AxInterop.MapWinGIS/AxMap_Deprecated.cs
+++ b/docs/AxInterop.MapWinGIS/AxMap_Deprecated.cs
@@ -1,7 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
#if nsp
namespace AxMapWinGIS
diff --git a/docs/AxInterop.MapWinGIS/Enums.cs b/docs/AxInterop.MapWinGIS/Enums.cs
index 4086ea86..6c038581 100644
--- a/docs/AxInterop.MapWinGIS/Enums.cs
+++ b/docs/AxInterop.MapWinGIS/Enums.cs
@@ -1,4 +1,10 @@
-///
+// ReSharper disable ArrangeAccessorOwnerBody
+// ReSharper disable DelegateSubtraction
+// ReSharper disable PossibleInvalidCastExceptionInForeachLoop
+// ReSharper disable CheckNamespace
+
+
+///
/// Justification of the labels
///
public enum tkHJustification { }
diff --git a/docs/AxInterop.MapWinGIS/Properties/AssemblyInfo.cs b/docs/AxInterop.MapWinGIS/Properties/AssemblyInfo.cs
index 04f7f8b6..98afea40 100644
--- a/docs/AxInterop.MapWinGIS/Properties/AssemblyInfo.cs
+++ b/docs/AxInterop.MapWinGIS/Properties/AssemblyInfo.cs
@@ -1,5 +1,4 @@
using System.Reflection;
-using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
diff --git a/docs/Examples/Description.cs b/docs/Examples/Description.cs
index c629ad1c..4f3c7e77 100644
--- a/docs/Examples/Description.cs
+++ b/docs/Examples/Description.cs
@@ -1,10 +1,12 @@
-
+// ReSharper disable ArrangeAccessorOwnerBody
+// ReSharper disable DelegateSubtraction
+// ReSharper disable PossibleInvalidCastExceptionInForeachLoop
+// ReSharper disable CheckNamespace
+
+// ReSharper disable UseNullPropagation
namespace Examples
{
- using System;
using System.Collections.Generic;
- using System.Linq;
- using System.Text;
///
/// The groups of the examples for GUI
@@ -25,9 +27,8 @@ public enum ExampleGroup
///
/// Holds description of the example to be displayed in the documentation and GUI of this project.
///
- class Example
+ public class Example
{
- private string guiName; // in the interface
public string function; // to call with reflection
public string description; // to generate documentation page and show in the GUI
public bool image; // whether an image should be attached to the page
@@ -38,24 +39,22 @@ public Example()
image = true;
}
- public string GuiName
- {
- get { return guiName; }
- set { guiName = value; }
- }
+ public string GuiName { get; set; }
}
- class Description
+ internal class Description
{
// list of the examples
- public List examples = new List();
+ public readonly List examples = new List();
// event declaration
- delegate void ExampleAddedEventHandler(Example ex, int index);
- event ExampleAddedEventHandler ExampleAdded;
- void FireExampleAdded(Example ex, int index)
+ private delegate void ExampleAddedEventHandler(Example ex, int index);
+
+ private event ExampleAddedEventHandler ExampleAdded;
+
+ private void FireExampleAdded(Example ex, int index)
{
- if (this.ExampleAdded != null)
+ if (ExampleAdded != null)
ExampleAdded(ex, index);
}
@@ -64,10 +63,10 @@ void FireExampleAdded(Example ex, int index)
///
public Description()
{
- this.ExampleAdded += Description_ExampleAdded;
- for (int i = 0; i < 30; i++)
+ ExampleAdded += Description_ExampleAdded;
+ for (var i = 0; i < 30; i++)
{
- Example ex = new Example();
+ var ex = new Example();
FireExampleAdded(ex, i);
examples.Add(ex);
}
@@ -76,7 +75,7 @@ public Description()
///
/// Adds description of the examples
///
- void Description_ExampleAdded(Example ex, int index)
+ private static void Description_ExampleAdded(Example ex, int index)
{
switch (index)
{
diff --git a/docs/Examples/MapEventHandler.cs b/docs/Examples/MapEventHandler.cs
index 6300db4e..1b490fe1 100644
--- a/docs/Examples/MapEventHandler.cs
+++ b/docs/Examples/MapEventHandler.cs
@@ -1,18 +1,16 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+// ReSharper disable ArrangeAccessorOwnerBody
+// ReSharper disable DelegateSubtraction
+// ReSharper disable PossibleInvalidCastExceptionInForeachLoop
+// ReSharper disable CheckNamespace
-static class MapEvents
+public static class MapEvents
{
- public static AxMapWinGIS._DMapEvents_MouseDownEventHandler _mouseDownDelegate;
- public static AxMapWinGIS._DMapEvents_MouseMoveEventHandler _mouseMoveDelegate;
- public static AxMapWinGIS._DMapEvents_MouseUpEventHandler _mouseUpDelegate;
- public static AxMapWinGIS._DMapEvents_SelectBoxFinalEventHandler _selectBoxDelegate;
- public static AxMapWinGIS._DMapEvents_ShapeHighlightedEventHandler _shapeHighlightedDelegate;
-
- private static Delegate[] m_delegates = new Delegate[5] { _mouseDownDelegate, _mouseMoveDelegate, _mouseUpDelegate,
- _selectBoxDelegate, _shapeHighlightedDelegate };
+ private static AxMapWinGIS._DMapEvents_MouseDownEventHandler _mouseDownDelegate;
+ private static AxMapWinGIS._DMapEvents_MouseMoveEventHandler _mouseMoveDelegate;
+ private static AxMapWinGIS._DMapEvents_MouseUpEventHandler _mouseUpDelegate;
+ private static AxMapWinGIS._DMapEvents_SelectBoxFinalEventHandler _selectBoxDelegate;
+ private static AxMapWinGIS._DMapEvents_ShapeHighlightedEventHandler _shapeHighlightedDelegate;
#region Attach delegate
///
@@ -22,31 +20,31 @@ public static void AttachMap(AxMapWinGIS.AxMap axMap1)
{
axMap1.MouseDownEvent += delegate(object sender, AxMapWinGIS._DMapEvents_MouseDownEvent e)
{
- object[] param = new object[2] { sender, e };
+ var param = new[] { sender, e };
Invoke(_mouseDownDelegate, param);
};
axMap1.MouseMoveEvent += delegate(object sender, AxMapWinGIS._DMapEvents_MouseMoveEvent e)
{
- object[] param = new object[2] { sender, e };
+ var param = new[] { sender, e };
Invoke(_mouseMoveDelegate, param);
};
axMap1.MouseUpEvent += delegate(object sender, AxMapWinGIS._DMapEvents_MouseUpEvent e)
{
- object[] param = new object[2] { sender, e };
+ var param = new[] { sender, e };
Invoke(_mouseUpDelegate, param);
};
axMap1.SelectBoxFinal += delegate(object sender, AxMapWinGIS._DMapEvents_SelectBoxFinalEvent e)
{
- object[] param = new object[2] { sender, e };
+ var param = new[] { sender, e };
Invoke(_selectBoxDelegate, param);
};
axMap1.ShapeHighlighted += delegate(object sender, AxMapWinGIS._DMapEvents_ShapeHighlightedEvent e)
{
- object[] param = new object[2] { sender, e };
+ var param = new[] { sender, e };
Invoke(_shapeHighlightedDelegate, param);
};
}
diff --git a/docs/Examples/Program.cs b/docs/Examples/Program.cs
index 7881f109..3584c2b5 100644
--- a/docs/Examples/Program.cs
+++ b/docs/Examples/Program.cs
@@ -1,18 +1,21 @@
-using MapWinGIS;
+// ReSharper disable ArrangeAccessorOwnerBody
+// ReSharper disable DelegateSubtraction
+// ReSharper disable PossibleInvalidCastExceptionInForeachLoop
+// ReSharper disable CheckNamespace
+
+using MapWinGIS;
using System;
-using System.Collections.Generic;
-using System.Linq;
using System.Windows.Forms;
namespace Examples
{
- static class Program
+ public static class Program
{
///
/// The main entry point for the application.
///
[STAThread]
- static void Main()
+ private static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
@@ -20,10 +23,9 @@ static void Main()
Application.Run(new StartForm());
}
- static void InitGlobalSettings()
+ private static void InitGlobalSettings()
{
- var gs = new GlobalSettings();
- gs.ReprojectLayersOnAdding = true;
+ var globalSettings = new GlobalSettings {ReprojectLayersOnAdding = true};
}
}
diff --git a/docs/Examples/Properties/AssemblyInfo.cs b/docs/Examples/Properties/AssemblyInfo.cs
index bcaee0dd..f8752bec 100644
--- a/docs/Examples/Properties/AssemblyInfo.cs
+++ b/docs/Examples/Properties/AssemblyInfo.cs
@@ -1,5 +1,4 @@
using System.Reflection;
-using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
diff --git a/docs/Examples/StartForm.cs b/docs/Examples/StartForm.cs
index ffef509a..dd33cf21 100644
--- a/docs/Examples/StartForm.cs
+++ b/docs/Examples/StartForm.cs
@@ -1,10 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Data;
-using System.Drawing;
-using System.Linq;
-using System.Text;
using System.Windows.Forms;
namespace Examples
@@ -18,7 +12,7 @@ public StartForm()
Shown += StartForm_Shown;
}
- void StartForm_Shown(object sender, EventArgs e)
+ private void StartForm_Shown(object sender, EventArgs e)
{
using (var form = new TestForm())
{
diff --git a/docs/Examples/TestForm.cs b/docs/Examples/TestForm.cs
index 24d8eec9..e281896d 100644
--- a/docs/Examples/TestForm.cs
+++ b/docs/Examples/TestForm.cs
@@ -1,14 +1,18 @@
-
+// ReSharper disable ArrangeAccessorOwnerBody
+// ReSharper disable DelegateSubtraction
+// ReSharper disable PossibleInvalidCastExceptionInForeachLoop
+// ReSharper disable CheckNamespace
+
+// ReSharper disable MergeSequentialChecks
+// ReSharper disable SuggestVarOrType_SimpleTypes
+// ReSharper disable SuggestVarOrType_Elsewhere
+// ReSharper disable SuggestVarOrType_BuiltInTypes
namespace Examples
{
#region Usings
using System;
using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
using System.Linq;
- using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Reflection;
@@ -18,11 +22,12 @@ namespace Examples
public partial class TestForm : Form
{
- MapExamples m_examples;
- Description m_description;
+ private readonly MapExamples m_examples;
+ private readonly Description m_description;
private string m_dataPath;
private string m_iconPath;
+ ///
///
/// Creates a new instance of the form1
///
@@ -30,14 +35,11 @@ public TestForm()
{
InitializeComponent();
-
-
MapEvents.AttachMap(axMap1);
- m_examples = new MapExamples();
- m_examples.axMap1 = axMap1;
+ m_examples = new MapExamples {axMap1 = axMap1};
m_description = new Description();
FillList();
- this.treeView1.SelectedNode = this.treeView1.Nodes[0];
+ treeView1.SelectedNode = treeView1.Nodes[0];
GenerateExamples();
btnClear_Click_1(null, null);
@@ -59,25 +61,24 @@ void axMap1_ProjectionMismatch(object sender, AxMapWinGIS._DMapEvents_Projection
///
/// Fills the list from the examples directory.
///
- public void FillList()
+ private void FillList()
{
m_dataPath = Path.GetDirectoryName(Application.ExecutablePath) + @"..\..\..\..\Data\";
m_iconPath = Path.GetDirectoryName(Application.ExecutablePath) + @"..\..\..\..\icons\";
if (!Directory.Exists(m_dataPath))
{
- MessageBox.Show("The directory with the data wasn't found:\n" + m_dataPath);
+ MessageBox.Show(@"The directory with the data wasn't found:\n" + m_dataPath);
return;
}
- this.treeView1.Nodes.Clear();
+ treeView1.Nodes.Clear();
string[] names = Enum.GetNames(typeof(ExampleGroup));
foreach (string name in names)
{
- if (name != "None")
- {
- TreeNode node = this.treeView1.Nodes.Add(name);
- node.Expand();
- }
+ if (name == "None") continue;
+
+ TreeNode node = treeView1.Nodes.Add(name);
+ node.Expand();
}
IEnumerable list = m_description.examples.Select(t => t.group.ToString()).Distinct();
@@ -87,7 +88,7 @@ public void FillList()
foreach (Example ex in examples)
{
TreeNode node = new TreeNode() { Text = ex.GuiName, Tag = ex };
- foreach (TreeNode parent in this.treeView1.Nodes)
+ foreach (TreeNode parent in treeView1.Nodes)
{
if (parent.Text == ex.group.ToString())
{
@@ -97,26 +98,25 @@ public void FillList()
}
}
- this.treeView1.NodeMouseDoubleClick += delegate(object sender, TreeNodeMouseClickEventArgs e)
+ treeView1.NodeMouseDoubleClick += delegate
{
- this.BtnRunClick(null, null);
+ BtnRunClick();
};
- this.treeView1.AfterSelect += new TreeViewEventHandler(treeView1_AfterSelect);
+ treeView1.AfterSelect += treeView1_AfterSelect;
}
///
/// Shows description for the selected example
///
- void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
+ private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
- this.lblDescription.Text = "Description: ";
- TreeNode node = this.treeView1.SelectedNode;
- if (node != null && node.Tag != null)
- {
- Example ex = node.Tag as Example;
- this.lblDescription.Text += "The example demonstrates how to " + ex.description;
- }
+ lblDescription.Text = @"Description: ";
+ TreeNode node = treeView1.SelectedNode;
+ if (node == null || node.Tag == null) return;
+
+ Example ex = node.Tag as Example;
+ if (ex != null) lblDescription.Text += @"The example demonstrates how to " + ex.description;
}
#endregion
@@ -124,59 +124,57 @@ void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
///
/// Runs the selected example
///
- private void BtnRunClick(object sender, EventArgs e)
+ private void BtnRunClick()
{
- this.btnClear_Click_1(null, null);
+ btnClear_Click_1(null, null);
- TreeNode node = this.treeView1.SelectedNode;
- if (node != null && node.Tag != null)
+ TreeNode node = treeView1.SelectedNode;
+ if (node == null || node.Tag == null) return;
+
+ Example ex = node.Tag as Example;
+ if (ex == null) return;
+
+ MethodInfo info = m_examples.GetType().GetMethod(ex.function);
+ if (info == null)
+ {
+ MessageBox.Show(@"Function wasn't found: " + ex.function);
+ return;
+ }
+
+ ParameterInfo[] list = info.GetParameters();
+ if (list.Any())
{
- Example ex = node.Tag as Example;
- if (ex != null)
+ object[] param = new object[list.Count()];
+ for (int i = 0; i < list.Count(); i++)
{
- MethodInfo info = m_examples.GetType().GetMethod(ex.function);
- if (info == null)
+ ParameterInfo item = list[i];
+ switch (item.ParameterType.ToString())
{
- MessageBox.Show("Function wasn't found: " + ex.function);
- }
- else
- {
- ParameterInfo[] list = info.GetParameters();
- if (list.Any())
- {
- object[] param = new object[list.Count()];
- for (int i = 0; i < list.Count(); i++)
+ case "AxMapWinGIS.AxMap":
+ param[i] = axMap1;
+ break;
+ case "System.String":
+ if (item.Name == "dataPath")
{
- ParameterInfo item = list[i];
- switch (item.ParameterType.ToString())
- {
- case "AxMapWinGIS.AxMap":
- param[i] = this.axMap1;
- break;
- case "System.String":
- if (item.Name == "dataPath")
- {
- param[i] = m_dataPath;
- }
- if (item.Name == "iconPath")
- {
- param[i] = m_iconPath;
- }
- break;
- case "System.Windows.Forms.ToolStripStatusLabel":
- param[i] = this.label1;
- break;
- }
- //MessageBox.Show(item.ParameterType.ToString());
+ param[i] = m_dataPath;
}
- info.Invoke(m_examples, param);
- }
- else
- {
- info.Invoke(m_examples, null);
- }
+
+ if (item.Name == "iconPath")
+ {
+ param[i] = m_iconPath;
+ }
+
+ break;
+ case "System.Windows.Forms.ToolStripStatusLabel":
+ param[i] = label1;
+ break;
}
}
+ info.Invoke(m_examples, param);
+ }
+ else
+ {
+ info.Invoke(m_examples, null);
}
}
#endregion
@@ -186,7 +184,7 @@ private void BtnRunClick(object sender, EventArgs e)
///
private void GenerateExamples()
{
- string path = System.IO.Path.GetDirectoryName(Application.ExecutablePath) + @"..\..\..\..\..\Interop.MapWinGIS\Related pages\examples_list.cs";
+ string path = Path.GetDirectoryName(Application.ExecutablePath) + @"..\..\..\..\..\Interop.MapWinGIS\Related pages\examples_list.cs";
StreamWriter writer = new StreamWriter(path);
foreach (Example item in m_description.examples)
{
@@ -207,7 +205,7 @@ private void btnClear_Click_1(object sender, EventArgs e)
{
axMap1.RemoveAllLayers();
axMap1.ClearDrawings();
- axMap1.CursorMode = MapWinGIS.tkCursorMode.cmZoomIn;
+ axMap1.CursorMode = tkCursorMode.cmZoomIn;
MapEvents.Clear();
axMap1.Projection = tkMapProjection.PROJECTION_GOOGLE_MERCATOR;
@@ -223,21 +221,18 @@ private void btnClear_Click_1(object sender, EventArgs e)
///
private void btnSnapshot_Click(object sender, EventArgs e)
{
- TreeNode node = this.treeView1.SelectedNode;
- if (node != null && node.Tag != null)
- {
- Example ex = node.Tag as Example;
- if (ex != null)
- {
- MapWinGIS.Image img = (MapWinGIS.Image)this.axMap1.SnapShot(this.axMap1.Extents);
- if (img != null)
- {
- string filename = Path.GetDirectoryName(Application.ExecutablePath) +
- @"..\..\..\..\Resources\images\" + ex.function + ".png";
- img.Save(filename, false, MapWinGIS.ImageType.USE_FILE_EXTENSION, null);
- }
- }
- }
+ TreeNode node = treeView1.SelectedNode;
+ if (node == null || node.Tag == null) return;
+
+ Example ex = node.Tag as Example;
+ if (ex == null) return;
+
+ Image img = axMap1.SnapShot(axMap1.Extents);
+ if (img == null) return;
+
+ string filename = Path.GetDirectoryName(Application.ExecutablePath) +
+ @"..\..\..\..\Resources\images\" + ex.function + ".png";
+ img.Save(filename, false, MapWinGIS.ImageType.USE_FILE_EXTENSION, null);
}
}
}
diff --git a/docs/Examples/src/AddCategoryRange.cs b/docs/Examples/src/AddCategoryRange.cs
index 7282dbd4..dc9e0ab2 100644
--- a/docs/Examples/src/AddCategoryRange.cs
+++ b/docs/Examples/src/AddCategoryRange.cs
@@ -1,8 +1,14 @@
-using System;
+// ReSharper disable ArrangeAccessorOwnerBody
+// ReSharper disable DelegateSubtraction
+// ReSharper disable PossibleInvalidCastExceptionInForeachLoop
+// ReSharper disable CheckNamespace
+
using System.IO;
using System.Windows.Forms;
using AxMapWinGIS;
using MapWinGIS;
+// ReSharper disable SuggestVarOrType_BuiltInTypes
+// ReSharper disable SuggestVarOrType_SimpleTypes
namespace Examples
{
@@ -11,97 +17,95 @@ public partial class MapExamples
//
// Calculates area of polygons and sets 3 range of categories with different symbology
//
- public void AddCategoryRange(AxMap axMap1, string dataPath)
+ public void AddCategoryRange(AxMap axMap, string dataPath)
{
- axMap1.Projection = tkMapProjection.PROJECTION_GOOGLE_MERCATOR;
+ axMap.Projection = tkMapProjection.PROJECTION_GOOGLE_MERCATOR;
string filename = dataPath + "landuse.shp";
if (File.Exists(filename) == false)
{
- MessageBox.Show("Failed to open file: " + filename);
+ MessageBox.Show(@"Failed to open file: " + filename);
return;
}
Shapefile sf = new Shapefile();
- if (sf.Open(filename, null))
+ if (!sf.Open(filename)) return;
+
+ if (!sf.StartEditingTable())
{
- if (!sf.StartEditingTable(null))
- {
- MessageBox.Show("Failed to open editing mode.");
- return;
- }
+ MessageBox.Show(@"Failed to open editing mode.");
+ return;
+ }
- int fieldIndex = sf.Table.FieldIndexByName["Area"];
+ int fieldIndex = sf.Table.FieldIndexByName["Area"];
- if (fieldIndex == -1)
- fieldIndex = sf.EditAddField("Area", FieldType.DOUBLE_FIELD, 15, 18);
+ if (fieldIndex == -1)
+ fieldIndex = sf.EditAddField("Area", FieldType.DOUBLE_FIELD, 15, 18);
- for (int i = 0; i < sf.NumShapes; i++)
- {
- double area = sf.Shape[i].Area * 100000.0;
- sf.EditCellValue(fieldIndex, i, area);
- }
+ for (int i = 0; i < sf.NumShapes; i++)
+ {
+ double area = sf.Shape[i].Area * 100000.0;
+ sf.EditCellValue(fieldIndex, i, area);
+ }
- // adding to map
- int handle = axMap1.AddLayer(sf, true);
- sf = axMap1.get_Shapefile(handle); // in case a copy of shapefile was created by GlobalSettings.ReprojectLayersOnAdding
+ // adding to map
+ int handle = axMap.AddLayer(sf, true);
+ sf = axMap.get_Shapefile(handle); // in case a copy of shapefile was created by GlobalSettings.ReprojectLayersOnAdding
- double mean = sf.Table.MeanValue[fieldIndex];
- double stDev = sf.Table.StandardDeviation[fieldIndex];
- double min = (double)sf.Table.MinValue[fieldIndex];
- double max = (double)sf.Table.MaxValue[fieldIndex];
+ double mean = sf.Table.MeanValue[fieldIndex];
+ double stDev = sf.Table.StandardDeviation[fieldIndex];
+ double min = (double)sf.Table.MinValue[fieldIndex];
+ double max = (double)sf.Table.MaxValue[fieldIndex];
- var scheme = new ColorScheme();
+ var scheme = new ColorScheme();
- // 1. the first range [min; mean - stDev]
- Utils utils = new Utils();
- sf.DefaultDrawingOptions.FillType = tkFillType.ftHatch;
- sf.DefaultDrawingOptions.FillHatchStyle = tkGDIPlusHatchStyle.hsDiagonalBrick;
+ // 1. the first range [min; mean - stDev]
+ Utils utils = new Utils();
+ sf.DefaultDrawingOptions.FillType = tkFillType.ftHatch;
+ sf.DefaultDrawingOptions.FillHatchStyle = tkGDIPlusHatchStyle.hsDiagonalBrick;
- bool res = sf.Categories.AddRange(fieldIndex, tkClassificationType.ctNaturalBreaks, 5, min, mean);
- scheme.SetColors2(tkMapColor.Red, tkMapColor.Yellow);
+ sf.Categories.AddRange(fieldIndex, tkClassificationType.ctNaturalBreaks, 5, min, mean);
+ scheme.SetColors2(tkMapColor.Red, tkMapColor.Yellow);
- // apply colors 0 and 4 are indices of categories, since 5 categories were added - from 0 to 4
- sf.Categories.ApplyColorScheme3(tkColorSchemeType.ctSchemeRandom, scheme, tkShapeElements.shElementFill, 0, 4);
+ // apply colors 0 and 4 are indices of categories, since 5 categories were added - from 0 to 4
+ sf.Categories.ApplyColorScheme3(tkColorSchemeType.ctSchemeRandom, scheme, tkShapeElements.shElementFill, 0, 4);
- // 2. the second range [mean - stDev; mean + stDev]
- // the default drawing options will be copied to the new categories
- sf.DefaultDrawingOptions.FillType = tkFillType.ftHatch;
- sf.DefaultDrawingOptions.FillHatchStyle = tkGDIPlusHatchStyle.hsCross;
- res = sf.Categories.AddRange(fieldIndex, tkClassificationType.ctEqualIntervals, 5, mean, mean + stDev);
- scheme.SetColors2(tkMapColor.Green, tkMapColor.Blue);
- sf.Categories.ApplyColorScheme3(tkColorSchemeType.ctSchemeGraduated, scheme, tkShapeElements.shElementFill, 5, 9);
+ // 2. the second range [mean - stDev; mean + stDev]
+ // the default drawing options will be copied to the new categories
+ sf.DefaultDrawingOptions.FillType = tkFillType.ftHatch;
+ sf.DefaultDrawingOptions.FillHatchStyle = tkGDIPlusHatchStyle.hsCross;
+ sf.Categories.AddRange(fieldIndex, tkClassificationType.ctEqualIntervals, 5, mean, mean + stDev);
+ scheme.SetColors2(tkMapColor.Green, tkMapColor.Blue);
+ sf.Categories.ApplyColorScheme3(tkColorSchemeType.ctSchemeGraduated, scheme, tkShapeElements.shElementFill, 5, 9);
- // 3. the third range [mean + stDev; max]
- // the default drawing options will be copied to the new categories
- sf.DefaultDrawingOptions.FillType = tkFillType.ftGradient;
- sf.DefaultDrawingOptions.FillColor2 = utils.ColorByName(tkMapColor.Gray);
- res = sf.Categories.AddRange(fieldIndex, tkClassificationType.ctEqualIntervals, 5, mean + stDev, max);
- scheme.SetColors2(tkMapColor.Pink, tkMapColor.Violet);
- sf.Categories.ApplyColorScheme3(tkColorSchemeType.ctSchemeGraduated, scheme, tkShapeElements.shElementFill, 10, 14);
+ // 3. the third range [mean + stDev; max]
+ // the default drawing options will be copied to the new categories
+ sf.DefaultDrawingOptions.FillType = tkFillType.ftGradient;
+ sf.DefaultDrawingOptions.FillColor2 = utils.ColorByName(tkMapColor.Gray);
+ sf.Categories.AddRange(fieldIndex, tkClassificationType.ctEqualIntervals, 5, mean + stDev, max);
+ scheme.SetColors2(tkMapColor.Pink, tkMapColor.Violet);
+ sf.Categories.ApplyColorScheme3(tkColorSchemeType.ctSchemeGraduated, scheme, tkShapeElements.shElementFill, 10, 14);
- // apply expresions should be called exlicitly
- sf.Categories.ApplyExpressions();
- axMap1.Redraw();
+ // apply expresions should be called exlicitly
+ sf.Categories.ApplyExpressions();
+ axMap.Redraw();
- // saving options to see categories desription in XML
- axMap1.SaveLayerOptions(handle, "categories_sample", true, "");
- }
+ // saving options to see categories desription in XML
+ axMap.SaveLayerOptions(handle, "categories_sample", true, "");
}
//
// To apply the same options on the next loading
//
- private void RestoreCategories(AxMap axMap1, string dataPath)
+ private void RestoreCategories(AxMap axMap, string dataPath)
{
string filename = dataPath + "landuse.shp";
Shapefile sf = new Shapefile();
- if (sf.Open(filename, null))
- {
- int handle = axMap1.AddLayer(sf, true);
- string description = "";
- axMap1.LoadLayerOptions(handle, "categories_sample", ref description);
- }
+ if (!sf.Open(filename)) return;
+
+ int handle = axMap.AddLayer(sf, true);
+ string description = "";
+ axMap.LoadLayerOptions(handle, "categories_sample", ref description);
}
}
}
\ No newline at end of file
diff --git a/docs/Interop.MapWinGIS.XML b/docs/Interop.MapWinGIS.XML
index 0c2d93aa..7cb6197d 100644
--- a/docs/Interop.MapWinGIS.XML
+++ b/docs/Interop.MapWinGIS.XML
@@ -702,6 +702,138 @@
The index of the break.
The new colour to set.
+
+
+ Implementation of the GDAL v2 librified functions.
+ Not all functions are implemented yet.
+
+ \new495 Added in version 4.9.5
+
+
+
+ Retrieves the last error generated in the object.
+
+ \new495 Added in version 4.9.5
+
+
+
+ The global callback is the interface used by MapWinGIS to pass progress and error events to interested applications.
+
+ \new495 Added in version 4.9.5
+
+
+
+ The key may be used by the programmer to store any string data associated with the object.
+
+ \new495 Added in version 4.9.5
+
+
+
+ Gets the detailed error message.
+
+ \new495 Added in version 4.9.5
+
+
+
+ Image reprojection and warping utility.
+ Implementing the librified function of GDAL's gdalwarp.exe tool
+
+ The source filename.
+ The destination filename.
+ The options, as a string array
+ See GDAL's documentation here: http://www.gdal.org/gdalwarp.html
+ \new495 Added in version 4.9.5
+
+ \code
+ // Example of creating VRT file from TIFF file. More options are possible:
+ var output = Path.GetTempPath() + "GdalWarp.vrt";
+ var options = new[]
+ {
+ "-of", "vrt",
+ "-overwrite"
+ };
+ var gdalUtils = new GdalUtils();
+ if (!gdalUtils.GDALWarp("test.tif", output, options))
+ {
+ Debug.WriteLine("GdalWarp failed: " + gdalUtils.ErrorMsg[gdalUtils.LastErrorCode] + " Detailed error: " + gdalUtils.DetailedErrorMsg);
+ }
+ \endcode
+
+ \code
+ // Example of cutting a TIFF file with a border file:
+ var output = Path.GetTempPath() + "GdalWarpCutline.vrt";
+ const string border = @"test.shp";
+ var options = new[]
+ {
+ "-of", "vrt",
+ "-overwrite",
+ "-crop_to_cutline",
+ "-cutline", border
+ };
+ var gdalUtils = new GdalUtils();
+ if (!gdalUtils.GDALWarp("test.tif", output, options))
+ {
+ Debug.WriteLine("GdalWarp failed: " + gdalUtils.ErrorMsg[gdalUtils.LastErrorCode] + " Detailed error: " + gdalUtils.DetailedErrorMsg);
+ }
+ \endcode
+
+
+
+ Converts simple features data between file formats.
+ Implementing the librified function of GDAL's ogr2ogr.exe tool
+
+ The source filename.
+ The destination filename.
+ The options, as a string array
+ If set to true improves performance but also might make it instable.
+ See GDAL's documentation here: http://www.gdal.org/ogr2ogr.html
+ \new495 Added in version 4.9.5
+
+ \code
+ // Converting shapefile to gml:
+ var outputFilename = Path.Combine(Path.GetTempPath(), "translated.gml");
+ var options = new[]
+ {
+ "-f", "GML"
+ };
+ var gdalUtils = new GdalUtils();
+ if (!gdalUtils.GdalVectorTranslate(inputFilename, outputFilename, options, true))
+ {
+ Debug.WriteLine("GdalVectorTranslate failed: " + gdalUtils.ErrorMsg[gdalUtils.LastErrorCode] + " Detailed error: " + gdalUtils.DetailedErrorMsg);
+ }
+ \endcode
+
+
+
+ Clips the vector with another vector.
+
+ The subject filename.
+ The overlay filename.
+ The destination filename.
+ If set to true improves performance but also might make it instable.
+ Uses GdalUtils.GdalVectorTranslate under the hood.
+ \new495 Added in version 4.9.5
+
+ \code
+ // Clipping large shapefile with border file
+ const string subjectFilename = @"D:\dev\GIS-Data\Issues\MWGIS-78 Clipper\Fishnet.shp";
+ const string borderFilename = @"D:\dev\GIS-Data\Issues\MWGIS-78 Clipper\border.shp";
+ var outputFilename = Path.Combine(tempFolder, "GdalVectorTranslate.shp");
+ var gdalUtils = new GdalUtils();
+ if (!gdalUtils.ClipVectorWithVector("LargeFile.shp", "Border.shp", outputFilename))
+ {
+ Debug.WriteLine("GdalVectorTranslate failed: " + gdalUtils.ErrorMsg[gdalUtils.LastErrorCode] + " Detailed error: " + gdalUtils.DetailedErrorMsg);
+ }
+ \endcode
+
+
+
+ Retrieves the error message associated with the specified error code.
+
+ The error code for which the error message is required.
+ The error message description for the specified error code.
+ \new495 Added in version 4.9.5
+
Represents a layer downloading and displaying the data from the particular WMS Server.
@@ -2269,7 +2401,7 @@
\note The fully working implementation of the shape editor can be examined in the the Demo application
included in MapWinGIS installation (starting from v4.9.3). The source code for this application is available in
- the repository.
+ the repository.
\new493 Added in version 4.9.3
@@ -3835,6 +3967,16 @@
\see OgrLayer.MaxFeatureCount
\new493 Added in version 4.9.3
+
+
+ Applies to conversion of OGR Shapefile layers to MapWinGIS Shapefiles (via GetBuffer), since
+ OGR Shapefiles do not support Logical fields. Instead, DBF Logical fields are read as single-
+ character strings. This property Gets or Sets a value which indicates whether to interpret
+ single-character Ogr strings as Logical/Boolean values, as long as the character contained
+ in the string is one of valid DBF logical characters (e.g. Y, N, T, F). The default value is true.
+
+ \new495 Added in version 4.9.5
+
Gets or sets a value which indicates whether OgrLayer.DynamicLoading mode will
@@ -3950,16 +4092,14 @@
- Gets or sets API key to access Bing maps. Without API key Bing Maps provider isn't available. See
- details here.
+ Gets or sets API key to access Bing maps. Without API key Bing Maps provider isn't available.
\new493 Added in version 4.9.3
Sets application credentials for Here Maps online tiles.
- Without these credentials Here Maps providers are not available. See
- details here.
+ Without these credentials Here Maps providers are not available.
Application Id. Can be obtained by registering on the site of the service.
Application code. Can be obtained by registering on the site of the service.
@@ -8033,7 +8173,7 @@
- Imports shape data from WKT format.
+ Exports shape data to WKT format.
String in WKT format with shape data.
\new490 Added in version 4.9.0
@@ -8139,6 +8279,23 @@
\new493 Added in version 4.9.3
+
+
+ Return a point at the specified distance (or percentage) along the specified line
+
+ Starting point along this line (specify Point[0] for beginning of line)
+ Distance along this line (or percentage of line length; if a percentage, specify a number between 0.0 and 1.0)
+ Optional value; if FALSE, 'distance' is actual distance; if TRUE, distance is percentage of length; defaults to FALSE
+ Returns a Point class representing the point along the sourceLine that is the specified distance (or percentage) along the line.
+
+ Only applies to a Polyline Shape. If 'distance' is greater than the the line length, the line's endpoint is returned.
+
+ 'startPoint' does not have to be on the line. If not on the line, actual starting point will be the nearest point to 'startPoint' that is on the line.
+
+ \see Utils.LineInterpolatePoint
+
+ \new500 Added in version 5.0.0
+
@@ -8947,125 +9104,6 @@
ShapefileCategory.Expression property will change it to cvExpression.
\new493 Added in version 4.9.3
-
-
- Defines a part of shapefile color scheme and specifies how a certain region of a shapefile will be colored.
-
- \deprecated in v. 4.8. Use ShapefileCategories, ShapefileCategory, ColorScheme classes instead.
- \removed493 Removed in 4.9.3
-
-
-
- Gets or sets the caption of the shapefile color break.
-
-
-
-
- Gets or sets the color which will be used for drawing objects characterized by ShapefileColorBreak.EndValue.
-
-
-
-
- Gets or sets the value which represent the end of shapefile color break.
-
-
-
-
- Gets or sets the color which will be used for drawing objects characterized by ShapefileColorBreak.StartValue.
-
-
-
-
- Gets or sets the value which represent the start of shapefile color break.
-
-
-
-
- Gets or sets a boolean value which indicates whether the objects defined by color break will be displayed.
-
-
-
-
- A shapefile color scheme defines how a shapefile will be colored.
-
- A shapefile color scheme consists of ShapefileColorBreak objects.
- \deprecated in v. 4.8. Use ShapefileCategories, ShapefileCategory, ColorScheme instead.
- \removed493 Removed in 4.9.3
-
-
-
- Adds a color break to the color scheme.
-
-
-
-
-
-
- Gets or sets the index in the attribute table the color scheme is associated with.
-
-
-
-
- Gets or sets callback object to return the information about the errors.
-
- \deprecated v4.9.3 Use GlobalSettings.ApplicationCallback instead.
-
-
-
- Insert a color break in the specified position of the scheme.
-
- The position to insert color break at.
- The color break to insert.
- The actual position color break was inserted at.
-
-
-
- Gets or sets text string associated with the object.
-
-
-
-
- Returns the code of the last error which took place inside this instance of class.
-
-
-
-
- Gets or sets the layer handle the color scheme is associated with.
-
-
-
-
- Gets the number of color breaks in the color scheme.
-
- The number of breaks.
-
-
-
- Removes specific color break from the scheme.
-
- The index of the break to remove.
-
-
-
- Gets a color break from the color scheme.
-
- The index of the break.
- The color break object or NULL reference on failure.
-
-
-
- Gets the description of the error code returned by ShapefileColorScheme.LastErrorCode.
-
- The code of error.
- The description of error.
-
-
-
- Replaces a color break in the color scheme.
-
- The index of color break to replace.
- The reference to the new color break.
-
Represents a network built from the polyline shapefile.
@@ -9887,12 +9925,21 @@
Type of cache to be cleared.
+
+
+ Clears cache of the specified to type for a given provider ID and scales.
+
+ Type of cache to be cleared.
+ Tile provider ID to be cleared. -1 will clear tiles for all providers.
+ Minimal scale (zoom) to clear tiles for.
+ Maximum scale (zoom) to clear tiles for.
+
Clears cache of the specified to type for a given provider and scales.
Type of cache to be cleared.
- Tile provider to be cleared. ProviderNone will clear tiles for all providers.
+ Tile provider to be cleared. ProviderNone will clear tiles for all providers.
Minimal scale (zoom) to clear tiles for.
Maximum scale (zoom) to clear tiles for.
@@ -9904,6 +9951,11 @@
Therefore in most cases tiles of particular zoom will be somewhat additionally scaled to fit the map,
i.e. their display size on map won't be equal to the original 256 pixels.
+
+
+ Gets or sets the delay request timeout.
+
+
Restores the state of Tiles class from string.
@@ -9919,7 +9971,7 @@
Gets the bounds of specific tile in decimal degrees (for inner use/debug purposes).
- Id of the provider.
+ Id of the provider.
Zoom level for a tile.
X coordinate of the tile within zoom level.
Y coordinate of the tile within zoom level.
@@ -9931,7 +9983,7 @@
Bounds in decimal degrees.
Zoom level.
- Id of the provider.
+ Id of the provider.
Extents object with tile bounds or null on failure.
Can be used at the first step of prefetching operation.
@@ -9962,7 +10014,7 @@
Minimal longitude to cache within.
Maximum longitude to cache within.
Zoom level.
- Id of the provider.
+ Id of the provider.
StopExecution interface implementation to stop the operation prematurely.
The number of tiles scheduled for caching.
The operation is executed asynchronously. To get the progress information use Tiles.GlobalCallback property.
@@ -9977,7 +10029,7 @@
Minimum Y index of tile to be cached (in coordinates of tile zoom level).
Maximum Y index of tile to be cached (in coordinates of tile zoom level).
Zoom level to be cached.
- Id of the provider.
+ Id of the provider.
StopExecution interface implementation to stop the operation prematurely.
Number of tiles scheduled for caching.
The operation is executed asynchronously. See details in Tiles.Prefetch.
@@ -9988,8 +10040,8 @@
Extents to cache within in decimal degrees.
Zoom level.
- Id of the provider.
- Directory to save files into. Nested folders for zoom levels,
+ Id of the provider.
+ Directory to save files into (must exists). Nested folders for zoom levels,
X/Y coordinates will be created automatically.
File extension to store tiles with.
StopExecution interface implementation to stop the operation prematurely.
@@ -10021,6 +10073,31 @@
Gets list of the available default and custom tile providers.
+
+
+ Gets the current size of cache.
+
+ The type of cache to return size for.
+ The size of cache in MB.
+
+
+
+ Gets the current size of cache used for specific provider and zoom level.
+
+ The type of cache to return size for.
+ Provider. ProviderNone will return size for all providers.
+ Scale (zoom) level. -1 will return size for all zoom levels.
+ The size of cache in MB.
+
+
+
+ Gets the current size of cache used for specific provider and zoom level.
+
+ Type of the cache.
+ The provider. -1 will return size for all providers.
+ The scale. -1 will return size for all zoom levels.
+ The size of cache in MB.
+
Gets proxy server settings for tiles class including IP and port, e.g. 192.168.0.1:80.
@@ -10059,22 +10136,6 @@
When set to false tiles won't be requested either from server or cache.
-
-
- Gets the current size of cache.
-
- The type of cache to return size for.
- The size of cache in MB.
-
-
-
- Gets the current size of cache used for specific provider and zoom level.
-
- The type of cache to return size for.
- Provider. ProviderNone will return size for all providers.
- Scale (zoom) level. -1 will return size for all zoom levels.
- The size of cache in MB.
-
Gets the value indicating whether tiles requested from server will be automatically cached.
@@ -10135,21 +10196,6 @@
\new491 Added in version 4.9.1
-
-
- Starts logging HTTP requests for tile server.
-
- Filename to write log into. New file will be created any existing file - overwritten.
- Indicate whether only unsuccessful requests should logged.
- True if log was opened, and false on failure.
- \new491 Added in version 4.9.1
-
-
-
- Stops logging of HTTP requests to a file.
-
- \new491 Added in version 4.9.1
-
Gets the number of unsuccessful HTTP requests during prefetching operation (Tiles.Prefetch and overloads).
@@ -10172,7 +10218,7 @@
Gets number of tiles stored in disk cache for a given provider, zoom and region.
- Id of provider.
+ Id of provider.
Zoom level.
Min X index of tile.
Max X index of tile.
@@ -10200,7 +10246,7 @@
Gets the description of the specific error code.
- The error code returned by LastErrorCode property.
+ The error code returned by LastErrorCode property.
String with the description.
@@ -10222,6 +10268,20 @@
This diagnostic value indicates whether tiles will be rendered without scaling and distortions and if they will be rendered at all.
\new491 Added in version 4.9.1
+
+
+ Gets or sets the proxy authentication scheme.
+
+ \new491 Added in version 4.9.1
+
+
+
+ Gets a value indicating whether [projection is spherical mercator].
+
+
+ true if [projection is spherical mercator]; otherwise, false.
+
+
Gets projection used by specific tile service.
@@ -10230,11 +10290,11 @@
- Clears user name and password set by Tiles.SetProxyAuthorization method.
+ Clears user name and password set by Tiles.SetProxyAuthentication method.
\new493 Added in version 4.9.3
-
+
Sets credentials for proxy authorization.
@@ -10488,6 +10548,7 @@
A utils object provides access to a set of utility functions to perform a variety of tasks on other objects such as grids, images, points, shapes, shapefiles, tins, etc.
+ Starting at v4.9.5 some specific GDAL methods are moved to GdalUtils.
@@ -10825,6 +10886,7 @@
See documentation here: http://www.gdal.org/gdalwarp.html
\new490 Added in version 4.9.0
+ \deprecated v4.9.5 Use GdalUtils.GDALWarp instead.
@@ -10913,6 +10975,7 @@
See documentation here: http://www.gdal.org/ogr2ogr.html
\new490 Added in version 4.9.0
+ \deprecated v4.9.5 Use GdalUtils.GdalVectorTranslate instead.
@@ -11131,6 +11194,41 @@
\new495 Added in version 4.9.5
+
+
+ Calculates the angle defined by the two specified coordinates
+
+
+
+ Geographic Angle (in degrees) of the vector measured from the first point to the second point
+
+ The angle returned is the so-called Geographic angle, measured in a clockwise direction
+ from the positive Y-axis, as opposed to the Arithmetic (Cartesian) angle measured in a
+ counter-clockwise direction from the positive X-axis. The returned value can be used
+ as-is to specify Shape or Label Rotation, which expect the Geographic angle for input.
+
+ \see Shapefile.set_ShapeRotation
+
+ \new500 Added in version 5.0.0
+
+
+
+ Return a point at the specified distance (or percentage) along the specified line
+
+ Polyline shape to traverse
+ Starting point along 'sourceLine' (specify Point[0] for beginning of line)
+ Distance along line (or percentage of line length; if a percentage, specify a number between 0.0 and 1.0)
+ Optional value; if FALSE, 'distance' is actual distance; if TRUE, distance is percentage of length; defaults to FALSE
+ Returns a Point class representing the point along the sourceLine that is the specified distance (or percentage) along the line.
+
+ 'sourceLine' must be a Polyline Shape. If 'distance' is greater than the source line length, the line's endpoint is returned.
+
+ 'startPoint' does not have to be on 'sourceLine'. If not on the line, actual starting point will be the nearest point to 'startPoint' that is on 'sourceline'.
+
+ \see Shape.InterpolatePoint
+
+ \new500 Added in version 5.0.0
+
A vector object is used to represent the light source for a grid color scheme.
@@ -11729,7 +11827,7 @@
The objects of the drawing layer are specified in screen coordinates and are not moved after the changes of the extents.
- To update such layers the full redraw is not needed. Therefore use AxMap.Refresh rather than AxMap.Redraw.
+ To update such layers the full redraw is not needed. Therefore use AxMap.Redraw2 rather than AxMap.Redraw.
@@ -12566,7 +12664,7 @@
Map will be rendered from the main buffer. Only measurements and coordinate display will be rendered anew.
- Corresponds to AxMap.Refresh/AxMap.Invalidate.
+ Corresponds to AxMap.Redraw2/AxMap.Invalidate.
@@ -14162,7 +14260,8 @@
\addtogroup shapefile_geoprocessing Shapefile geoprocessing
Here is a list of methods to perform geoprocessing tasks using shapefile data.
- This module is a part of the documentation of Shapefile class.
+ This module is a part of the documentation of Shapefile class.\n\n
+ Use GlobalSettings.MinAreaToPerimeterRatio and GlobalSettings.MinPolygonArea to tweak which polygon needs to be included in the output file.
\dot
digraph shapefile_geoprocessing {
splines = true;
@@ -14703,7 +14802,13 @@
\addtogroup shapefile_selection Shapefile selection
Here is a list of properties and methods for managing shapefile selection.
- This module is a part of the documentation of Shapefile class.
+ This module is a part of the documentation of the Shapefile class.
+
+ Historically, using the cmSelection and cmSelectByPolygon tools, you would specify a LayerHandle in the ChooseLayer map event
+ to indicate which single layer you were selecting shapes from. Starting in v5.0, you can select from multiple layers concurrently
+ by setting the 'Selectable' property of each layer you would like to select shapes from. If the LayerHandle returned from the
+ ChooseLayer event is left unspecified (-1), then instead, all layers having the 'Selectable' property = TRUE
+ will be selectable by the tool.
\dot
digraph shapefile_selection {
splines = true;
@@ -14791,6 +14896,17 @@
\new48 Added in version 4.8
+
+
+ Gets or sets a value indicating whether this shapefile will be selectable by the cmSelection and cmSelectByPolygon tool.
+
+
+ This property allows for multiple shapefiles to be concurrently selectable.
+ If only selecting from one layer, you can still use the ChooseLayer map event to specify the selectable layer.
+
+ \see AxMap.CursorMode
+ \new500 Added in version 5.0.0
+
Gets or sets the way shapefile selection will be displayed.
diff --git a/docs/Interop.MapWinGIS/Com Classes/Chart.cs b/docs/Interop.MapWinGIS/Com Classes/Chart.cs
index 4098b2e8..482cb018 100644
--- a/docs/Interop.MapWinGIS/Com Classes/Chart.cs
+++ b/docs/Interop.MapWinGIS/Com Classes/Chart.cs
@@ -3,7 +3,6 @@ namespace MapWinGIS
{
#endif
using System;
-
///
/// Represents a single chart on the map.
///
@@ -59,7 +58,7 @@ namespace MapWinGIS
/// \new48 Added in version 4.8
#if nsp
#if upd
- public class Chart : MapWinGIS.IChart
+ public class Chart : IChart
#else
public class IChart
#endif
@@ -107,9 +106,19 @@ public double PositionY
/// This property will return NULL in case Chart.IsDrawn returns false.
public Extents ScreenExtents
{
- get { throw new NotImplementedException(); }
+ get
+ {
+ throw new NotImplementedException();
+ }
}
+
+
+// public Extents ScreenExtents
+// {
+// get { throw new NotImplementedException(); }
+// }
+
///
/// Gets or sets the value which indicates whether the chart should be drawn on the map.
///
diff --git a/docs/Interop.MapWinGIS/Com Classes/Charts.cs b/docs/Interop.MapWinGIS/Com Classes/Charts.cs
index 1c614cb5..e27d9ddc 100644
--- a/docs/Interop.MapWinGIS/Com Classes/Charts.cs
+++ b/docs/Interop.MapWinGIS/Com Classes/Charts.cs
@@ -89,7 +89,8 @@ namespace MapWinGIS
/// \new48 Added in version 4.8
#if nsp
#if upd
- public class Charts : MapWinGIS.ICharts
+ //public class Charts : MapWinGIS.ICharts
+ public class ICharts
#else
public class ICharts
#endif
@@ -692,7 +693,6 @@ public ChartField get_Field(int FieldIndex)
{
throw new NotImplementedException();
}
-
#endregion
}
#if nsp
diff --git a/docs/Interop.MapWinGIS/Com Classes/GdalUtils.cs b/docs/Interop.MapWinGIS/Com Classes/GdalUtils.cs
index 174c193a..17572225 100644
--- a/docs/Interop.MapWinGIS/Com Classes/GdalUtils.cs
+++ b/docs/Interop.MapWinGIS/Com Classes/GdalUtils.cs
@@ -158,15 +158,5 @@ public string get_ErrorMsg(int ErrorCode)
{
throw new NotImplementedException();
}
-
- ///
- /// The global callback is the interface used by MapWinGIS to pass progress and error events to interested applications.
- ///
- /// \new495 Added in version 4.9.5
- ICallback IGdalUtils.GlobalCallback
- {
- get { throw new NotImplementedException(); }
- set { throw new NotImplementedException(); }
- }
}
}
diff --git a/docs/Interop.MapWinGIS/Com Classes/Shape.cs b/docs/Interop.MapWinGIS/Com Classes/Shape.cs
index a06e3cf6..bf8da318 100644
--- a/docs/Interop.MapWinGIS/Com Classes/Shape.cs
+++ b/docs/Interop.MapWinGIS/Com Classes/Shape.cs
@@ -704,7 +704,7 @@ public bool ImportFromWKT(string Serialized)
}
///
- /// Imports shape data from WKT format.
+ /// Exports shape data to WKT format.
///
/// String in WKT format with shape data.
/// \new490 Added in version 4.9.0
@@ -846,6 +846,27 @@ public bool IsEmpty
{
get { throw new NotImplementedException(); }
}
+
+ ///
+ /// Return a point at the specified distance (or percentage) along the specified line
+ ///
+ /// Starting point along this line (specify Point[0] for beginning of line)
+ /// Distance along this line (or percentage of line length; if a percentage, specify a number between 0.0 and 1.0)
+ /// Optional value; if FALSE, 'distance' is actual distance; if TRUE, distance is percentage of length; defaults to FALSE
+ /// Returns a Point class representing the point along the sourceLine that is the specified distance (or percentage) along the line.
+ ///
+ /// Only applies to a Polyline Shape. If 'distance' is greater than the the line length, the line's endpoint is returned.
+ ///
+ /// 'startPoint' does not have to be on the line. If not on the line, actual starting point will be the nearest point to 'startPoint' that is on the line.
+ ///
+ /// \see Utils.LineInterpolatePoint
+ ///
+ /// \new500 Added in version 5.0.0
+ public Point InterpolatePoint(Point startPoint, double distance, bool normalized)
+ {
+ throw new NotImplementedException();
+ }
+
}
#if nsp
}
diff --git a/docs/Interop.MapWinGIS/Com Classes/Shapefile.cs b/docs/Interop.MapWinGIS/Com Classes/Shapefile.cs
index 45b8856f..9eb741e8 100644
--- a/docs/Interop.MapWinGIS/Com Classes/Shapefile.cs
+++ b/docs/Interop.MapWinGIS/Com Classes/Shapefile.cs
@@ -956,7 +956,8 @@ public bool Snappable
/// \addtogroup shapefile_geoprocessing Shapefile geoprocessing
/// Here is a list of methods to perform geoprocessing tasks using shapefile data.
- /// This module is a part of the documentation of Shapefile class.
+ /// This module is a part of the documentation of Shapefile class.\n\n
+ /// Use GlobalSettings.MinAreaToPerimeterRatio and GlobalSettings.MinPolygonArea to tweak which polygon needs to be included in the output file.
/// \dot
/// digraph shapefile_geoprocessing {
/// splines = true;
@@ -1665,7 +1666,13 @@ public bool RefreshShapeExtents(int ShapeId)
#region Selection
/// \addtogroup shapefile_selection Shapefile selection
/// Here is a list of properties and methods for managing shapefile selection.
- /// This module is a part of the documentation of Shapefile class.
+ /// This module is a part of the documentation of the Shapefile class.
+ ///
+ /// Historically, using the cmSelection and cmSelectByPolygon tools, you would specify a LayerHandle in the ChooseLayer map event
+ /// to indicate which single layer you were selecting shapes from. Starting in v5.0, you can select from multiple layers concurrently
+ /// by setting the 'Selectable' property of each layer you would like to select shapes from. If the LayerHandle returned from the
+ /// ChooseLayer event is left unspecified (-1), then instead, all layers having the 'Selectable' property = TRUE
+ /// will be selectable by the tool.
/// \dot
/// digraph shapefile_selection {
/// splines = true;
@@ -1781,6 +1788,21 @@ public void SelectNone()
throw new NotImplementedException();
}
+ ///
+ /// Gets or sets a value indicating whether this shapefile will be selectable by the cmSelection and cmSelectByPolygon tool.
+ ///
+ ///
+ /// This property allows for multiple shapefiles to be concurrently selectable.
+ /// If only selecting from one layer, you can still use the ChooseLayer map event to specify the selectable layer.
+ ///
+ /// \see AxMap.CursorMode
+ /// \new500 Added in version 5.0.0
+ public bool Selectable
+ {
+ get { throw new NotImplementedException(); }
+ set { throw new NotImplementedException(); }
+ }
+
///
/// Gets or sets the way shapefile selection will be displayed.
///
diff --git a/docs/Interop.MapWinGIS/Com Classes/Utils.cs b/docs/Interop.MapWinGIS/Com Classes/Utils.cs
index 6f1f3c36..39ff9882 100644
--- a/docs/Interop.MapWinGIS/Com Classes/Utils.cs
+++ b/docs/Interop.MapWinGIS/Com Classes/Utils.cs
@@ -872,6 +872,47 @@ public bool GetProjectionList(tkProjectionSet projectionSets, ref Object list)
throw new NotImplementedException();
}
+ ///
+ /// Calculates the angle defined by the two specified coordinates
+ ///
+ ///
+ ///
+ /// Geographic Angle (in degrees) of the vector measured from the first point to the second point
+ ///
+ /// The angle returned is the so-called Geographic angle, measured in a clockwise direction
+ /// from the positive Y-axis, as opposed to the Arithmetic (Cartesian) angle measured in a
+ /// counter-clockwise direction from the positive X-axis. The returned value can be used
+ /// as-is to specify Shape or Label Rotation, which expect the Geographic angle for input.
+ ///
+ /// \see Shapefile.set_ShapeRotation
+ ///
+ /// \new500 Added in version 5.0.0
+ public double GetAngle(Point firstPoint, Point secondPoint)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Return a point at the specified distance (or percentage) along the specified line
+ ///
+ /// Polyline shape to traverse
+ /// Starting point along 'sourceLine' (specify Point[0] for beginning of line)
+ /// Distance along line (or percentage of line length; if a percentage, specify a number between 0.0 and 1.0)
+ /// Optional value; if FALSE, 'distance' is actual distance; if TRUE, distance is percentage of length; defaults to FALSE
+ /// Returns a Point class representing the point along the sourceLine that is the specified distance (or percentage) along the line.
+ ///
+ /// 'sourceLine' must be a Polyline Shape. If 'distance' is greater than the source line length, the line's endpoint is returned.
+ ///
+ /// 'startPoint' does not have to be on 'sourceLine'. If not on the line, actual starting point will be the nearest point to 'startPoint' that is on 'sourceline'.
+ ///
+ /// \see Shape.InterpolatePoint
+ ///
+ /// \new500 Added in version 5.0.0
+ public Point LineInterpolatePoint(Shape sourceLine, Point startPoint, double distance, bool normalized)
+ {
+ throw new NotImplementedException();
+ }
+
}
#if nsp
}
diff --git a/docs/Interop.MapWinGIS/Enumerations/Enumerations.cs b/docs/Interop.MapWinGIS/Enumerations/Enumerations.cs
index af58b1d6..2700f512 100644
--- a/docs/Interop.MapWinGIS/Enumerations/Enumerations.cs
+++ b/docs/Interop.MapWinGIS/Enumerations/Enumerations.cs
@@ -485,7 +485,7 @@ public enum tkDrawReferenceList
///
/// The objects of the drawing layer are specified in screen coordinates and are not moved after the changes of the extents.
///
- /// To update such layers the full redraw is not needed. Therefore use AxMap.Refresh rather than AxMap.Redraw.
+ /// To update such layers the full redraw is not needed. Therefore use AxMap.Redraw2 rather than AxMap.Redraw.
dlScreenReferencedList = 0,
///
@@ -1688,7 +1688,7 @@ public enum tkRedrawType
///
/// Map will be rendered from the main buffer. Only measurements and coordinate display will be rendered anew.
///
- /// Corresponds to AxMap.Refresh/AxMap.Invalidate.
+ /// Corresponds to AxMap.Redraw2/AxMap.Invalidate.
RedrawMinimal = 3,
}
diff --git a/docs/Interop.MapWinGIS/Interop.MapWinGIS.csproj b/docs/Interop.MapWinGIS/Interop.MapWinGIS.csproj
index d0030097..2572bd6a 100644
--- a/docs/Interop.MapWinGIS/Interop.MapWinGIS.csproj
+++ b/docs/Interop.MapWinGIS/Interop.MapWinGIS.csproj
@@ -151,7 +151,6 @@
-
diff --git a/docs/Interop.MapWinGIS/Related Pages/Hints.cs b/docs/Interop.MapWinGIS/Related Pages/Hints.cs
index 424bfbd3..675e7b0f 100644
--- a/docs/Interop.MapWinGIS/Related Pages/Hints.cs
+++ b/docs/Interop.MapWinGIS/Related Pages/Hints.cs
@@ -1,10 +1,10 @@
#pragma warning disable 1587
/// \page hints Hints
///
-/// A. COM objects. \n\n
+/// A. COM objects. \n
/// MapWinGIS is COM-based, therefore it counts the references of particular objects to determine when they are no longer needed and can be released.
/// -# Environments like .NET or VB6 add and release these references automatically. Calling the operations
-/// explicitly (Marshal.AddRef, Marshal.Release for example) in most cases will cause problems and sometimes even crashes.\n\n
+/// explicitly (Marshal.AddRef, Marshal.Release for example) in most cases will cause problems and sometimes even crashes.\n
/// -# In the languages like unmanaged C++ the client is responsible for maintaining the number of reference,
/// so AddRef(), Release() must be called explicitly.\n
/// .
@@ -26,8 +26,8 @@
/// \endcode
/// MapWinGIS objects are not thread-safe. Therefore accessing the same object from several threads should be made with caution especially
/// when the editing takes place.\n
-///
-/// B. Error handling and progress information. \n\n
+/// \n
+/// B. Error handling and progress information. \n
/// By design MapWinGIS doesn't throw exceptions to return the information about errors. If an unhandled exception is still thrown,
/// in the most cases it should be treated as a bug and reported to the Issue tracker.\n
///
@@ -60,7 +60,8 @@
/// // 1. Class.LastErrorCode and Class.get_ErrorMessage properties, which are defined for all major classes.
/// If no error took place within this instance of class "No error" string will be return.
/// Every call of LastErrorCode property will clear the error, i.e. reset it to the "No error" state.
-/// \code Shapefile sf = some_shapefile;
+/// \code
+/// Shapefile sf = some_shapefile;
/// Shape shp = sf.get_Shape(sf.NumShapes); // deliberately faulty line; the last index is NumShapes - 1
/// Debug.Print(sf.get_ErrorMessage(sf.LastErrorCode)); // "Index Out of Bounds" error will be reported
/// Debug.Print(sf.get_ErrorMessage(sf.LastErrorCode)); // "No error" will be reported as the error was cleared by previous call
@@ -87,28 +88,30 @@
/// }
/// }
/// \endcode
-///
-/// C. Map redraw.\n\n
+/// \n
+/// C. Map redraw.\n
/// Map control tracks some of the changes of its properties and data layers and trigger redraws to display them. It's usually applicable
/// to all the AxMap members. But changes to the data layers made through API of other classes (like Shapefile or Image) will not be tracked.
/// Therefore an explicit AxMap.Redraw() call will be needed to display the changes. In general it's a good practice to call redraw explicitly
/// and not to rely on built-in tracking of state change. \n
-/// \code AxMap axMap = map_instance;
+/// \code
+/// AxMap axMap = map_instance;
/// Shapefile sf = some_shapefile;
/// axMap.AddLayer(sf, true); // the map will be updated automatically
/// sf.DefaultDrawingOptions.LineWidth = 3; // the map wasn't be updated
/// axMap.Redraw(); // the thick lines will be shown only here
/// \endcode
-/// AxMap.Refresh rather AxMap.%Redraw should be called when there is need to update only temporary objects on map (so-called "drawing layers")
+/// AxMap.Redraw2 rather AxMap.Redraw should be called when there is need to update only temporary objects on map (so-called "drawing layers")
/// rather then to redraw the whole map. The former operation is fast and can be used for display of objects being dragged atop the map for example.
-/// \code AxMap axMap = map_instance;
-/// int handle = axMap.NewDrawing(tkScreenReferencedList);
+/// \code
+/// AxMap axMap = map_instance;
+/// int handle = axMap.NewDrawing(tkDrawReferenceList.dlScreenReferencedList);
/// axMap.DrawPolygon(arguments);
-/// axMap.Refresh(); // redraw of drawing layer only to see the polygon (fast)
+/// axMap.Redraw2(); // redraw of drawing layer only to see the polygon (fast)
/// axMap.Redraw(); // complete redraw of the map (slow)
/// \endcode
-///
-/// D. Some aspects of interaction with .NET. \n\n
+/// \n
+/// D. Some aspects of interaction with .NET.
/// 1. Interop libraries. In order to use MapWinGIS in .NET environment 2 interop assemblies (wrappers) must be generated: AxInteriop.MapWinGIS.dll
/// and Interop.MapWinGIS dll. Visual Studio generates these assemblies automatically in the process of adding AxMap control on the form. Tlbimp.exe and
/// Aximp.exe command line utilities can be used to do the same tasks manually.\n\n
@@ -129,13 +132,14 @@
/// - to return *any* COM class with IDispath interface (see AxMap.get_GetObject);
/// - to return the array of objects (see Shapefile.SelectShapes);
/// - to get or set the values in the attribute table, which can be of either double, integer or string type (see Table.get_CellValue).
-/// Use the documentation to find out the data type the output values should be cast to on the .NET side.
-/// .
+/// Use the documentation to find out the data type the output values should be cast to on the .NET side. \n
+/// \n
+/// 4. Create registrationless COM manifest file. Registrationless COM lets you use MapWinGIS without it being registered in the registry.
+/// This means it's possible to deploy MapWinGIS along with your own application using plain xcopy semantics.\n
+/// How to generate this manifest?
+/// - In Visual Studio right click on the MapWinGIS reference and select Properties
+/// - Click on the Isolated DropDown and select True
+/// - Compile and that's all there's to it. Visual Studio will create a yourApp.exe.manifest file right alongside your application's EXE.
///
-/// E. MapWindow 4 \n\n
-/// MapWindow 4 is the largest application build upon MapWinGIS (http://www.mapwindow.org).
-/// -# From version 4.8 (May 2011) MapWinGIS can load MapWindow 4 projects using AxMap.LoadMapState call.
-/// It provides the the fastest way to setup the visualization options for the layers and pass them to custom application. \n\n
-/// -# The functionality present in MapWindow can be more or less easily implemented in other custom application based on MapWinGIS.
-/// MapWindow 4 repository is here.
+/// When you copy the MapWinGIS files to your client, don't forget to include all files including the GDAL files and folders.
#pragma warning restore 1587
\ No newline at end of file
diff --git a/docs/MapWinGIS.doxyfile b/docs/MapWinGIS.doxyfile
index c2c3a014..edd04387 100644
--- a/docs/MapWinGIS.doxyfile
+++ b/docs/MapWinGIS.doxyfile
@@ -245,6 +245,7 @@ ALIASES = "new48=\xrefitem newpage48 \"New API 4.8\" \"New API 4.
"new493=\xrefitem newpage493 \"New API 4.9.3\" \"New API 4.9.3\"" \
"new494=\xrefitem newpage494 \"New API 4.9.4\" \"New API 4.9.4\"" \
"new495=\xrefitem newpage495 \"New API 4.9.5\" \"New API 4.9.5\"" \
+ "new500=\xrefitem newpage500 \"New API 5.0.0\" \"New API 5.0.0\"" \
"removed493=\xrefitem removed493 \"Removed in 4.9.3\" \"Removed in 4.9.3\""
# This tag can be used to specify a number of word-keyword mappings (TCL only).
diff --git a/src/COM classes/Expression.cpp b/src/COM classes/Expression.cpp
index 3e50276c..49b3ade0 100644
--- a/src/COM classes/Expression.cpp
+++ b/src/COM classes/Expression.cpp
@@ -37,7 +37,7 @@ STDMETHODIMP CExpression::get_LastErrorMessage(BSTR* pVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *pVal = A2BSTR(_lastErrorMessage);
+ *pVal = W2BSTR(_lastErrorMessage);
return S_OK;
}
@@ -104,7 +104,7 @@ STDMETHODIMP CExpression::Parse(BSTR expr, VARIANT_BOOL* retVal)
Clear();
USES_CONVERSION;
- *retVal = _expression.Parse(OLE2A(expr), true, _lastErrorMessage) ? VARIANT_TRUE : VARIANT_FALSE;
+ *retVal = _expression.Parse(OLE2W(expr), true, _lastErrorMessage) ? VARIANT_TRUE : VARIANT_FALSE;
return S_OK;
}
@@ -131,7 +131,7 @@ STDMETHODIMP CExpression::ParseForTable(BSTR expr, ITable* table, VARIANT_BOOL*
_expression.ReadFieldNames(table);
USES_CONVERSION;
- *retVal = _expression.Parse(OLE2A(expr), true, _lastErrorMessage) ? VARIANT_TRUE : VARIANT_FALSE;
+ *retVal = _expression.Parse(OLE2W(expr), true, _lastErrorMessage) ? VARIANT_TRUE : VARIANT_FALSE;
return S_OK;
}
diff --git a/src/COM classes/Expression.h b/src/COM classes/Expression.h
index 7ebf0ae4..cbabb7d4 100644
--- a/src/COM classes/Expression.h
+++ b/src/COM classes/Expression.h
@@ -65,7 +65,7 @@ class ATL_NO_VTABLE CExpression :
private:
CustomExpression _expression;
- CString _lastErrorMessage;
+ CStringW _lastErrorMessage;
int _lastErrorPosition;
ITable* _table;
diff --git a/src/COM classes/Function.cpp b/src/COM classes/Function.cpp
index 18386df6..8d3fd172 100644
--- a/src/COM classes/Function.cpp
+++ b/src/COM classes/Function.cpp
@@ -29,7 +29,7 @@ STDMETHODIMP CFunction::get_Name(BSTR* pVal)
}
USES_CONVERSION;
- *pVal = A2BSTR(_function->GetName());
+ *pVal = W2BSTR(_function->GetName());
return S_OK;
}
@@ -45,7 +45,7 @@ STDMETHODIMP CFunction::get_Alias(long aliasIndex, BSTR* pVal)
{
aliasIndex++; // the first alias is name
- vector* aliases = _function->getAliases();
+ vector* aliases = _function->getAliases();
if (aliasIndex <= 0 || aliasIndex >= (long)aliases->size())
{
@@ -53,7 +53,7 @@ STDMETHODIMP CFunction::get_Alias(long aliasIndex, BSTR* pVal)
}
else
{
- *pVal = A2BSTR((*aliases)[aliasIndex]);
+ *pVal = W2BSTR((*aliases)[aliasIndex]);
return S_OK;
}
}
@@ -75,7 +75,7 @@ STDMETHODIMP CFunction::get_NumAliases(long* pVal)
return S_OK;
}
- vector* aliases = _function->getAliases();
+ vector* aliases = _function->getAliases();
*pVal = aliases->size() - 1;
diff --git a/src/COM classes/GeoProjection.cpp b/src/COM classes/GeoProjection.cpp
index cad598a5..61841ab2 100644
--- a/src/COM classes/GeoProjection.cpp
+++ b/src/COM classes/GeoProjection.cpp
@@ -940,7 +940,7 @@ bool CGeoProjection::WriteToFileCore(CStringW filename, bool esri)
if (proj.GetLength() != 0)
{
- fprintf(prjFile, "%s", proj);
+ fprintf(prjFile, "%s", (LPCSTR)proj);
}
fclose(prjFile);
@@ -1073,7 +1073,7 @@ STDMETHODIMP CGeoProjection::SetNad83Projection(tkNad83Projection projection)
STDMETHODIMP CGeoProjection::get_HasTransformation(VARIANT_BOOL* retval)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *retval = _transformation != NULL;
+ *retval = (_transformation != NULL) ? VARIANT_TRUE : VARIANT_FALSE;
return S_OK;
}
@@ -1320,8 +1320,10 @@ bool CGeoProjection::ParseLinearUnits(CString s, tkUnitsOfMeasure& units)
{
return false;
}
- else if (s.CompareNoCase("meters") == 0 || s.CompareNoCase("metre") == 0)
- {
+ else if (s.CompareNoCase("meter") == 0 || s.CompareNoCase("metre") == 0 || s.CompareNoCase("meters") == 0 || s.CompareNoCase("metres") == 0)
+ { // jf: based on input on GitHub from ultraTCS, I'm adding the variations of 'meter(s)';
+ // although I do not see any WKT UNIT references being plural 'meters', we had included
+ // that case before, so I am leaving it - (and the 'metres' variation for completeness)
units = umMeters;
return true;
}
diff --git a/src/COM classes/Labels.cpp b/src/COM classes/Labels.cpp
index cd0db04f..b8187157 100644
--- a/src/COM classes/Labels.cpp
+++ b/src/COM classes/Labels.cpp
@@ -980,7 +980,7 @@ void CLabels::ApplyExpression_(long CategoryIndex)
if (parsingIsNeeded)
{
// building list of expressions
- std::vector expressions;
+ std::vector expressions;
for (unsigned int i = 0; i < _categories.size(); i++)
{
if (i == CategoryIndex || CategoryIndex == -1 )
@@ -989,7 +989,7 @@ void CLabels::ApplyExpression_(long CategoryIndex)
if (val->vt != VT_EMPTY && _classificationField != -1)
{
// we analyzed this one before, so just a dummy string here
- CString str = "";
+ CStringW str = L"";
expressions.push_back(str);
}
else
@@ -997,14 +997,14 @@ void CLabels::ApplyExpression_(long CategoryIndex)
CComBSTR expr;
_categories[i]->get_Expression(&expr);
USES_CONVERSION;
- CString str = OLE2CA(expr);
+ CStringW str = OLE2CW(expr);
expressions.push_back(str);
}
}
else
{
// we don't need this categories, so dummy strings for them
- CString str = "";
+ CStringW str = L"";
expressions.push_back(str);
}
}
@@ -1732,7 +1732,7 @@ STDMETHODIMP CLabels::put_Expression(BSTR newVal)
return S_OK;
}
- CString str = OLE2CA(newVal);
+ CStringW str = OLE2CW(newVal);
_labelExpression = str;
if (!_synchronized && _labels.size() > 0)
@@ -1748,7 +1748,7 @@ STDMETHODIMP CLabels::put_Expression(BSTR newVal)
if (table)
{
// analyzes expression
- CString strError;
+ CStringW strError;
std::vector results;
if (TableHelper::Cast(table)->CalculateCore(str, results, strError, floatFormat))
{
@@ -2432,7 +2432,7 @@ STDMETHODIMP CLabels::Generate(BSTR Expression, tkLabelPositioning Method, VARIA
CComPtr table = NULL;
_shapefile->get_Table(&table);
- CString error;
+ CStringW error;
VARIANT_BOOL vbretval;
TableHelper::Cast(table)->ParseExpressionCore(Expression, vtString, error, &vbretval);
diff --git a/src/COM classes/OgrLayer.cpp b/src/COM classes/OgrLayer.cpp
index 4a4d43de..0e6cbe11 100644
--- a/src/COM classes/OgrLayer.cpp
+++ b/src/COM classes/OgrLayer.cpp
@@ -1575,8 +1575,15 @@ STDMETHODIMP COgrLayer::get_AvailableShapeTypes(VARIANT* pVal)
{
vector shapeTypes;
+ // querying the MSSQL datasource for available types doesn't work if
+ // we're looking at a query result set rather than an actual table.
+ // instead, we'll let it fall into the 'else' logic, which iterates the
+ // local layer instead of the database to determine which types are present.
+ CStringW layerName = Utility::ConvertFromUtf8(_layer->GetName());
+
if (m_globalSettings.ogrListAllGeometryTypes &&
- OgrHelper::IsMsSqlDatasource(_dataset))
+ OgrHelper::IsMsSqlDatasource(_dataset) &&
+ (layerName != "SELECT" && layerName != "UPDATE"))
{
GetMsSqlShapeTypes(shapeTypes);
}
@@ -1665,11 +1672,19 @@ STDMETHODIMP COgrLayer::put_ActiveShapeType(ShpfileType newVal)
ShpfileType shpType;
get_ShapeType(&shpType);
+ // SHP_NULLSHAPE indicates multiple shape types
if (shpType == SHP_NULLSHAPE)
{
- _activeShapeType = newVal;
- }
- else
+ // if re-assigning the active type
+ if (_activeShapeType != newVal)
+ {
+ // clear current buffer to force new
+ CloseShapefile();
+ }
+ // assign active type
+ _activeShapeType = newVal;
+ }
+ else
{
CallbackHelper::ErrorMsg("OGR layer has single geometry type. ActiveShapeType provided will be ignored.");
}
diff --git a/src/COM classes/Shape.cpp b/src/COM classes/Shape.cpp
index 84a1d5d4..879dbcba 100644
--- a/src/COM classes/Shape.cpp
+++ b/src/COM classes/Shape.cpp
@@ -716,7 +716,7 @@ STDMETHODIMP CShape::DeletePoint(long PointIndex, VARIANT_BOOL *retval)
STDMETHODIMP CShape::get_XY(long PointIndex, double* x, double* y, VARIANT_BOOL* retval)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
- *retval = get_XY(PointIndex, x, y);
+ *retval = get_XY(PointIndex, x, y) ? VARIANT_TRUE : VARIANT_FALSE;
return S_OK;
}
@@ -726,7 +726,7 @@ STDMETHODIMP CShape::get_XY(long PointIndex, double* x, double* y, VARIANT_BOOL*
STDMETHODIMP CShape::put_XY(LONG pointIndex, double x, double y, VARIANT_BOOL* retVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *retVal = (VARIANT_BOOL)_shp->put_PointXY(pointIndex, x, y);
+ *retVal = _shp->put_PointXY(pointIndex, x, y) ? VARIANT_TRUE : VARIANT_FALSE;
if (*retVal == VARIANT_FALSE)
{
ErrorMessage(_shp->get_LastErrorCode());
@@ -740,7 +740,7 @@ STDMETHODIMP CShape::put_XY(LONG pointIndex, double x, double y, VARIANT_BOOL* r
STDMETHODIMP CShape::put_M(LONG pointIndex, double m, VARIANT_BOOL* retVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *retVal = (VARIANT_BOOL)_shp->put_PointM(pointIndex, m);
+ *retVal = _shp->put_PointM(pointIndex, m) ? VARIANT_TRUE : VARIANT_FALSE;
if (!(*retVal))
{
ErrorMessage(_shp->get_LastErrorCode());
@@ -754,7 +754,7 @@ STDMETHODIMP CShape::put_M(LONG pointIndex, double m, VARIANT_BOOL* retVal)
STDMETHODIMP CShape::put_Z(LONG pointIndex, double z, VARIANT_BOOL* retVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *retVal = (VARIANT_BOOL)_shp->put_PointZ(pointIndex, z);
+ *retVal = _shp->put_PointZ(pointIndex, z) ? VARIANT_TRUE : VARIANT_FALSE;
if (!(*retVal))
{
ErrorMessage(_shp->get_LastErrorCode());
@@ -768,7 +768,7 @@ STDMETHODIMP CShape::put_Z(LONG pointIndex, double z, VARIANT_BOOL* retVal)
STDMETHODIMP CShape::get_Z(long PointIndex, double* z, VARIANT_BOOL* retval)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
- *retval = get_Z(PointIndex, z);
+ *retval = get_Z(PointIndex, z) ? VARIANT_TRUE : VARIANT_FALSE;
return S_OK;
}
@@ -778,7 +778,7 @@ STDMETHODIMP CShape::get_Z(long PointIndex, double* z, VARIANT_BOOL* retval)
STDMETHODIMP CShape::get_M(long PointIndex, double* m, VARIANT_BOOL* retval)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
- *retval = get_M(PointIndex, m);
+ *retval = get_M(PointIndex, m) ? VARIANT_TRUE : VARIANT_FALSE;
return S_OK;
}
@@ -1190,7 +1190,7 @@ STDMETHODIMP CShape::Relates(IShape* Shape, tkSpatialRelation Relation, VARIANT_
case srCrosses: res = oGeom1->Crosses(oGeom2); break;
case srDisjoint: res = oGeom1->Disjoint(oGeom2); break;
case srEquals: res = oGeom1->Equals(oGeom2); break;
- case srIntersects: res = oGeom1->Intersect(oGeom2); break;
+ case srIntersects: res = oGeom1->Intersects(oGeom2); break;
case srOverlaps: res = oGeom1->Overlaps(oGeom2); break;
case srTouches: res = oGeom1->Touches(oGeom2); break;
case srWithin: res = oGeom1->Within(oGeom2); break;
@@ -1261,9 +1261,9 @@ STDMETHODIMP CShape::Within(IShape* Shape, VARIANT_BOOL* retval)
STDMETHODIMP CShape::Clip(IShape* Shape, tkClipOperation Operation, IShape** retval)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *retval = NULL;
+ *retval = nullptr;
- if( Shape == NULL)
+ if( Shape == nullptr)
{
ErrorMessage(tkUNEXPECTED_NULL_PARAMETER);
return S_OK;
@@ -1275,23 +1275,23 @@ STDMETHODIMP CShape::Clip(IShape* Shape, tkClipOperation Operation, IShape** ret
return S_OK;
}
- OGRGeometry* oGeom1 = NULL;
- OGRGeometry* oGeom2 = NULL;
+ OGRGeometry* oGeom1 = nullptr;
+ OGRGeometry* oGeom2 = nullptr;
oGeom1 = OgrConverter::ShapeToGeometry(this);
- if (oGeom1 == NULL)
+ if (oGeom1 == nullptr)
return S_OK;
OGRwkbGeometryType oReturnType = oGeom1->getGeometryType();
oGeom2 = OgrConverter::ShapeToGeometry(Shape);
- if (oGeom2 == NULL)
+ if (oGeom2 == nullptr)
{
OGRGeometryFactory::destroyGeometry(oGeom1);
return S_OK;
}
- OGRGeometry* oGeom3 = NULL;
+ OGRGeometry* oGeom3 = nullptr;
switch (Operation)
{
@@ -1306,7 +1306,7 @@ STDMETHODIMP CShape::Clip(IShape* Shape, tkClipOperation Operation, IShape** ret
oGeom3 = oGeom1->Intersection(oGeom2);
break;
case clSymDifference:
- oGeom3 = oGeom1->SymmetricDifference(oGeom2);
+ oGeom3 = oGeom1->SymDifference(oGeom2);
break;
default:
break;
@@ -2575,8 +2575,9 @@ STDMETHODIMP CShape::ExportToWKT(BSTR * retVal)
geom->exportToWkt(&s);
(*retVal) = A2BSTR(s);
OGRGeometryFactory::destroyGeometry(geom);
- delete[] s;
- }
+ // allocated in GDAL; free using CPLFree
+ CPLFree(s);
+ }
else {
(*retVal) = A2BSTR("");
}
@@ -2868,3 +2869,12 @@ STDMETHODIMP CShape::Clear()
return S_OK;
}
+
+//*****************************************************************
+//* InterpolatePoint()
+//*****************************************************************
+STDMETHODIMP CShape::InterpolatePoint(IPoint* startPoint, double distance, VARIANT_BOOL normalized, IPoint **retVal)
+{
+ // simply call Utility function
+ return GetUtils()->LineInterpolatePoint(this, startPoint, distance, normalized, retVal);
+}
diff --git a/src/COM classes/Shape.h b/src/COM classes/Shape.h
index b3c9d046..d75ba6a6 100644
--- a/src/COM classes/Shape.h
+++ b/src/COM classes/Shape.h
@@ -145,6 +145,7 @@ class ATL_NO_VTABLE CShape :
STDMETHOD(get_IsEmpty)(VARIANT_BOOL* pVal);
STDMETHOD(Clear)();
STDMETHOD(FixUp2)(tkUnitsOfMeasure units, IShape** retVal);
+ STDMETHOD(InterpolatePoint)(IPoint* startPoint, double distance, VARIANT_BOOL normalized, IPoint **retVal);
private:
BSTR _key;
diff --git a/src/COM classes/Shapefile.cpp b/src/COM classes/Shapefile.cpp
index 60365864..5a0969a3 100644
--- a/src/COM classes/Shapefile.cpp
+++ b/src/COM classes/Shapefile.cpp
@@ -15,8 +15,12 @@
//Utah State University and the Idaho National Engineering and Environmental Lab that were released as
//public domain in March 2004.
//********************************************************************************************************
-
-#include "stdafx.h"
+//
+//Contributor(s): (Open source contributors should list themselves and their modifications here).
+// -------------------------------------------------------------------------------------------------------
+// Paul Meems August 2018: Modernized the code as suggested by CLang and ReSharper
+
+#include "StdAfx.h"
#include
#include "Shapefile.h"
#include "Labels.h"
@@ -24,16 +28,13 @@
#include "GeoProjection.h"
#include "Templates.h"
#include
-#include "ShapeValidator.h"
#include "ShapefileCategories.h"
#include "Shape.h"
-#include "UndoList.h"
#include "GeosConverter.h"
#include "ShapefileHelper.h"
#include "LabelsHelper.h"
#include "ShapeStyleHelper.h"
#include "TableClass.h"
-#include "TableHelper.h"
#ifdef _DEBUG
#define new DEBUG_NEW
@@ -42,201 +43,206 @@
#endif
CShapefile::CShapefile()
-{
- _pUnkMarshaler = NULL;
-
- _sortingChanged = true;
- _sortAscending = VARIANT_FALSE;
- _sortField = SysAllocString(L"");
-
- _appendStartShapeCount = -1;
- _appendMode = VARIANT_FALSE;
- _snappable = VARIANT_TRUE;
- _interactiveEditing = VARIANT_FALSE;
- _hotTracking = VARIANT_TRUE;
- _geosGeometriesRead = false;
- _stopExecution = NULL;
-
- _selectionTransparency = 180;
- _selectionAppearance = saSelectionColor;
- _selectionColor = RGB(255, 255, 0);
- _collisionMode = tkCollisionMode::LocalList;
-
- _geometryEngine = m_globalSettings.geometryEngine;
-
- _sourceType = sstUninitialized;
-
- _writing = false;
- _reading = false;
-
- _isEditingShapes = FALSE;
- _fastMode = m_globalSettings.shapefileFastMode ? TRUE : FALSE;
- _minDrawingSize = 1;
- _volatile = false;
+{
+ _pUnkMarshaler = nullptr;
+
+ _sortingChanged = true;
+ _sortAscending = VARIANT_FALSE;
+ _sortField = SysAllocString(L"");
+
+ _appendStartShapeCount = -1;
+ _appendMode = VARIANT_FALSE;
+ _snappable = VARIANT_TRUE;
+ _interactiveEditing = VARIANT_FALSE;
+ _hotTracking = VARIANT_TRUE;
+ _selectable = VARIANT_FALSE;
+ _geosGeometriesRead = false;
+ _stopExecution = nullptr;
+
+ _selectionTransparency = 180;
+ _selectionAppearance = saSelectionColor;
+ _selectionColor = RGB(255, 255, 0);
+ _collisionMode = tkCollisionMode::LocalList;
+
+ _geometryEngine = m_globalSettings.geometryEngine;
+
+ _sourceType = sstUninitialized;
+
+ _writing = false;
+ _reading = false;
+
+ _isEditingShapes = FALSE;
+ _fastMode = m_globalSettings.shapefileFastMode ? TRUE : FALSE;
+ _minDrawingSize = 1;
+ _volatile = false;
_useSpatialIndex = TRUE;
_hasSpatialIndex = FALSE;
_spatialIndexLoaded = FALSE;
- _spatialIndexMaxAreaPercent = 0.5;
- _spatialIndexNodeCapacity = 100;
-
- //Neio 20090721
- _useQTree = VARIANT_FALSE;
- _cacheExtents = FALSE;
- _qtree = NULL;
- _tempTree = NULL;
-
- _shpfile = NULL;
- _shxfile = NULL;
-
- _shpfiletype = SHP_NULLSHAPE;
- _nextShapeHandle = 0;
-
- _minX = 0.0;
- _minY = 0.0;
- _minZ = 0.0;
- _maxX = 0.0;
- _maxY = 0.0;
- _maxZ = 0.0;
- _minM = 0.0;
- _maxM = 0.0;
-
- _key = SysAllocString(L"");
- _expression = SysAllocString(L"");
- _globalCallback = NULL;
- _lastErrorCode = tkNO_ERROR;
- _table = NULL;
-
- // creation of children classes
- _selectDrawOpt = NULL;
- _defaultDrawOpt = NULL;
- _labels = NULL;
- _categories = NULL;
- _charts = NULL;
- _geoProjection = NULL;
-
- ComHelper::CreateInstance(idShapeValidationInfo, (IDispatch**)&_inputValidation);
- ComHelper::CreateInstance(idShapeValidationInfo, (IDispatch**)&_outputValidation);
-
- CoCreateInstance(CLSID_ShapeDrawingOptions,NULL,CLSCTX_INPROC_SERVER,IID_IShapeDrawingOptions,(void**)&_selectDrawOpt);
- CoCreateInstance(CLSID_ShapeDrawingOptions,NULL,CLSCTX_INPROC_SERVER,IID_IShapeDrawingOptions,(void**)&_defaultDrawOpt);
- CoCreateInstance(CLSID_ShapefileCategories,NULL,CLSCTX_INPROC_SERVER,IID_IShapefileCategories,(void**)&_categories);
- CoCreateInstance(CLSID_Labels,NULL,CLSCTX_INPROC_SERVER,IID_ILabels,(void**)&_labels);
- CoCreateInstance(CLSID_Charts,NULL,CLSCTX_INPROC_SERVER,IID_ICharts,(void**)&_charts);
- CoCreateInstance(CLSID_GeoProjection,NULL,CLSCTX_INPROC_SERVER,IID_IGeoProjection,(void**)&_geoProjection);
-
- this->put_ReferenceToLabels();
- this->put_ReferenceToCategories();
- this->put_ReferenceToCharts();
-
- ComHelper::CreateInstance(idUndoList, (IDispatch**)&_undoList);
-
- gReferenceCounter.AddRef(tkInterface::idShapefile);
+ _spatialIndexMaxAreaPercent = 0.5;
+ _spatialIndexNodeCapacity = 100;
+
+ //Neio 20090721
+ _useQTree = VARIANT_FALSE;
+ _cacheExtents = FALSE;
+ _qtree = nullptr;
+ _tempTree = nullptr;
+
+ _shpfile = nullptr;
+ _shxfile = nullptr;
+
+ _shpfiletype = SHP_NULLSHAPE;
+ _nextShapeHandle = 0;
+
+ _minX = 0.0;
+ _minY = 0.0;
+ _minZ = 0.0;
+ _maxX = 0.0;
+ _maxY = 0.0;
+ _maxZ = 0.0;
+ _minM = 0.0;
+ _maxM = 0.0;
+
+ _key = SysAllocString(L"");
+ _expression = SysAllocString(L"");
+ _globalCallback = nullptr;
+ _lastErrorCode = tkNO_ERROR;
+ _table = nullptr;
+
+ // creation of children classes
+ _selectDrawOpt = nullptr;
+ _defaultDrawOpt = nullptr;
+ _labels = nullptr;
+ _categories = nullptr;
+ _charts = nullptr;
+ _geoProjection = nullptr;
+
+ ComHelper::CreateInstance(idShapeValidationInfo, (IDispatch**)&_inputValidation);
+ ComHelper::CreateInstance(idShapeValidationInfo, (IDispatch**)&_outputValidation);
+
+ CoCreateInstance(CLSID_ShapeDrawingOptions, nullptr, CLSCTX_INPROC_SERVER, IID_IShapeDrawingOptions,
+ (void**)&_selectDrawOpt);
+ CoCreateInstance(CLSID_ShapeDrawingOptions, nullptr, CLSCTX_INPROC_SERVER, IID_IShapeDrawingOptions,
+ (void**)&_defaultDrawOpt);
+ CoCreateInstance(CLSID_ShapefileCategories, nullptr, CLSCTX_INPROC_SERVER, IID_IShapefileCategories,
+ (void**)&_categories);
+ CoCreateInstance(CLSID_Labels, nullptr, CLSCTX_INPROC_SERVER, IID_ILabels, (void**)&_labels);
+ CoCreateInstance(CLSID_Charts, nullptr, CLSCTX_INPROC_SERVER, IID_ICharts, (void**)&_charts);
+ CoCreateInstance(CLSID_GeoProjection, nullptr, CLSCTX_INPROC_SERVER, IID_IGeoProjection, (void**)&_geoProjection);
+
+ this->put_ReferenceToLabels();
+ this->put_ReferenceToCategories();
+ this->put_ReferenceToCharts();
+
+ ComHelper::CreateInstance(idUndoList, (IDispatch**)&_undoList);
+
+ gReferenceCounter.AddRef(tkInterface::idShapefile);
}
CShapefile::~CShapefile()
-{
- VARIANT_BOOL vbretval;
- this->Close(&vbretval);
-
- ::SysFreeString(_key);
- ::SysFreeString(_expression);
- ::SysFreeString(_sortField);
-
- if (_selectDrawOpt != NULL)
- _selectDrawOpt->Release();
-
- if (_defaultDrawOpt != NULL)
- _defaultDrawOpt->Release();
-
- if (_labels != NULL)
- {
- put_ReferenceToLabels(true); // labels class maybe referenced by client and won't be deleted as a result
- _labels->Release(); // therefore we must clear the reference to the parent as it will be invalid
- }
-
- if (_categories != NULL)
- {
- put_ReferenceToCategories(true);
- _categories->Release();
- }
-
- if (_charts != NULL)
- {
- put_ReferenceToCharts(true);
- _charts->Release();
- }
-
- if (_stopExecution)
- _stopExecution->Release();
-
- if (_geoProjection)
- _geoProjection->Release();
-
- if (_undoList) {
- _undoList->Release();
- }
- gReferenceCounter.Release(tkInterface::idShapefile);
+{
+ VARIANT_BOOL vbretval;
+ this->CShapefile::Close(&vbretval);
+
+ SysFreeString(_key);
+ SysFreeString(_expression);
+ SysFreeString(_sortField);
+
+ if (_selectDrawOpt != nullptr)
+ _selectDrawOpt->Release();
+
+ if (_defaultDrawOpt != nullptr)
+ _defaultDrawOpt->Release();
+
+ if (_labels != nullptr)
+ {
+ put_ReferenceToLabels(true); // labels class maybe referenced by client and won't be deleted as a result
+ _labels->Release(); // therefore we must clear the reference to the parent as it will be invalid
+ }
+
+ if (_categories != nullptr)
+ {
+ put_ReferenceToCategories(true);
+ _categories->Release();
+ }
+
+ if (_charts != nullptr)
+ {
+ put_ReferenceToCharts(true);
+ _charts->Release();
+ }
+
+ if (_stopExecution)
+ _stopExecution->Release();
+
+ if (_geoProjection)
+ _geoProjection->Release();
+
+ if (_undoList)
+ {
+ _undoList->Release();
+ }
+ gReferenceCounter.Release(tkInterface::idShapefile);
}
std::vector* CShapefile::get_ShapeVector()
{
- return &_shapeData;
+ return &_shapeData;
}
IShapeWrapper* CShapefile::get_ShapeWrapper(int ShapeIndex)
{
- return ((CShape*)_shapeData[ShapeIndex]->shape)->get_ShapeWrapper();
+ return ((CShape*)_shapeData[ShapeIndex]->shape)->get_ShapeWrapper();
}
IShapeData* CShapefile::get_ShapeRenderingData(int ShapeIndex)
{
- return _shapeData[ShapeIndex]->get_RenderingData();
+ return _shapeData[ShapeIndex]->get_RenderingData();
}
void CShapefile::put_ShapeRenderingData(int ShapeIndex, CShapeData* data)
{
- return _shapeData[ShapeIndex]->put_RenderingData(data);
+ return _shapeData[ShapeIndex]->put_RenderingData(data);
}
void CShapefile::SetValidationInfo(IShapeValidationInfo* info, tkShapeValidationType validationType)
{
- ComHelper::SetRef(info,
- (IDispatch**)&(validationType == svtInput ? _inputValidation : _outputValidation), true);
+ ComHelper::SetRef(info,
+ (IDispatch**)&(validationType == svtInput ? _inputValidation : _outputValidation), true);
}
-#pragma region Properties
+#pragma region Properties
// ************************************************************
// get_EditingShapes()
// ************************************************************
-STDMETHODIMP CShapefile::get_EditingShapes(VARIANT_BOOL *pVal)
+STDMETHODIMP CShapefile::get_EditingShapes(VARIANT_BOOL* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- *pVal = _isEditingShapes?VARIANT_TRUE:VARIANT_FALSE;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ *pVal = _isEditingShapes ? VARIANT_TRUE : VARIANT_FALSE;
+ return S_OK;
}
// ************************************************************
// get_LastErrorCode()
// ************************************************************
-STDMETHODIMP CShapefile::get_LastErrorCode(long *pVal)
+STDMETHODIMP CShapefile::get_LastErrorCode(long* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- *pVal = _lastErrorCode;
- _lastErrorCode = tkNO_ERROR;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ *pVal = _lastErrorCode;
+ _lastErrorCode = tkNO_ERROR;
+ return S_OK;
}
// ************************************************************
// get_CdlgFilter()
// ************************************************************
-STDMETHODIMP CShapefile::get_CdlgFilter(BSTR *pVal)
+STDMETHODIMP CShapefile::get_CdlgFilter(BSTR* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- USES_CONVERSION;
- *pVal = A2BSTR("ESRI Shapefiles (*.shp)|*.shp");
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ USES_CONVERSION;
+ *pVal = A2BSTR("ESRI Shapefiles (*.shp)|*.shp");
+ return S_OK;
}
// ************************************************************
@@ -244,11 +250,11 @@ STDMETHODIMP CShapefile::get_CdlgFilter(BSTR *pVal)
// ************************************************************
STDMETHODIMP CShapefile::get_LastInputValidation(IShapeValidationInfo** retVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- if (_inputValidation)
- _inputValidation->AddRef();
- *retVal = _inputValidation;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ if (_inputValidation)
+ _inputValidation->AddRef();
+ *retVal = _inputValidation;
+ return S_OK;
}
// ************************************************************
@@ -256,33 +262,34 @@ STDMETHODIMP CShapefile::get_LastInputValidation(IShapeValidationInfo** retVal)
// ************************************************************
STDMETHODIMP CShapefile::get_LastOutputValidation(IShapeValidationInfo** retVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- if (_outputValidation)
- _outputValidation->AddRef();
- *retVal = _outputValidation;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ if (_outputValidation)
+ _outputValidation->AddRef();
+ *retVal = _outputValidation;
+ return S_OK;
}
// ************************************************************
// get/put_GlobalCallback()
// ************************************************************
-STDMETHODIMP CShapefile::get_GlobalCallback(ICallback **pVal)
+STDMETHODIMP CShapefile::get_GlobalCallback(ICallback** pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
- *pVal = _globalCallback;
- if( _globalCallback != NULL )
- _globalCallback->AddRef();
- return S_OK;
+ *pVal = _globalCallback;
+ if (_globalCallback != nullptr)
+ _globalCallback->AddRef();
+ return S_OK;
}
-STDMETHODIMP CShapefile::put_GlobalCallback(ICallback *newVal)
+
+STDMETHODIMP CShapefile::put_GlobalCallback(ICallback* newVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- ComHelper::SetRef(newVal, (IDispatch**)&_globalCallback);
- if( _table != NULL )
- _table->put_GlobalCallback(newVal);
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ ComHelper::SetRef(newVal, (IDispatch**)&_globalCallback);
+ if (_table != nullptr)
+ _table->put_GlobalCallback(newVal);
- return S_OK;
+ return S_OK;
}
// ************************************************************
@@ -290,142 +297,147 @@ STDMETHODIMP CShapefile::put_GlobalCallback(ICallback *newVal)
// ************************************************************
STDMETHODIMP CShapefile::put_StopExecution(IStopExecution* stopper)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- ComHelper::SetRef((IDispatch*)stopper, (IDispatch**)&_stopExecution, true);
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ ComHelper::SetRef((IDispatch*)stopper, (IDispatch**)&_stopExecution, true);
+ return S_OK;
}
// ************************************************************
// get/put_Key()
// ************************************************************
-STDMETHODIMP CShapefile::get_Key(BSTR *pVal)
+STDMETHODIMP CShapefile::get_Key(BSTR* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- USES_CONVERSION;
- *pVal = OLE2BSTR(_key);
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ USES_CONVERSION;
+ *pVal = OLE2BSTR(_key);
+ return S_OK;
}
+
STDMETHODIMP CShapefile::put_Key(BSTR newVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- ::SysFreeString(_key);
- _key = OLE2BSTR(newVal);
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ SysFreeString(_key);
+ _key = OLE2BSTR(newVal);
+ return S_OK;
}
// ************************************************************
// get/put_VisibilityExpression
// ************************************************************
-STDMETHODIMP CShapefile::get_VisibilityExpression(BSTR *pVal)
+STDMETHODIMP CShapefile::get_VisibilityExpression(BSTR* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- USES_CONVERSION;
- *pVal = OLE2BSTR(_expression);
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ USES_CONVERSION;
+ *pVal = OLE2BSTR(_expression);
+ return S_OK;
}
+
STDMETHODIMP CShapefile::put_VisibilityExpression(BSTR newVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- ::SysFreeString(_expression);
- _expression = OLE2BSTR(newVal);
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ SysFreeString(_expression);
+ _expression = OLE2BSTR(newVal);
+ return S_OK;
}
// ************************************************************
// get/put_Volatile
// ************************************************************
-STDMETHODIMP CShapefile::get_Volatile(VARIANT_BOOL *pVal)
+STDMETHODIMP CShapefile::get_Volatile(VARIANT_BOOL* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- if (_interactiveEditing) {
- *pVal = VARIANT_TRUE;
- }
- else {
- *pVal = _volatile ? VARIANT_TRUE : VARIANT_FALSE;
- }
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ if (_interactiveEditing)
+ {
+ *pVal = VARIANT_TRUE;
+ }
+ else
+ {
+ *pVal = _volatile ? VARIANT_TRUE : VARIANT_FALSE;
+ }
+ return S_OK;
}
+
STDMETHODIMP CShapefile::put_Volatile(VARIANT_BOOL newVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- _volatile = newVal == VARIANT_TRUE;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ _volatile = newVal == VARIANT_TRUE;
+ return S_OK;
}
// *****************************************************************
// get_NumShapes()
// *****************************************************************
-STDMETHODIMP CShapefile::get_NumShapes(long *pVal)
+STDMETHODIMP CShapefile::get_NumShapes(long* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- *pVal = _shapeData.size(); //_numShapes;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ *pVal = _shapeData.size(); //_numShapes;
+ return S_OK;
}
// **************************************************************
// get_NumFields()
// **************************************************************
-STDMETHODIMP CShapefile::get_NumFields(long *pVal)
+STDMETHODIMP CShapefile::get_NumFields(long* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- if( _table != NULL )
- _table->get_NumFields(pVal);
- else
- {
- ErrorMessage(tkFILE_NOT_OPEN);
- *pVal = 0;
- }
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ if (_table != nullptr)
+ _table->get_NumFields(pVal);
+ else
+ {
+ ErrorMessage(tkFILE_NOT_OPEN);
+ *pVal = 0;
+ }
+ return S_OK;
}
// ************************************************************
// get_ShapefileType()
// ************************************************************
-STDMETHODIMP CShapefile::get_ShapefileType(ShpfileType *pVal)
+STDMETHODIMP CShapefile::get_ShapefileType(ShpfileType* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- *pVal = _shpfiletype;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ *pVal = _shpfiletype;
+ return S_OK;
}
// *****************************************************************
// get_ErrorMsg()
// *****************************************************************
-STDMETHODIMP CShapefile::get_ErrorMsg(long ErrorCode, BSTR *pVal)
+STDMETHODIMP CShapefile::get_ErrorMsg(long ErrorCode, BSTR* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- USES_CONVERSION;
- *pVal = A2BSTR(ErrorMsg(ErrorCode));
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ USES_CONVERSION;
+ *pVal = A2BSTR(ErrorMsg(ErrorCode));
+ return S_OK;
}
// *****************************************************************
// get_FileHandle()
// *****************************************************************
-STDMETHODIMP CShapefile::get_FileHandle(long * pVal)
+STDMETHODIMP CShapefile::get_FileHandle(long* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- if( _shpfile != NULL )
- {
- int handle = _fileno(_shpfile);
- *pVal = _dup(handle);
- }
- else
- *pVal = -1;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ if (_shpfile != nullptr)
+ {
+ const int handle = _fileno(_shpfile);
+ *pVal = _dup(handle);
+ }
+ else
+ *pVal = -1;
- return S_OK;
+ return S_OK;
}
// **************************************************************
// get_Filename()
// **************************************************************
-STDMETHODIMP CShapefile::get_Filename(BSTR *pVal)
+STDMETHODIMP CShapefile::get_Filename(BSTR* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
- *pVal = W2BSTR(_shpfileName);
+ *pVal = W2BSTR(_shpfileName);
- return S_OK;
+ return S_OK;
}
// **************************************************************
@@ -433,15 +445,16 @@ STDMETHODIMP CShapefile::get_Filename(BSTR *pVal)
// **************************************************************
void CShapefile::ErrorMessage(long ErrorCode)
{
- _lastErrorCode = ErrorCode;
- CallbackHelper::ErrorMsg("Shapefile", _globalCallback, _key, ErrorMsg(_lastErrorCode));
+ _lastErrorCode = ErrorCode;
+ CallbackHelper::ErrorMsg("Shapefile", _globalCallback, _key, ErrorMsg(_lastErrorCode));
}
+
void CShapefile::ErrorMessage(long ErrorCode, ICallback* cBack)
{
- _lastErrorCode = ErrorCode;
- CallbackHelper::ErrorMsg("Shapefile", _globalCallback, _key, ErrorMsg(_lastErrorCode));
- if (cBack != _globalCallback)
- CallbackHelper::ErrorMsg("Shapefile", cBack, _key, ErrorMsg(_lastErrorCode));
+ _lastErrorCode = ErrorCode;
+ CallbackHelper::ErrorMsg("Shapefile", _globalCallback, _key, ErrorMsg(_lastErrorCode));
+ if (cBack != _globalCallback)
+ CallbackHelper::ErrorMsg("Shapefile", cBack, _key, ErrorMsg(_lastErrorCode));
}
// ************************************************************
@@ -449,15 +462,16 @@ void CShapefile::ErrorMessage(long ErrorCode, ICallback* cBack)
// ************************************************************
STDMETHODIMP CShapefile::get_MinDrawingSize(LONG* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *pVal = _minDrawingSize;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ *pVal = _minDrawingSize;
+ return S_OK;
}
+
STDMETHODIMP CShapefile::put_MinDrawingSize(LONG newVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- _minDrawingSize = newVal;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ _minDrawingSize = newVal;
+ return S_OK;
}
// ************************************************************
@@ -465,9 +479,9 @@ STDMETHODIMP CShapefile::put_MinDrawingSize(LONG newVal)
// ************************************************************
STDMETHODIMP CShapefile::get_SourceType(tkShapefileSourceType* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *pVal = _sourceType;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ *pVal = _sourceType;
+ return S_OK;
}
#pragma endregion
@@ -479,378 +493,377 @@ STDMETHODIMP CShapefile::get_SourceType(tkShapefileSourceType* pVal)
// LoadDataFrom()
// ************************************************************
// Loads shape and DBF data from disk file into in-memory mode
-STDMETHODIMP CShapefile::LoadDataFrom(BSTR ShapefileName, ICallback *cBack, VARIANT_BOOL *retval)
-{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
-
- USES_CONVERSION;
- *retval = VARIANT_FALSE;
- if (_sourceType != sstInMemory)
- {
- ErrorMessage(tkINMEMORY_SHAPEFILE_EXPECTED);
- return S_OK;
- }
-
- if (OpenCore(OLE2CA(ShapefileName), cBack))
- {
- // loading data in-memory
- VARIANT_BOOL vb;
- _isEditingShapes = false;
- StartEditingShapes(VARIANT_TRUE, cBack, &vb);
-
- // this will trigger loading of all DBF values into the memory
- long numFields;
- this->get_NumFields(&numFields);
- if (numFields > 0)
- {
- CComVariant var;
- for(size_t i = 0; i < _shapeData.size(); i++)
- {
- _table->get_CellValue(0, i, &var);
- }
- }
-
- // closing disk file despite the result success or failure
- _shpfileName = "";
- _shxfileName = "";
- _dbffileName = "";
-
- if( _shpfile != NULL)
- fclose(_shpfile);
- _shpfile = NULL;
-
- if( _shxfile != NULL)
- fclose(_shxfile);
- _shxfile = NULL;
-
- if( _table != NULL )
- ((CTableClass*)_table)->CloseUnderlyingFile();
-
- *retval = vb;
- }
- return S_OK;
+STDMETHODIMP CShapefile::LoadDataFrom(BSTR ShapefileName, ICallback* cBack, VARIANT_BOOL* retval)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+
+ USES_CONVERSION;
+ *retval = VARIANT_FALSE;
+ if (_sourceType != sstInMemory)
+ {
+ ErrorMessage(tkINMEMORY_SHAPEFILE_EXPECTED);
+ return S_OK;
+ }
+
+ if (OpenCore(OLE2CA(ShapefileName), cBack))
+ {
+ // loading data in-memory
+ VARIANT_BOOL vb;
+ _isEditingShapes = false;
+ StartEditingShapes(VARIANT_TRUE, cBack, &vb);
+
+ // this will trigger loading of all DBF values into the memory
+ long numFields;
+ this->get_NumFields(&numFields);
+ if (numFields > 0)
+ {
+ CComVariant var;
+ for (size_t i = 0; i < _shapeData.size(); i++)
+ {
+ _table->get_CellValue(0, i, &var);
+ }
+ }
+
+ // closing disk file despite the result success or failure
+ _shpfileName = "";
+ _shxfileName = "";
+ _dbffileName = "";
+
+ if (_shpfile != nullptr)
+ fclose(_shpfile);
+ _shpfile = nullptr;
+
+ if (_shxfile != nullptr)
+ fclose(_shxfile);
+ _shxfile = nullptr;
+
+ if (_table != nullptr)
+ ((CTableClass*)_table)->CloseUnderlyingFile();
+
+ *retval = vb;
+ }
+ return S_OK;
}
// ************************************************************
// OpenCore()
// ************************************************************
-bool CShapefile::OpenCore(CStringW tmp_shpfileName, ICallback* cBack)
-{
- USES_CONVERSION;
- VARIANT_BOOL vbretval;
-
- // saving the provided names;
- // from now on we must clean the class variables in case the operation won't succeed
- _shpfileName = tmp_shpfileName;
- _shxfileName = tmp_shpfileName.Left(tmp_shpfileName.GetLength() - 3) + L"shx";
- _dbffileName = tmp_shpfileName.Left(tmp_shpfileName.GetLength() - 3) + L"dbf";
- _prjfileName = tmp_shpfileName.Left(tmp_shpfileName.GetLength() - 3) + L"prj";
-
- // read mode
- _shpfile = _wfopen( _shpfileName, L"rb");
- _shxfile = _wfopen(_shxfileName,L"rb");
-
- // opening DBF
- if (!_table)
- {
- CoCreateInstance(CLSID_Table,NULL,CLSCTX_INPROC_SERVER,IID_ITable,(void**)&_table);
- }
- else
- {
- VARIANT_BOOL vb;
- _table->Close(&vb);
- }
-
- _table->put_GlobalCallback(_globalCallback);
- ((CTableClass*)_table)->InjectShapefile(this);
-
- CComBSTR bstrDbf(_dbffileName);
- _table->Open(bstrDbf, cBack, &vbretval);
-
- if( _shpfile == NULL )
- {
- ErrorMessage(tkCANT_OPEN_SHP);
- this->Close(&vbretval);
- }
- else if( _shxfile == NULL )
- {
- ErrorMessage(tkCANT_OPEN_SHX);
- this->Close(&vbretval);
- }
- else if( vbretval == VARIANT_FALSE )
- {
- _table->get_LastErrorCode(&_lastErrorCode);
- ErrorMessage(_lastErrorCode);
- this->Close(&vbretval);
- }
- else
- {
- if( !ReadShx()) // shapefile header is read here as well
- {
- ErrorMessage(tkINVALID_SHX_FILE);
- this->Close(&vbretval);
- }
- else
- {
- //Check for supported types
- if( _shpfiletype != SHP_NULLSHAPE &&
- _shpfiletype != SHP_POINT &&
- _shpfiletype != SHP_POLYLINE &&
- _shpfiletype != SHP_POLYGON &&
- _shpfiletype != SHP_POINTZ &&
- _shpfiletype != SHP_POLYLINEZ &&
- _shpfiletype != SHP_POLYGONZ &&
- _shpfiletype != SHP_MULTIPOINT &&
- _shpfiletype != SHP_MULTIPOINTZ &&
- _shpfiletype != SHP_POLYLINEM &&
- _shpfiletype != SHP_POLYGONM &&
- _shpfiletype != SHP_POINTM &&
- _shpfiletype != SHP_MULTIPOINTM )
- {
- ErrorMessage(tkUNSUPPORTED_SHAPEFILE_TYPE);
- this->Close(&vbretval);
- }
- else
- {
- _shapeData.reserve(_shpOffsets.size());
- for (size_t i = 0; i < _shpOffsets.size(); i++)
- {
- _shapeData.push_back(new ShapeRecord());
- }
- return true;
- }
- }
- }
- return false;
+bool CShapefile::OpenCore(CStringW tmpShpfileName, ICallback* cBack)
+{
+ USES_CONVERSION;
+ VARIANT_BOOL vbretval;
+
+ // saving the provided names;
+ // from now on we must clean the class variables in case the operation won't succeed
+ _shpfileName = tmpShpfileName;
+ _shxfileName = tmpShpfileName.Left(tmpShpfileName.GetLength() - 3) + L"shx";
+ _dbffileName = tmpShpfileName.Left(tmpShpfileName.GetLength() - 3) + L"dbf";
+ _prjfileName = tmpShpfileName.Left(tmpShpfileName.GetLength() - 3) + L"prj";
+
+ // read mode
+ _shpfile = _wfopen(_shpfileName, L"rb");
+ _shxfile = _wfopen(_shxfileName, L"rb");
+
+ // opening DBF
+ if (!_table)
+ {
+ CoCreateInstance(CLSID_Table, nullptr, CLSCTX_INPROC_SERVER, IID_ITable, (void**)&_table);
+ }
+ else
+ {
+ VARIANT_BOOL vb;
+ _table->Close(&vb);
+ }
+
+ _table->put_GlobalCallback(_globalCallback);
+ ((CTableClass*)_table)->InjectShapefile(this);
+
+ const CComBSTR bstrDbf(_dbffileName);
+ _table->Open(bstrDbf, cBack, &vbretval);
+
+ if (_shpfile == nullptr)
+ {
+ ErrorMessage(tkCANT_OPEN_SHP);
+ this->Close(&vbretval);
+ }
+ else if (_shxfile == nullptr)
+ {
+ ErrorMessage(tkCANT_OPEN_SHX);
+ this->Close(&vbretval);
+ }
+ else if (vbretval == VARIANT_FALSE)
+ {
+ _table->get_LastErrorCode(&_lastErrorCode);
+ ErrorMessage(_lastErrorCode);
+ this->Close(&vbretval);
+ }
+ else
+ {
+ if (!ReadShx()) // shapefile header is read here as well
+ {
+ ErrorMessage(tkINVALID_SHX_FILE);
+ this->Close(&vbretval);
+ }
+ else
+ {
+ //Check for supported types
+ if (_shpfiletype != SHP_NULLSHAPE &&
+ _shpfiletype != SHP_POINT &&
+ _shpfiletype != SHP_POLYLINE &&
+ _shpfiletype != SHP_POLYGON &&
+ _shpfiletype != SHP_POINTZ &&
+ _shpfiletype != SHP_POLYLINEZ &&
+ _shpfiletype != SHP_POLYGONZ &&
+ _shpfiletype != SHP_MULTIPOINT &&
+ _shpfiletype != SHP_MULTIPOINTZ &&
+ _shpfiletype != SHP_POLYLINEM &&
+ _shpfiletype != SHP_POLYGONM &&
+ _shpfiletype != SHP_POINTM &&
+ _shpfiletype != SHP_MULTIPOINTM)
+ {
+ ErrorMessage(tkUNSUPPORTED_SHAPEFILE_TYPE);
+ this->Close(&vbretval);
+ }
+ else
+ {
+ _shapeData.reserve(_shpOffsets.size());
+ for (size_t i = 0; i < _shpOffsets.size(); i++)
+ {
+ _shapeData.push_back(new ShapeRecord());
+ }
+ return true;
+ }
+ }
+ }
+ return false;
}
// ************************************************************
// Open()
// ************************************************************
-STDMETHODIMP CShapefile::Open(BSTR ShapefileName, ICallback *cBack, VARIANT_BOOL *retval)
-{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- *retval = VARIANT_FALSE;
- VARIANT_BOOL vbretval;
-
- if(_globalCallback == NULL && cBack !=NULL)
- {
- _globalCallback = cBack;
- _globalCallback->AddRef();
- }
-
- USES_CONVERSION;
- CStringW tmp_shpfileName = OLE2CW(ShapefileName);
-
- if (tmp_shpfileName.GetLength() == 0)
- {
- // better to use CreateNew directly, but this call will be preserved for backward compatibility
- this->CreateNew(m_globalSettings.emptyBstr, _shpfiletype, &vbretval);
- }
- else if( tmp_shpfileName.GetLength() <= 3 )
- {
- ErrorMessage(tkINVALID_FILENAME);
- }
- else
- {
- // close the opened shapefile
- this->Close(&vbretval);
-
- if( vbretval == VARIANT_FALSE )
- {
- // error code in the function
- return S_OK;
- }
-
- if (OpenCore(tmp_shpfileName, cBack))
- {
- _sourceType = sstDiskBased;
-
- // reading projection
- CComBSTR bstrPrj(_prjfileName);
- _geoProjection->ReadFromFileEx(bstrPrj, VARIANT_TRUE, &vbretval);
-
- ShapeStyleHelper::ApplyRandomDrawingOptions(this);
- LabelsHelper::UpdateLabelsPositioning(this);
- *retval = VARIANT_TRUE;
- }
- }
- return S_OK;
+STDMETHODIMP CShapefile::Open(BSTR ShapefileName, ICallback* cBack, VARIANT_BOOL* retval)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ *retval = VARIANT_FALSE;
+ VARIANT_BOOL vbretval;
+
+ if (_globalCallback == nullptr && cBack != nullptr)
+ {
+ _globalCallback = cBack;
+ _globalCallback->AddRef();
+ }
+
+ USES_CONVERSION;
+ CStringW tmp_shpfileName = OLE2CW(ShapefileName);
+
+ if (tmp_shpfileName.GetLength() == 0)
+ {
+ // better to use CreateNew directly, but this call will be preserved for backward compatibility
+ this->CreateNew(m_globalSettings.emptyBstr, _shpfiletype, &vbretval);
+ }
+ else if (tmp_shpfileName.GetLength() <= 3)
+ {
+ ErrorMessage(tkINVALID_FILENAME);
+ }
+ else
+ {
+ // close the opened shapefile
+ this->Close(&vbretval);
+
+ if (vbretval == VARIANT_FALSE)
+ {
+ // error code in the function
+ return S_OK;
+ }
+
+ if (OpenCore(tmp_shpfileName, cBack))
+ {
+ _sourceType = sstDiskBased;
+
+ // reading projection
+ const CComBSTR bstrPrj(_prjfileName);
+ _geoProjection->ReadFromFileEx(bstrPrj, VARIANT_TRUE, &vbretval);
+
+ ShapeStyleHelper::ApplyRandomDrawingOptions(this);
+ LabelsHelper::UpdateLabelsPositioning(this);
+ *retval = VARIANT_TRUE;
+ }
+ }
+ return S_OK;
}
// *********************************************************
// CreateNew()
// *********************************************************
-STDMETHODIMP CShapefile::CreateNew(BSTR ShapefileName, ShpfileType ShapefileType, VARIANT_BOOL *retval)
+STDMETHODIMP CShapefile::CreateNew(BSTR ShapefileName, ShpfileType ShapefileType, VARIANT_BOOL* retval)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- return this->CreateNewCore(ShapefileName, ShapefileType, true, retval);
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ return this->CreateNewCore(ShapefileName, ShapefileType, true, retval);
}
// *********************************************************
// CreateNewCore()
// *********************************************************
-HRESULT CShapefile::CreateNewCore(BSTR ShapefileName, ShpfileType ShapefileType, bool applyRandomOptions, VARIANT_BOOL *retval)
-{
- *retval = VARIANT_FALSE;
- VARIANT_BOOL vb;
-
- // check for supported types
- if( ShapefileType != SHP_NULLSHAPE &&
- ShapefileType != SHP_POINT &&
- ShapefileType != SHP_POLYLINE &&
- ShapefileType != SHP_POLYGON &&
- ShapefileType != SHP_POINTZ &&
- ShapefileType != SHP_POLYLINEZ &&
- ShapefileType != SHP_POLYGONZ &&
- ShapefileType != SHP_MULTIPOINT &&
- ShapefileType != SHP_MULTIPOINTZ &&
- ShapefileType != SHP_POINTM && // MWGIS-69
- ShapefileType != SHP_POLYLINEM &&
- ShapefileType != SHP_POLYGONM &&
- ShapefileType != SHP_MULTIPOINTM )
- {
- ErrorMessage(tkUNSUPPORTED_SHAPEFILE_TYPE);
- return S_OK;
- }
-
- USES_CONVERSION;
- CString tmp_shpfileName = OLE2CA(ShapefileName);
-
- // ----------------------------------------------
- // in memory shapefile (without name)
- // ----------------------------------------------
- if (tmp_shpfileName.GetLength() == 0)
- {
- // closing the old shapefile (error code inside the function)
- Close(&vb);
-
- if( vb == VARIANT_TRUE )
- {
- CoCreateInstance(CLSID_Table,NULL,CLSCTX_INPROC_SERVER,IID_ITable,(void**)&_table);
-
- _table->CreateNew(m_globalSettings.emptyBstr, &vb);
-
- if (!vb)
- {
- long error;
- _table->get_LastErrorCode(&error);
- ErrorMessage(error);
- _table->Release();
- _table = NULL;
- }
- else
- {
- _shpfiletype = ShapefileType;
- _isEditingShapes = true;
- _sourceType = sstInMemory;
-
- if (applyRandomOptions) {
- ShapeStyleHelper::ApplyRandomDrawingOptions(this);
- }
-
- *retval = VARIANT_TRUE;
- }
- }
-
- return S_OK;
- }
-
- if (tmp_shpfileName.GetLength() <= 3)
- {
- ErrorMessage(tkINVALID_FILENAME);
- return S_OK;
- }
-
- // ----------------------------------------------
- // in memory shapefile (name specified, is acceptable and available)
- // ----------------------------------------------
- CString shpName, shxName, dbfName, prjName;
- shpName = tmp_shpfileName;
- shxName = tmp_shpfileName.Left(tmp_shpfileName.GetLength() - 3) + "shx";
- dbfName = tmp_shpfileName.Left(tmp_shpfileName.GetLength() - 3) + "dbf";
- prjName = tmp_shpfileName.Left(tmp_shpfileName.GetLength() - 3) + "prj";
-
- // new file is created, so there must not be any files with this names
- if( Utility::FileExists(shpName) != FALSE )
- {
- ErrorMessage(tkSHP_FILE_EXISTS);
- return S_OK;
- }
- if( Utility::FileExists(shxName) != FALSE )
- {
- ErrorMessage(tkSHX_FILE_EXISTS);
- return S_OK;
- }
- if( Utility::FileExists(dbfName) != FALSE )
- {
- ErrorMessage(tkDBF_FILE_EXISTS);
- return S_OK;
- }
- if( Utility::FileExists(prjName) != FALSE )
- {
- ErrorMessage(tkPRJ_FILE_EXISTS);
- return S_OK;
- }
-
- // closing the old shapefile (error code inside the function)
- this->Close(&vb);
-
- if( vb == VARIANT_TRUE )
- {
- CoCreateInstance(CLSID_Table,NULL,CLSCTX_INPROC_SERVER,IID_ITable,(void**)&_table);
-
- _table->put_GlobalCallback(_globalCallback);
-
- CString newDbfName = tmp_shpfileName.Left(tmp_shpfileName.GetLength() - 3) + "dbf";
- CComBSTR bstrName(newDbfName);
- _table->CreateNew(bstrName, &vb);
-
- if (!vb)
- {
- _table->get_LastErrorCode(&_lastErrorCode);
- ErrorMessage(_lastErrorCode);
- _table->Release();
- _table = NULL;
- }
- else
- {
- _shpfileName = tmp_shpfileName;
- _shxfileName = tmp_shpfileName.Left(tmp_shpfileName.GetLength() - 3) + "shx";
- _dbffileName = tmp_shpfileName.Left(tmp_shpfileName.GetLength() - 3) + "dbf";
- _prjfileName = tmp_shpfileName.Left(tmp_shpfileName.GetLength() - 3) + "prj";
-
- _shpfiletype = ShapefileType;
- _isEditingShapes = true;
- _sourceType = sstInMemory;
-
- if (applyRandomOptions) {
- ShapeStyleHelper::ApplyRandomDrawingOptions(this);
- }
-
- *retval = VARIANT_TRUE;
- }
- }
-
- LabelsHelper::UpdateLabelsPositioning(this);
-
- return S_OK;
+HRESULT CShapefile::CreateNewCore(BSTR ShapefileName, ShpfileType ShapefileType, bool applyRandomOptions,
+ VARIANT_BOOL* retval)
+{
+ *retval = VARIANT_FALSE;
+ VARIANT_BOOL vb;
+
+ // check for supported types
+ if (ShapefileType != SHP_NULLSHAPE &&
+ ShapefileType != SHP_POINT &&
+ ShapefileType != SHP_POLYLINE &&
+ ShapefileType != SHP_POLYGON &&
+ ShapefileType != SHP_POINTZ &&
+ ShapefileType != SHP_POLYLINEZ &&
+ ShapefileType != SHP_POLYGONZ &&
+ ShapefileType != SHP_MULTIPOINT &&
+ ShapefileType != SHP_MULTIPOINTZ &&
+ ShapefileType != SHP_POINTM && // MWGIS-69
+ ShapefileType != SHP_POLYLINEM &&
+ ShapefileType != SHP_POLYGONM &&
+ ShapefileType != SHP_MULTIPOINTM)
+ {
+ ErrorMessage(tkUNSUPPORTED_SHAPEFILE_TYPE);
+ return S_OK;
+ }
+
+ USES_CONVERSION;
+ CString tmp_shpfileName = OLE2CA(ShapefileName);
+
+ // ----------------------------------------------
+ // in memory shapefile (without name)
+ // ----------------------------------------------
+ if (tmp_shpfileName.GetLength() == 0)
+ {
+ // closing the old shapefile (error code inside the function)
+ Close(&vb);
+
+ if (vb == VARIANT_TRUE)
+ {
+ CoCreateInstance(CLSID_Table, nullptr, CLSCTX_INPROC_SERVER, IID_ITable, (void**)&_table);
+
+ _table->CreateNew(m_globalSettings.emptyBstr, &vb);
+
+ if (!vb)
+ {
+ long error;
+ _table->get_LastErrorCode(&error);
+ ErrorMessage(error);
+ _table->Release();
+ _table = nullptr;
+ }
+ else
+ {
+ _shpfiletype = ShapefileType;
+ _isEditingShapes = true;
+ _sourceType = sstInMemory;
+
+ if (applyRandomOptions)
+ {
+ ShapeStyleHelper::ApplyRandomDrawingOptions(this);
+ }
+
+ *retval = VARIANT_TRUE;
+ }
+ }
+
+ return S_OK;
+ }
+
+ if (tmp_shpfileName.GetLength() <= 3)
+ {
+ ErrorMessage(tkINVALID_FILENAME);
+ return S_OK;
+ }
+
+ const CString& shpName = tmp_shpfileName;
+ const CString shxName = tmp_shpfileName.Left(tmp_shpfileName.GetLength() - 3) + "shx";
+ const CString dbfName = tmp_shpfileName.Left(tmp_shpfileName.GetLength() - 3) + "dbf";
+ const CString prjName = tmp_shpfileName.Left(tmp_shpfileName.GetLength() - 3) + "prj";
+
+ // new file is created, so there must not be any files with this names
+ if (Utility::FileExists(shpName) != FALSE)
+ {
+ ErrorMessage(tkSHP_FILE_EXISTS);
+ return S_OK;
+ }
+ if (Utility::FileExists(shxName) != FALSE)
+ {
+ ErrorMessage(tkSHX_FILE_EXISTS);
+ return S_OK;
+ }
+ if (Utility::FileExists(dbfName) != FALSE)
+ {
+ ErrorMessage(tkDBF_FILE_EXISTS);
+ return S_OK;
+ }
+ if (Utility::FileExists(prjName) != FALSE)
+ {
+ ErrorMessage(tkPRJ_FILE_EXISTS);
+ return S_OK;
+ }
+
+ // closing the old shapefile (error code inside the function)
+ this->Close(&vb);
+
+ if (vb == VARIANT_TRUE)
+ {
+ CoCreateInstance(CLSID_Table, nullptr, CLSCTX_INPROC_SERVER, IID_ITable, (void**)&_table);
+
+ _table->put_GlobalCallback(_globalCallback);
+
+ const CString newDbfName = tmp_shpfileName.Left(tmp_shpfileName.GetLength() - 3) + "dbf";
+ const CComBSTR bstrName(newDbfName);
+ _table->CreateNew(bstrName, &vb);
+
+ if (!vb)
+ {
+ _table->get_LastErrorCode(&_lastErrorCode);
+ ErrorMessage(_lastErrorCode);
+ _table->Release();
+ _table = nullptr;
+ }
+ else
+ {
+ _shpfileName = tmp_shpfileName;
+ _shxfileName = tmp_shpfileName.Left(tmp_shpfileName.GetLength() - 3) + "shx";
+ _dbffileName = tmp_shpfileName.Left(tmp_shpfileName.GetLength() - 3) + "dbf";
+ _prjfileName = tmp_shpfileName.Left(tmp_shpfileName.GetLength() - 3) + "prj";
+
+ _shpfiletype = ShapefileType;
+ _isEditingShapes = true;
+ _sourceType = sstInMemory;
+
+ if (applyRandomOptions)
+ {
+ ShapeStyleHelper::ApplyRandomDrawingOptions(this);
+ }
+
+ *retval = VARIANT_TRUE;
+ }
+ }
+
+ LabelsHelper::UpdateLabelsPositioning(this);
+
+ return S_OK;
}
// *********************************************************
// CreateNewWithShapeID()
// *********************************************************
-STDMETHODIMP CShapefile::CreateNewWithShapeID(BSTR ShapefileName, ShpfileType ShapefileType, VARIANT_BOOL *retval)
+STDMETHODIMP CShapefile::CreateNewWithShapeID(BSTR ShapefileName, ShpfileType ShapefileType, VARIANT_BOOL* retval)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- USES_CONVERSION;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ USES_CONVERSION;
- CreateNew(ShapefileName, ShapefileType, retval);
-
- if (*retval)
- ShapefileHelper::InsertMwShapeIdField(this);
+ CreateNew(ShapefileName, ShapefileType, retval);
- return S_OK;
+ if (*retval)
+ ShapefileHelper::InsertMwShapeIdField(this);
+
+ return S_OK;
}
#pragma endregion
@@ -859,544 +872,547 @@ STDMETHODIMP CShapefile::CreateNewWithShapeID(BSTR ShapefileName, ShpfileType Sh
// *****************************************************************
// Close()
// *****************************************************************
-STDMETHODIMP CShapefile::Close(VARIANT_BOOL *retval)
-{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
-
- if (_appendMode) {
- StopAppendMode();
- }
-
- ClearCachedGeometries();
-
- if( _isEditingShapes )
- {
- // just stop editing shapes, if the shape is in open status
- this->StopEditingShapes(VARIANT_FALSE, VARIANT_TRUE, NULL, retval);
- }
-
- // stop editing table in case only it have been edited
- VARIANT_BOOL isEditingTable = VARIANT_FALSE;
- if( _table )
- {
- _table->get_EditingTable(&isEditingTable);
- if (isEditingTable)
- {
- this->StopEditingTable(VARIANT_FALSE,_globalCallback,retval);
- _table->get_EditingTable(&isEditingTable);
- }
- }
-
- // removing shape data
- this->ReleaseMemoryShapes();
- for (unsigned int i = 0; i < _shapeData.size(); i++)
- {
- delete _shapeData[i];
- }
- _shapeData.clear();
-
- if (_spatialIndexLoaded)
- IndexSearching::unloadSpatialIndex(_spatialIndexID);
-
- _sourceType = sstUninitialized;
- _shpfiletype = SHP_NULLSHAPE;
- LabelsHelper::UpdateLabelsPositioning(this);
-
- _shpfileName = "";
- _shxfileName = "";
- _dbffileName = "";
-
- _minX = 0.0;
- _minY = 0.0;
- _minZ = 0.0;
- _maxX = 0.0;
- _maxY = 0.0;
- _maxZ = 0.0;
- _minM = 0.0;
- _maxM = 0.0;
-
- if (_inputValidation != NULL)
- {
- _inputValidation->Release();
- _inputValidation = NULL;
- }
-
- if (_outputValidation != NULL)
- {
- _outputValidation->Release();
- _outputValidation = NULL;
- }
-
- if( _shpfile != NULL) fclose(_shpfile);
- _shpfile = NULL;
-
- if( _shxfile != NULL) fclose(_shxfile);
- _shxfile = NULL;
-
- if( _table != NULL )
- {
- VARIANT_BOOL vbretval;
- _table->Close(&vbretval);
- _table->Release();
- _table = NULL;
- }
- if (_labels)
- {
- _labels->Clear();
- _labels->ClearCategories();
- }
- if (_charts)
- {
- _charts->Clear();
- }
- if (_categories)
- {
- _categories->Clear();
- }
- *retval = VARIANT_TRUE;
-
- return S_OK;
+STDMETHODIMP CShapefile::Close(VARIANT_BOOL* retval)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+
+ if (_appendMode)
+ {
+ StopAppendMode();
+ }
+
+ ClearCachedGeometries();
+
+ if (_isEditingShapes)
+ {
+ // just stop editing shapes, if the shape is in open status
+ this->StopEditingShapes(VARIANT_FALSE, VARIANT_TRUE, nullptr, retval);
+ }
+
+ // stop editing table in case only it have been edited
+ VARIANT_BOOL isEditingTable = VARIANT_FALSE;
+ if (_table)
+ {
+ _table->get_EditingTable(&isEditingTable);
+ if (isEditingTable)
+ {
+ this->StopEditingTable(VARIANT_FALSE, _globalCallback, retval);
+ _table->get_EditingTable(&isEditingTable);
+ }
+ }
+
+ // removing shape data
+ this->ReleaseMemoryShapes();
+ for (auto& i : _shapeData)
+ {
+ delete i;
+ }
+ _shapeData.clear();
+
+ if (_spatialIndexLoaded)
+ IndexSearching::unloadSpatialIndex(_spatialIndexID);
+
+ _sourceType = sstUninitialized;
+ _shpfiletype = SHP_NULLSHAPE;
+ LabelsHelper::UpdateLabelsPositioning(this);
+
+ _shpfileName = "";
+ _shxfileName = "";
+ _dbffileName = "";
+
+ _minX = 0.0;
+ _minY = 0.0;
+ _minZ = 0.0;
+ _maxX = 0.0;
+ _maxY = 0.0;
+ _maxZ = 0.0;
+ _minM = 0.0;
+ _maxM = 0.0;
+
+ if (_inputValidation != nullptr)
+ {
+ _inputValidation->Release();
+ _inputValidation = nullptr;
+ }
+
+ if (_outputValidation != nullptr)
+ {
+ _outputValidation->Release();
+ _outputValidation = nullptr;
+ }
+
+ if (_shpfile != nullptr) fclose(_shpfile);
+ _shpfile = nullptr;
+
+ if (_shxfile != nullptr) fclose(_shxfile);
+ _shxfile = nullptr;
+
+ if (_table != nullptr)
+ {
+ VARIANT_BOOL vbretval;
+ _table->Close(&vbretval);
+ _table->Release();
+ _table = nullptr;
+ }
+ if (_labels)
+ {
+ _labels->Clear();
+ _labels->ClearCategories();
+ }
+ if (_charts)
+ {
+ _charts->Clear();
+ }
+ if (_categories)
+ {
+ _categories->Clear();
+ }
+ *retval = VARIANT_TRUE;
+
+ return S_OK;
}
// **********************************************************
// Dump()
// **********************************************************
//Saves shapefile without reopening it in a new location
-STDMETHODIMP CShapefile::Dump(BSTR ShapefileName, ICallback *cBack, VARIANT_BOOL *retval)
-{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- *retval = VARIANT_FALSE;
-
- bool callbackIsNull = (_globalCallback == NULL);
- if(_globalCallback == NULL && cBack != NULL)
- {
- _globalCallback = cBack;
- _globalCallback->AddRef();
- }
-
- if (_table == NULL || _sourceType == sstUninitialized)
- {
- ErrorMessage(tkSHAPEFILE_UNINITIALIZED);
- return S_OK;
- }
-
- // in case someone else is writing, we leave
- if (_writing)
- {
- ErrorMessage(tkSHP_WRITE_VIOLATION);
- return S_OK;
- }
-
- if (!this->ValidateOutput(this, "Dump", "Shapefile", false))
- return S_OK;
-
- USES_CONVERSION;
- CString sa_shpfileName;
- sa_shpfileName = OLE2CA(ShapefileName);
-
- if( sa_shpfileName.GetLength() <= 3 )
- {
- ErrorMessage(tkINVALID_FILENAME);
- }
- else
- {
- CString sa_shxfileName = sa_shpfileName.Left(sa_shpfileName.GetLength() - 3) + "shx";
- CString sa_dbffileName = sa_shpfileName.Left(sa_shpfileName.GetLength() - 3) + "dbf";
-
- // -----------------------------------------------
- // it's not allowed to rewrite the existing files
- // -----------------------------------------------
- if( Utility::FileExists(sa_shpfileName) )
- {
- ErrorMessage(tkSHP_FILE_EXISTS);
- return S_OK;
- }
- if( Utility::FileExists(sa_shxfileName) )
- {
- ErrorMessage(tkSHX_FILE_EXISTS);
- return S_OK;
- }
- if( Utility::FileExists(sa_dbffileName) )
- {
- ErrorMessage(tkDBF_FILE_EXISTS);
- return S_OK;
- }
-
- // -----------------------------------------------
- // checking in-memory shapes
- // -----------------------------------------------
- if( _isEditingShapes )
- {
- if( VerifyMemShapes(cBack) == FALSE )
- {
- // error Code is set in function
- return S_OK;
- }
-
- // refresh extents
- VARIANT_BOOL retVal;
- this->RefreshExtents(&retVal);
- }
-
- // -----------------------------------------------
- // opening files
- // -----------------------------------------------
- FILE * shpfile = fopen( sa_shpfileName, "wb+" );
- if( shpfile == NULL )
- {
- ErrorMessage(tkCANT_CREATE_SHP);
- return S_OK;
- }
-
- //shx
- FILE * shxfile = fopen( sa_shxfileName, "wb+" );
- if( shxfile == NULL )
- {
- fclose( shpfile );
- ErrorMessage(tkCANT_CREATE_SHX);
- return S_OK;
- }
-
- // ------------------------------------------------
- // writing the files
- // ------------------------------------------------
- this->WriteShp(shpfile,cBack);
- this->WriteShx(shxfile,cBack);
-
- fclose(shpfile);
- fclose(shxfile);
-
- // ------------------------------------------------
- // saving dbf table
- // ------------------------------------------------
- _table->Dump(sa_dbffileName.AllocSysString(), cBack, retval);
- if( *retval == FALSE )
- {
- _table->get_LastErrorCode(&_lastErrorCode);
- return S_OK;
- }
-
- // saving projection in new format
- VARIANT_BOOL vbretval;
- CStringW prjfileName = sa_shpfileName.Left(sa_shpfileName.GetLength() - 3) + L"prj";
- CComBSTR bstr(prjfileName);
- _geoProjection->WriteToFileEx(bstr, VARIANT_TRUE, &vbretval);
-
- *retval = VARIANT_TRUE;
- }
-
- // restoring callback
- if (callbackIsNull) {
- _globalCallback = NULL;
- }
-
- return S_OK;
+STDMETHODIMP CShapefile::Dump(BSTR ShapefileName, ICallback* cBack, VARIANT_BOOL* retval)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ *retval = VARIANT_FALSE;
+
+ const bool callbackIsNull = _globalCallback == nullptr;
+ if (_globalCallback == nullptr && cBack != nullptr)
+ {
+ _globalCallback = cBack;
+ _globalCallback->AddRef();
+ }
+
+ if (_table == nullptr || _sourceType == sstUninitialized)
+ {
+ ErrorMessage(tkSHAPEFILE_UNINITIALIZED);
+ return S_OK;
+ }
+
+ // in case someone else is writing, we leave
+ if (_writing)
+ {
+ ErrorMessage(tkSHP_WRITE_VIOLATION);
+ return S_OK;
+ }
+
+ if (!this->ValidateOutput(this, "Dump", "Shapefile", false))
+ return S_OK;
+
+ USES_CONVERSION;
+ CString sa_shpfileName = OLE2CA(ShapefileName);
+
+ if (sa_shpfileName.GetLength() <= 3)
+ {
+ ErrorMessage(tkINVALID_FILENAME);
+ }
+ else
+ {
+ const CString sa_shxfileName = sa_shpfileName.Left(sa_shpfileName.GetLength() - 3) + "shx";
+ CString sa_dbffileName = sa_shpfileName.Left(sa_shpfileName.GetLength() - 3) + "dbf";
+
+ // -----------------------------------------------
+ // it's not allowed to rewrite the existing files
+ // -----------------------------------------------
+ if (Utility::FileExists(sa_shpfileName))
+ {
+ ErrorMessage(tkSHP_FILE_EXISTS);
+ return S_OK;
+ }
+ if (Utility::FileExists(sa_shxfileName))
+ {
+ ErrorMessage(tkSHX_FILE_EXISTS);
+ return S_OK;
+ }
+ if (Utility::FileExists(sa_dbffileName))
+ {
+ ErrorMessage(tkDBF_FILE_EXISTS);
+ return S_OK;
+ }
+
+ // -----------------------------------------------
+ // checking in-memory shapes
+ // -----------------------------------------------
+ if (_isEditingShapes)
+ {
+ if (VerifyMemShapes(cBack) == FALSE)
+ {
+ // error Code is set in function
+ return S_OK;
+ }
+
+ // refresh extents
+ VARIANT_BOOL retVal;
+ this->RefreshExtents(&retVal);
+ }
+
+ // -----------------------------------------------
+ // opening files
+ // -----------------------------------------------
+ FILE* shpfile = fopen(sa_shpfileName, "wb+");
+ if (shpfile == nullptr)
+ {
+ ErrorMessage(tkCANT_CREATE_SHP);
+ return S_OK;
+ }
+
+ //shx
+ FILE* shxfile = fopen(sa_shxfileName, "wb+");
+ if (shxfile == nullptr)
+ {
+ fclose(shpfile);
+ ErrorMessage(tkCANT_CREATE_SHX);
+ return S_OK;
+ }
+
+ // ------------------------------------------------
+ // writing the files
+ // ------------------------------------------------
+ this->WriteShp(shpfile, cBack);
+ this->WriteShx(shxfile, cBack);
+
+ fclose(shpfile);
+ fclose(shxfile);
+
+ // ------------------------------------------------
+ // saving dbf table
+ // ------------------------------------------------
+ _table->Dump(sa_dbffileName.AllocSysString(), cBack, retval);
+ if (*retval == FALSE)
+ {
+ _table->get_LastErrorCode(&_lastErrorCode);
+ return S_OK;
+ }
+
+ // saving projection in new format
+ VARIANT_BOOL vbretval;
+ const CStringW prjfileName = sa_shpfileName.Left(sa_shpfileName.GetLength() - 3) + L"prj";
+ const CComBSTR bstr(prjfileName);
+ _geoProjection->WriteToFileEx(bstr, VARIANT_TRUE, &vbretval);
+
+ *retval = VARIANT_TRUE;
+ }
+
+ // restoring callback
+ if (callbackIsNull)
+ {
+ _globalCallback = nullptr;
+ }
+
+ return S_OK;
}
// **********************************************************
// SaveAs()
// **********************************************************
// Saves shapefile to the new or the same location. Doesn't stop editing mode.
-STDMETHODIMP CShapefile::SaveAs(BSTR ShapefileName, ICallback *cBack, VARIANT_BOOL *retval)
-{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- *retval = VARIANT_FALSE;
-
- bool callbackIsNull = (_globalCallback == NULL);
- if(_globalCallback == NULL && cBack != NULL)
- {
- _globalCallback = cBack;
- _globalCallback->AddRef();
- }
-
- if (_table == NULL || _sourceType == sstUninitialized)
- {
- ErrorMessage(tkSHAPEFILE_UNINITIALIZED);
- return S_OK;
- }
-
- // in case someone else is writing, we leave
- if (_writing)
- {
- ErrorMessage(tkSHP_WRITE_VIOLATION);
- return S_OK;
- }
-
- if (!this->ValidateOutput(this, "SaveAs", "Shapefile", false))
- return S_OK;
-
- USES_CONVERSION;
- CStringW newShpName;
- newShpName = OLE2W(ShapefileName);
-
- if( newShpName.GetLength() <= 3 )
- {
- ErrorMessage(tkINVALID_FILENAME);
- }
- else if (!Utility::EndsWith(newShpName, L".shp"))
- {
- ErrorMessage(tkINVALID_FILE_EXTENSION);
- }
- else
- {
- CStringW newShxName = newShpName.Left(newShpName.GetLength() - 3) + L"shx";
- CStringW newDbfName = newShpName.Left(newShpName.GetLength() - 3) + L"dbf";
-
- // -----------------------------------------------
- // it's not allowed to rewrite the existing files
- // -----------------------------------------------
- if( Utility::FileExistsW(newShpName) )
- {
- ErrorMessage(tkSHP_FILE_EXISTS);
- return S_OK;
- }
- if (Utility::FileExistsW(newShxName))
- {
- ErrorMessage(tkSHX_FILE_EXISTS);
- return S_OK;
- }
- if (Utility::FileExistsW(newDbfName))
- {
- ErrorMessage(tkDBF_FILE_EXISTS);
- return S_OK;
- }
-
- // -----------------------------------------------
- // checking in-memory shapes
- // -----------------------------------------------
- if( _isEditingShapes )
- {
- if( VerifyMemShapes(cBack) == FALSE )
- {
- // error Code is set in function
- return S_OK;
- }
-
- // refresh extents
- VARIANT_BOOL retVal;
- RefreshExtents(&retVal);
- }
-
- // -----------------------------------------------
- // opening files
- // -----------------------------------------------
- FILE * shpfile = _wfopen(newShpName, L"wb+");
- if( shpfile == NULL )
- {
- ErrorMessage(tkCANT_CREATE_SHP);
- return S_OK;
- }
-
- //shx
- FILE * shxfile = _wfopen(newShxName, L"wb+");
- if( shxfile == NULL )
- {
- fclose( shpfile );
- ErrorMessage(tkCANT_CREATE_SHX);
- return S_OK;
- }
-
- // ------------------------------------------------
- // writing the files
- // ------------------------------------------------
- WriteShp(shpfile,cBack);
- WriteShx(shxfile,cBack);
-
- fclose(shpfile);
- fclose(shxfile);
-
- // ------------------------------------------------
- // saving dbf table
- // ------------------------------------------------
- CComBSTR bstrDbf(newDbfName);
- _table->SaveAs(bstrDbf, cBack, retval);
-
- if( *retval != VARIANT_TRUE )
- {
- _table->get_LastErrorCode(&_lastErrorCode);
- _wunlink(newShpName);
- _wunlink(newShxName);
- return S_OK;
- }
-
- // -------------------------------------------------
- // switching to the new files
- // -------------------------------------------------
- shpfile = _wfopen(newShpName, L"rb");
- shxfile = _wfopen(newShxName, L"rb");
-
- if( _shpfile != NULL ) fclose(_shpfile);
- _shpfile = shpfile;
-
- if( _shxfile != NULL ) fclose(_shxfile);
- _shxfile = shxfile;
-
- // update all filenames:
- _shpfileName = newShpName; // saving of shp filename should be done before writing the projection;
- _shxfileName = newShxName; // otherwise projection string will be written to the memory
- _dbffileName = newDbfName;
- _prjfileName = newShpName.Left(newShpName.GetLength() - 3) + L"prj";
-
- _sourceType = sstDiskBased;
-
- // saving projection in new format
- VARIANT_BOOL vbretval, isEmpty;
- _geoProjection->get_IsEmpty(&isEmpty);
- if (!isEmpty) {
- CComBSTR bstr(_prjfileName);
- _geoProjection->WriteToFileEx(bstr, VARIANT_TRUE, &vbretval);
- }
-
- if (_useQTree)
- GenerateQTree();
-
- *retval = VARIANT_TRUE;
- }
-
- // restoring callback
- if (callbackIsNull) {
- _globalCallback = NULL;
- }
-
- return S_OK;
+STDMETHODIMP CShapefile::SaveAs(BSTR ShapefileName, ICallback* cBack, VARIANT_BOOL* retval)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ *retval = VARIANT_FALSE;
+
+ const bool callbackIsNull = _globalCallback == nullptr;
+ if (_globalCallback == nullptr && cBack != nullptr)
+ {
+ _globalCallback = cBack;
+ _globalCallback->AddRef();
+ }
+
+ if (_table == nullptr || _sourceType == sstUninitialized)
+ {
+ ErrorMessage(tkSHAPEFILE_UNINITIALIZED);
+ return S_OK;
+ }
+
+ // in case someone else is writing, we leave
+ if (_writing)
+ {
+ ErrorMessage(tkSHP_WRITE_VIOLATION);
+ return S_OK;
+ }
+
+ if (!this->ValidateOutput(this, "SaveAs", "Shapefile", false))
+ return S_OK;
+
+ USES_CONVERSION;
+ CStringW newShpName = OLE2W(ShapefileName);
+
+ if (newShpName.GetLength() <= 3)
+ {
+ ErrorMessage(tkINVALID_FILENAME);
+ }
+ else if (!Utility::EndsWith(newShpName, L".shp"))
+ {
+ ErrorMessage(tkINVALID_FILE_EXTENSION);
+ }
+ else
+ {
+ const CStringW newShxName = newShpName.Left(newShpName.GetLength() - 3) + L"shx";
+ const CStringW newDbfName = newShpName.Left(newShpName.GetLength() - 3) + L"dbf";
+
+ // -----------------------------------------------
+ // it's not allowed to rewrite the existing files
+ // -----------------------------------------------
+ if (Utility::FileExistsW(newShpName))
+ {
+ ErrorMessage(tkSHP_FILE_EXISTS);
+ return S_OK;
+ }
+ if (Utility::FileExistsW(newShxName))
+ {
+ ErrorMessage(tkSHX_FILE_EXISTS);
+ return S_OK;
+ }
+ if (Utility::FileExistsW(newDbfName))
+ {
+ ErrorMessage(tkDBF_FILE_EXISTS);
+ return S_OK;
+ }
+
+ // -----------------------------------------------
+ // checking in-memory shapes
+ // -----------------------------------------------
+ if (_isEditingShapes)
+ {
+ if (VerifyMemShapes(cBack) == FALSE)
+ {
+ // error Code is set in function
+ return S_OK;
+ }
+
+ // refresh extents
+ VARIANT_BOOL retVal;
+ RefreshExtents(&retVal);
+ }
+
+ // -----------------------------------------------
+ // opening files
+ // -----------------------------------------------
+ FILE* shpfile = _wfopen(newShpName, L"wb+");
+ if (shpfile == nullptr)
+ {
+ ErrorMessage(tkCANT_CREATE_SHP);
+ return S_OK;
+ }
+
+ //shx
+ FILE* shxfile = _wfopen(newShxName, L"wb+");
+ if (shxfile == nullptr)
+ {
+ fclose(shpfile);
+ ErrorMessage(tkCANT_CREATE_SHX);
+ return S_OK;
+ }
+
+ // ------------------------------------------------
+ // writing the files
+ // ------------------------------------------------
+ WriteShp(shpfile, cBack);
+ WriteShx(shxfile, cBack);
+
+ fclose(shpfile);
+ fclose(shxfile);
+
+ // ------------------------------------------------
+ // saving dbf table
+ // ------------------------------------------------
+ const CComBSTR bstrDbf(newDbfName);
+ _table->SaveAs(bstrDbf, cBack, retval);
+
+ if (*retval != VARIANT_TRUE)
+ {
+ _table->get_LastErrorCode(&_lastErrorCode);
+ _wunlink(newShpName);
+ _wunlink(newShxName);
+ return S_OK;
+ }
+
+ // -------------------------------------------------
+ // switching to the new files
+ // -------------------------------------------------
+ shpfile = _wfopen(newShpName, L"rb");
+ shxfile = _wfopen(newShxName, L"rb");
+
+ if (_shpfile != nullptr) fclose(_shpfile);
+ _shpfile = shpfile;
+
+ if (_shxfile != nullptr) fclose(_shxfile);
+ _shxfile = shxfile;
+
+ // update all filenames:
+ _shpfileName = newShpName; // saving of shp filename should be done before writing the projection;
+ _shxfileName = newShxName; // otherwise projection string will be written to the memory
+ _dbffileName = newDbfName;
+ _prjfileName = newShpName.Left(newShpName.GetLength() - 3) + L"prj";
+
+ _sourceType = sstDiskBased;
+
+ // saving projection in new format
+ VARIANT_BOOL vbretval, isEmpty;
+ _geoProjection->get_IsEmpty(&isEmpty);
+ if (!isEmpty)
+ {
+ const CComBSTR bstr(_prjfileName);
+ _geoProjection->WriteToFileEx(bstr, VARIANT_TRUE, &vbretval);
+ }
+
+ if (_useQTree)
+ GenerateQTree();
+
+ *retval = VARIANT_TRUE;
+ }
+
+ // restoring callback
+ if (callbackIsNull)
+ {
+ _globalCallback = nullptr;
+ }
+
+ return S_OK;
}
// **************************************************************
// Save()
// **************************************************************
// saving without exiting edit mode
-STDMETHODIMP CShapefile::Save(ICallback *cBack, VARIANT_BOOL *retval)
-{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- *retval = VARIANT_FALSE;
-
- if (_globalCallback == NULL && cBack != NULL)
- {
- _globalCallback = cBack;
- _globalCallback->AddRef();
- }
-
- // no edits were made; it doesn't make sense to save it
- if( _isEditingShapes == FALSE )
- {
- ErrorMessage( tkSHPFILE_NOT_IN_EDIT_MODE );
- return S_OK;
- }
-
- if( VerifyMemShapes(_globalCallback) == FALSE )
- {
- // error Code is set in function
- return S_OK;
- }
-
- if (!this->ValidateOutput(this, "Save", "Shapefile", false))
- return S_OK;
-
- // compute the extents
- VARIANT_BOOL res;
- RefreshExtents(&res);
-
- // -------------------------------------------------
- // Reopen the files in the write mode
- // -------------------------------------------------
- if (_shpfile && _shxfile)
- {
- _shpfile = _wfreopen(_shpfileName,L"wb+",_shpfile);
- _shxfile = _wfreopen(_shxfileName,L"wb+",_shxfile);
- }
- else
- {
- _shpfile = _wfopen(_shpfileName,L"wb+");
- _shxfile = _wfopen(_shxfileName,L"wb+");
- }
-
- if( _shpfile == NULL || _shxfile == NULL )
- {
- if( _shxfile != NULL )
- {
- fclose( _shxfile );
- _shxfile = NULL;
- _lastErrorCode = tkCANT_OPEN_SHX;
- }
- if( _shpfile != NULL )
- {
- fclose( _shpfile );
- _shpfile = NULL;
- _lastErrorCode = tkCANT_OPEN_SHP;
- }
- *retval = FALSE;
-
- ErrorMessage(_lastErrorCode);
- }
- else
- {
- _writing = true;
-
- // -------------------------------------------------
- // Writing the files
- // -------------------------------------------------
- WriteShp(_shpfile,cBack);
- WriteShx(_shxfile,cBack);
-
- if (_useQTree)
- GenerateQTree();
-
- // -------------------------------------------------
- // Reopen the updated files
- // -------------------------------------------------
- _shpfile = _wfreopen(_shpfileName,L"rb+",_shpfile);
- _shxfile = _wfreopen(_shxfileName,L"rb+",_shxfile);
-
- if( _shpfile == NULL || _shxfile == NULL )
- {
- if( _shxfile != NULL )
- {
- fclose( _shxfile );
- _shxfile = NULL;
- _lastErrorCode = tkCANT_OPEN_SHX;
- }
- if( _shpfile != NULL )
- {
- fclose( _shpfile );
- _shpfile = NULL;
- _lastErrorCode = tkCANT_OPEN_SHP;
- }
- *retval = FALSE;
-
- ErrorMessage( _lastErrorCode );
- }
- else
- {
- //Save the table file
- _table->Save(cBack,retval);
-
- _sourceType = sstDiskBased;
-
- // saving projection in new format
- VARIANT_BOOL vbretval, isEmpty;
- _geoProjection->get_IsEmpty(&isEmpty);
- if (!isEmpty) {
- CComBSTR bstr(_prjfileName);
- _geoProjection->WriteToFileEx(bstr, VARIANT_TRUE, &vbretval);
- }
-
- *retval = VARIANT_TRUE;
- }
- }
-
- _writing = false;
- return S_OK;
+STDMETHODIMP CShapefile::Save(ICallback* cBack, VARIANT_BOOL* retval)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ *retval = VARIANT_FALSE;
+
+ if (_globalCallback == nullptr && cBack != nullptr)
+ {
+ _globalCallback = cBack;
+ _globalCallback->AddRef();
+ }
+
+ // no edits were made; it doesn't make sense to save it
+ if (_isEditingShapes == FALSE)
+ {
+ ErrorMessage(tkSHPFILE_NOT_IN_EDIT_MODE);
+ return S_OK;
+ }
+
+ if (VerifyMemShapes(_globalCallback) == FALSE)
+ {
+ // error Code is set in function
+ return S_OK;
+ }
+
+ if (!this->ValidateOutput(this, "Save", "Shapefile", false))
+ return S_OK;
+
+ // compute the extents
+ VARIANT_BOOL res;
+ RefreshExtents(&res);
+
+ // -------------------------------------------------
+ // Reopen the files in the write mode
+ // -------------------------------------------------
+ if (_shpfile && _shxfile)
+ {
+ _shpfile = _wfreopen(_shpfileName, L"wb+", _shpfile);
+ _shxfile = _wfreopen(_shxfileName, L"wb+", _shxfile);
+ }
+ else
+ {
+ _shpfile = _wfopen(_shpfileName, L"wb+");
+ _shxfile = _wfopen(_shxfileName, L"wb+");
+ }
+
+ if (_shpfile == nullptr || _shxfile == nullptr)
+ {
+ if (_shxfile != nullptr)
+ {
+ fclose(_shxfile);
+ _shxfile = nullptr;
+ _lastErrorCode = tkCANT_OPEN_SHX;
+ }
+ if (_shpfile != nullptr)
+ {
+ fclose(_shpfile);
+ _shpfile = nullptr;
+ _lastErrorCode = tkCANT_OPEN_SHP;
+ }
+ *retval = FALSE;
+
+ ErrorMessage(_lastErrorCode);
+ }
+ else
+ {
+ _writing = true;
+
+ // -------------------------------------------------
+ // Writing the files
+ // -------------------------------------------------
+ WriteShp(_shpfile, cBack);
+ WriteShx(_shxfile, cBack);
+
+ if (_useQTree)
+ GenerateQTree();
+
+ // -------------------------------------------------
+ // Reopen the updated files
+ // -------------------------------------------------
+ _shpfile = _wfreopen(_shpfileName, L"rb+", _shpfile);
+ _shxfile = _wfreopen(_shxfileName, L"rb+", _shxfile);
+
+ if (_shpfile == nullptr || _shxfile == nullptr)
+ {
+ if (_shxfile != nullptr)
+ {
+ fclose(_shxfile);
+ _shxfile = nullptr;
+ _lastErrorCode = tkCANT_OPEN_SHX;
+ }
+ if (_shpfile != nullptr)
+ {
+ fclose(_shpfile);
+ _shpfile = nullptr;
+ _lastErrorCode = tkCANT_OPEN_SHP;
+ }
+ *retval = FALSE;
+
+ ErrorMessage(_lastErrorCode);
+ }
+ else
+ {
+ //Save the table file
+ _table->Save(cBack, retval);
+
+ _sourceType = sstDiskBased;
+
+ // saving projection in new format
+ VARIANT_BOOL vbretval, isEmpty;
+ _geoProjection->get_IsEmpty(&isEmpty);
+ if (!isEmpty)
+ {
+ const CComBSTR bstr(_prjfileName);
+ _geoProjection->WriteToFileEx(bstr, VARIANT_TRUE, &vbretval);
+ }
+
+ *retval = VARIANT_TRUE;
+ }
+ }
+
+ _writing = false;
+ return S_OK;
}
// ************************************************************
// Resource()
// ************************************************************
-STDMETHODIMP CShapefile::Resource(BSTR newShpPath, VARIANT_BOOL *retval)
+STDMETHODIMP CShapefile::Resource(BSTR newShpPath, VARIANT_BOOL* retval)
{
- USES_CONVERSION;
- Close(retval);
- Open(newShpPath, NULL, retval);
- return S_OK;
+ USES_CONVERSION;
+ Close(retval);
+ Open(newShpPath, nullptr, retval);
+ return S_OK;
}
#pragma endregion
@@ -1406,324 +1422,320 @@ STDMETHODIMP CShapefile::Resource(BSTR newShpPath, VARIANT_BOOL *retval)
// Creates new shapefile with the same type and fields as existing one
STDMETHODIMP CShapefile::Clone(IShapefile** retVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- ShapefileHelper::CloneCore(this, retVal, _shpfiletype);
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ ShapefileHelper::CloneCore(this, retVal, _shpfiletype);
+ return S_OK;
}
// ************************************************************
// get_Extents()
// ************************************************************
-STDMETHODIMP CShapefile::get_Extents(IExtents **pVal)
+STDMETHODIMP CShapefile::get_Extents(IExtents** pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+
+ IExtents* bBox = nullptr;
+ ComHelper::CreateExtents(&bBox);
- IExtents * bBox = NULL;
- ComHelper::CreateExtents(&bBox);
-
- // Extents could change because of the moving of points of a single shape
- // It's difficult to track such changes, so we still need to recalculate them
- // here to enforce proper drawing; _fastMode mode - for those who want
- // to call refresh extents theirselfs
- if (!_fastMode)
- {
- VARIANT_BOOL vbretval;
- this->RefreshExtents(&vbretval);
- }
+ // Extents could change because of the moving of points of a single shape
+ // It's difficult to track such changes, so we still need to recalculate them
+ // here to enforce proper drawing; _fastMode mode - for those who want
+ // to call refresh extents theirselfs
+ if (!_fastMode)
+ {
+ VARIANT_BOOL vbretval;
+ this->RefreshExtents(&vbretval);
+ }
- bBox->SetBounds(_minX,_minY,_minZ,_maxX,_maxY,_maxZ);
- bBox->SetMeasureBounds(_minM,_maxM);
- *pVal = bBox;
+ bBox->SetBounds(_minX, _minY, _minZ, _maxX, _maxY, _maxZ);
+ bBox->SetMeasureBounds(_minM, _maxM);
+ *pVal = bBox;
- return S_OK;
+ return S_OK;
}
#pragma region AttributeTable
// ****************************************************************
// EditInsertField()
// ****************************************************************
-STDMETHODIMP CShapefile::EditInsertField(IField *NewField, long *FieldIndex, ICallback *cBack, VARIANT_BOOL *retval)
+STDMETHODIMP CShapefile::EditInsertField(IField* NewField, long* FieldIndex, ICallback* cBack, VARIANT_BOOL* retval)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
- if(cBack == NULL && _globalCallback!=NULL)
- cBack = _globalCallback;
+ if (cBack == nullptr && _globalCallback != nullptr)
+ cBack = _globalCallback;
- if( _table != NULL )
- {
- _table->EditInsertField(NewField,FieldIndex,cBack,retval);
- }
- else
- {
- *retval = VARIANT_FALSE;
- _lastErrorCode = tkFILE_NOT_OPEN;
- ErrorMessage(_lastErrorCode, cBack);
- return S_OK;
- }
+ if (_table != nullptr)
+ {
+ _table->EditInsertField(NewField, FieldIndex, cBack, retval);
+ }
+ else
+ {
+ *retval = VARIANT_FALSE;
+ _lastErrorCode = tkFILE_NOT_OPEN;
+ ErrorMessage(_lastErrorCode, cBack);
+ return S_OK;
+ }
- if( *retval == VARIANT_FALSE )
- {
- _table->get_LastErrorCode(&_lastErrorCode);
- *retval = VARIANT_FALSE;
- }
+ if (*retval == VARIANT_FALSE)
+ {
+ _table->get_LastErrorCode(&_lastErrorCode);
+ *retval = VARIANT_FALSE;
+ }
- return S_OK;
+ return S_OK;
}
// ****************************************************************
// EditDeleteField()
// ****************************************************************
-STDMETHODIMP CShapefile::EditDeleteField(long FieldIndex, ICallback *cBack, VARIANT_BOOL *retval)
+STDMETHODIMP CShapefile::EditDeleteField(long FieldIndex, ICallback* cBack, VARIANT_BOOL* retval)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
- if(_globalCallback == NULL && cBack != NULL)
- {
- _globalCallback = cBack;
- _globalCallback->AddRef();
- }
+ if (_globalCallback == nullptr && cBack != nullptr)
+ {
+ _globalCallback = cBack;
+ _globalCallback->AddRef();
+ }
- if( _table != NULL )
- {
- _table->EditDeleteField(FieldIndex,cBack,retval);
- }
- else
- {
- *retval = VARIANT_FALSE;
- ErrorMessage(tkFILE_NOT_OPEN);
- return S_OK;
- }
+ if (_table != nullptr)
+ {
+ _table->EditDeleteField(FieldIndex, cBack, retval);
+ }
+ else
+ {
+ *retval = VARIANT_FALSE;
+ ErrorMessage(tkFILE_NOT_OPEN);
+ return S_OK;
+ }
- if( *retval == VARIANT_FALSE )
- {
- _table->get_LastErrorCode(&_lastErrorCode);
- *retval = VARIANT_FALSE;
- }
+ if (*retval == VARIANT_FALSE)
+ {
+ _table->get_LastErrorCode(&_lastErrorCode);
+ *retval = VARIANT_FALSE;
+ }
- return S_OK;
+ return S_OK;
}
// ****************************************************************
// EditCellValue()
// ****************************************************************
-STDMETHODIMP CShapefile::EditCellValue(long FieldIndex, long ShapeIndex, VARIANT NewVal, VARIANT_BOOL *retval)
+STDMETHODIMP CShapefile::EditCellValue(long FieldIndex, long ShapeIndex, VARIANT NewVal, VARIANT_BOOL* retval)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
- if( _table != NULL )
- {
- _table->EditCellValue(FieldIndex,ShapeIndex,NewVal,retval);
- }
- else
- {
- *retval = VARIANT_FALSE;
- ErrorMessage(tkFILE_NOT_OPEN);
- return S_OK;
- }
+ if (_table != nullptr)
+ {
+ _table->EditCellValue(FieldIndex, ShapeIndex, NewVal, retval);
+ }
+ else
+ {
+ *retval = VARIANT_FALSE;
+ ErrorMessage(tkFILE_NOT_OPEN);
+ return S_OK;
+ }
- if( *retval == VARIANT_FALSE )
- {
- _table->get_LastErrorCode(&_lastErrorCode);
- }
+ if (*retval == VARIANT_FALSE)
+ {
+ _table->get_LastErrorCode(&_lastErrorCode);
+ }
- return S_OK;
+ return S_OK;
}
// ****************************************************************
// StartEditingTable()
// ****************************************************************
-STDMETHODIMP CShapefile::StartEditingTable(ICallback *cBack, VARIANT_BOOL *retval)
-{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
-
- if (_appendMode)
- {
- ErrorMessage(tkDBF_NO_EDIT_MODE_WHEN_APPENDING);
- *retval = VARIANT_FALSE;
- return S_OK;
- }
-
- if(_globalCallback == NULL && cBack != NULL)
- {
- _globalCallback = cBack;
- _globalCallback->AddRef();
- }
-
- if( _table != NULL )
- {
- _table->StartEditingTable(cBack,retval);
- }
- else
- {
- *retval = VARIANT_FALSE;
- ErrorMessage(tkFILE_NOT_OPEN);
- return S_OK;
- }
-
- if( *retval == VARIANT_FALSE )
- {
- _table->get_LastErrorCode(&_lastErrorCode);
- *retval = VARIANT_FALSE;
- }
-
- return S_OK;
+STDMETHODIMP CShapefile::StartEditingTable(ICallback* cBack, VARIANT_BOOL* retval)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+
+ if (_appendMode)
+ {
+ ErrorMessage(tkDBF_NO_EDIT_MODE_WHEN_APPENDING);
+ *retval = VARIANT_FALSE;
+ return S_OK;
+ }
+
+ if (_globalCallback == nullptr && cBack != nullptr)
+ {
+ _globalCallback = cBack;
+ _globalCallback->AddRef();
+ }
+
+ if (_table != nullptr)
+ {
+ _table->StartEditingTable(cBack, retval);
+ }
+ else
+ {
+ *retval = VARIANT_FALSE;
+ ErrorMessage(tkFILE_NOT_OPEN);
+ return S_OK;
+ }
+
+ if (*retval == VARIANT_FALSE)
+ {
+ _table->get_LastErrorCode(&_lastErrorCode);
+ *retval = VARIANT_FALSE;
+ }
+
+ return S_OK;
}
// ****************************************************************
// StopEditingTable()
// ****************************************************************
-STDMETHODIMP CShapefile::StopEditingTable(VARIANT_BOOL ApplyChanges, ICallback *cBack, VARIANT_BOOL *retval)
-{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
-
- if(_globalCallback == NULL && cBack!=NULL)
- {
- _globalCallback = cBack;
- _globalCallback->AddRef();
- }
-
- if( _table != NULL )
- {
- _table->StopEditingTable(ApplyChanges,cBack,retval);
- }
- else
- {
- *retval = VARIANT_FALSE;
- ErrorMessage(tkFILE_NOT_OPEN);
- return S_OK;
- }
-
- if( *retval == FALSE )
- {
- _table->get_LastErrorCode(&_lastErrorCode);
- *retval = VARIANT_FALSE;
- }
-
- return S_OK;
+STDMETHODIMP CShapefile::StopEditingTable(VARIANT_BOOL ApplyChanges, ICallback* cBack, VARIANT_BOOL* retval)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+
+ if (_globalCallback == nullptr && cBack != nullptr)
+ {
+ _globalCallback = cBack;
+ _globalCallback->AddRef();
+ }
+
+ if (_table != nullptr)
+ {
+ _table->StopEditingTable(ApplyChanges, cBack, retval);
+ }
+ else
+ {
+ *retval = VARIANT_FALSE;
+ ErrorMessage(tkFILE_NOT_OPEN);
+ return S_OK;
+ }
+
+ if (*retval == FALSE)
+ {
+ _table->get_LastErrorCode(&_lastErrorCode);
+ *retval = VARIANT_FALSE;
+ }
+
+ return S_OK;
}
// *****************************************************************
// get_Field()
// *****************************************************************
-STDMETHODIMP CShapefile::get_Field(long FieldIndex, IField **pVal)
-{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
-
- if( _table != NULL )
- {
- _table->get_Field(FieldIndex,pVal);
- if(*pVal != NULL)
- {
- // we need to report error from field class, and will use callback from this class for it
- ICallback* cBack = NULL;
- if ((*pVal)->get_GlobalCallback(&cBack) == NULL && this->_globalCallback != NULL)
- (*pVal)->put_GlobalCallback(_globalCallback);
-
- if (cBack != NULL)
- cBack->Release(); // we put a reference in field class so must release it here
- }
- }
- else
- {
- ErrorMessage(tkFILE_NOT_OPEN);
- return S_OK;
- }
-
- return S_OK;
+STDMETHODIMP CShapefile::get_Field(long FieldIndex, IField** pVal)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+
+ if (_table != nullptr)
+ {
+ _table->get_Field(FieldIndex, pVal);
+ if (*pVal != nullptr)
+ {
+ // we need to report error from field class, and will use callback from this class for it
+ ICallback* cBack = nullptr;
+ if ((*pVal)->get_GlobalCallback(&cBack) == NULL && this->_globalCallback != nullptr)
+ (*pVal)->put_GlobalCallback(_globalCallback);
+
+ if (cBack != nullptr)
+ cBack->Release(); // we put a reference in field class so must release it here
+ }
+ }
+ else
+ {
+ ErrorMessage(tkFILE_NOT_OPEN);
+ return S_OK;
+ }
+
+ return S_OK;
}
// *****************************************************************
// get_FieldByName()
// *****************************************************************
-STDMETHODIMP CShapefile::get_FieldByName(BSTR Fieldname, IField **pVal)
+STDMETHODIMP CShapefile::get_FieldByName(BSTR Fieldname, IField** pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- USES_CONVERSION;
-
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ USES_CONVERSION;
+
long max;
-
- CString strTestname;
- CString strFieldname;
- IField *testVal;
-
- _table->get_NumFields(&max);
- if( _table != NULL )
- {
- if( _tcslen( OLE2CA(Fieldname) ) > 0 )
- {
- strFieldname = OLE2A(Fieldname);
- }
- else
- {
- ErrorMessage(tkZERO_LENGTH_STRING);
- }
-
- for (int fld=0; fld < max; fld++)
- {
- _table->get_Field(fld,&testVal);
- CComBSTR Testname;
- testVal->get_Name(&Testname);
- strTestname = OLE2A(Testname);
- if( strTestname.CompareNoCase(strFieldname) == 0)
- {
- *pVal = testVal;
- return S_OK;
- }
- else
- {
- testVal->Release();
- }
- }
- }
- else
- {
- ErrorMessage(tkFILE_NOT_OPEN);
- return S_OK;
- }
-
- // we did not have a file error, but we also didn't match the name
- pVal = NULL;
- return S_OK;
+
+ CString strFieldname;
+ IField* testVal;
+
+ _table->get_NumFields(&max);
+ if (_table != nullptr)
+ {
+ if (_tcslen(OLE2CA(Fieldname)) > 0)
+ {
+ strFieldname = OLE2A(Fieldname);
+ }
+ else
+ {
+ ErrorMessage(tkZERO_LENGTH_STRING);
+ }
+
+ for (int fld = 0; fld < max; fld++)
+ {
+ _table->get_Field(fld, &testVal);
+ CComBSTR Testname;
+ testVal->get_Name(&Testname);
+ CString strTestname = OLE2A(Testname);
+ if (strTestname.CompareNoCase(strFieldname) == 0)
+ {
+ *pVal = testVal;
+ return S_OK;
+ }
+ testVal->Release();
+ }
+ }
+ else
+ {
+ ErrorMessage(tkFILE_NOT_OPEN);
+ return S_OK;
+ }
+
+ // we did not have a file error, but we also didn't match the name
+ pVal = nullptr;
+ return S_OK;
}
// *****************************************************************
// get_CellValue()
// *****************************************************************
-STDMETHODIMP CShapefile::get_CellValue(long FieldIndex, long ShapeIndex, VARIANT *pVal)
+STDMETHODIMP CShapefile::get_CellValue(long FieldIndex, long ShapeIndex, VARIANT* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
- if( _table != NULL )
- {
- _table->get_CellValue(FieldIndex,ShapeIndex,pVal);
- }
- else
- {
- ErrorMessage(tkFILE_NOT_OPEN);
- return S_OK;
- }
+ if (_table != nullptr)
+ {
+ _table->get_CellValue(FieldIndex, ShapeIndex, pVal);
+ }
+ else
+ {
+ ErrorMessage(tkFILE_NOT_OPEN);
+ return S_OK;
+ }
- return S_OK;
+ return S_OK;
}
// *****************************************************************
// get_EditingTable()
// *****************************************************************
-STDMETHODIMP CShapefile::get_EditingTable(VARIANT_BOOL *pVal)
+STDMETHODIMP CShapefile::get_EditingTable(VARIANT_BOOL* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- if( _table != NULL )
- {
- _table->get_EditingTable(pVal);
- }
- else
- {
- *pVal = VARIANT_FALSE;
- ErrorMessage(tkFILE_NOT_OPEN);
- return S_OK;
- }
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ if (_table != nullptr)
+ {
+ _table->get_EditingTable(pVal);
+ }
+ else
+ {
+ *pVal = VARIANT_FALSE;
+ ErrorMessage(tkFILE_NOT_OPEN);
+ return S_OK;
+ }
- return S_OK;
+ return S_OK;
}
// *************************************************************
@@ -1731,13 +1743,13 @@ STDMETHODIMP CShapefile::get_EditingTable(VARIANT_BOOL *pVal)
// *************************************************************
STDMETHODIMP CShapefile::get_Table(ITable** retVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- *retVal = _table;
- if ( _table )
- {
- _table->AddRef();
- }
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ *retVal = _table;
+ if (_table)
+ {
+ _table->AddRef();
+ }
+ return S_OK;
}
#pragma endregion
@@ -1748,27 +1760,28 @@ STDMETHODIMP CShapefile::get_Table(ITable** retVal)
// *************************************************************
STDMETHODIMP CShapefile::get_ShapeRotation(long ShapeIndex, double* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- if( ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size())
- {
- *pVal = -1;
- ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
- }
- else
- *pVal = _shapeData[ShapeIndex]->rotation;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ if (ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size())
+ {
+ *pVal = -1;
+ ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
+ }
+ else
+ *pVal = _shapeData[ShapeIndex]->rotation;
+ return S_OK;
}
+
STDMETHODIMP CShapefile::put_ShapeRotation(long ShapeIndex, double newVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- if( ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size())
- {
- ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
- }
- else
- _shapeData[ShapeIndex]->rotation = static_cast(newVal);
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ if (ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size())
+ {
+ ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
+ }
+ else
+ _shapeData[ShapeIndex]->rotation = static_cast(newVal);
- return S_OK;
+ return S_OK;
}
// *************************************************************
@@ -1776,40 +1789,42 @@ STDMETHODIMP CShapefile::put_ShapeRotation(long ShapeIndex, double newVal)
// *************************************************************
STDMETHODIMP CShapefile::get_ShapeVisible(long ShapeIndex, VARIANT_BOOL* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *pVal = VARIANT_FALSE;
- if (ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size())
- {
- ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
- }
- else {
- // this particular shape was not hidden explicitly or via visibility expression
- if (!_shapeData[ShapeIndex]->hidden() && _shapeData[ShapeIndex]->isVisible())
- {
- long ctIndex = -1;
- get_ShapeCategory(ShapeIndex, &ctIndex);
- if (ctIndex == -1)
- {
- // no category, check default options
- _defaultDrawOpt->get_Visible(pVal);
- }
- else
- {
- // there is category, check whether it is visible
- CComPtr ct = NULL;
- get_ShapeCategory3(ShapeIndex, &ct);
- if (ct)
- {
- CComPtr options = NULL;
- ct->get_DrawingOptions(&options);
- if (options) {
- options->get_Visible(pVal);
- }
- }
- }
- }
- }
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ *pVal = VARIANT_FALSE;
+ if (ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size())
+ {
+ ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
+ }
+ else
+ {
+ // this particular shape was not hidden explicitly or via visibility expression
+ if (!_shapeData[ShapeIndex]->hidden() && _shapeData[ShapeIndex]->isVisible())
+ {
+ long ctIndex = -1;
+ get_ShapeCategory(ShapeIndex, &ctIndex);
+ if (ctIndex == -1)
+ {
+ // no category, check default options
+ _defaultDrawOpt->get_Visible(pVal);
+ }
+ else
+ {
+ // there is category, check whether it is visible
+ CComPtr ct = nullptr;
+ get_ShapeCategory3(ShapeIndex, &ct);
+ if (ct)
+ {
+ CComPtr options = nullptr;
+ ct->get_DrawingOptions(&options);
+ if (options)
+ {
+ options->get_Visible(pVal);
+ }
+ }
+ }
+ }
+ }
+ return S_OK;
}
// *************************************************************
@@ -1817,29 +1832,30 @@ STDMETHODIMP CShapefile::get_ShapeVisible(long ShapeIndex, VARIANT_BOOL* pVal)
// *************************************************************
STDMETHODIMP CShapefile::get_ShapeIsHidden(LONG shapeIndex, VARIANT_BOOL* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- if (shapeIndex < 0 || shapeIndex >= (long)_shapeData.size())
- {
- *pVal = VARIANT_FALSE;
- ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
- }
- else {
- *pVal = _shapeData[shapeIndex]->hidden() ? VARIANT_TRUE : VARIANT_FALSE;
- }
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ if (shapeIndex < 0 || shapeIndex >= (long)_shapeData.size())
+ {
+ *pVal = VARIANT_FALSE;
+ ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
+ }
+ else
+ {
+ *pVal = _shapeData[shapeIndex]->hidden() ? VARIANT_TRUE : VARIANT_FALSE;
+ }
+ return S_OK;
}
STDMETHODIMP CShapefile::put_ShapeIsHidden(LONG shapeIndex, VARIANT_BOOL newVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- if (shapeIndex < 0 || shapeIndex >= (long)_shapeData.size())
- {
- ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
- }
- else
- _shapeData[shapeIndex]->hidden(newVal ? true : false);
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ if (shapeIndex < 0 || shapeIndex >= (long)_shapeData.size())
+ {
+ ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
+ }
+ else
+ _shapeData[shapeIndex]->hidden(newVal != 0);
- return S_OK;
+ return S_OK;
}
// *************************************************************
@@ -1847,31 +1863,33 @@ STDMETHODIMP CShapefile::put_ShapeIsHidden(LONG shapeIndex, VARIANT_BOOL newVal)
// *************************************************************
STDMETHODIMP CShapefile::get_ShapeModified(long ShapeIndex, VARIANT_BOOL* retVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- if (ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size())
- {
- *retVal = -1;
- ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
- }
- else {
- *retVal = _shapeData[ShapeIndex]->modified() ? VARIANT_TRUE : VARIANT_FALSE;
- }
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ if (ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size())
+ {
+ *retVal = -1;
+ ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
+ }
+ else
+ {
+ *retVal = _shapeData[ShapeIndex]->modified() ? VARIANT_TRUE : VARIANT_FALSE;
+ }
- return S_OK;
+ return S_OK;
}
STDMETHODIMP CShapefile::put_ShapeModified(long ShapeIndex, VARIANT_BOOL newVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- if (ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size())
- {
- ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
- }
- else {
- _shapeData[ShapeIndex]->modified(newVal ? true : false);
- }
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ if (ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size())
+ {
+ ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
+ }
+ else
+ {
+ _shapeData[ShapeIndex]->modified(newVal != 0);
+ }
- return S_OK;
+ return S_OK;
}
@@ -1880,27 +1898,28 @@ STDMETHODIMP CShapefile::put_ShapeModified(long ShapeIndex, VARIANT_BOOL newVal)
// *************************************************************
STDMETHODIMP CShapefile::get_ShapeCategory(long ShapeIndex, long* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- if( ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size()) //_numShapes)
- {
- *pVal = -1;
- ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
- }
- else
- *pVal = _shapeData[ShapeIndex]->category;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ if (ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size()) //_numShapes)
+ {
+ *pVal = -1;
+ ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
+ }
+ else
+ *pVal = _shapeData[ShapeIndex]->category;
+ return S_OK;
}
+
STDMETHODIMP CShapefile::put_ShapeCategory(long ShapeIndex, long newVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- if( ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size()) //_numShapes )
- {
- ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
- }
- else
- _shapeData[ShapeIndex]->category = (int)newVal;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ if (ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size()) //_numShapes )
+ {
+ ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
+ }
+ else
+ _shapeData[ShapeIndex]->category = (int)newVal;
- return S_OK;
+ return S_OK;
}
// *************************************************************
@@ -1908,54 +1927,51 @@ STDMETHODIMP CShapefile::put_ShapeCategory(long ShapeIndex, long newVal)
// *************************************************************
STDMETHODIMP CShapefile::put_ShapeCategory2(long ShapeIndex, BSTR categoryName)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- if( ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size())
- {
- ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
- }
- else
- {
- int index;
- _categories->get_CategoryIndexByName(categoryName, &index);
- if (index == -1)
- {
- ErrorMessage(tkCATEGORY_WASNT_FOUND);
- }
- else
- {
- _shapeData[ShapeIndex]->category = (int)index;
- }
- }
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ if (ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size())
+ {
+ ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
+ }
+ else
+ {
+ int index;
+ _categories->get_CategoryIndexByName(categoryName, &index);
+ if (index == -1)
+ {
+ ErrorMessage(tkCATEGORY_WASNT_FOUND);
+ }
+ else
+ {
+ _shapeData[ShapeIndex]->category = (int)index;
+ }
+ }
+ return S_OK;
}
STDMETHODIMP CShapefile::get_ShapeCategory2(long ShapeIndex, BSTR* categoryName)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- if( ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size())
- {
- ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
- }
- else
- {
- int index = _shapeData[ShapeIndex]->category;
- long count;
- _categories->get_Count(&count);
- if (index >= 0 && index < count)
- {
- IShapefileCategory* ct;
- _categories->get_Item(index, &ct);
- ct->get_Name(categoryName);
- ct->Release();
- return S_OK;
- }
- else
- {
- ErrorMessage(tkCATEGORY_WASNT_FOUND);
- }
- }
- *categoryName = SysAllocString(L"");
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ if (ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size())
+ {
+ ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
+ }
+ else
+ {
+ const int index = _shapeData[ShapeIndex]->category;
+ long count;
+ _categories->get_Count(&count);
+ if (index >= 0 && index < count)
+ {
+ IShapefileCategory* ct;
+ _categories->get_Item(index, &ct);
+ ct->get_Name(categoryName);
+ ct->Release();
+ return S_OK;
+ }
+ ErrorMessage(tkCATEGORY_WASNT_FOUND);
+ }
+ *categoryName = SysAllocString(L"");
+ return S_OK;
}
// *************************************************************
@@ -1963,52 +1979,52 @@ STDMETHODIMP CShapefile::get_ShapeCategory2(long ShapeIndex, BSTR* categoryName)
// *************************************************************
STDMETHODIMP CShapefile::put_ShapeCategory3(long ShapeIndex, IShapefileCategory* category)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- if( ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size())
- {
- ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
- }
- else
- {
- int index;
- _categories->get_CategoryIndex(category, &index);
- if (index == -1)
- {
- ErrorMessage(tkCATEGORY_WASNT_FOUND);
- }
- else
- {
- _shapeData[ShapeIndex]->category = (int)index;
- }
- }
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ if (ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size())
+ {
+ ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
+ }
+ else
+ {
+ int index;
+ _categories->get_CategoryIndex(category, &index);
+ if (index == -1)
+ {
+ ErrorMessage(tkCATEGORY_WASNT_FOUND);
+ }
+ else
+ {
+ _shapeData[ShapeIndex]->category = (int)index;
+ }
+ }
+ return S_OK;
}
STDMETHODIMP CShapefile::get_ShapeCategory3(long ShapeIndex, IShapefileCategory** category)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *category = NULL;
- if( ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size())
- {
- ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
- }
- else
- {
- int index = _shapeData[ShapeIndex]->category;
- long count;
- _categories->get_Count(&count);
- if (index >= 0 && index < count)
- {
- IShapefileCategory* ct;
- _categories->get_Item(index, &ct);
- *category = ct; // ref was added in the get_Item
- }
- else
- {
- ErrorMessage(tkCATEGORY_WASNT_FOUND);
- }
- }
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ *category = nullptr;
+ if (ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size())
+ {
+ ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
+ }
+ else
+ {
+ const int index = _shapeData[ShapeIndex]->category;
+ long count;
+ _categories->get_Count(&count);
+ if (index >= 0 && index < count)
+ {
+ IShapefileCategory* ct;
+ _categories->get_Item(index, &ct);
+ *category = ct; // ref was added in the get_Item
+ }
+ else
+ {
+ ErrorMessage(tkCATEGORY_WASNT_FOUND);
+ }
+ }
+ return S_OK;
}
// *******************************************************************
@@ -2017,24 +2033,25 @@ STDMETHODIMP CShapefile::get_ShapeCategory3(long ShapeIndex, IShapefileCategory*
// Returns and sets parameters used to draw selection for the shapefile.
STDMETHODIMP CShapefile::get_SelectionDrawingOptions(IShapeDrawingOptions** pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *pVal = _selectDrawOpt;
- if (_selectDrawOpt)
- _selectDrawOpt->AddRef();
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ *pVal = _selectDrawOpt;
+ if (_selectDrawOpt)
+ _selectDrawOpt->AddRef();
+ return S_OK;
}
+
STDMETHODIMP CShapefile::put_SelectionDrawingOptions(IShapeDrawingOptions* newVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- if (!newVal)
- {
- ErrorMessage(tkINVALID_PARAMETER_VALUE);
- }
- else
- {
- ComHelper::SetRef(newVal, (IDispatch**)&_selectDrawOpt, false);
- }
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ if (!newVal)
+ {
+ ErrorMessage(tkINVALID_PARAMETER_VALUE);
+ }
+ else
+ {
+ ComHelper::SetRef(newVal, (IDispatch**)&_selectDrawOpt, false);
+ }
+ return S_OK;
}
// *******************************************************************
@@ -2043,57 +2060,59 @@ STDMETHODIMP CShapefile::put_SelectionDrawingOptions(IShapeDrawingOptions* newVa
// Returns and sets parameters used to draw shapefile by default.
STDMETHODIMP CShapefile::get_DefaultDrawingOptions(IShapeDrawingOptions** pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *pVal = _defaultDrawOpt;
- if (_defaultDrawOpt)
- _defaultDrawOpt->AddRef();
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ *pVal = _defaultDrawOpt;
+ if (_defaultDrawOpt)
+ _defaultDrawOpt->AddRef();
+ return S_OK;
}
+
STDMETHODIMP CShapefile::put_DefaultDrawingOptions(IShapeDrawingOptions* newVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
-
- if (!newVal)
- {
- ErrorMessage(tkINVALID_PARAMETER_VALUE);
- }
- else
- {
- ComHelper::SetRef(newVal, (IDispatch**)&_defaultDrawOpt);
- }
- return S_OK;
-}
-
-/***********************************************************************/
-/* put_ReferenceToCategories
-/***********************************************************************/
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+
+ if (!newVal)
+ {
+ ErrorMessage(tkINVALID_PARAMETER_VALUE);
+ }
+ else
+ {
+ ComHelper::SetRef(newVal, (IDispatch**)&_defaultDrawOpt);
+ }
+ return S_OK;
+}
+
+// ***********************************************************************
+// put_ReferenceToCategories
+// ***********************************************************************
void CShapefile::put_ReferenceToCategories(bool bNullReference)
{
- if (_categories == NULL) return;
- CShapefileCategories* coCategories = static_cast(_categories);
- if (!bNullReference)
- coCategories->put_ParentShapefile(this);
- else
- coCategories->put_ParentShapefile(NULL);
+ if (_categories == nullptr) return;
+ auto* coCategories = dynamic_cast(_categories);
+ if (!bNullReference)
+ coCategories->put_ParentShapefile(this);
+ else
+ coCategories->put_ParentShapefile(nullptr);
};
-/***********************************************************************/
-/* get/put_Categories
-/***********************************************************************/
+// ***********************************************************************
+// get/put_Categories
+// ***********************************************************************
STDMETHODIMP CShapefile::get_Categories(IShapefileCategories** pVal)
{
- *pVal = _categories;
- if (_categories != NULL)
- _categories->AddRef();
- return S_OK;
+ *pVal = _categories;
+ if (_categories != nullptr)
+ _categories->AddRef();
+ return S_OK;
}
+
STDMETHODIMP CShapefile::put_Categories(IShapefileCategories* newVal)
{
- if (ComHelper::SetRef((IDispatch*)newVal, (IDispatch**) &_categories, false))
- {
- ((CShapefileCategories*)_categories)->put_ParentShapefile(this);
- }
- return S_OK;
+ if (ComHelper::SetRef((IDispatch*)newVal, (IDispatch**)&_categories, false))
+ {
+ ((CShapefileCategories*)_categories)->put_ParentShapefile(this);
+ }
+ return S_OK;
}
#pragma endregion
@@ -2102,33 +2121,34 @@ STDMETHODIMP CShapefile::put_Categories(IShapefileCategories* newVal)
// ********************************************************************
STDMETHODIMP CShapefile::get_SelectionColor(OLE_COLOR* retval)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *retval = _selectionColor;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ *retval = _selectionColor;
+ return S_OK;
}
+
STDMETHODIMP CShapefile::put_SelectionColor(OLE_COLOR newVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- _selectionColor = newVal;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ _selectionColor = newVal;
+ return S_OK;
}
// ********************************************************************
// get_SelectionTransparency
// ********************************************************************
-STDMETHODIMP CShapefile::get_SelectionTransparency (BYTE* retval)
+STDMETHODIMP CShapefile::get_SelectionTransparency(BYTE* retval)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *retval = _selectionTransparency;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ *retval = _selectionTransparency;
+ return S_OK;
}
-STDMETHODIMP CShapefile::put_SelectionTransparency (BYTE newVal)
+
+STDMETHODIMP CShapefile::put_SelectionTransparency(BYTE newVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- if (newVal > 255) newVal = 255;
- if (newVal < 0) newVal = 0;
- _selectionTransparency = newVal;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ if (newVal > 255) newVal = 255;
+ _selectionTransparency = newVal;
+ return S_OK;
}
// ********************************************************************
@@ -2136,15 +2156,16 @@ STDMETHODIMP CShapefile::put_SelectionTransparency (BYTE newVal)
// ********************************************************************
STDMETHODIMP CShapefile::get_SelectionAppearance(tkSelectionAppearance* retval)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *retval = _selectionAppearance;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ *retval = _selectionAppearance;
+ return S_OK;
}
+
STDMETHODIMP CShapefile::put_SelectionAppearance(tkSelectionAppearance newVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- _selectionAppearance = newVal;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ _selectionAppearance = newVal;
+ return S_OK;
}
// ********************************************************************
@@ -2152,15 +2173,16 @@ STDMETHODIMP CShapefile::put_SelectionAppearance(tkSelectionAppearance newVal)
// ********************************************************************
STDMETHODIMP CShapefile::get_CollisionMode(tkCollisionMode* retval)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *retval = _collisionMode;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ *retval = _collisionMode;
+ return S_OK;
}
+
STDMETHODIMP CShapefile::put_CollisionMode(tkCollisionMode newVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- _collisionMode = newVal;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ _collisionMode = newVal;
+ return S_OK;
}
#pragma region "Seialization"
@@ -2169,166 +2191,182 @@ STDMETHODIMP CShapefile::put_CollisionMode(tkCollisionMode newVal)
// ********************************************************
STDMETHODIMP CShapefile::Serialize(VARIANT_BOOL SaveSelection, BSTR* retVal)
{
- return Serialize2(SaveSelection, VARIANT_FALSE, retVal);
+ return Serialize2(SaveSelection, VARIANT_FALSE, retVal);
}
STDMETHODIMP CShapefile::Serialize2(VARIANT_BOOL SaveSelection, VARIANT_BOOL SerializeCategories, BSTR* retVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- CPLXMLNode* psTree = this->SerializeCore(VARIANT_TRUE, "ShapefileClass", SerializeCategories ? true : false);
- Utility::SerializeAndDestroyXmlTree(psTree, retVal);
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ CPLXMLNode* psTree = this->SerializeCore(VARIANT_TRUE, "ShapefileClass", SerializeCategories != 0);
+ Utility::SerializeAndDestroyXmlTree(psTree, retVal);
+ return S_OK;
}
// ********************************************************
// SerializeCore()
// ********************************************************
- CPLXMLNode* CShapefile::SerializeCore(VARIANT_BOOL SaveSelection, CString ElementName, bool serializeCategories)
-{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- USES_CONVERSION;
-
- CPLXMLNode* psTree = CPLCreateXMLNode( NULL, CXT_Element, ElementName );
-
- if (psTree)
- {
- CString s = OLE2CA(_expression);
- if (s != "")
- Utility::CPLCreateXMLAttributeAndValue(psTree, "VisibilityExpression", s);
-
-
-
- if (_useQTree != FALSE)
- Utility::CPLCreateXMLAttributeAndValue(psTree, "UseQTree", CPLString().Printf("%d", (int)_useQTree));
-
- if (_collisionMode != LocalList )
- Utility::CPLCreateXMLAttributeAndValue(psTree, "CollisionMode", CPLString().Printf("%d", (int)_collisionMode));
-
- if (_selectionAppearance != saSelectionColor)
- Utility::CPLCreateXMLAttributeAndValue(psTree, "SelectionAppearance", CPLString().Printf("%d", (int)_selectionAppearance));
-
- if (_selectionColor != RGB(255, 255, 0))
- Utility::CPLCreateXMLAttributeAndValue(psTree, "SelectionColor", CPLString().Printf("%d", (int)_selectionColor));
-
- if (_selectionTransparency != 180)
- Utility::CPLCreateXMLAttributeAndValue(psTree, "SelectionTransparency", CPLString().Printf("%d", (int)_selectionTransparency));
-
- if (_minDrawingSize != 1)
- Utility::CPLCreateXMLAttributeAndValue(psTree, "MinDrawingSize", CPLString().Printf("%d", _minDrawingSize));
-
- // for in-memory shapefiles only
- if (_sourceType == sstInMemory)
- Utility::CPLCreateXMLAttributeAndValue(psTree, "ShpType", CPLString().Printf("%d", (int)this->_shpfiletype));
-
- s = OLE2CA(_sortField);
- if (s != "")
- Utility::CPLCreateXMLAttributeAndValue(psTree, "SortField", s);
-
- if (_sortAscending != VARIANT_FALSE)
- Utility::CPLCreateXMLAttributeAndValue(psTree, "SortAscending", CPLString().Printf("%d", (int)_sortAscending));
-
- // drawing options
- CPLXMLNode* node = ((CShapeDrawingOptions*)_defaultDrawOpt)->SerializeCore("DefaultDrawingOptions");
- if (node)
- {
- CPLAddXMLChild(psTree, node);
- }
-
- if(_selectionAppearance == saDrawingOptions)
- {
- CPLXMLNode* node = ((CShapeDrawingOptions*)_selectDrawOpt)->SerializeCore("SelectionDrawingOptions");
- if (node)
- {
- CPLAddXMLChild(psTree, node);
- }
- }
-
- // categories
- node = ((CShapefileCategories*)_categories)->SerializeCore("ShapefileCategoriesClass");
- if (node)
- {
- CPLAddXMLChild(psTree, node);
- }
-
- // labels
- CPLXMLNode* psLabels = ((CLabels*)_labels)->SerializeCore("LabelsClass");
- if (psLabels)
- {
- CPLAddXMLChild(psTree, psLabels);
- }
-
- // charts
- CPLXMLNode* psCharts = ((CCharts*)_charts)->SerializeCore("ChartsClass");
- if (psCharts)
- {
- CPLAddXMLChild(psTree, psCharts);
- }
-
- // ----------------------------------------------------
- // selection
- // ----------------------------------------------------
- long numSelected;
- this->get_NumSelected(&numSelected);
-
- if (numSelected > 0 && SaveSelection)
- {
- char* selection = new char[_shapeData.size() + 1];
- selection[_shapeData.size()] = '\0';
- for (unsigned int i = 0; i < _shapeData.size(); i++)
- {
- selection[i] = _shapeData[i]->selected() ? '1' : '0';
- }
-
- CPLXMLNode* nodeSelection = CPLCreateXMLElementAndValue(psTree, "Selection", selection);
- if (nodeSelection)
- {
- Utility::CPLCreateXMLAttributeAndValue(nodeSelection, "TotalCount", CPLString().Printf("%d", _shapeData.size()));
- Utility::CPLCreateXMLAttributeAndValue(nodeSelection, "SelectedCount", CPLString().Printf("%d", numSelected));
- }
- delete[] selection;
- }
-
- // ----------------------------------------------------
- // serialization of category indices
- // ----------------------------------------------------
- bool serializeCategories = false;
-
- for(size_t i = 0; i < _shapeData.size(); i++)
- {
- if (_shapeData[i]->category != -1) {
- serializeCategories = true;
- }
- }
-
- if (serializeCategories)
- {
- s = "";
- // doing it with CString is ugly of course, better to allocate a buffer
- CString temp;
- for(size_t i = 0; i < _shapeData.size(); i++) {
- temp.Format("%d,", _shapeData[i]->category);
- s += temp;
- }
-
- // when there are no indices assigned, write an empty node with Count = 0;
- // to signal, that categories must not be applied automatically (behavior for older versions)
- CPLXMLNode* nodeCats = CPLCreateXMLElementAndValue(psTree, "CategoryIndices", s.GetBuffer());
- if (nodeCats) {
- Utility::CPLCreateXMLAttributeAndValue(nodeCats, "Count", CPLString().Printf("%d", serializeCategories ? _shapeData.size() : 0));
- }
- }
-
- // ----------------------------------------------------
- // table
- // ----------------------------------------------------
- if (_table) {
- CPLXMLNode* psTable = ((CTableClass*)_table)->SerializeCore("TableClass");
- if (psTable) {
- CPLAddXMLChild(psTree, psTable);
- }
- }
- }
- return psTree;
+CPLXMLNode* CShapefile::SerializeCore(VARIANT_BOOL SaveSelection, CString ElementName, bool serializeCategories)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ USES_CONVERSION;
+
+ CPLXMLNode* psTree = CPLCreateXMLNode(nullptr, CXT_Element, ElementName);
+
+ if (psTree)
+ {
+ CString s = OLE2CA(_expression);
+ if (s != "")
+ Utility::CPLCreateXMLAttributeAndValue(psTree, "VisibilityExpression", s);
+
+
+ if (_useQTree != FALSE)
+ Utility::CPLCreateXMLAttributeAndValue(psTree, "UseQTree", CPLString().Printf("%d", (int)_useQTree));
+
+ if (_collisionMode != LocalList)
+ Utility::CPLCreateXMLAttributeAndValue(psTree, "CollisionMode",
+ CPLString().Printf("%d", (int)_collisionMode));
+
+ if (_selectionAppearance != saSelectionColor)
+ Utility::CPLCreateXMLAttributeAndValue(psTree, "SelectionAppearance",
+ CPLString().Printf("%d", (int)_selectionAppearance));
+
+ if (_selectionColor != RGB(255, 255, 0))
+ Utility::CPLCreateXMLAttributeAndValue(psTree, "SelectionColor",
+ CPLString().Printf("%d", (int)_selectionColor));
+
+ if (_selectionTransparency != 180)
+ Utility::CPLCreateXMLAttributeAndValue(psTree, "SelectionTransparency",
+ CPLString().Printf("%d", (int)_selectionTransparency));
+
+ if (_minDrawingSize != 1)
+ Utility::CPLCreateXMLAttributeAndValue(psTree, "MinDrawingSize", CPLString().Printf("%d", _minDrawingSize));
+
+ // for in-memory shapefiles only
+ if (_sourceType == sstInMemory)
+ Utility::CPLCreateXMLAttributeAndValue(psTree, "ShpType",
+ CPLString().Printf("%d", (int)this->_shpfiletype));
+
+ s = OLE2CA(_sortField);
+ if (s != "")
+ Utility::CPLCreateXMLAttributeAndValue(psTree, "SortField", s);
+
+ if (_sortAscending != VARIANT_FALSE)
+ Utility::CPLCreateXMLAttributeAndValue(psTree, "SortAscending",
+ CPLString().Printf("%d", (int)_sortAscending));
+
+ // drawing options
+ CPLXMLNode* node = ((CShapeDrawingOptions*)_defaultDrawOpt)->SerializeCore("DefaultDrawingOptions");
+ if (node)
+ {
+ CPLAddXMLChild(psTree, node);
+ }
+
+ if (_selectionAppearance == saDrawingOptions)
+ {
+ node = ((CShapeDrawingOptions*)_selectDrawOpt)->SerializeCore("SelectionDrawingOptions");
+ if (node)
+ {
+ CPLAddXMLChild(psTree, node);
+ }
+ }
+
+ // categories
+ node = ((CShapefileCategories*)_categories)->SerializeCore("ShapefileCategoriesClass");
+ if (node)
+ {
+ CPLAddXMLChild(psTree, node);
+ }
+
+ // labels
+ CPLXMLNode* psLabels = ((CLabels*)_labels)->SerializeCore("LabelsClass");
+ if (psLabels)
+ {
+ CPLAddXMLChild(psTree, psLabels);
+ }
+
+ // charts
+ CPLXMLNode* psCharts = ((CCharts*)_charts)->SerializeCore("ChartsClass");
+ if (psCharts)
+ {
+ CPLAddXMLChild(psTree, psCharts);
+ }
+
+ // ----------------------------------------------------
+ // selection
+ // ----------------------------------------------------
+ long numSelected;
+ this->get_NumSelected(&numSelected);
+
+ if (numSelected > 0 && SaveSelection)
+ {
+ auto* selection = new char[_shapeData.size() + 1];
+ selection[_shapeData.size()] = '\0';
+ for (unsigned int i = 0; i < _shapeData.size(); i++)
+ {
+ selection[i] = _shapeData[i]->selected() ? '1' : '0';
+ }
+
+ CPLXMLNode* nodeSelection = CPLCreateXMLElementAndValue(psTree, "Selection", selection);
+ if (nodeSelection)
+ {
+ Utility::CPLCreateXMLAttributeAndValue(nodeSelection, "TotalCount",
+ CPLString().Printf("%d", _shapeData.size()));
+ Utility::CPLCreateXMLAttributeAndValue(nodeSelection, "SelectedCount",
+ CPLString().Printf("%d", numSelected));
+ }
+ delete[] selection;
+ }
+
+ // ----------------------------------------------------
+ // serialization of category indices
+ // ----------------------------------------------------
+ // Paul Meems TODO: This variable comes in as a parameter as well.
+ // Is this correct?
+ bool serializeCategories = false;
+
+ for (auto& i : _shapeData)
+ {
+ if (i->category != -1)
+ {
+ serializeCategories = true;
+ }
+ }
+
+ if (serializeCategories)
+ {
+ s = "";
+ // doing it with CString is ugly of course, better to allocate a buffer
+ CString temp;
+ for (auto& i : _shapeData)
+ {
+ temp.Format("%d,", i->category);
+ s += temp;
+ }
+
+ // when there are no indices assigned, write an empty node with Count = 0;
+ // to signal, that categories must not be applied automatically (behavior for older versions)
+ CPLXMLNode* nodeCats = CPLCreateXMLElementAndValue(psTree, "CategoryIndices", s.GetBuffer());
+ if (nodeCats)
+ {
+ Utility::CPLCreateXMLAttributeAndValue(nodeCats, "Count",
+ CPLString().Printf(
+ "%d", serializeCategories ? _shapeData.size() : 0));
+ }
+ }
+
+ // ----------------------------------------------------
+ // table
+ // ----------------------------------------------------
+ if (_table)
+ {
+ CPLXMLNode* psTable = ((CTableClass*)_table)->SerializeCore("TableClass");
+ if (psTable)
+ {
+ CPLAddXMLChild(psTree, psTable);
+ }
+ }
+ }
+ return psTree;
}
// ********************************************************
@@ -2336,21 +2374,21 @@ STDMETHODIMP CShapefile::Serialize2(VARIANT_BOOL SaveSelection, VARIANT_BOOL Ser
// ********************************************************
STDMETHODIMP CShapefile::Deserialize(VARIANT_BOOL LoadSelection, BSTR newVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- USES_CONVERSION;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ USES_CONVERSION;
- CString s = OLE2CA(newVal);
- CPLXMLNode* node = CPLParseXMLString(s.GetString());
- if (node)
- {
- CPLXMLNode* nodeSf = CPLGetXMLNode(node, "=ShapefileClass");
- if (nodeSf)
- {
- this->DeserializeCore(VARIANT_TRUE, nodeSf);
- }
- CPLDestroyXMLNode(node);
- }
- return S_OK;
+ CString s = OLE2CA(newVal);
+ CPLXMLNode* node = CPLParseXMLString(s.GetString());
+ if (node)
+ {
+ CPLXMLNode* nodeSf = CPLGetXMLNode(node, "=ShapefileClass");
+ if (nodeSf)
+ {
+ this->DeserializeCore(VARIANT_TRUE, nodeSf);
+ }
+ CPLDestroyXMLNode(node);
+ }
+ return S_OK;
}
// ********************************************************
@@ -2358,173 +2396,173 @@ STDMETHODIMP CShapefile::Deserialize(VARIANT_BOOL LoadSelection, BSTR newVal)
// ********************************************************
bool CShapefile::DeserializeCore(VARIANT_BOOL LoadSelection, CPLXMLNode* node)
{
- USES_CONVERSION;
-
- if (!node )
- return false;
-
- CString s;
- s = CPLGetXMLValue( node, "VisibilityExpression", NULL );
- SysFreeString(_expression);
- _expression = A2BSTR(s);
-
- s = CPLGetXMLValue( node, "UseQTree", NULL );
- _useQTree = (s != "") ? (BOOL)atoi(s.GetString()) : FALSE;
-
- s = CPLGetXMLValue( node, "CollisionMode", NULL );
- _collisionMode = (s != "") ? (tkCollisionMode)atoi(s.GetString()) : LocalList;
-
- s = CPLGetXMLValue( node, "SelectionAppearance", NULL );
- _selectionAppearance = (s != "") ? (tkSelectionAppearance)atoi(s.GetString()): saSelectionColor;
-
- s = CPLGetXMLValue( node, "SelectionColor", NULL );
- _selectionColor = (s != "") ? (OLE_COLOR)atoi(s.GetString()) : RGB(255, 255, 0);
-
- s = CPLGetXMLValue( node, "SelectionTransparency", NULL );
- _selectionTransparency = (s != "") ? (unsigned char)atoi(s.GetString()) : 180;
-
- s = CPLGetXMLValue( node, "MinDrawingSize", NULL );
- _minDrawingSize = (s != "") ? atoi(s.GetString()) : 1;
-
- s = CPLGetXMLValue(node, "SortField", NULL);
- CComBSTR bstrSortField = A2W(s);
- this->put_SortField(bstrSortField);
-
- s = CPLGetXMLValue(node, "SortAscending", NULL);
- VARIANT_BOOL sortAsc = (s != "") ? (VARIANT_BOOL)atoi(s.GetString()) : VARIANT_FALSE;
- this->put_SortAscending(sortAsc);
-
- if (_sourceType == sstInMemory)
- {
- s = CPLGetXMLValue( node, "ShpType", NULL );
- if (s != "") {
- _shpfiletype = (ShpfileType)atoi(s.GetString());
- }
- }
-
- // drawing options
- CPLXMLNode* psChild = CPLGetXMLNode(node, "DefaultDrawingOptions");
- if (psChild) {
- ((CShapeDrawingOptions*)_defaultDrawOpt)->DeserializeCore(psChild);
- }
-
- if (_selectionAppearance == saDrawingOptions)
- {
- CPLXMLNode* psChild = CPLGetXMLNode(node, "SelectionDrawingOptions");
- if (psChild) {
- ((CShapeDrawingOptions*)_selectDrawOpt)->DeserializeCore(psChild);
- }
- }
-
- // Categories
- psChild = CPLGetXMLNode(node, "ShapefileCategoriesClass");
- if (psChild)
- {
- ((CShapefileCategories*)_categories)->DeserializeCore(psChild, false);
- }
-
- // category indices
- bool hasIndices = false;
- CPLXMLNode* nodeCats = CPLGetXMLNode(node, "CategoryIndices");
-
- if (nodeCats)
- {
- CString indices = CPLGetXMLValue(nodeCats, "=CategoryIndices", "");
- if (indices.GetLength() > 0)
- {
- s = CPLGetXMLValue(nodeCats, "Count", "0");
- long savedCount = atoi(s);
- int foundCount = 0;
- char* buffer = indices.GetBuffer();
- for (int i = 0; i < indices.GetLength(); i++) {
- if (buffer[i] == ',') {
- foundCount++;
- }
- }
-
- if (foundCount == savedCount && foundCount == _shapeData.size())
- {
- int size = _shapeData.size();
- int pos = 0, count = 0;
- CString ct;
- ct = indices.Tokenize(",", pos);
- while (ct.GetLength() != 0 && count < size)
- {
- _shapeData[count]->category = atoi(ct);
- ct = indices.Tokenize(",", pos);
- count++;
- };
- hasIndices = true;
- }
- }
- }
- else
- {
- // for older versions of file without indices apply previously loaded cats
- ((CShapefileCategories*)_categories)->ApplyExpressions();
- }
-
- // Labels
- psChild = CPLGetXMLNode(node, "LabelsClass");
- if (psChild)
- {
- ((CLabels*)_labels)->DeserializeCore(psChild);
- }
-
- // Charts
- psChild = CPLGetXMLNode(node, "ChartsClass");
- if (psChild)
- {
- ((CCharts*)_charts)->DeserializeCore(psChild);
- }
-
- // selection
- CPLXMLNode* nodeSelection = CPLGetXMLNode(node, "Selection");
- if (nodeSelection && LoadSelection)
- {
- this->SelectNone();
-
- s = CPLGetXMLValue(nodeSelection, "TotalCount", "0");
- long count = atoi(s);
- s = CPLGetXMLValue(nodeSelection, "=Selection", "");
- if (s.GetLength() == count && s.GetLength() == _shapeData.size())
- {
- char* selection = s.GetBuffer();
- for (unsigned int i = 0; i < _shapeData.size(); i++)
- {
- if (selection[i] == '1')
- {
- _shapeData[i]->selected(true);
- }
- }
- }
- }
-
-
- // table
- if (_table)
- {
- psChild = CPLGetXMLNode(node, "TableClass");
- if (psChild)
- {
- ((CTableClass*)_table)->DeserializeCore(psChild);
- }
- }
- return true;
+ USES_CONVERSION;
+
+ if (!node)
+ return false;
+
+ CString s = CPLGetXMLValue(node, "VisibilityExpression", nullptr);
+ SysFreeString(_expression);
+ _expression = A2BSTR(s);
+
+ s = CPLGetXMLValue(node, "UseQTree", nullptr);
+ _useQTree = s != "" ? (BOOL)atoi(s.GetString()) : FALSE;
+
+ s = CPLGetXMLValue(node, "CollisionMode", nullptr);
+ _collisionMode = s != "" ? (tkCollisionMode)atoi(s.GetString()) : LocalList;
+
+ s = CPLGetXMLValue(node, "SelectionAppearance", nullptr);
+ _selectionAppearance = s != "" ? (tkSelectionAppearance)atoi(s.GetString()) : saSelectionColor;
+
+ s = CPLGetXMLValue(node, "SelectionColor", nullptr);
+ _selectionColor = s != "" ? (OLE_COLOR)atoi(s.GetString()) : RGB(255, 255, 0);
+
+ s = CPLGetXMLValue(node, "SelectionTransparency", nullptr);
+ _selectionTransparency = s != "" ? (unsigned char)atoi(s.GetString()) : 180;
+
+ s = CPLGetXMLValue(node, "MinDrawingSize", nullptr);
+ _minDrawingSize = s != "" ? atoi(s.GetString()) : 1;
+
+ s = CPLGetXMLValue(node, "SortField", nullptr);
+ const CComBSTR bstrSortField = A2W(s);
+ this->put_SortField(bstrSortField);
+
+ s = CPLGetXMLValue(node, "SortAscending", nullptr);
+ const VARIANT_BOOL sortAsc = s != "" ? (VARIANT_BOOL)atoi(s.GetString()) : VARIANT_FALSE;
+ this->put_SortAscending(sortAsc);
+
+ if (_sourceType == sstInMemory)
+ {
+ s = CPLGetXMLValue(node, "ShpType", nullptr);
+ if (s != "")
+ {
+ _shpfiletype = (ShpfileType)atoi(s.GetString());
+ }
+ }
+
+ // drawing options
+ CPLXMLNode* psChild = CPLGetXMLNode(node, "DefaultDrawingOptions");
+ if (psChild)
+ {
+ ((CShapeDrawingOptions*)_defaultDrawOpt)->DeserializeCore(psChild);
+ }
+
+ if (_selectionAppearance == saDrawingOptions)
+ {
+ psChild = CPLGetXMLNode(node, "SelectionDrawingOptions");
+ if (psChild)
+ {
+ ((CShapeDrawingOptions*)_selectDrawOpt)->DeserializeCore(psChild);
+ }
+ }
+
+ // Categories
+ psChild = CPLGetXMLNode(node, "ShapefileCategoriesClass");
+ if (psChild)
+ {
+ ((CShapefileCategories*)_categories)->DeserializeCore(psChild, false);
+ }
+
+ CPLXMLNode* nodeCats = CPLGetXMLNode(node, "CategoryIndices");
+
+ if (nodeCats)
+ {
+ CString indices = CPLGetXMLValue(nodeCats, "=CategoryIndices", "");
+ if (indices.GetLength() > 0)
+ {
+ s = CPLGetXMLValue(nodeCats, "Count", "0");
+ const long savedCount = atoi(s);
+ int foundCount = 0;
+ char* buffer = indices.GetBuffer();
+ for (int i = 0; i < indices.GetLength(); i++)
+ {
+ if (buffer[i] == ',')
+ {
+ foundCount++;
+ }
+ }
+
+ if (foundCount == savedCount && foundCount == _shapeData.size())
+ {
+ const int size = _shapeData.size();
+ int pos = 0, count = 0;
+ CString ct = indices.Tokenize(",", pos);
+ while (ct.GetLength() != 0 && count < size)
+ {
+ _shapeData[count]->category = atoi(ct);
+ ct = indices.Tokenize(",", pos);
+ count++;
+ };
+ // bool hasIndices = true;
+ }
+ }
+ }
+ else
+ {
+ // for older versions of file without indices apply previously loaded cats
+ ((CShapefileCategories*)_categories)->ApplyExpressions();
+ }
+
+ // Labels
+ psChild = CPLGetXMLNode(node, "LabelsClass");
+ if (psChild)
+ {
+ ((CLabels*)_labels)->DeserializeCore(psChild);
+ }
+
+ // Charts
+ psChild = CPLGetXMLNode(node, "ChartsClass");
+ if (psChild)
+ {
+ ((CCharts*)_charts)->DeserializeCore(psChild);
+ }
+
+ // selection
+ CPLXMLNode* nodeSelection = CPLGetXMLNode(node, "Selection");
+ if (nodeSelection && LoadSelection)
+ {
+ this->SelectNone();
+
+ s = CPLGetXMLValue(nodeSelection, "TotalCount", "0");
+ const long count = atoi(s);
+ s = CPLGetXMLValue(nodeSelection, "=Selection", "");
+ if (s.GetLength() == count && s.GetLength() == _shapeData.size())
+ {
+ char* selection = s.GetBuffer();
+ for (unsigned int i = 0; i < _shapeData.size(); i++)
+ {
+ if (selection[i] == '1')
+ {
+ _shapeData[i]->selected(true);
+ }
+ }
+ }
+ }
+
+
+ // table
+ if (_table)
+ {
+ psChild = CPLGetXMLNode(node, "TableClass");
+ if (psChild)
+ {
+ ((CTableClass*)_table)->DeserializeCore(psChild);
+ }
+ }
+ return true;
}
#pragma endregion
-
#pragma region Projection
// *****************************************************************
// get_Projection()
// *****************************************************************
-STDMETHODIMP CShapefile::get_Projection(BSTR *pVal)
+STDMETHODIMP CShapefile::get_Projection(BSTR* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- _geoProjection->ExportToProj4(pVal);
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ _geoProjection->ExportToProj4(pVal);
+ return S_OK;
}
// *****************************************************************
@@ -2532,17 +2570,17 @@ STDMETHODIMP CShapefile::get_Projection(BSTR *pVal)
// *****************************************************************
STDMETHODIMP CShapefile::put_Projection(BSTR proj4Projection)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- USES_CONVERSION;
-
- VARIANT_BOOL vbretval;
- _geoProjection->ImportFromProj4(proj4Projection, &vbretval);
- if (vbretval)
- {
- CComBSTR bstrFilename(_prjfileName);
- _geoProjection->WriteToFileEx(bstrFilename, VARIANT_TRUE, &vbretval);
- }
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ USES_CONVERSION;
+
+ VARIANT_BOOL vbretval;
+ _geoProjection->ImportFromProj4(proj4Projection, &vbretval);
+ if (vbretval)
+ {
+ const CComBSTR bstrFilename(_prjfileName);
+ _geoProjection->WriteToFileEx(bstrFilename, VARIANT_TRUE, &vbretval);
+ }
+ return S_OK;
}
// *****************************************************************
@@ -2550,12 +2588,12 @@ STDMETHODIMP CShapefile::put_Projection(BSTR proj4Projection)
// *****************************************************************
STDMETHODIMP CShapefile::get_GeoProjection(IGeoProjection** retVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- if (_geoProjection)
- _geoProjection->AddRef();
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ if (_geoProjection)
+ _geoProjection->AddRef();
- *retVal = _geoProjection;
- return S_OK;
+ *retVal = _geoProjection;
+ return S_OK;
}
// *****************************************************************
@@ -2563,15 +2601,30 @@ STDMETHODIMP CShapefile::get_GeoProjection(IGeoProjection** retVal)
// *****************************************************************
STDMETHODIMP CShapefile::put_GeoProjection(IGeoProjection* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- ComHelper::SetRef((IDispatch*)pVal, (IDispatch**)&_geoProjection, false);
- if (_prjfileName.GetLength() != 0)
- {
- VARIANT_BOOL vbretval;
- CComBSTR bstr(_prjfileName);
- _geoProjection->WriteToFileEx(bstr, VARIANT_TRUE, &vbretval);
- }
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ ComHelper::SetRef((IDispatch*)pVal, (IDispatch**)&_geoProjection, false);
+ if (_prjfileName.GetLength() != 0)
+ {
+ VARIANT_BOOL vbretval;
+ const CComBSTR bstr(_prjfileName);
+ _geoProjection->WriteToFileEx(bstr, VARIANT_TRUE, &vbretval);
+ }
+ return S_OK;
+}
+
+// ****************************************************************
+// get_IsGeographicProjection
+// ****************************************************************
+STDMETHODIMP CShapefile::get_IsGeographicProjection(VARIANT_BOOL* pVal)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+
+ *pVal = VARIANT_FALSE;
+
+ if (_geoProjection)
+ _geoProjection->get_IsGeographic(pVal);
+
+ return S_OK;
}
// *****************************************************************
@@ -2579,11 +2632,11 @@ STDMETHODIMP CShapefile::put_GeoProjection(IGeoProjection* pVal)
// *****************************************************************
STDMETHODIMP CShapefile::Reproject(IGeoProjection* newProjection, LONG* reprojectedCount, IShapefile** retVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
-
- if (!this->ReprojectCore(newProjection, reprojectedCount, retVal, false))
- *retVal = NULL;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+
+ if (!this->ReprojectCore(newProjection, reprojectedCount, retVal, false))
+ *retVal = nullptr;
+ return S_OK;
}
// *****************************************************************
@@ -2591,200 +2644,204 @@ STDMETHODIMP CShapefile::Reproject(IGeoProjection* newProjection, LONG* reprojec
// *****************************************************************
STDMETHODIMP CShapefile::ReprojectInPlace(IGeoProjection* newProjection, LONG* reprojectedCount, VARIANT_BOOL* retVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- if (!_isEditingShapes)
- {
- ErrorMessage(tkSHPFILE_NOT_IN_EDIT_MODE);
- *retVal = VARIANT_FALSE;
- }
- else
- {
- if (this->ReprojectCore(newProjection, reprojectedCount, NULL, true))
- {
- // spatial index must be deleted, as it became useful all the same
- VARIANT_BOOL vb;
- RemoveSpatialIndex(&vb);
-
- // update qtree
- if (_useQTree)
- GenerateQTree();
-
- VARIANT_BOOL vbretval;
- this->RefreshExtents(&vbretval);
- *retVal = VARIANT_TRUE;
- return S_OK;
- }
- *retVal = NULL;
- }
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ if (!_isEditingShapes)
+ {
+ ErrorMessage(tkSHPFILE_NOT_IN_EDIT_MODE);
+ *retVal = VARIANT_FALSE;
+ }
+ else
+ {
+ if (this->ReprojectCore(newProjection, reprojectedCount, nullptr, true))
+ {
+ // spatial index must be deleted, as it became useful all the same
+ VARIANT_BOOL vb;
+ RemoveSpatialIndex(&vb);
+
+ // update qtree
+ if (_useQTree)
+ GenerateQTree();
+
+ VARIANT_BOOL vbretval;
+ this->RefreshExtents(&vbretval);
+ *retVal = VARIANT_TRUE;
+ return S_OK;
+ }
+ *retVal = NULL;
+ }
+ return S_OK;
}
// *****************************************************************
// ReprojectCore()
// *****************************************************************
-bool CShapefile::ReprojectCore(IGeoProjection* newProjection, LONG* reprojectedCount, IShapefile** retVal, bool reprojectInPlace)
-{
- // ------------------------------------------------------
- // Validation
- // ------------------------------------------------------
- if (!newProjection)
- {
- ErrorMessage(tkUNEXPECTED_NULL_PARAMETER);
- return false;
- }
-
- VARIANT_BOOL isEmpty1, isEmpty2;
- newProjection->get_IsEmpty(&isEmpty1);
- _geoProjection->get_IsEmpty(&isEmpty2);
- if (isEmpty1 || isEmpty2)
- {
- ErrorMessage(tkPROJECTION_NOT_INITIALIZED);
- return false;
- }
-
- if (!ValidateInput(this, "Reproject/ReprojectInPlace", "this", VARIANT_FALSE))
- return false;
-
- m_globalSettings.gdalErrorMessage = "";
- OGRSpatialReference* projSource = ((CGeoProjection*)_geoProjection)->get_SpatialReference();
- OGRSpatialReference* projTarget = ((CGeoProjection*)newProjection)->get_SpatialReference();
-
- OGRCoordinateTransformation* transf = OGRCreateCoordinateTransformation( projSource, projTarget );
- if (!transf)
- {
- m_globalSettings.gdalErrorMessage = CPLGetLastErrorMsg();
- ErrorMessage(tkFAILED_TO_REPROJECT);
- return false;
- }
-
- // ------------------------------------------------------
- // Creating output
- // ------------------------------------------------------
- if (!reprojectInPlace)
- this->Clone(retVal);
-
- // ------------------------------------------------------
- // Processing
- // ------------------------------------------------------
- CComVariant var;
- long numShapes = _shapeData.size();
- long count = 0;
-
- long numFields, percent = 0;
- this->get_NumFields(&numFields);
-
- VARIANT_BOOL vb = VARIANT_FALSE;
- *reprojectedCount = 0;
-
- for (long i = 0; i < numShapes; i++)
- {
- CallbackHelper::Progress(_globalCallback, i, numShapes, "Reprojecting...", _key, percent);
-
- IShape* shp = NULL;
- this->GetValidatedShape(i, &shp);
- if (!shp) continue;
-
- if (!reprojectInPlace)
- {
- IShape* shpNew = NULL;
- shp->Clone(&shpNew);
- shp->Release();
- shp = shpNew;
- }
-
- if (shp)
- {
- long numPoints;
- shp->get_NumPoints(&numPoints);
-
- if(numPoints > 0)
- {
- double* x = new double[numPoints];
- double* y = new double[numPoints];
-
- // extracting coordinates
- for (long j = 0; j < numPoints; j++)
- {
- shp->get_XY(j, x + j, y + j, &vb);
- }
-
- // will work faster after embedding to the CShape class
- BOOL res = transf->Transform( numPoints, x, y);
- if (!res)
- {
- if (m_globalSettings.gdalErrorMessage == "")
- m_globalSettings.gdalErrorMessage = CPLGetLastErrorMsg();
- }
- else
- {
- // saving updated coordinates
- for (long j = 0; j < numPoints; j++)
- {
- shp->put_XY(j, x[j], y[j], &vb);
- }
-
- if (!reprojectInPlace)
- {
- (*retVal)->get_NumShapes(&count);
- (*retVal)->EditInsertShape(shp, &count, &vb);
-
- // copying attributes
- for (long j = 0; j < numFields; j++)
- {
- this->get_CellValue(j, i, &var);
- (*retVal)->EditCellValue(j, i, var, &vb);
- }
- }
- (*reprojectedCount)++;
- }
- delete[] x; delete[] y;
- }
- shp->Release();
- }
- }
-
- if (transf)
- {
- OGRCoordinateTransformation::DestroyCT(transf);
- transf = NULL;
- }
-
- // When creating the new shapefile was successfull:
- if (vb)
- {
- // setting new projection
- if (reprojectInPlace)
- {
- _geoProjection->CopyFrom(newProjection, &vb);
- }
- else
- {
- IGeoProjection* proj = NULL;
- (*retVal)->get_GeoProjection(&proj);
- if (proj)
- {
- proj->CopyFrom(newProjection, &vb);
- proj->Release();
- }
- }
- }
-
- ShapefileHelper::ClearShapefileModifiedFlag((*retVal)); // inserted shapes were marked as modified, correct this
-
- // --------------------------------------
- // Output validation
- // --------------------------------------
- CallbackHelper::ProgressCompleted(_globalCallback, _key);
-
- if (!reprojectInPlace) {
- this->ValidateOutput(retVal, "Reproject/ReprojectInPlace", "Shapefile", false);
- }
- else {
- this->ValidateOutput(this, "Reproject/ReprojectInPlace", "Shapefile", false);
- }
-
- // it's critical to set correct projection, so false will be returned if it wasn't done
- return vb ? true : false;
+bool CShapefile::ReprojectCore(IGeoProjection* newProjection, LONG* reprojectedCount, IShapefile** retVal,
+ bool reprojectInPlace)
+{
+ // ------------------------------------------------------
+ // Validation
+ // ------------------------------------------------------
+ if (!newProjection)
+ {
+ ErrorMessage(tkUNEXPECTED_NULL_PARAMETER);
+ return false;
+ }
+
+ VARIANT_BOOL isEmpty1, isEmpty2;
+ newProjection->get_IsEmpty(&isEmpty1);
+ _geoProjection->get_IsEmpty(&isEmpty2);
+ if (isEmpty1 || isEmpty2)
+ {
+ ErrorMessage(tkPROJECTION_NOT_INITIALIZED);
+ return false;
+ }
+
+ if (!ValidateInput(this, "Reproject/ReprojectInPlace", "this", VARIANT_FALSE))
+ return false;
+
+ m_globalSettings.gdalErrorMessage = "";
+ OGRSpatialReference* projSource = ((CGeoProjection*)_geoProjection)->get_SpatialReference();
+ OGRSpatialReference* projTarget = ((CGeoProjection*)newProjection)->get_SpatialReference();
+
+ OGRCoordinateTransformation* transf = OGRCreateCoordinateTransformation(projSource, projTarget);
+ if (!transf)
+ {
+ m_globalSettings.gdalErrorMessage = CPLGetLastErrorMsg();
+ ErrorMessage(tkFAILED_TO_REPROJECT);
+ return false;
+ }
+
+ // ------------------------------------------------------
+ // Creating output
+ // ------------------------------------------------------
+ if (!reprojectInPlace)
+ this->Clone(retVal);
+
+ // ------------------------------------------------------
+ // Processing
+ // ------------------------------------------------------
+ CComVariant var;
+ const long numShapes = _shapeData.size();
+ long count = 0;
+
+ long numFields, percent = 0;
+ this->get_NumFields(&numFields);
+
+ VARIANT_BOOL vb = VARIANT_FALSE;
+ *reprojectedCount = 0;
+
+ for (long i = 0; i < numShapes; i++)
+ {
+ CallbackHelper::Progress(_globalCallback, i, numShapes, "Reprojecting...", _key, percent);
+
+ IShape* shp = nullptr;
+ this->GetValidatedShape(i, &shp);
+ if (!shp) continue;
+
+ if (!reprojectInPlace)
+ {
+ IShape* shpNew = nullptr;
+ shp->Clone(&shpNew);
+ shp->Release();
+ shp = shpNew;
+ }
+
+ if (shp)
+ {
+ long numPoints;
+ shp->get_NumPoints(&numPoints);
+
+ if (numPoints > 0)
+ {
+ auto* x = new double[numPoints];
+ auto* y = new double[numPoints];
+
+ // extracting coordinates
+ for (long j = 0; j < numPoints; j++)
+ {
+ shp->get_XY(j, x + j, y + j, &vb);
+ }
+
+ // will work faster after embedding to the CShape class
+ const BOOL res = transf->Transform(numPoints, x, y);
+ if (!res)
+ {
+ if (m_globalSettings.gdalErrorMessage == "")
+ m_globalSettings.gdalErrorMessage = CPLGetLastErrorMsg();
+ }
+ else
+ {
+ // saving updated coordinates
+ for (long j = 0; j < numPoints; j++)
+ {
+ shp->put_XY(j, x[j], y[j], &vb);
+ }
+
+ if (!reprojectInPlace)
+ {
+ (*retVal)->get_NumShapes(&count);
+ (*retVal)->EditInsertShape(shp, &count, &vb);
+
+ // copying attributes
+ for (long j = 0; j < numFields; j++)
+ {
+ this->get_CellValue(j, i, &var);
+ (*retVal)->EditCellValue(j, i, var, &vb);
+ }
+ }
+ (*reprojectedCount)++;
+ }
+ delete[] x;
+ delete[] y;
+ }
+ shp->Release();
+ }
+ }
+
+ if (transf)
+ {
+ OGRCoordinateTransformation::DestroyCT(transf);
+ transf = nullptr;
+ }
+
+ // When creating the new shapefile was successfull:
+ if (vb)
+ {
+ // setting new projection
+ if (reprojectInPlace)
+ {
+ _geoProjection->CopyFrom(newProjection, &vb);
+ }
+ else
+ {
+ IGeoProjection* proj = nullptr;
+ (*retVal)->get_GeoProjection(&proj);
+ if (proj)
+ {
+ proj->CopyFrom(newProjection, &vb);
+ proj->Release();
+ }
+ }
+ }
+
+ ShapefileHelper::ClearShapefileModifiedFlag(*retVal); // inserted shapes were marked as modified, correct this
+
+ // --------------------------------------
+ // Output validation
+ // --------------------------------------
+ CallbackHelper::ProgressCompleted(_globalCallback, _key);
+
+ if (!reprojectInPlace)
+ {
+ this->ValidateOutput(retVal, "Reproject/ReprojectInPlace", "Shapefile", false);
+ }
+ else
+ {
+ this->ValidateOutput(this, "Reproject/ReprojectInPlace", "Shapefile", false);
+ }
+
+ // it's critical to set correct projection, so false will be returned if it wasn't done
+ return vb != 0;
}
#pragma endregion
@@ -2793,12 +2850,12 @@ bool CShapefile::ReprojectCore(IGeoProjection* newProjection, LONG* reprojectedC
// *****************************************************************
STDMETHODIMP CShapefile::FixUpShapes(IShapefile** retVal, VARIANT_BOOL* fixed)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
-
- // MWGIS-90: default to all shapes:
- FixUpShapes2(VARIANT_FALSE, retVal, fixed);
-
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+
+ // MWGIS-90: default to all shapes:
+ FixUpShapes2(VARIANT_FALSE, retVal, fixed);
+
+ return S_OK;
}
// *********************************************************
@@ -2806,17 +2863,18 @@ STDMETHODIMP CShapefile::FixUpShapes(IShapefile** retVal, VARIANT_BOOL* fixed)
// *********************************************************
STDMETHODIMP CShapefile::FixUpShapes2(VARIANT_BOOL SelectedOnly, IShapefile** result, VARIANT_BOOL* fixed)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *fixed = VARIANT_FALSE;
+ *fixed = VARIANT_FALSE;
- if (*result == NULL) {
- Clone(result);
- }
+ if (*result == nullptr)
+ {
+ Clone(result);
+ }
- *fixed = FixupShapesCore(SelectedOnly, *result);
+ *fixed = FixupShapesCore(SelectedOnly, *result);
- return S_OK;
+ return S_OK;
}
// *********************************************************
@@ -2824,180 +2882,208 @@ STDMETHODIMP CShapefile::FixUpShapes2(VARIANT_BOOL SelectedOnly, IShapefile** re
// *********************************************************
VARIANT_BOOL CShapefile::FixupShapesCore(VARIANT_BOOL selectedOnly, IShapefile* result)
{
- if (!result) return VARIANT_FALSE;
+ if (!result) return VARIANT_FALSE;
- tkUnitsOfMeasure units;
- _geoProjection->get_LinearUnits(&units);
+ tkUnitsOfMeasure units;
+ _geoProjection->get_LinearUnits(&units);
- long numFields;
- this->get_NumFields(&numFields);
+ long numFields;
+ this->get_NumFields(&numFields);
- long percent = 0;
- int numShapes = _shapeData.size();
- VARIANT_BOOL fixed = VARIANT_TRUE;
+ long percent = 0;
+ const int numShapes = _shapeData.size();
+ // VARIANT_BOOL fixed = VARIANT_TRUE;
- for (int i = 0; i < numShapes; i++)
- {
- CallbackHelper::Progress(_globalCallback, i, numShapes, "Fixing...", _key, percent);
+ for (int i = 0; i < numShapes; i++)
+ {
+ CallbackHelper::Progress(_globalCallback, i, numShapes, "Fixing...", _key, percent);
- if (!ShapeAvailable(i, selectedOnly))
- continue;
+ if (!ShapeAvailable(i, selectedOnly))
+ continue;
- IShape* shp = NULL;
- get_Shape(i, &shp);
- if (!shp) {
- continue;
- }
+ IShape* shp = nullptr;
+ get_Shape(i, &shp);
+ if (!shp)
+ {
+ continue;
+ }
- IShape* shpNew = NULL;
- shp->FixUp2(units, &shpNew);
- shp->Release();
+ IShape* shpNew = nullptr;
+ shp->FixUp2(units, &shpNew);
+ shp->Release();
- // failed to fix the shape? skip it.
- if (!shpNew) {
- CString s;
- s.Format("Failed to fix shape: %d", i);
- CallbackHelper::ErrorMsg("Shapefile", NULL, "", s);
- continue;
- }
+ // failed to fix the shape? skip it.
+ if (!shpNew)
+ {
+ CString s;
+ s.Format("Failed to fix shape: %d", i);
+ CallbackHelper::ErrorMsg("Shapefile", nullptr, "", s);
+ continue;
+ }
- long shapeIndex = 0;
- result->get_NumShapes(&shapeIndex);
+ long shapeIndex = 0;
+ result->get_NumShapes(&shapeIndex);
- VARIANT_BOOL vbretval = VARIANT_FALSE;
- result->EditInsertShape(shpNew, &shapeIndex, &vbretval);
- shpNew->Release();
+ VARIANT_BOOL vbretval = VARIANT_FALSE;
+ result->EditInsertShape(shpNew, &shapeIndex, &vbretval);
+ shpNew->Release();
- if (vbretval)
- {
- // TODO: extract, it's definitely used in other methods as well
- CComVariant var;
- for (int iFld = 0; iFld < numFields; iFld++)
- {
- get_CellValue(iFld, i, &var);
- result->EditCellValue(iFld, shapeIndex, var, &vbretval);
- }
- }
- }
+ if (vbretval)
+ {
+ // TODO: extract, it's definitely used in other methods as well
+ CComVariant var;
+ for (int iFld = 0; iFld < numFields; iFld++)
+ {
+ get_CellValue(iFld, i, &var);
+ result->EditCellValue(iFld, shapeIndex, var, &vbretval);
+ }
+ }
+ }
- CallbackHelper::ProgressCompleted(_globalCallback, _key);
+ CallbackHelper::ProgressCompleted(_globalCallback, _key);
- return VARIANT_TRUE;
+ return VARIANT_TRUE;
}
// *********************************************************
// GetRelatedShapes()
// *********************************************************
-STDMETHODIMP CShapefile::GetRelatedShapes(long referenceIndex, tkSpatialRelation relation, VARIANT* resultArray, VARIANT_BOOL* retval)
-{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *retval = VARIANT_FALSE;
- if (referenceIndex < 0 || referenceIndex > (long)_shapeData.size())
- {
- this->ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
- return S_OK;
- }
-
- IShape* shp = NULL;
- this->get_Shape(referenceIndex, &shp);
- if (shp)
- {
- this->GetRelatedShapeCore(shp, referenceIndex, relation, resultArray, retval);
- shp->Release();
- }
- return S_OK;
+STDMETHODIMP CShapefile::GetRelatedShapes(long referenceIndex, tkSpatialRelation relation, VARIANT* resultArray,
+ VARIANT_BOOL* retval)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ *retval = VARIANT_FALSE;
+ if (referenceIndex < 0 || referenceIndex > (long)_shapeData.size())
+ {
+ this->ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
+ return S_OK;
+ }
+
+ IShape* shp = nullptr;
+ this->get_Shape(referenceIndex, &shp);
+ if (shp)
+ {
+ this->GetRelatedShapeCore(shp, referenceIndex, relation, resultArray, retval);
+ shp->Release();
+ }
+ return S_OK;
}
// *********************************************************
// GetRelatedShapes2()
// *********************************************************
-STDMETHODIMP CShapefile::GetRelatedShapes2(IShape* referenceShape, tkSpatialRelation relation, VARIANT* resultArray, VARIANT_BOOL* retval)
+STDMETHODIMP CShapefile::GetRelatedShapes2(IShape* referenceShape, tkSpatialRelation relation, VARIANT* resultArray,
+ VARIANT_BOOL* retval)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *retval = VARIANT_FALSE;
- if (!referenceShape)
- {
- this->ErrorMessage(tkUNEXPECTED_NULL_PARAMETER);
- return S_OK;
- }
-
- this->GetRelatedShapeCore(referenceShape, -1, relation, resultArray, retval);
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ *retval = VARIANT_FALSE;
+ if (!referenceShape)
+ {
+ this->ErrorMessage(tkUNEXPECTED_NULL_PARAMETER);
+ return S_OK;
+ }
+
+ this->GetRelatedShapeCore(referenceShape, -1, relation, resultArray, retval);
+ return S_OK;
}
// *********************************************************
// GetRelatedShapeCore()
// *********************************************************
-void CShapefile::GetRelatedShapeCore(IShape* referenceShape, long referenceIndex, tkSpatialRelation relation, VARIANT* resultArray, VARIANT_BOOL* retval)
-{
- if (relation == srDisjoint)
- {
- // TODO: implement
- ErrorMessage(tkMETHOD_NOT_IMPLEMENTED);
- return;
- }
-
- this->ReadGeosGeometries(VARIANT_TRUE);
-
- // turns on the quad tree
- VARIANT_BOOL useQTree = VARIANT_FALSE;
- this->get_UseQTree(&useQTree);
- if (!useQTree) this->put_UseQTree(VARIANT_TRUE);
-
- double xMin, xMax, yMin, yMax;
- if(((CShape*)referenceShape)->get_ExtentsXY(xMin, yMin, xMax, yMax))
- {
- QTreeExtent query(xMin, xMax, yMax, yMin);
- std::vector shapes = this->_qtree->GetNodes(query);
- std::vector arr;
-
- GEOSGeom geomBase = NULL;
- if (referenceIndex > 0)
- {
- geomBase = _shapeData[referenceIndex]->geosGeom;
- }
- else
- {
- geomBase = GeosConverter::ShapeToGeom(referenceShape);
- }
-
- if (geomBase)
- {
- for (size_t i = 0; i < shapes.size(); i++)
- {
- if (i == referenceIndex)
- continue; // it doesn't make sense to compare the shape with itself
-
- GEOSGeom geom = _shapeData[shapes[i]]->geosGeom;
- if (geom != NULL)
- {
- char res = 0;
- switch (relation)
- {
- case srContains: res = GeosHelper::Contains(geomBase, geom); break;
- case srCrosses: res = GeosHelper::Crosses(geomBase, geom); break;
- case srEquals: res = GeosHelper::Equals(geomBase, geom); break;
- case srIntersects: res = GeosHelper::Intersects(geomBase, geom); break;
- case srOverlaps: res = GeosHelper::Overlaps(geomBase, geom); break;
- case srTouches: res = GeosHelper::Touches(geomBase, geom); break;
- case srWithin: res = GeosHelper::Within(geomBase, geom); break;
- }
- if (res)
- {
- arr.push_back(shapes[i]);
- }
- }
- }
-
- if (referenceIndex == -1)
- GeosHelper::DestroyGeometry(geomBase); // the geometry was created in this function so it must be destroyed
- }
-
- *retval = Templates::Vector2SafeArray(&arr, VT_I4, resultArray);
- }
-
- // Don't clear the list here as function may be called in a loop
- //this->ClearCachedGeometries();
+void CShapefile::GetRelatedShapeCore(IShape* referenceShape, long referenceIndex, tkSpatialRelation relation,
+ VARIANT* resultArray, VARIANT_BOOL* retval)
+{
+ if (relation == srDisjoint)
+ {
+ // TODO: implement
+ ErrorMessage(tkMETHOD_NOT_IMPLEMENTED);
+ return;
+ }
+
+ // rather than generate geometries for all shapes,
+ // only generate for those within qtree extent (see below)
+ //this->ReadGeosGeometries(VARIANT_FALSE);
+
+ // turns on the quad tree
+ VARIANT_BOOL useQTree = VARIANT_FALSE;
+ this->get_UseQTree(&useQTree);
+ if (!useQTree) this->put_UseQTree(VARIANT_TRUE);
+
+ double xMin, xMax, yMin, yMax;
+ if (((CShape*)referenceShape)->get_ExtentsXY(xMin, yMin, xMax, yMax))
+ {
+ const QTreeExtent query(xMin, xMax, yMax, yMin);
+ std::vector shapes = this->_qtree->GetNodes(query);
+ std::vector arr;
+
+ // generate GEOS geometries only for shapes within qtree extent
+ for (size_t i = 0; i < shapes.size(); i++)
+ // minimize work by 'select'ing necessary shapes
+ this->put_ShapeSelected(shapes[i], VARIANT_TRUE);
+ // now generate only for 'select'ed shapes
+ this->ReadGeosGeometries(VARIANT_TRUE);
+ // don't leave shapes 'select'ed
+ for (size_t i = 0; i < shapes.size(); i++)
+ this->put_ShapeSelected(shapes[i], VARIANT_FALSE);
+
+ GEOSGeom geomBase;
+ if (referenceIndex > 0)
+ {
+ geomBase = _shapeData[referenceIndex]->geosGeom;
+ }
+ else
+ {
+ geomBase = GeosConverter::ShapeToGeom(referenceShape);
+ }
+
+ if (geomBase)
+ {
+ for (size_t i = 0; i < shapes.size(); i++)
+ {
+ if (i == referenceIndex)
+ continue; // it doesn't make sense to compare the shape with itself
+
+ // ReSharper disable once CppLocalVariableMayBeConst
+ GEOSGeom geom = _shapeData[shapes[i]]->geosGeom;
+ if (geom != nullptr)
+ {
+ char res = 0;
+ switch (relation)
+ {
+ case srContains: res = GeosHelper::Contains(geomBase, geom);
+ break;
+ case srCrosses: res = GeosHelper::Crosses(geomBase, geom);
+ break;
+ case srEquals: res = GeosHelper::Equals(geomBase, geom);
+ break;
+ case srIntersects: res = GeosHelper::Intersects(geomBase, geom);
+ break;
+ case srOverlaps: res = GeosHelper::Overlaps(geomBase, geom);
+ break;
+ case srTouches: res = GeosHelper::Touches(geomBase, geom);
+ break;
+ case srWithin: res = GeosHelper::Within(geomBase, geom);
+ break;
+ case srDisjoint: break;
+ default: ;
+ }
+ if (res)
+ {
+ arr.push_back(shapes[i]);
+ }
+ }
+ }
+
+ if (referenceIndex == -1)
+ GeosHelper::DestroyGeometry(geomBase);
+ // the geometry was created in this function so it must be destroyed
+ }
+
+ *retval = Templates::Vector2SafeArray(&arr, VT_I4, resultArray);
+ }
+
+ // Don't clear the list here as function may be called in a loop
+ //this->ClearCachedGeometries();
}
// ***************************************************
@@ -3005,33 +3091,33 @@ void CShapefile::GetRelatedShapeCore(IShape* referenceShape, long referenceIndex
// ***************************************************
STDMETHODIMP CShapefile::get_Identifiable(VARIANT_BOOL* retVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *retVal = _hotTracking;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ *retVal = _hotTracking;
+ return S_OK;
}
STDMETHODIMP CShapefile::put_Identifiable(VARIANT_BOOL newVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- _hotTracking = newVal;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ _hotTracking = newVal;
+ return S_OK;
}
// *****************************************************************
// EditAddField()
// *****************************************************************
-STDMETHODIMP CShapefile::EditAddField(BSTR name, FieldType type, int precision, int width, long *fieldIndex)
+STDMETHODIMP CShapefile::EditAddField(BSTR name, FieldType type, int precision, int width, long* fieldIndex)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- if (!this->_table)
- {
- this->ErrorMessage(tkDBF_FILE_DOES_NOT_EXIST);
- }
- else
- {
- _table->EditAddField(name, type, precision, width, fieldIndex);
- }
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ if (!this->_table)
+ {
+ this->ErrorMessage(tkDBF_FILE_DOES_NOT_EXIST);
+ }
+ else
+ {
+ _table->EditAddField(name, type, precision, width, fieldIndex);
+ }
+ return S_OK;
}
// *****************************************************************
@@ -3039,52 +3125,53 @@ STDMETHODIMP CShapefile::EditAddField(BSTR name, FieldType type, int precision,
// *****************************************************************
STDMETHODIMP CShapefile::EditAddShape(IShape* shape, long* shapeIndex)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
- VARIANT_BOOL retval;
- *shapeIndex = _shapeData.size();
+ VARIANT_BOOL retval;
+ *shapeIndex = _shapeData.size();
- EditInsertShape(shape, shapeIndex, &retval);
+ EditInsertShape(shape, shapeIndex, &retval);
- if (retval == VARIANT_FALSE)
- *shapeIndex = -1;
+ if (retval == VARIANT_FALSE)
+ *shapeIndex = -1;
- return S_OK;
+ return S_OK;
}
// *****************************************************************
// GetClosestVertex()
// *****************************************************************
-STDMETHODIMP CShapefile::GetClosestVertex(double x, double y, double maxDistance,
- long* shapeIndex, long* pointIndex, double* distance, VARIANT_BOOL* retVal)
-{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
-
- *retVal = VARIANT_FALSE;
- *shapeIndex = -1;
- *pointIndex = -1;
-
- bool result= false;
- if (maxDistance <= 0.0)
- {
- // search through all shapefile
- std::vector ids;
- for (size_t i = 0; i < _shapeData.size(); i++) {
- ids.push_back(i);
- }
- result = ShapefileHelper::GetClosestPoint(this, x, y, maxDistance, ids, shapeIndex, pointIndex, *distance);
- }
- else
- {
- std::vector ids;
- Extent box(x - maxDistance, x + maxDistance, y - maxDistance, y + maxDistance);
- if (this->SelectShapesCore(box, 0.0, SelectMode::INTERSECTION, ids, false))
- {
- result = ShapefileHelper::GetClosestPoint(this, x, y, maxDistance, ids, shapeIndex, pointIndex, *distance);
- }
- }
- *retVal = result ? VARIANT_TRUE: VARIANT_FALSE;
- return S_OK;
+STDMETHODIMP CShapefile::GetClosestVertex(double x, double y, double maxDistance,
+ long* shapeIndex, long* pointIndex, double* distance, VARIANT_BOOL* retVal)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+
+ *retVal = VARIANT_FALSE;
+ *shapeIndex = -1;
+ *pointIndex = -1;
+
+ bool result = false;
+ if (maxDistance <= 0.0)
+ {
+ // search through all shapefile
+ std::vector ids;
+ for (size_t i = 0; i < _shapeData.size(); i++)
+ {
+ ids.push_back(i);
+ }
+ result = ShapefileHelper::GetClosestPoint(this, x, y, maxDistance, ids, shapeIndex, pointIndex, *distance);
+ }
+ else
+ {
+ std::vector ids;
+ Extent box(x - maxDistance, x + maxDistance, y - maxDistance, y + maxDistance);
+ if (this->SelectShapesCore(box, 0.0, SelectMode::INTERSECTION, ids, false))
+ {
+ result = ShapefileHelper::GetClosestPoint(this, x, y, maxDistance, ids, shapeIndex, pointIndex, *distance);
+ }
+ }
+ *retVal = result ? VARIANT_TRUE : VARIANT_FALSE;
+ return S_OK;
}
// *****************************************************************
@@ -3092,31 +3179,31 @@ STDMETHODIMP CShapefile::GetClosestVertex(double x, double y, double maxDistance
// *****************************************************************
STDMETHODIMP CShapefile::HasInvalidShapes(VARIANT_BOOL* result)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *result = VARIANT_FALSE;
- int numShapes = _shapeData.size();
-
- for (int i = 0; i < numShapes; i++)
- {
- IShape* shp = NULL;
- this->get_Shape(i, &shp);
-
- if (!shp)
- {
- *result = VARIANT_TRUE;
- break;
- }
-
- VARIANT_BOOL retval = VARIANT_TRUE;
- shp->get_IsValid(&retval);
- shp->Release();
- if (retval == VARIANT_FALSE)
- {
- *result = VARIANT_TRUE;
- break;
- }
- }
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ *result = VARIANT_FALSE;
+ const int numShapes = _shapeData.size();
+
+ for (int i = 0; i < numShapes; i++)
+ {
+ IShape* shp = nullptr;
+ this->get_Shape(i, &shp);
+
+ if (!shp)
+ {
+ *result = VARIANT_TRUE;
+ break;
+ }
+
+ VARIANT_BOOL retval = VARIANT_TRUE;
+ shp->get_IsValid(&retval);
+ shp->Release();
+ if (retval == VARIANT_FALSE)
+ {
+ *result = VARIANT_TRUE;
+ break;
+ }
+ }
+ return S_OK;
}
// *****************************************************************
@@ -3124,11 +3211,11 @@ STDMETHODIMP CShapefile::HasInvalidShapes(VARIANT_BOOL* result)
// *****************************************************************
STDMETHODIMP CShapefile::get_UndoList(IUndoList** pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- if (_undoList)
- _undoList->AddRef();
- *pVal = _undoList;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ if (_undoList)
+ _undoList->AddRef();
+ *pVal = _undoList;
+ return S_OK;
}
// *****************************************************************
@@ -3136,15 +3223,16 @@ STDMETHODIMP CShapefile::get_UndoList(IUndoList** pVal)
// *****************************************************************
STDMETHODIMP CShapefile::get_Snappable(VARIANT_BOOL* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *pVal = _snappable;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ *pVal = _snappable;
+ return S_OK;
}
+
STDMETHODIMP CShapefile::put_Snappable(VARIANT_BOOL newVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- _snappable = newVal;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ _snappable = newVal;
+ return S_OK;
}
// *****************************************************************
@@ -3152,9 +3240,9 @@ STDMETHODIMP CShapefile::put_Snappable(VARIANT_BOOL newVal)
// *****************************************************************
STDMETHODIMP CShapefile::get_ShapefileType2D(ShpfileType* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *pVal = ShapeUtility::Convert2D(_shpfiletype);
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ *pVal = ShapeUtility::Convert2D(_shpfiletype);
+ return S_OK;
}
// *****************************************************************
@@ -3162,9 +3250,26 @@ STDMETHODIMP CShapefile::get_ShapefileType2D(ShpfileType* pVal)
// *****************************************************************
STDMETHODIMP CShapefile::get_FieldIndexByName(BSTR FieldName, LONG* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- _table->get_FieldIndexByName(FieldName, pVal);
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ _table->get_FieldIndexByName(FieldName, pVal);
+ return S_OK;
+}
+
+// ***************************************************
+// get_Selectable
+// ***************************************************
+STDMETHODIMP CShapefile::get_Selectable(VARIANT_BOOL* retVal)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ *retVal = _selectable;
+ return S_OK;
+}
+
+STDMETHODIMP CShapefile::put_Selectable(VARIANT_BOOL newVal)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ _selectable = newVal;
+ return S_OK;
}
// *****************************************************************
@@ -3172,25 +3277,26 @@ STDMETHODIMP CShapefile::get_FieldIndexByName(BSTR FieldName, LONG* pVal)
// *****************************************************************
STDMETHODIMP CShapefile::Move(DOUBLE xProjOffset, DOUBLE yProjOffset, VARIANT_BOOL* retVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *retVal = VARIANT_FALSE;
- if (_sourceType != sstInMemory)
- {
- ErrorMessage(tkSHPFILE_NOT_IN_EDIT_MODE);
- return S_OK;
- }
- long numShapes;
- get_NumShapes(&numShapes);
- for (long i = 0; i < numShapes; i++)
- {
- CComPtr shp = NULL;
- get_Shape(i, &shp);
- if (shp) {
- shp->Move(xProjOffset, yProjOffset);
- }
- }
- *retVal = VARIANT_TRUE;
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ *retVal = VARIANT_FALSE;
+ if (_sourceType != sstInMemory)
+ {
+ ErrorMessage(tkSHPFILE_NOT_IN_EDIT_MODE);
+ return S_OK;
+ }
+ long numShapes;
+ get_NumShapes(&numShapes);
+ for (long i = 0; i < numShapes; i++)
+ {
+ CComPtr shp = nullptr;
+ get_Shape(i, &shp);
+ if (shp)
+ {
+ shp->Move(xProjOffset, yProjOffset);
+ }
+ }
+ *retVal = VARIANT_TRUE;
+ return S_OK;
}
// *****************************************************************
@@ -3198,17 +3304,18 @@ STDMETHODIMP CShapefile::Move(DOUBLE xProjOffset, DOUBLE yProjOffset, VARIANT_BO
// *****************************************************************
STDMETHODIMP CShapefile::get_ShapeRendered(LONG ShapeIndex, VARIANT_BOOL* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *pVal = VARIANT_FALSE;
- if (ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size())
- {
- ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
- }
- else {
- *pVal = _shapeData[ShapeIndex]->wasRendered() ? VARIANT_TRUE : VARIANT_FALSE;
- }
- return S_OK;
+ *pVal = VARIANT_FALSE;
+ if (ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size())
+ {
+ ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
+ }
+ else
+ {
+ *pVal = _shapeData[ShapeIndex]->wasRendered() ? VARIANT_TRUE : VARIANT_FALSE;
+ }
+ return S_OK;
}
// *****************************************************************
@@ -3216,9 +3323,10 @@ STDMETHODIMP CShapefile::get_ShapeRendered(LONG ShapeIndex, VARIANT_BOOL* pVal)
// *****************************************************************
void CShapefile::MarkUndrawn()
{
- for (size_t i = 0; i < _shapeData.size(); i++) {
- _shapeData[i]->wasRendered(false);
- }
+ for (auto& i : _shapeData)
+ {
+ i->wasRendered(false);
+ }
}
// *************************************************************
@@ -3226,28 +3334,30 @@ void CShapefile::MarkUndrawn()
// *************************************************************
STDMETHODIMP CShapefile::get_SortField(BSTR* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
- USES_CONVERSION;
- *pVal = OLE2BSTR(_sortField);
+ USES_CONVERSION;
+ *pVal = OLE2BSTR(_sortField);
- return S_OK;
+ return S_OK;
}
+
STDMETHODIMP CShapefile::put_SortField(BSTR newVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
- ::SysFreeString(_sortField);
- USES_CONVERSION;
- _sortField = OLE2BSTR(newVal);
+ SysFreeString(_sortField);
+ USES_CONVERSION;
+ _sortField = OLE2BSTR(newVal);
- _sortingChanged = true;
+ _sortingChanged = true;
- if (_labels) {
- _labels->UpdateSizeField();
- }
+ if (_labels)
+ {
+ _labels->UpdateSizeField();
+ }
- return S_OK;
+ return S_OK;
}
// *************************************************************
@@ -3255,20 +3365,21 @@ STDMETHODIMP CShapefile::put_SortField(BSTR newVal)
// *************************************************************
STDMETHODIMP CShapefile::get_SortAscending(VARIANT_BOOL* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *pVal = _sortAscending;
+ *pVal = _sortAscending;
- return S_OK;
+ return S_OK;
}
+
STDMETHODIMP CShapefile::put_SortAscending(VARIANT_BOOL newVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
- _sortAscending = newVal;
- _sortingChanged = true;
+ _sortAscending = newVal;
+ _sortingChanged = true;
- return S_OK;
+ return S_OK;
}
// *************************************************************
@@ -3276,12 +3387,12 @@ STDMETHODIMP CShapefile::put_SortAscending(VARIANT_BOOL newVal)
// *************************************************************
STDMETHODIMP CShapefile::UpdateSortField()
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
- // this will trigger rereading of the table on next redraw
- _sortingChanged = true;
+ // this will trigger rereading of the table on next redraw
+ _sortingChanged = true;
- return S_OK;
+ return S_OK;
}
// *************************************************************
@@ -3289,40 +3400,40 @@ STDMETHODIMP CShapefile::UpdateSortField()
// *************************************************************
bool CShapefile::GetSorting(vector** indices)
{
- *indices = NULL;
+ *indices = nullptr;
- if (!_sortingChanged) {
- *indices = &_sorting;
- return true;
- }
+ if (!_sortingChanged)
+ {
+ *indices = &_sorting;
+ return true;
+ }
- long fieldIndex;
- get_FieldIndexByName(_sortField, &fieldIndex);
+ long fieldIndex;
+ get_FieldIndexByName(_sortField, &fieldIndex);
- if (fieldIndex == -1) {
- return false;
- }
+ if (fieldIndex == -1)
+ {
+ return false;
+ }
- if (!_table) {
- return false;
- }
+ if (!_table)
+ {
+ return false;
+ }
- _sortingChanged = false;
+ _sortingChanged = false;
- if (((CTableClass*)_table)->GetSorting(fieldIndex, _sorting))
- {
- if (!_sortAscending)
- {
- std::reverse(_sorting.begin(), _sorting.end());
- }
+ if (((CTableClass*)_table)->GetSorting(fieldIndex, _sorting))
+ {
+ if (!_sortAscending)
+ {
+ std::reverse(_sorting.begin(), _sorting.end());
+ }
- *indices = &_sorting;
- return true;
- }
- else {
- CallbackHelper::ErrorMsg("Failed to sort labels");
- }
+ *indices = &_sorting;
+ return true;
+ }
+ CallbackHelper::ErrorMsg("Failed to sort labels");
- return false;
+ return false;
}
-
diff --git a/src/COM classes/Shapefile.h b/src/COM classes/Shapefile.h
index 8e0ef02b..f57f474f 100644
--- a/src/COM classes/Shapefile.h
+++ b/src/COM classes/Shapefile.h
@@ -256,6 +256,9 @@ class ATL_NO_VTABLE CShapefile :
STDMETHOD(StartAppendMode)(VARIANT_BOOL* retVal);
STDMETHOD(StopAppendMode)();
STDMETHOD(get_AppendMode)(VARIANT_BOOL* pVal);
+ STDMETHOD(get_IsGeographicProjection)(VARIANT_BOOL* pVal);
+ STDMETHOD(get_Selectable)(VARIANT_BOOL* retVal);
+ STDMETHOD(put_Selectable)(VARIANT_BOOL newVal);
private:
// data for point in shapefile test
@@ -321,7 +324,8 @@ class ATL_NO_VTABLE CShapefile :
IUndoList* _undoList;
VARIANT_BOOL _hotTracking;
- bool _geosGeometriesRead;
+ VARIANT_BOOL _selectable;
+ bool _geosGeometriesRead;
tkCollisionMode _collisionMode; // collision mode for point shapefiles
tkGeometryEngine _geometryEngine; // GEOS or Clipper
bool _writing; // is currently writing to the file
@@ -408,7 +412,7 @@ class ATL_NO_VTABLE CShapefile :
void AggregateShapesCore(VARIANT_BOOL SelectedOnly, LONG FieldIndex, IFieldStatOperations* statOperations, IShapefile** retval);
void DissolveCore(long FieldIndex, VARIANT_BOOL SelectedOnly, IFieldStatOperations* statOperations, IShapefile** sf);
void CalculateFieldStats(map*>& indicesMap, IFieldStatOperations* operations, IShapefile* output);
- void InsertShapesVector(IShapefile* sf, vector& vShapes, IShapefile* sfSubject, long subjectId, std::map* fieldMapSubject = NULL, IShapefile* sfClip = NULL, long clipId = -1, std::map* fieldMapClip = NULL);
+ static void InsertShapesVector(IShapefile* sf, vector& vShapes, IShapefile* sfSubject, long subjectId, std::map* fieldMapSubject = NULL, IShapefile* sfClip = NULL, long clipId = -1, std::map* fieldMapClip = NULL);
void GetRelatedShapeCore(IShape* referenceShape, long referenceIndex, tkSpatialRelation relation, VARIANT* resultArray, VARIANT_BOOL* retval);
void ReleaseRenderingCache();
bool ReadShapeExtents(long ShapeIndex, Extent& result);
diff --git a/src/COM classes/ShapefileCategories.cpp b/src/COM classes/ShapefileCategories.cpp
index e677df49..5513a244 100644
--- a/src/COM classes/ShapefileCategories.cpp
+++ b/src/COM classes/ShapefileCategories.cpp
@@ -23,8 +23,9 @@
* Contributor(s):
* (Open source contributors should list themselves and their modifications here). */
// lsu 9 may 2010 - created the file
+ // Paul Meems August 2018: Modernized the code as suggested by CLang and ReSharper
-#include "stdafx.h"
+#include "StdAfx.h"
#include "ShapefileCategories.h"
#include "ShapefileCategory.h"
#include "ShapeDrawingOptions.h"
@@ -40,7 +41,7 @@ STDMETHODIMP CShapefileCategories::get_Count(long* pVal)
AFX_MANAGE_STATE(AfxGetStaticModuleState())
*pVal = _categories.size();
return S_OK;
-};
+}
// ***************************************************************
// Add()
@@ -62,24 +63,24 @@ STDMETHODIMP CShapefileCategories::Insert(long Index, BSTR Name, IShapefileCateg
if(Index < 0 || Index > (long)_categories.size())
{
ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
- *retVal = VARIANT_FALSE;
+ *retVal = nullptr;
return NULL;
}
- *retVal = NULL;
- IShapefileCategory* cat = NULL;
- CoCreateInstance( CLSID_ShapefileCategory, NULL, CLSCTX_INPROC_SERVER, IID_IShapefileCategory, (void**)&cat);
- if (cat == NULL) return S_OK;
+ *retVal = nullptr;
+ IShapefileCategory* cat = nullptr;
+ CoCreateInstance( CLSID_ShapefileCategory, nullptr, CLSCTX_INPROC_SERVER, IID_IShapefileCategory, (void**)&cat);
+ if (cat == nullptr) return S_OK;
// initialization with default options if shapefile is present
- if (_shapefile != NULL)
+ if (_shapefile != nullptr)
{
- IShapeDrawingOptions* defaultOpt = NULL;
+ IShapeDrawingOptions* defaultOpt = nullptr;
_shapefile->get_DefaultDrawingOptions(&defaultOpt);
CDrawingOptionsEx* newOpt =((CShapeDrawingOptions*)defaultOpt)->get_UnderlyingOptions();
defaultOpt->Release();
- IShapeDrawingOptions* opt = NULL;
+ IShapeDrawingOptions* opt = nullptr;
cat->get_DrawingOptions(&opt);
((CShapeDrawingOptions*)opt)->put_underlyingOptions(newOpt);
opt->Release();
@@ -105,22 +106,22 @@ STDMETHODIMP CShapefileCategories::Insert(long Index, BSTR Name, IShapefileCateg
// ***************************************************************
// Remove()
// ***************************************************************
-STDMETHODIMP CShapefileCategories::Remove(long Index, VARIANT_BOOL* vbretval)
+STDMETHODIMP CShapefileCategories::Remove(long Index, VARIANT_BOOL* vbRetval)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
- *vbretval = VARIANT_FALSE;
+ *vbRetval = VARIANT_FALSE;
if( Index < 0 || Index >= (long)_categories.size() )
{
ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
- *vbretval = VARIANT_FALSE;
+ *vbRetval = VARIANT_FALSE;
}
else
{
_categories[Index]->Release();
- _categories[Index] = NULL;
+ _categories[Index] = nullptr;
_categories.erase(_categories.begin() + Index);
- *vbretval = VARIANT_TRUE;
+ *vbRetval = VARIANT_TRUE;
}
return S_OK;
}
@@ -131,18 +132,18 @@ STDMETHODIMP CShapefileCategories::Remove(long Index, VARIANT_BOOL* vbretval)
STDMETHODIMP CShapefileCategories::Clear()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
- for (unsigned int i=0; i < _categories.size(); i++ )
+ for (auto& _categorie : _categories)
{
- _categories[i]->Release();
+ _categorie->Release();
}
_categories.clear();
if (_shapefile)
{
std::vector* data = ((CShapefile*)_shapefile)->get_ShapeVector();
- for (unsigned int i = 0; i < data->size(); i++)
+ for (auto& i : *data)
{
- (*data)[i]->category = -1;
+ i->category = -1;
}
}
return S_OK;
@@ -157,7 +158,7 @@ STDMETHODIMP CShapefileCategories::get_Item (long Index, IShapefileCategory** re
if( Index < 0 || Index >= (long)_categories.size() )
{
ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
- *retval = NULL;
+ *retval = nullptr;
}
else
{
@@ -175,24 +176,18 @@ STDMETHODIMP CShapefileCategories::put_Item(long Index, IShapefileCategory* newV
ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
return S_OK;
}
- else
- {
- if (!newVal)
- {
- ErrorMessage(tkUNEXPECTED_NULL_PARAMETER);
- return S_OK;
- }
- else
- {
- if (_categories[Index] != newVal)
- {
- _categories[Index]->Release();
- _categories[Index] = newVal;
- _categories[Index]->AddRef();
- }
- return S_OK;
- }
- }
+ if (!newVal)
+ {
+ ErrorMessage(tkUNEXPECTED_NULL_PARAMETER);
+ return S_OK;
+ }
+ if (_categories[Index] != newVal)
+ {
+ _categories[Index]->Release();
+ _categories[Index] = newVal;
+ _categories[Index]->AddRef();
+ }
+ return S_OK;
}
// ***************************************************************
@@ -205,10 +200,10 @@ STDMETHODIMP CShapefileCategories::AddRange(long FieldIndex, tkClassificationTyp
USES_CONVERSION;
*retVal = VARIANT_FALSE;
- if(_shapefile == NULL)
+ if(_shapefile == nullptr)
return S_OK;
- CComPtr tbl = NULL;
+ CComPtr tbl = nullptr;
_shapefile->get_Table(&tbl);
if (!tbl)
return S_OK;
@@ -220,18 +215,18 @@ STDMETHODIMP CShapefileCategories::AddRange(long FieldIndex, tkClassificationTyp
_classificationField = -1; // fast processing is off
- IShapefileCategory* cat = NULL;
+ IShapefileCategory* cat = nullptr;
- for (int i = 0; i < (int)values->size(); i++ )
+ for (auto& value : *values)
{
CString strValue;
- CComBSTR bstrName((*values)[i].name);
- CComBSTR bstrExpression((*values)[i].expression);
+ CComBSTR bstrName(value.name);
+ CComBSTR bstrExpression(value.expression);
this->Add(bstrName, &cat);
cat->put_Expression(bstrExpression);
- cat->put_MinValue((*values)[i].minValue);
- cat->put_MaxValue((*values)[i].maxValue);
+ cat->put_MinValue(value.minValue);
+ cat->put_MaxValue(value.maxValue);
cat->Release();
}
@@ -259,7 +254,7 @@ STDMETHODIMP CShapefileCategories::Generate2(BSTR fieldName, tkClassificationTyp
if (!_shapefile) return S_OK;
- CComPtr tbl = NULL;
+ CComPtr tbl = nullptr;
_shapefile->get_Table(&tbl);
if (!tbl) return S_OK;
@@ -280,10 +275,10 @@ STDMETHODIMP CShapefileCategories::Generate(long FieldIndex, tkClassificationTyp
USES_CONVERSION;
*retVal = VARIANT_FALSE;
- if(_shapefile == NULL)
+ if(_shapefile == nullptr)
return S_OK;
- CComPtr tbl = NULL;
+ CComPtr tbl = nullptr;
_shapefile->get_Table(&tbl);
if (!tbl)
return S_OK;
@@ -311,21 +306,20 @@ void CShapefileCategories::GenerateCore(std::vector* categories,
this->Clear();
_classificationField = -1; // fast processing is off
- IShapefileCategory* icat = NULL;
- CShapefileCategory* ct = NULL;
+ IShapefileCategory* icat = nullptr;
+ // CShapefileCategory* ct = nullptr;
- for (int i = 0; i < (int)categories->size(); i++)
+ for (auto& categorie : *categories)
{
- CString strValue;
- CComBSTR bstrName((*categories)[i].name);
- CComBSTR bstrExpression((*categories)[i].expression);
+ CComBSTR bstrName(categorie.name);
+ CComBSTR bstrExpression(categorie.expression);
this->Add(bstrName, &icat);
icat->put_Expression(bstrExpression);
icat->put_ValueType(ClassificationType == tkClassificationType::ctUniqueValues ? cvSingleValue : cvRange);
- icat->put_MinValue((*categories)[i].minValue);
- icat->put_MaxValue((*categories)[i].maxValue);
+ icat->put_MinValue(categorie.minValue);
+ icat->put_MaxValue(categorie.maxValue);
icat->Release();
}
@@ -346,7 +340,7 @@ STDMETHODIMP CShapefileCategories::get_Key(BSTR *pVal)
STDMETHODIMP CShapefileCategories::put_Key(BSTR newVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
- ::SysFreeString(_key);
+ SysFreeString(_key);
USES_CONVERSION;
_key = OLE2BSTR(newVal);
return S_OK;
@@ -365,7 +359,7 @@ STDMETHODIMP CShapefileCategories::get_Caption(BSTR *pVal)
STDMETHODIMP CShapefileCategories::put_Caption(BSTR newVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
- ::SysFreeString(_caption);
+ SysFreeString(_caption);
USES_CONVERSION;
_caption = OLE2BSTR(newVal);
return S_OK;
@@ -403,7 +397,7 @@ STDMETHODIMP CShapefileCategories::get_GlobalCallback(ICallback **pVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
*pVal = _globalCallback;
- if( _globalCallback != NULL ) _globalCallback->AddRef();
+ if( _globalCallback != nullptr ) _globalCallback->AddRef();
return S_OK;
}
@@ -434,7 +428,7 @@ void CShapefileCategories::put_ParentShapefile(IShapefile* newVal)
{
_shapefile = newVal;
}
-IShapefile* CShapefileCategories::get_ParentShapefile()
+IShapefile* CShapefileCategories::get_ParentShapefile() const
{
return _shapefile;
}
@@ -446,8 +440,7 @@ CDrawingOptionsEx* CShapefileCategories::get_UnderlyingOptions(int Index)
{
if (Index >=0 && Index < (int)_categories.size())
return ((CShapefileCategory*)_categories[Index])->get_UnderlyingOptions();
- else
- return NULL;
+ return nullptr;
}
// *******************************************************************
@@ -469,11 +462,11 @@ STDMETHODIMP CShapefileCategories::ApplyExpression(long CategoryIndex)
// switching off shapes that are currently included in the category
std::vector* data = ((CShapefile*)_shapefile)->get_ShapeVector();
- for (unsigned int i = 0; i < data->size(); i++)
+ for (auto& i : *data)
{
- if ((*data)[i]->category == CategoryIndex)
+ if (i->category == CategoryIndex)
{
- (*data)[i]->category = -1;
+ i->category = -1;
}
}
@@ -489,7 +482,7 @@ void CShapefileCategories::ApplyExpressionCore(long CategoryIndex)
if (!_shapefile)
return;
- CComPtr tbl = NULL;
+ CComPtr tbl = nullptr;
_shapefile->get_Table(&tbl);
if ( !tbl ) return;
@@ -501,9 +494,10 @@ void CShapefileCategories::ApplyExpressionCore(long CategoryIndex)
results.resize(numShapes, -1);
bool uniqueValues = true;
- for (unsigned int i = 0; i < _categories.size(); i++) {
+ for (auto& _categorie : _categories)
+ {
tkCategoryValue value;
- _categories[i]->get_ValueType(&value);
+ _categorie->get_ValueType(&value);
if (value != cvSingleValue) {
uniqueValues = false;
break;
@@ -554,7 +548,7 @@ void CShapefileCategories::ApplyExpressionCore(long CategoryIndex)
if (parsingIsNeeded)
{
// building list of expressions
- std::vector expressions;
+ std::vector expressions;
for (unsigned int i = 0; i < _categories.size(); i++)
{
if (i == CategoryIndex || CategoryIndex == -1 )
@@ -562,13 +556,13 @@ void CShapefileCategories::ApplyExpressionCore(long CategoryIndex)
CComBSTR expr;
_categories[i]->get_Expression(&expr);
USES_CONVERSION;
- CString str = OLE2CA(expr);
+ CStringW str = OLE2CW(expr);
expressions.push_back(str);
}
else
{
// we don't need this categories, so dummy strings for them
- CString str = "";
+ CStringW str = L"";
expressions.push_back(str);
}
}
@@ -678,7 +672,7 @@ STDMETHODIMP CShapefileCategories::ApplyColorScheme3 (tkColorSchemeType Type, IC
}
}
- IShapeDrawingOptions* options = NULL;
+ IShapeDrawingOptions* options = nullptr;
for (int i = CategoryStartIndex; i <= CategoryEndIndex; i++)
{
OLE_COLOR color;
@@ -704,6 +698,8 @@ STDMETHODIMP CShapefileCategories::ApplyColorScheme3 (tkColorSchemeType Type, IC
case shElementFill2: options->put_FillColor2(color); break;
case shElementLines: options->put_LineColor(color); break;
case shElementFillBackground: options->put_FillBgColor(color); break;
+ case shElementDefault: break;
+ default: ;
}
options->Release();
}
@@ -724,15 +720,15 @@ STDMETHODIMP CShapefileCategories::MoveUp (long Index, VARIANT_BOOL* retval)
_categories[Index] = catBefore;
std::vector* data = ((CShapefile*)_shapefile)->get_ShapeVector();
- for (unsigned int i = 0; i < data->size(); i++)
+ for (auto& i : *data)
{
- if ((*data)[i]->category == Index)
+ if (i->category == Index)
{
- (*data)[i]->category = Index - 1;
+ i->category = Index - 1;
}
- else if ((*data)[i]->category == Index - 1)
+ else if (i->category == Index - 1)
{
- (*data)[i]->category = Index;
+ i->category = Index;
}
}
@@ -759,15 +755,15 @@ STDMETHODIMP CShapefileCategories::MoveDown (long Index, VARIANT_BOOL* retval)
_categories[Index] = catAfter;
std::vector* data = ((CShapefile*)_shapefile)->get_ShapeVector();
- for (unsigned int i = 0; i < data->size(); i++)
+ for (auto& i : *data)
{
- if ((*data)[i]->category == Index)
+ if (i->category == Index)
{
- (*data)[i]->category = Index + 1;
+ i->category = Index + 1;
}
- else if ((*data)[i]->category == Index + 1)
+ else if (i->category == Index + 1)
{
- (*data)[i]->category = Index;
+ i->category = Index;
}
}
*retval = VARIANT_TRUE;
@@ -799,19 +795,18 @@ CPLXMLNode* CShapefileCategories::SerializeCore(CString ElementName)
{
USES_CONVERSION;
- CPLXMLNode* psTree = CPLCreateXMLNode( NULL, CXT_Element, ElementName);
- CString str;
+ CPLXMLNode* psTree = CPLCreateXMLNode( nullptr, CXT_Element, ElementName);
- // classification field
+ // classification field
Utility::CPLCreateXMLAttributeAndValue(psTree, "ClassificationField", CPLString().Printf("%d", _classificationField));
// field type
FieldType type;
- CComPtr table = NULL;
+ CComPtr table = nullptr;
_shapefile->get_Table(&table);
if (table && _classificationField != -1)
{
- CComPtr fld = NULL;
+ CComPtr fld = nullptr;
table->get_Field(_classificationField, &fld);
if (fld)
{
@@ -820,24 +815,24 @@ CPLXMLNode* CShapefileCategories::SerializeCore(CString ElementName)
}
}
- for (unsigned int i = 0; i < _categories.size(); i++)
+ for (auto& _categorie : _categories)
{
CPLXMLNode* psNode = CPLCreateXMLNode(psTree, CXT_Element, "ShapefileCategoryClass");
// name
BSTR vbstr;
- _categories[i]->get_Name(&vbstr);
+ _categorie->get_Name(&vbstr);
Utility::CPLCreateXMLAttributeAndValue( psNode, "Name", OLE2CA(vbstr));
SysFreeString(vbstr);
// expression
- _categories[i]->get_Expression(&vbstr);
- str = OLE2CA(vbstr);
+ _categorie->get_Expression(&vbstr);
+ CString str = OLE2CA(vbstr);
Utility::CPLCreateXMLAttributeAndValue( psNode, "Expression", str);
SysFreeString(vbstr);
- CShapefileCategory* ct = (CShapefileCategory*)_categories[i];
+ auto* ct = (CShapefileCategory*)_categorie;
Utility::CPLCreateXMLAttributeAndValue(psNode, "ValueType", CPLString().Printf("%d", (int)ct->GetCategoryValue()));
// values
@@ -846,7 +841,7 @@ CPLXMLNode* CShapefileCategories::SerializeCore(CString ElementName)
// options
IShapeDrawingOptions* options;
- _categories[i]->get_DrawingOptions(&options);
+ _categorie->get_DrawingOptions(&options);
CPLXMLNode* psChild = ((CShapeDrawingOptions*)options)->SerializeCore("ShapeDrawingOptionsClass");
if (psChild)
{
@@ -872,7 +867,7 @@ bool CShapefileCategories::DeserializeCore(CPLXMLNode* node, bool applyExpressio
bool loadField = false;
FieldType type = INTEGER_FIELD;
- CString s = CPLGetXMLValue( node, "FieldType", NULL );
+ CString s = CPLGetXMLValue( node, "FieldType", nullptr );
if (s != "")
{
type = (FieldType)atoi(s);
@@ -881,16 +876,16 @@ bool CShapefileCategories::DeserializeCore(CPLXMLNode* node, bool applyExpressio
if (loadField)
{
- s = CPLGetXMLValue( node, "ClassificationField", NULL );
+ s = CPLGetXMLValue( node, "ClassificationField", nullptr );
if (s != "")
{
- int fieldIndex = atoi(s);
+ const int fieldIndex = atoi(s);
- CComPtr table = NULL;
+ CComPtr table = nullptr;
_shapefile->get_Table(&table);
if (table)
{
- IField* fld = NULL;
+ IField* fld = nullptr;
table->get_Field(fieldIndex, &fld);
if (fld)
{
@@ -916,30 +911,30 @@ bool CShapefileCategories::DeserializeCore(CPLXMLNode* node, bool applyExpressio
if (strcmp(node->pszValue, "ShapefileCategoryClass") == 0)
{
CString str;
- str = CPLGetXMLValue( node, "Name", NULL );
+ str = CPLGetXMLValue( node, "Name", nullptr );
CComBSTR bstrName( str );
- IShapefileCategory* cat = NULL;
+ IShapefileCategory* cat = nullptr;
this->Add(bstrName, &cat);
- str = CPLGetXMLValue( node, "Expression", NULL );
+ str = CPLGetXMLValue( node, "Expression", nullptr );
CComBSTR bstrExpression(str);
cat->put_Expression(bstrExpression);
- str = CPLGetXMLValue(node, "ValueType", NULL);
- tkCategoryValue ctVal = (str != "") ? (tkCategoryValue)atoi(str.GetString()) : cvExpression;
+ str = CPLGetXMLValue(node, "ValueType", nullptr);
+ const tkCategoryValue ctVal = str != "" ? (tkCategoryValue)atoi(str.GetString()) : cvExpression;
cat->put_ValueType(ctVal);
- str = CPLGetXMLValue(node, "Value", NULL);
+ str = CPLGetXMLValue(node, "Value", nullptr);
Utility::DeserializeVariant(str, type, ((CShapefileCategory*)cat)->GetMinValue());
- str = CPLGetXMLValue(node, "MaxValue", NULL);
+ str = CPLGetXMLValue(node, "MaxValue", nullptr);
Utility::DeserializeVariant(str, type, ((CShapefileCategory*)cat)->GetMaxValue());
// drawing options
CPLXMLNode* nodeOptions = CPLGetXMLNode( node, "ShapeDrawingOptionsClass" );
if (nodeOptions)
{
- IShapeDrawingOptions* options = NULL;
+ IShapeDrawingOptions* options = nullptr;
cat->get_DrawingOptions(&options);
((CShapeDrawingOptions*)options)->DeserializeCore(nodeOptions);
options->Release();
@@ -1064,19 +1059,19 @@ STDMETHODIMP CShapefileCategories::GeneratePolygonColors(IColorScheme* scheme, V
Coloring::ColorGraph* graph = ((CShapefile*)_shapefile)->GeneratePolygonColors();
if (graph)
{
- int colorCount = graph->GetColorCount();
+ const int colorCount = graph->GetColorCount();
// -------------------------------------------------
// create categories
// -------------------------------------------------
- int firstCategory = _categories.size();
+ const int firstCategory = _categories.size();
long numBreaks;
scheme->get_NumBreaks(&numBreaks);
for(int i = 0; i < colorCount; i++)
{
CString s;
s.Format("Color %d", i + 1);
- IShapefileCategory* ct = NULL;
+ IShapefileCategory* ct = nullptr;
CComBSTR bstrName(s);
this->Add(bstrName, &ct);
@@ -1101,10 +1096,10 @@ STDMETHODIMP CShapefileCategories::GeneratePolygonColors(IColorScheme* scheme, V
// -------------------------------------------------
// apply indices to polygons
// -------------------------------------------------
- for(size_t i = 0; i < graph->nodes.size(); i++)
+ for (auto& node : graph->nodes)
{
- int shapeId = graph->nodes[i]->id;
- _shapefile->put_ShapeCategory(shapeId, firstCategory + graph->nodes[i]->color);
+ const int shapeId = node->id;
+ _shapefile->put_ShapeCategory(shapeId, firstCategory + node->color);
}
delete graph;
}
@@ -1140,11 +1135,11 @@ STDMETHODIMP CShapefileCategories::Sort(LONG FieldIndex, VARIANT_BOOL Ascending,
return S_OK;
}
- CComPtr table = NULL;
+ CComPtr table = nullptr;
_shapefile->get_Table(&table);
if (!table) return S_OK;
- IField* fld = NULL;
+ IField* fld = nullptr;
table->get_Field(FieldIndex, &fld);
FieldType type;
fld->get_Type(&type);
@@ -1163,40 +1158,39 @@ STDMETHODIMP CShapefileCategories::Sort(LONG FieldIndex, VARIANT_BOOL Ascending,
multimap map;
- for (unsigned int i = 0; i < _categories.size(); i++)
+ for (auto& _categorie : _categories)
{
- VARIANT_BOOL vbretval = VARIANT_FALSE;
+ const VARIANT_BOOL vbretval = VARIANT_FALSE;
CComVariant var = NULL;
BSTR expr;
- _categories[i]->get_Expression(&expr);
+ _categorie->get_Expression(&expr);
// TODO: implement
//table->CalculateStat(FieldIndex, Operation, expr, &var, &vbretval);
if (vbretval)
{
- pair myPair(var, _categories[i]);
+ pair myPair(var, _categorie);
map.insert(myPair);
}
else
{
- pair myPair(valDefault, _categories[i]);
+ pair myPair(valDefault, _categorie);
map.insert(myPair);
}
}
-
- // returning result
- multimap ::iterator p;
- p = map.begin();
+
+ multimap::iterator p = map.begin();
int i = 0;
ASSERT(map.size() == _categories.size());
while(p != map.end())
{
- IShapefileCategory* cat = p->second;
+ // IShapefileCategory* cat = p->second;
_categories[i] = p->second;
- i++; p++;
+ i++;
+ ++p;
}
*retVal = VARIANT_TRUE;
@@ -1226,14 +1220,14 @@ void CShapefileCategories::GetCategoryData(vector& data)
{
USES_CONVERSION;
data.clear();
- for (size_t i = 0; i < _categories.size(); i++)
+ for (auto& _categorie : _categories)
{
- CategoriesData* ct = new CategoriesData();
- _categories[i]->get_MinValue(&ct->minValue);
- _categories[i]->get_MaxValue(&ct->maxValue);
- _categories[i]->get_ValueType(&ct->valueType);
+ auto* ct = new CategoriesData();
+ _categorie->get_MinValue(&ct->minValue);
+ _categorie->get_MaxValue(&ct->maxValue);
+ _categorie->get_ValueType(&ct->valueType);
CComBSTR expr;
- _categories[i]->get_Expression(&expr);
+ _categorie->get_Expression(&expr);
ct->expression = OLE2A(expr);
ct->classificationField = _classificationField;
data.push_back(ct);
diff --git a/src/COM classes/ShapefileCategories.h b/src/COM classes/ShapefileCategories.h
index 81638520..d82e04d0 100644
--- a/src/COM classes/ShapefileCategories.h
+++ b/src/COM classes/ShapefileCategories.h
@@ -158,7 +158,7 @@ class ATL_NO_VTABLE CShapefileCategories :
CPLXMLNode* SerializeCore(CString ElementName);
void put_ParentShapefile(IShapefile* newVal);
- IShapefile* get_ParentShapefile();
+ IShapefile* get_ParentShapefile() const;
CDrawingOptionsEx* get_UnderlyingOptions(int Index);
void GenerateCore(std::vector* categories, long FieldIndex, tkClassificationType ClassificationType, VARIANT_BOOL* retVal);
void GetCategoryData(vector& data);
diff --git a/src/COM classes/Shapefile_Geoprocessing.cpp b/src/COM classes/Shapefile_Geoprocessing.cpp
index 1743d507..9739a09c 100644
--- a/src/COM classes/Shapefile_Geoprocessing.cpp
+++ b/src/COM classes/Shapefile_Geoprocessing.cpp
@@ -1,5 +1,5 @@
//********************************************************************************************************
-//File name: Shapefile.cpp
+//File name: Shapefile_Geoprocessing.cpp
//Description: Implementation of the CShapefile (see other cpp files as well)
//********************************************************************************************************
//The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License");
@@ -18,8 +18,9 @@
//Contributor(s): (Open source contributors should list themselves and their modifications here).
// -------------------------------------------------------------------------------------------------------
// lsu 3-02-2011: split the initial Shapefile.cpp file to make entities of the reasonable size
+// Paul Meems August 2018: Modernized the code as suggested by CLang and ReSharper
-#include "stdafx.h"
+#include "StdAfx.h"
#include "Shapefile.h"
#include "OgrConverter.h"
#include "Templates.h"
@@ -49,23 +50,24 @@
// ********************************************************************
int CloneField(IShapefile* source, IShapefile* target, int fieldIndex, long newFieldIndex)
{
- IField* fld = NULL;
- source->get_Field(fieldIndex, &fld);
- if (fld)
- {
- IField* newField = NULL;
- fld->Clone(&newField);
- fld->Release();
- VARIANT_BOOL vb;
- if (newFieldIndex == -1) {
- long numShapes;
- target->get_NumShapes(&numShapes);
- newFieldIndex = numShapes;
- }
- target->EditInsertField(newField, &newFieldIndex, NULL, &vb);
- newField->Release();
- }
- return newFieldIndex;
+ IField* fld = nullptr;
+ source->get_Field(fieldIndex, &fld);
+ if (fld)
+ {
+ IField* newField = nullptr;
+ fld->Clone(&newField);
+ fld->Release();
+ VARIANT_BOOL vb;
+ if (newFieldIndex == -1)
+ {
+ long numShapes;
+ target->get_NumShapes(&numShapes);
+ newFieldIndex = numShapes;
+ }
+ target->EditInsertField(newField, &newFieldIndex, nullptr, &vb);
+ newField->Release();
+ }
+ return newFieldIndex;
}
// ******************************************************************
@@ -73,104 +75,98 @@ int CloneField(IShapefile* source, IShapefile* target, int fieldIndex, long newF
// ******************************************************************
// Inserts shapes, resulting from intersection of one shape of subject shapefile,
// and one shape of clip shapefile, attributes a copied from both shapefiles
-void CShapefile::InsertShapesVector(IShapefile* sf, vector& vShapes,
- IShapefile* sfSubject, long subjectId, std::map* fieldMapSubject,
- IShapefile* sfClip, long clipId, std::map* fieldMapClip)
+void CShapefile::InsertShapesVector(IShapefile* sf, vector& vShapes,
+ IShapefile* sfSubject, long subjectId, std::map* fieldMapSubject,
+ IShapefile* sfClip, long clipId, std::map* fieldMapClip)
{
- long numFieldSubject, numFieldsClip;
- sfSubject->get_NumFields(&numFieldSubject);
- if (sfClip)
- sfClip->get_NumFields(&numFieldsClip);
-
- VARIANT_BOOL vbretval;
-
- ShpfileType fileType;
- sf->get_ShapefileType(&fileType);
-
- CComVariant var;
-
- IGeoProjection* proj = NULL;
- sf->get_GeoProjection(&proj);
- VARIANT_BOOL isGeographic;
- proj->get_IsGeographic(&isGeographic);
- proj->Release();
-
- for (int i = 0; i < (int)vShapes.size(); i++)
- {
- IShape* shp = NULL;
- shp = vShapes[i];
-
- ShpfileType shpType;
- shp->get_ShapeType(&shpType);
-
- if (shpType == fileType)
- {
- // area checking
- shpType = ShapeUtility::Convert2D(shpType);
- if (shpType == SHP_POLYGON)
- {
- double area;
- shp->get_Area(&area);
- if (area < m_globalSettings.GetMinPolygonArea(isGeographic))
- {
- shp->Release();
- continue;
- }
-
- double perimeter;
- shp->get_Perimeter(&perimeter);
-
- if (isGeographic)
- area *= METERS_PER_DEGREE; // comparison is performed in meters, area will grow as square of linear size
- // we multilpy area only; in reality:((area * c^2)/ (perimeter * c))
-
- if (area/perimeter < m_globalSettings.minAreaToPerimeterRatio)
- {
- shp->Release();
- continue;
- }
- }
-
- long newId;
- sf->get_NumShapes(&newId);
- sf->EditInsertShape(shp, &newId, &vbretval);
-
- // passing the values from subject shapefile
- // can be optimized for not extracting the same values many times
- if (fieldMapSubject)
- {
-
- std::map::iterator p = fieldMapSubject->begin();
- while (p != fieldMapSubject->end())
- {
- sfSubject->get_CellValue(p->first, subjectId, &var);
- sf->EditCellValue(p->second, newId, var, &vbretval);
- ++p;
- }
- }
- else
- {
- for (int iFld = 0; iFld < numFieldSubject; iFld++)
- {
- sfSubject->get_CellValue(iFld, subjectId, &var);
- sf->EditCellValue(iFld, newId, var, &vbretval);
- }
- }
-
- // passing the values from clip shapefile
- if ( sfClip && fieldMapClip)
- {
- std::map::iterator p = fieldMapClip->begin();
- while (p != fieldMapClip->end())
- {
- sfClip->get_CellValue(p->first, clipId, &var);
- sf->EditCellValue(p->second, newId, var, &vbretval);
- ++p;
- }
- }
- }
- shp->Release();
- }
+ long numFieldSubject, numFieldsClip;
+ sfSubject->get_NumFields(&numFieldSubject);
+ if (sfClip)
+ sfClip->get_NumFields(&numFieldsClip);
+
+ VARIANT_BOOL vbretval;
+
+ ShpfileType fileType;
+ sf->get_ShapefileType(&fileType);
+
+ CComVariant var;
+
+ VARIANT_BOOL isGeographic = VARIANT_FALSE;
+ sf->get_IsGeographicProjection(&isGeographic);
+
+ for (auto shp : vShapes)
+ {
+ ShpfileType shpType;
+ shp->get_ShapeType(&shpType);
+
+ if (shpType == fileType)
+ {
+ // area checking
+ shpType = ShapeUtility::Convert2D(shpType);
+ if (shpType == SHP_POLYGON)
+ {
+ double area;
+ shp->get_Area(&area);
+ if (area < m_globalSettings.GetMinPolygonArea(isGeographic))
+ {
+ shp->Release();
+ continue;
+ }
+
+ double perimeter;
+ shp->get_Perimeter(&perimeter);
+
+ if (isGeographic)
+ area *= METERS_PER_DEGREE;
+ // comparison is performed in meters, area will grow as square of linear size
+ // we multilpy area only; in reality:((area * c^2)/ (perimeter * c))
+
+ if (area / perimeter < m_globalSettings.minAreaToPerimeterRatio)
+ {
+ shp->Release();
+ continue;
+ }
+ }
+
+ long newId;
+ sf->get_NumShapes(&newId);
+ sf->EditInsertShape(shp, &newId, &vbretval);
+
+ // passing the values from subject shapefile
+ // can be optimized for not extracting the same values many times
+ if (fieldMapSubject)
+ {
+ auto p = fieldMapSubject->begin();
+ while (p != fieldMapSubject->end())
+ {
+ sfSubject->get_CellValue(p->first, subjectId, &var);
+ sf->EditCellValue(p->second, newId, var, &vbretval);
+ ++p;
+ }
+ }
+ else
+ {
+ for (int iFld = 0; iFld < numFieldSubject; iFld++)
+ {
+ sfSubject->get_CellValue(iFld, subjectId, &var);
+ sf->EditCellValue(iFld, newId, var, &vbretval);
+ }
+ }
+
+ // passing the values from clip shapefile
+ if (sfClip && fieldMapClip)
+ {
+ auto p = fieldMapClip->begin();
+ while (p != fieldMapClip->end())
+ {
+ sfClip->get_CellValue(p->first, clipId, &var);
+ sf->EditCellValue(p->second, newId, var, &vbretval);
+ ++p;
+ }
+ }
+ }
+ shp->Release();
+ }
}
// **********************************************************************
@@ -179,41 +175,41 @@ void CShapefile::InsertShapesVector(IShapefile* sf, vector& vShapes,
// A utility function to add geometry produced by simplification routine to the sfTarget shapefile,
// with copying of attributes from source shapefile.
// initShapeIndex - the index of shape to copy the attribute from
-bool InsertGeosGeometry(IShapefile* sfTarget, GEOSGeometry* gsNew, IShapefile* sfSouce, int initShapeIndex )
+bool InsertGeosGeometry(IShapefile* sfTarget, GEOSGeometry* gsNew, IShapefile* sfSouce, int initShapeIndex)
{
- if (gsNew)
- {
- ShpfileType shpType;
- sfTarget->get_ShapefileType(&shpType);
- bool isM = ShapeUtility::IsM(shpType);
-
- std::vector shapes;
- if (GeosConverter::GeomToShapes(gsNew, &shapes, isM))
- {
- long index, numFields;
- VARIANT_BOOL vbretval;
- sfTarget->get_NumFields(&numFields);
-
- for (unsigned int j = 0; j < shapes.size(); j++)
- {
- sfTarget->get_NumShapes(&index);
- sfTarget->EditInsertShape(shapes[j], &index, &vbretval);
-
- if (vbretval)
- {
- CComVariant val;
- for (int f = 0; f < numFields; f++)
- {
- sfSouce->get_CellValue(f, initShapeIndex, &val);
- sfTarget->EditCellValue(f, index, val, &vbretval);
- }
- }
- shapes[j]->Release();
- }
- return true;
- }
- }
- return false;
+ if (gsNew)
+ {
+ ShpfileType shpType;
+ sfTarget->get_ShapefileType(&shpType);
+ const bool isM = ShapeUtility::IsM(shpType);
+
+ std::vector shapes;
+ if (GeosConverter::GeomToShapes(gsNew, &shapes, isM))
+ {
+ long index, numFields;
+ VARIANT_BOOL vbretval;
+ sfTarget->get_NumFields(&numFields);
+
+ for (auto& shape : shapes)
+ {
+ sfTarget->get_NumShapes(&index);
+ sfTarget->EditInsertShape(shape, &index, &vbretval);
+
+ if (vbretval)
+ {
+ CComVariant val;
+ for (int f = 0; f < numFields; f++)
+ {
+ sfSouce->get_CellValue(f, initShapeIndex, &val);
+ sfTarget->EditCellValue(f, index, val, &vbretval);
+ }
+ }
+ shape->Release();
+ }
+ return true;
+ }
+ }
+ return false;
}
// ********************************************************************
@@ -223,49 +219,49 @@ bool InsertGeosGeometry(IShapefile* sfTarget, GEOSGeometry* gsNew, IShapefile* s
// The row index of attribute table are taken from the key property of the shape
void CopyShape(IShapefile* sfSource, IShape* shp, IShapefile* sfResult)
{
- if (shp)
- {
- USES_CONVERSION;
- CComBSTR key;
- shp->get_Key(&key);
- CString str = OLE2CA(key);
- int initIndex = atoi(str);
-
- VARIANT_BOOL isEditingShapes, vbretval;
- sfSource->get_EditingShapes(&isEditingShapes);
-
- LONG numShapes;
- sfResult->get_NumShapes(&numShapes);
-
- if (isEditingShapes)
- {
- // in the editing mode we share a shape with the parent shapefile
- // a copy is needed to avoid conflicts
- IShape* shpCopy = NULL;
- shp->Clone(&shpCopy);
- sfResult->EditInsertShape(shpCopy, &numShapes, &vbretval);
- shpCopy->Release();
- }
- else
- {
- sfResult->EditInsertShape(shp, &numShapes, &vbretval);
- }
-
- if (vbretval)
- {
- LONG numFields;
- sfSource->get_NumFields(&numFields);
-
- // copy attributes
- CComVariant val;
- for (int iFld = 0; iFld < numFields; iFld++)
- {
- sfSource->get_CellValue(iFld, initIndex, &val);
- sfResult->EditCellValue(iFld, numShapes, val, &vbretval);
- }
- }
- shp->Release();
- }
+ if (shp)
+ {
+ USES_CONVERSION;
+ CComBSTR key;
+ shp->get_Key(&key);
+ const CString str = OLE2CA(key);
+ const int initIndex = atoi(str);
+
+ VARIANT_BOOL isEditingShapes, vbretval;
+ sfSource->get_EditingShapes(&isEditingShapes);
+
+ LONG numShapes;
+ sfResult->get_NumShapes(&numShapes);
+
+ if (isEditingShapes)
+ {
+ // in the editing mode we share a shape with the parent shapefile
+ // a copy is needed to avoid conflicts
+ IShape* shpCopy = nullptr;
+ shp->Clone(&shpCopy);
+ sfResult->EditInsertShape(shpCopy, &numShapes, &vbretval);
+ shpCopy->Release();
+ }
+ else
+ {
+ sfResult->EditInsertShape(shp, &numShapes, &vbretval);
+ }
+
+ if (vbretval)
+ {
+ LONG numFields;
+ sfSource->get_NumFields(&numFields);
+
+ // copy attributes
+ CComVariant val;
+ for (int iFld = 0; iFld < numFields; iFld++)
+ {
+ sfSource->get_CellValue(iFld, initIndex, &val);
+ sfResult->EditCellValue(iFld, numShapes, val, &vbretval);
+ }
+ }
+ shp->Release();
+ }
}
#pragma endregion
@@ -277,159 +273,154 @@ void CopyShape(IShapefile* sfSource, IShape* shp, IShapefile* sfResult)
// Returns numbers(ids) of shapes of this shapefile which are situated
// in certain spatial relation to the shapes of the input shapefile.
-STDMETHODIMP CShapefile::SelectByShapefile(IShapefile* sf, tkSpatialRelation Relation,
- VARIANT_BOOL SelectedOnly, VARIANT* arr, ICallback* cBack, VARIANT_BOOL *retval)
+STDMETHODIMP CShapefile::SelectByShapefile(IShapefile* sf, tkSpatialRelation Relation,
+ VARIANT_BOOL SelectedOnly, VARIANT* arr, ICallback* cBack,
+ VARIANT_BOOL* retval)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- USES_CONVERSION;
- *retval = VARIANT_FALSE;
-
- if(_globalCallback == NULL && cBack != NULL)
- {
- _globalCallback = cBack;
- _globalCallback->AddRef();
- }
-
- if( sf == NULL)
- {
- ErrorMessage( tkUNEXPECTED_NULL_PARAMETER );
- return S_OK;
- }
-
- long _numShapes1, _numShapes2;
- _numShapes1 = _shapeData.size();
- sf->get_NumShapes(&_numShapes2);
- if (_numShapes1 == 0)return NULL;
- if (_numShapes2 == 0) return NULL;
-
- QTree* qTree = this->GenerateQTreeCore(false);
- if (!qTree)
- {
- ErrorMessage(tkFAILED_TO_BUILD_SPATIAL_INDEX);
- return NULL;
- }
-
- // ids of selected shapes
- set result;
-
- // to avoid converting same shapes to ogr geometry multiple times
- vector vGeometries;
- vGeometries.assign(_numShapes1, NULL);
-
- vector* data = ((CShapefile*)sf)->get_ShapeVector();
-
- long percent = 0;
- for(long shapeid2 = 0; shapeid2 < _numShapes2; shapeid2++)
- {
- CallbackHelper::Progress(_globalCallback, shapeid2, _numShapes2, "Calculating...", _key, percent);
-
- if (SelectedOnly && !(*data)[shapeid2]->selected())
- continue;
-
- vector shapeIds;
- double xMin, xMax, yMin, yMax;
- ((CShapefile*)sf)->QuickExtentsCore(shapeid2, &xMin, &yMin, &xMax, &yMax);
- shapeIds = qTree->GetNodes(QTreeExtent(xMin,xMax,yMax,yMin));
-
- if (shapeIds.size() > 0)
- {
- IShape* shp2 = NULL;
- OGRGeometry* oGeom2 = NULL;
- sf->get_Shape(shapeid2, &shp2);
- oGeom2 = OgrConverter::ShapeToGeometry(shp2);
- shp2->Release();
-
- if (oGeom2 != NULL)
- {
- for (int j=0; j < (int)shapeIds.size(); j++)
- {
- long shapeId1 = shapeIds[j];
-
- // shape wasn't selected so far
- if (result.find(shapeId1) == result.end())
- {
- OGRGeometry* oGeom1 = NULL;
-
- if (vGeometries[shapeId1] == NULL)
- {
- IShape* shp1 = NULL;
- this->get_Shape(shapeId1, &shp1);
- oGeom1 = OgrConverter::ShapeToGeometry(shp1);
- shp1->Release();
- vGeometries[shapeId1] = oGeom1;
- }
- else
- {
- oGeom1 = vGeometries[shapeId1];
- }
-
- OGRBoolean res;
- if (Relation == srContains) res = oGeom1->Contains(oGeom2);
- else if (Relation == srCrosses) res = oGeom1->Crosses(oGeom2);
- else if (Relation == srEquals) res = oGeom1->Equal(oGeom2);
- else if (Relation == srIntersects) res = oGeom1->Intersect(oGeom2);
- else if (Relation == srDisjoint) res = oGeom1->Intersect(oGeom2);
- else if (Relation == srOverlaps) res = oGeom1->Overlaps(oGeom2);
- else if (Relation == srTouches) res = oGeom1->Touches(oGeom2);
- else if (Relation == srWithin) res = oGeom1->Within(oGeom2);
-
- if (res)
- {
- result.insert(shapeId1);
- }
- }
- }
- OGRGeometryFactory::destroyGeometry(oGeom2);
- }
- }
- }
-
- // disjoint is opposite to intersects; so to get it we need to find shapes that do intersect with input
- // and then invert the selection
- if (Relation == srDisjoint)
- {
- vector v;
- set::iterator p = result.begin();
- bool include;
-
- for (int i = 0; i < _numShapes1; i++)
- {
- include = true;
- while(p != result.end())
- {
- if (*p == i)
- include = false; // this shape actually intersects, so it can't be disjointed
-
- if (*p > i)
- break;
-
- ++p;
- }
- if (include)
- {
- v.push_back(i);
- }
- }
- *retval = Templates::Vector2SafeArray(&v, VT_I4, arr);
- }
- else
- {
- *retval = Templates::Set2SafeArray(&result, VT_I4, arr);
- }
-
- // cleaning
- CallbackHelper::ProgressCompleted(_globalCallback, _key);
-
- for(int i = 0; i < (int)vGeometries.size(); i++)
- {
- if (vGeometries[i] !=NULL)
- OGRGeometryFactory::destroyGeometry(vGeometries[i]);
- }
-
- if (qTree !=NULL)
- delete qTree;
-
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ USES_CONVERSION;
+ *retval = VARIANT_FALSE;
+
+ if (_globalCallback == nullptr && cBack != nullptr)
+ {
+ _globalCallback = cBack;
+ _globalCallback->AddRef();
+ }
+
+ if (sf == nullptr)
+ {
+ ErrorMessage(tkUNEXPECTED_NULL_PARAMETER);
+ return S_OK;
+ }
+
+ long _numShapes2;
+ const long _numShapes1 = _shapeData.size();
+ sf->get_NumShapes(&_numShapes2);
+ if (_numShapes1 == 0)return NULL;
+ if (_numShapes2 == 0) return NULL;
+
+ QTree* qTree = this->GenerateQTreeCore(false);
+ if (!qTree)
+ {
+ ErrorMessage(tkFAILED_TO_BUILD_SPATIAL_INDEX);
+ return NULL;
+ }
+
+ // ids of selected shapes
+ set result;
+
+ // to avoid converting same shapes to ogr geometry multiple times
+ vector vGeometries;
+ vGeometries.assign(_numShapes1, nullptr);
+
+ vector* data = ((CShapefile*)sf)->get_ShapeVector();
+
+ long percent = 0;
+ for (long shapeid2 = 0; shapeid2 < _numShapes2; shapeid2++)
+ {
+ CallbackHelper::Progress(_globalCallback, shapeid2, _numShapes2, "Calculating...", _key, percent);
+
+ if (SelectedOnly && !(*data)[shapeid2]->selected())
+ continue;
+
+ double xMin, xMax, yMin, yMax;
+ ((CShapefile*)sf)->QuickExtentsCore(shapeid2, &xMin, &yMin, &xMax, &yMax);
+ vector shapeIds = qTree->GetNodes(QTreeExtent(xMin, xMax, yMax, yMin));
+
+ if (!shapeIds.empty())
+ {
+ IShape* shp2 = nullptr;
+ sf->get_Shape(shapeid2, &shp2);
+ OGRGeometry* oGeom2 = OgrConverter::ShapeToGeometry(shp2);
+ shp2->Release();
+
+ if (oGeom2 != nullptr)
+ {
+ for (long shapeId1 : shapeIds)
+ {
+ // shape wasn't selected so far
+ if (result.find(shapeId1) == result.end())
+ {
+ OGRGeometry* oGeom1;
+
+ if (vGeometries[shapeId1] == nullptr)
+ {
+ IShape* shp1 = nullptr;
+ this->get_Shape(shapeId1, &shp1);
+ oGeom1 = OgrConverter::ShapeToGeometry(shp1);
+ shp1->Release();
+ vGeometries[shapeId1] = oGeom1;
+ }
+ else
+ {
+ oGeom1 = vGeometries[shapeId1];
+ }
+
+ OGRBoolean res = 0;
+ if (Relation == srContains) res = oGeom1->Contains(oGeom2);
+ else if (Relation == srCrosses) res = oGeom1->Crosses(oGeom2);
+ else if (Relation == srEquals) res = oGeom1->Equals(oGeom2);
+ else if (Relation == srIntersects) res = oGeom1->Intersects(oGeom2);
+ else if (Relation == srDisjoint) res = oGeom1->Intersects(oGeom2);
+ else if (Relation == srOverlaps) res = oGeom1->Overlaps(oGeom2);
+ else if (Relation == srTouches) res = oGeom1->Touches(oGeom2);
+ else if (Relation == srWithin) res = oGeom1->Within(oGeom2);
+
+ if (res)
+ {
+ result.insert(shapeId1);
+ }
+ }
+ }
+ OGRGeometryFactory::destroyGeometry(oGeom2);
+ }
+ }
+ }
+
+ // disjoint is opposite to intersects; so to get it we need to find shapes that do intersect with input
+ // and then invert the selection
+ if (Relation == srDisjoint)
+ {
+ vector v;
+ auto p = result.begin();
+
+ for (int i = 0; i < _numShapes1; i++)
+ {
+ bool include = true;
+ while (p != result.end())
+ {
+ if (*p == i)
+ include = false; // this shape actually intersects, so it can't be disjointed
+
+ if (*p > i)
+ break;
+
+ ++p;
+ }
+ if (include)
+ {
+ v.push_back(i);
+ }
+ }
+ *retval = Templates::Vector2SafeArray(&v, VT_I4, arr);
+ }
+ else
+ {
+ *retval = Templates::Set2SafeArray(&result, VT_I4, arr);
+ }
+
+ // cleaning
+ CallbackHelper::ProgressCompleted(_globalCallback, _key);
+
+ for (auto& vGeometrie : vGeometries)
+ {
+ if (vGeometrie != nullptr)
+ OGRGeometryFactory::destroyGeometry(vGeometrie);
+ }
+
+ delete qTree;
+
+ return S_OK;
}
// ***********************************************************
@@ -440,71 +431,67 @@ STDMETHODIMP CShapefile::SelectByShapefile(IShapefile* sf, tkSpatialRelation Rel
// a substitute for SelectShapes function after some improvements.
// returns VARIANT_TRUE when shapes were selected, and VARIANT_FALSE if
// no shapes fell into selection
-VARIANT_BOOL CShapefile::SelectShapesAlt(IExtents *BoundBox, double Tolerance, SelectMode SelectMode, VARIANT* arr)
+VARIANT_BOOL CShapefile::SelectShapesAlt(IExtents* BoundBox, double Tolerance, SelectMode SelectMode, VARIANT* arr)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- VARIANT_BOOL retval = VARIANT_FALSE;
-
- double xMin, xMax, yMin, yMax, zMin, zMax;
- BoundBox->GetBounds(&xMin,&yMin,&zMin,&xMax,&yMax,&zMax);
-
- if( xMin == xMax && yMin == yMax )
- {
- xMax +=1;
- yMax +=1;
- }
-
- QTree* qTree = this->GenerateQTreeCore(false);
- if (!qTree)
- {
- ErrorMessage(tkFAILED_TO_BUILD_SPATIAL_INDEX);
- return NULL;
- }
-
- if( Tolerance > 0.0 )
- { xMin = xMin - Tolerance/2;
- yMin = yMin - Tolerance/2;
- xMax = xMax + Tolerance/2;
- yMax = yMax + Tolerance/2;
- }
-
- BoundBox->SetBounds(xMin, yMin, zMin, xMax, yMax, zMax);
-
- set results;
- vector shapeIds;
- shapeIds = qTree->GetNodes(QTreeExtent(xMin,xMax,yMax,yMin));
-
- IShape* temp = NULL;
- OGRGeometry* oBox;
- ((CExtents*)BoundBox)->ToShape(&temp);
- oBox = OgrConverter::ShapeToGeometry(temp);
- temp->Release();
-
- for(int i=0; i < (int)shapeIds.size(); i++)
- {
- IShape* shp = NULL;
- OGRGeometry* oGeom;
- OGRBoolean res = 0;
- this->get_Shape((long)shapeIds[i], &shp);
- oGeom = OgrConverter::ShapeToGeometry(shp);
- shp->Release();
-
- res = oBox->Contains(oGeom);
-
- if (!res)
- res = oGeom->Contains(oBox);
-
- if( SelectMode == INTERSECTION && !res)
- res = oGeom->Intersect (oBox);
-
- if (res) results.insert(shapeIds[i]);
- OGRGeometryFactory::destroyGeometry(oGeom);
- }
-
- if (qTree!=NULL) delete qTree;
- if (oBox!=NULL) OGRGeometryFactory::destroyGeometry(oBox);
- retval = Templates::Set2SafeArray(&results, VT_I4, arr);
- return retval;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+
+ double xMin, xMax, yMin, yMax, zMin, zMax;
+ BoundBox->GetBounds(&xMin, &yMin, &zMin, &xMax, &yMax, &zMax);
+
+ if (xMin == xMax && yMin == yMax)
+ {
+ xMax += 1;
+ yMax += 1;
+ }
+
+ QTree* qTree = this->GenerateQTreeCore(false);
+ if (!qTree)
+ {
+ ErrorMessage(tkFAILED_TO_BUILD_SPATIAL_INDEX);
+ return NULL;
+ }
+
+ if (Tolerance > 0.0)
+ {
+ xMin = xMin - Tolerance / 2;
+ yMin = yMin - Tolerance / 2;
+ xMax = xMax + Tolerance / 2;
+ yMax = yMax + Tolerance / 2;
+ }
+
+ BoundBox->SetBounds(xMin, yMin, zMin, xMax, yMax, zMax);
+
+ set results;
+ vector shapeIds = qTree->GetNodes(QTreeExtent(xMin, xMax, yMax, yMin));
+
+ IShape* temp = nullptr;
+ ((CExtents*)BoundBox)->ToShape(&temp);
+ OGRGeometry* oBox = OgrConverter::ShapeToGeometry(temp);
+ temp->Release();
+
+ for (int shapeId : shapeIds)
+ {
+ IShape* shp = nullptr;
+ this->get_Shape((long)shapeId, &shp);
+ OGRGeometry* oGeom = OgrConverter::ShapeToGeometry(shp);
+ shp->Release();
+
+ OGRBoolean res = oBox->Contains(oGeom);
+
+ if (!res)
+ res = oGeom->Contains(oBox);
+
+ if (SelectMode == INTERSECTION && !res)
+ res = oGeom->Intersects(oBox);
+
+ if (res) results.insert(shapeId);
+ OGRGeometryFactory::destroyGeometry(oGeom);
+ }
+
+ delete qTree;
+ if (oBox != nullptr) OGRGeometryFactory::destroyGeometry(oBox);
+ const VARIANT_BOOL retval = Templates::Set2SafeArray(&results, VT_I4, arr);
+ return retval;
}
#pragma endregion
@@ -517,19 +504,20 @@ VARIANT_BOOL CShapefile::SelectShapesAlt(IExtents *BoundBox, double Tolerance, S
// field. Shapes with the same attribute are merged into one.
STDMETHODIMP CShapefile::Dissolve(long FieldIndex, VARIANT_BOOL SelectedOnly, IShapefile** sf)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- DissolveCore(FieldIndex, SelectedOnly, NULL, sf);
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ DissolveCore(FieldIndex, SelectedOnly, nullptr, sf);
+ return S_OK;
}
// *************************************************************
// DissolveWithStats()
// *************************************************************
-STDMETHODIMP CShapefile::DissolveWithStats(long FieldIndex, VARIANT_BOOL SelectedOnly, IFieldStatOperations* statOperations, IShapefile** sf)
+STDMETHODIMP CShapefile::DissolveWithStats(long FieldIndex, VARIANT_BOOL SelectedOnly,
+ IFieldStatOperations* statOperations, IShapefile** sf)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- DissolveCore(FieldIndex, SelectedOnly, statOperations, sf);
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ DissolveCore(FieldIndex, SelectedOnly, statOperations, sf);
+ return S_OK;
}
// *************************************************************
@@ -537,66 +525,67 @@ STDMETHODIMP CShapefile::DissolveWithStats(long FieldIndex, VARIANT_BOOL Selecte
// *************************************************************
// Merges shapes of the shapefile based on the attribute of the given
// field. Shapes with the same attribute are merged into one.
-void CShapefile::DissolveCore(long FieldIndex, VARIANT_BOOL SelectedOnly, IFieldStatOperations* operations, IShapefile** sf)
+void CShapefile::DissolveCore(long FieldIndex, VARIANT_BOOL SelectedOnly, IFieldStatOperations* operations,
+ IShapefile** sf)
{
- // ----------------------------------------------
- // Validation
- // ----------------------------------------------
- long numFields;
- this->get_NumFields(&numFields);
-
- if( FieldIndex < 0 || FieldIndex >= numFields)
- {
- ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
- return;
- }
-
- if (!ValidateInput(this, "Dissolve", "this", SelectedOnly))
- return;
-
- // ----------------------------------------------
- // Creating output
- // ----------------------------------------------
- ShpfileType type = _shpfiletype;
-
- // for points change to multi-point type, as there is no other way to group them
- if (type == SHP_POINT) type = SHP_MULTIPOINT;
- if (type == SHP_POINTZ) type = SHP_MULTIPOINTZ;
- if (type == SHP_POINTM) type = SHP_MULTIPOINTM;
-
- // ShapefileHelper::CloneNoFields(this, sf, type);
- // -----------------------------------------------
- // Creating output
- // -----------------------------------------------
- if (!ShapefileHelper::CloneNoFields(this, sf, type))
- {
- // Get errorcode and pass the source:
- long errorCode;
- (*sf)->get_LastErrorCode(&errorCode);
- *sf = NULL;
- ErrorMessage(errorCode);
- return;
- }
- CloneField(this, *sf, FieldIndex, -1);
-
- // -------------------------------------------
- // processing
- // -------------------------------------------
- if (_geometryEngine == engineGeos)
- {
- this->DissolveGEOS(FieldIndex, SelectedOnly, operations, *sf);
- }
- else
- {
- this->DissolveClipper(FieldIndex, SelectedOnly, operations, *sf);
- }
-
- // -------------------------------------------
- // output validation
- // -------------------------------------------
- CallbackHelper::ProgressCompleted(_globalCallback, _key);
- ValidateOutput(sf, "Dissolve");
- return;
+ // ----------------------------------------------
+ // Validation
+ // ----------------------------------------------
+ long numFields;
+ this->get_NumFields(&numFields);
+
+ if (FieldIndex < 0 || FieldIndex >= numFields)
+ {
+ ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
+ return;
+ }
+
+ if (!ValidateInput(this, "Dissolve", "this", SelectedOnly))
+ return;
+
+ // ----------------------------------------------
+ // Creating output
+ // ----------------------------------------------
+ ShpfileType type = _shpfiletype;
+
+ // for points change to multi-point type, as there is no other way to group them
+ if (type == SHP_POINT) type = SHP_MULTIPOINT;
+ if (type == SHP_POINTZ) type = SHP_MULTIPOINTZ;
+ if (type == SHP_POINTM) type = SHP_MULTIPOINTM;
+
+ // ShapefileHelper::CloneNoFields(this, sf, type);
+ // -----------------------------------------------
+ // Creating output
+ // -----------------------------------------------
+ if (!ShapefileHelper::CloneNoFields(this, sf, type))
+ {
+ // Get errorcode and pass the source:
+ long errorCode;
+ (*sf)->get_LastErrorCode(&errorCode);
+ *sf = nullptr;
+ ErrorMessage(errorCode);
+ return;
+ }
+ CloneField(this, *sf, FieldIndex, -1);
+
+ // -------------------------------------------
+ // processing
+ // -------------------------------------------
+ if (_geometryEngine == engineGeos)
+ {
+ this->DissolveGEOS(FieldIndex, SelectedOnly, operations, *sf);
+ }
+ else
+ {
+ this->DissolveClipper(FieldIndex, SelectedOnly, operations, *sf);
+ }
+
+ // -------------------------------------------
+ // output validation
+ // -------------------------------------------
+ CallbackHelper::ProgressCompleted(_globalCallback, _key);
+ ValidateOutput(sf, "Dissolve");
+ return;
}
// *************************************************************
@@ -604,519 +593,526 @@ void CShapefile::DissolveCore(long FieldIndex, VARIANT_BOOL SelectedOnly, IField
// *************************************************************
char* GetStatOperationName(tkFieldStatOperation op)
{
- switch(op)
- {
- case fsoSum:
- return "SUM";
- case fsoAvg:
- return "AVG";
- case fsoMin:
- return "MIN";
- case fsoMax:
- return "MAX";
- case fsoMode:
- return "MOD";
- case fsoWeightedAvg:
- return "WAVG";
- default:
- return "";
- }
+ switch (op)
+ {
+ case fsoSum:
+ return "SUM";
+ case fsoAvg:
+ return "AVG";
+ case fsoMin:
+ return "MIN";
+ case fsoMax:
+ return "MAX";
+ case fsoMode:
+ return "MOD";
+ case fsoWeightedAvg:
+ return "WAVG";
+ default:
+ return "";
+ }
}
// *************************************************************
// CalculateFieldStats()
// *************************************************************
-void CShapefile::CalculateFieldStats(map*>& fieldMap, IFieldStatOperations* ioperations, IShapefile* sf)
+void CShapefile::CalculateFieldStats(map*>& fieldMap, IFieldStatOperations* ioperations,
+ IShapefile* sf)
{
- // --------------------------------------------
- // validating operations
- // --------------------------------------------
- USES_CONVERSION;
- long numFields;
- this->get_NumFields(&numFields);
- std::vector* operations = &((CFieldStatOperations*)ioperations)->_operations;
-
- VARIANT_BOOL vb;
- ioperations->Validate(this, &vb);
-
- for(size_t i = 0; i < operations->size(); i++)
- {
- FieldOperation* op = (*operations)[i];
-
- // creating output field for operation
- if (op->valid)
- {
- IField* field = NULL;
- this->get_Field(op->fieldIndex, &field);
- if (field)
- {
- CComBSTR bstr;
- field->get_Name(&bstr);
- CStringW name = OLE2W(bstr);
- name = name + "_" + A2W(GetStatOperationName(op->operation));
-
- FieldType type;
- field->get_Type(&type);
- if (type == INTEGER_FIELD && op->operation == fsoAvg)
- type = DOUBLE_FIELD;
-
- long precision;
- field->get_Precision(&precision);
- long width;
- field->get_Width(&width);
-
- long fieldIndex;
- CComBSTR bstrName(name);
- sf->EditAddField(bstrName, type, precision, width, &fieldIndex);
-
- op->targetIndex = fieldIndex;
- op->targetFieldType = type;
- field->Release();
- }
- }
- }
-
- // make sure that output field names are unique
- FieldHelper::UniqueFieldNames(sf);
-
- // --------------------------------------------
- // calculating
- // --------------------------------------------
- double areaSum;
- double area;
- double val;
- double sum = 0.0;
- CString sVal;
- CString sSum;
- CComVariant var;
- int index = 0;
- int size = fieldMap.size();
- long percent = 0;
- map frequencies;
-
- ShpfileType type;
- sf->get_ShapefileType(&type);
- type = ShapeUtility::Convert2D(type);
-
- map *>::iterator p = fieldMap.begin(); // row in the output, rows in the input
- while(p != fieldMap.end())
- {
- CallbackHelper::Progress(_globalCallback, index, size, "Calculating stats", _key, percent);
-
- for(size_t i = 0; i < operations->size(); i++)
- {
- FieldOperation* op = (*operations)[i];
- if (!op->valid) continue;
-
- if (op->targetFieldType == STRING_FIELD)
- {
- sVal = "";
- frequencies.clear();
- for(size_t j = 0; j < p->second->size(); j++)
- {
- this->get_CellValue(op->fieldIndex, (*p->second)[j], &var);
- stringVal(var, sVal);
-
- if (op->operation == fsoMode)
- {
- frequencies[sVal] = frequencies.find(sVal) == frequencies.end() ? 1 : frequencies[sVal] + 1;
- }
- else
- {
- // take the first one, as output despite the operation
- if (sSum.GetLength() == 0)
- {
- sSum = sVal;
- }
- else
- {
- int res = sSum.CompareNoCase(sVal);
- if ((res < 0 && op->operation == fsoMax) ||
- (res > 0 && op->operation == fsoMin))
- {
- sSum = sVal;
- }
- }
- }
- }
-
- if (op->operation == fsoMode)
- {
- int max = INT_MIN;
- map ::iterator p = frequencies.begin();
- while(p != frequencies.end())
- {
- if (max < p->second) {
- max = p->second;
- sSum = p->first;
- }
- ++p;
- }
- }
-
- CComVariant result(sSum);
- sf->EditCellValue(op->targetIndex, p->first, result, &vb);
- }
- else
- {
- switch(op->operation)
- {
- case fsoSum:
- case fsoAvg:
- case fsoWeightedAvg:
- sum = 0.0;
- areaSum = 0.0;
- break;
- case fsoMin:
- sum = DBL_MAX;
- break;
- case fsoMax:
- sum = DBL_MIN;
- break;
- }
-
- // going through rows of original shapefile, which fell into the same group
- for(size_t j = 0; j < p->second->size(); j++)
- {
- this->get_CellValue(op->fieldIndex, (*p->second)[j], &var);
- dVal(var, val);
-
- switch(op->operation)
- {
- case fsoSum:
- case fsoAvg:
- sum += val;
- break;
- case fsoMin:
- if (val < sum) sum = val;
- case fsoMax:
- if (val > sum) sum = val;
- break;
- case fsoWeightedAvg:
- {
- if (type == SHP_POLYGON || type == SHP_POLYLINE)
- {
- IShape* shp = NULL;
- this->GetValidatedShape((*p->second)[j], &shp);
- if (shp)
- {
- if (type == SHP_POLYGON) shp->get_Area(&area);
- else shp->get_Length(&area); // weighting by length of polylines
- shp->Release();
- areaSum += area;
- sum += val * area;
- }
- }
- else
- {
- sum += val; // regular sum for points
- }
- }
- break;
- }
- }
-
- if (op->operation == fsoAvg)
- {
- sum /= p->second->size();
- }
- if (op->operation == fsoWeightedAvg)
- {
- sum /= areaSum;
- }
-
- if (op->targetFieldType == INTEGER_FIELD)
- {
- CComVariant result(Utility::Rint(sum));
- sf->EditCellValue(op->targetIndex, p->first, result, &vb);
- }
- else
- {
- CComVariant result(sum);
- sf->EditCellValue(op->targetIndex, p->first, result, &vb);
- }
- }
- }
- index++;
- ++p;
- }
-
- CallbackHelper::ProgressCompleted(_globalCallback, _key);
+ // --------------------------------------------
+ // validating operations
+ // --------------------------------------------
+ USES_CONVERSION;
+ long numFields;
+ this->get_NumFields(&numFields);
+ std::vector* operations = &((CFieldStatOperations*)ioperations)->_operations;
+
+ VARIANT_BOOL vb;
+ ioperations->Validate(this, &vb);
+
+ for (auto op : *operations)
+ {
+ // creating output field for operation
+ if (op->valid)
+ {
+ IField* field = nullptr;
+ this->get_Field(op->fieldIndex, &field);
+ if (field)
+ {
+ CComBSTR bstr;
+ field->get_Name(&bstr);
+ CStringW name = OLE2W(bstr);
+ name = name + "_" + A2W(GetStatOperationName(op->operation));
+
+ FieldType type;
+ field->get_Type(&type);
+ if (type == INTEGER_FIELD && op->operation == fsoAvg)
+ type = DOUBLE_FIELD;
+
+ long precision;
+ field->get_Precision(&precision);
+ long width;
+ field->get_Width(&width);
+
+ long fieldIndex;
+ const CComBSTR bstrName(name);
+ sf->EditAddField(bstrName, type, precision, width, &fieldIndex);
+
+ op->targetIndex = fieldIndex;
+ op->targetFieldType = type;
+ field->Release();
+ }
+ }
+ }
+
+ // make sure that output field names are unique
+ FieldHelper::UniqueFieldNames(sf);
+
+ // --------------------------------------------
+ // calculating
+ // --------------------------------------------
+ double areaSum = 0;
+ double area;
+ double val;
+ double sum = 0.0;
+ CString sSum;
+ CComVariant var;
+ int index = 0;
+ const int size = fieldMap.size();
+ long percent = 0;
+ map frequencies;
+
+ ShpfileType type;
+ sf->get_ShapefileType(&type);
+ type = ShapeUtility::Convert2D(type);
+
+ auto p = fieldMap.begin(); // row in the output, rows in the input
+ while (p != fieldMap.end())
+ {
+ CallbackHelper::Progress(_globalCallback, index, size, "Calculating stats", _key, percent);
+
+ for (auto op : *operations)
+ {
+ if (!op->valid) continue;
+
+ if (op->targetFieldType == STRING_FIELD)
+ {
+ CString sVal = "";
+ frequencies.clear();
+ for (int j : *p->second)
+ {
+ this->get_CellValue(op->fieldIndex, j, &var);
+ stringVal(var, sVal);
+
+ if (op->operation == fsoMode)
+ {
+ frequencies[sVal] = frequencies.find(sVal) == frequencies.end() ? 1 : frequencies[sVal] + 1;
+ }
+ else
+ {
+ // take the first one, as output despite the operation
+ if (sSum.GetLength() == 0)
+ {
+ sSum = sVal;
+ }
+ else
+ {
+ const int res = sSum.CompareNoCase(sVal);
+ if (res < 0 && op->operation == fsoMax ||
+ res > 0 && op->operation == fsoMin)
+ {
+ sSum = sVal;
+ }
+ }
+ }
+ }
+
+ if (op->operation == fsoMode)
+ {
+ int max = INT_MIN;
+ auto frequency = frequencies.begin();
+ while (frequency != frequencies.end())
+ {
+ if (max < frequency->second)
+ {
+ max = frequency->second;
+ sSum = frequency->first;
+ }
+ ++frequency;
+ }
+ }
+
+ const CComVariant result(sSum);
+ sf->EditCellValue(op->targetIndex, p->first, result, &vb);
+ }
+ else
+ {
+ switch (op->operation)
+ {
+ case fsoSum:
+ case fsoAvg:
+ case fsoWeightedAvg:
+ sum = 0.0;
+ areaSum = 0.0;
+ break;
+ case fsoMin:
+ sum = DBL_MAX;
+ break;
+ case fsoMax:
+ sum = DBL_MIN;
+ break;
+ case fsoMode: break;
+ default: ;
+ }
+
+ // going through rows of original shapefile, which fell into the same group
+ for (int j : *p->second)
+ {
+ this->get_CellValue(op->fieldIndex, j, &var);
+ dVal(var, val);
+
+ switch (op->operation)
+ {
+ case fsoSum:
+ case fsoAvg:
+ sum += val;
+ break;
+ case fsoMin:
+ if (val < sum) sum = val;
+ case fsoMax:
+ if (val > sum) sum = val;
+ break;
+ case fsoWeightedAvg:
+ {
+ if (type == SHP_POLYGON || type == SHP_POLYLINE)
+ {
+ IShape* shp = nullptr;
+ this->GetValidatedShape(j, &shp);
+ if (shp)
+ {
+ if (type == SHP_POLYGON) shp->get_Area(&area);
+ else shp->get_Length(&area); // weighting by length of polylines
+ shp->Release();
+ areaSum += area;
+ sum += val * area;
+ }
+ }
+ else
+ {
+ sum += val; // regular sum for points
+ }
+ }
+ break;
+ case fsoMode: break;
+ default: ;
+ }
+ }
+
+ if (op->operation == fsoAvg)
+ {
+ sum /= p->second->size();
+ }
+ if (op->operation == fsoWeightedAvg)
+ {
+ sum /= areaSum;
+ }
+
+ if (op->targetFieldType == INTEGER_FIELD)
+ {
+ const CComVariant result(Utility::Rint(sum));
+ sf->EditCellValue(op->targetIndex, p->first, result, &vb);
+ }
+ else
+ {
+ const CComVariant result(sum);
+ sf->EditCellValue(op->targetIndex, p->first, result, &vb);
+ }
+ }
+ }
+ index++;
+ ++p;
+ }
+
+ CallbackHelper::ProgressCompleted(_globalCallback, _key);
}
// *************************************************************
// DissolveGEOS()
// *************************************************************
-void CShapefile::DissolveGEOS(long FieldIndex, VARIANT_BOOL SelectedOnly, IFieldStatOperations* operations, IShapefile* sf)
+void CShapefile::DissolveGEOS(long FieldIndex, VARIANT_BOOL SelectedOnly, IFieldStatOperations* operations,
+ IShapefile* sf)
{
- map *> fieldMap; // index in output, indices in input
- map *> indicesMap; // value in input, indices in input
- map *> shapeMap;
-
- CComVariant val; // VARIANT hasn't got comparison operators and therefore
- // can't be used with associative containers
-
- bool calcStats = false;
- if (operations)
- {
- int count;
- operations->get_Count(&count);
- calcStats = count > 0;
- }
-
- ReadGeosGeometries(SelectedOnly);
-
- long percent = 0;
- int size = (int)_shapeData.size();
- for(long i = 0; i < size; i++)
- {
- CallbackHelper::Progress(_globalCallback, i, size, "Grouping shapes...", _key, percent);
-
- if (!ShapeAvailable(i, SelectedOnly))
- continue;
-
- GEOSGeometry* gsGeom = this->GetGeosGeometry(i);
- if (gsGeom != NULL)
- {
- this->get_CellValue(FieldIndex, i, &val);
- if(shapeMap.find(val) != shapeMap.end())
- {
- shapeMap[val]->push_back(gsGeom);
- if (calcStats) {
- indicesMap[val]->push_back(i);
- }
- }
- else
- {
- vector* v = new vector;
- v->push_back(gsGeom);
- shapeMap[val] = v;
-
- if (calcStats) {
- vector* v2 = new vector;
- v2->push_back(i);
- indicesMap[val] = v2;
- }
- }
- }
- }
-
- bool isM = ShapeUtility::IsM(_shpfiletype);
-
- // saving results
- long count = 0; // number of shapes inserted
- int shapeProcessed = 0; // for progress bar
- percent = 0;
- size = shapeMap.size();
-
- VARIANT_BOOL vbretval;
- map *>::iterator p = shapeMap.begin();
-
- ShpfileType targetType;
- sf->get_ShapefileType(&targetType);
-
- while(p != shapeMap.end())
- {
- CallbackHelper::Progress(_globalCallback, shapeProcessed, size, "Merging shapes...", _key, percent);
-
- GEOSGeometry* gsGeom = GeosConverter::MergeGeometries(*(p->second), NULL, false, false);
- delete p->second; // deleting the vector
-
- if (gsGeom != NULL)
- {
- std::vector vShapes;
- if (GeosConverter::GeomToShapes(gsGeom, &vShapes, isM))
- {
- for (unsigned int i = 0; i < vShapes.size(); i++)
- {
- IShape* shp = vShapes[i];
- if (shp != NULL)
- {
- ShapeHelper::ForceProperShapeType(shp, targetType);
-
- sf->EditInsertShape(shp, &count, &vbretval);
- if (vbretval)
- sf->EditCellValue(0, count, (VARIANT)p->first, &vbretval);
-
- shp->Release();
-
- if (calcStats)
- {
- std::vector* indices = indicesMap[p->first];
- fieldMap[count] = indices;
- }
-
- count++;
- }
- }
- }
- GeosHelper::DestroyGeometry(gsGeom);
- }
- ++p;
- shapeProcessed++;
- }
-
- if (calcStats)
- {
- CalculateFieldStats(fieldMap, operations, sf);
-
- // delete indices map
- map *>::iterator p2 = indicesMap.begin();
- while(p2 != indicesMap.end())
- {
- delete p2->second;
- ++p2;
- }
- }
-
- this->ClearCachedGeometries();
- CallbackHelper::ProgressCompleted(_globalCallback, _key);
+ map*> fieldMap; // index in output, indices in input
+ map*> indicesMap; // value in input, indices in input
+ map*> shapeMap;
+
+ CComVariant val; // VARIANT hasn't got comparison operators and therefore
+ // can't be used with associative containers
+
+ bool calcStats = false;
+ if (operations)
+ {
+ int count;
+ operations->get_Count(&count);
+ calcStats = count > 0;
+ }
+
+ ReadGeosGeometries(SelectedOnly);
+
+ long percent = 0;
+ auto size = (int)_shapeData.size();
+ for (long i = 0; i < size; i++)
+ {
+ CallbackHelper::Progress(_globalCallback, i, size, "Grouping shapes...", _key, percent);
+
+ if (!ShapeAvailable(i, SelectedOnly))
+ continue;
+
+ GEOSGeometry* gsGeom = this->GetGeosGeometry(i);
+ if (gsGeom != nullptr)
+ {
+ this->get_CellValue(FieldIndex, i, &val);
+ if (shapeMap.find(val) != shapeMap.end())
+ {
+ shapeMap[val]->push_back(gsGeom);
+ if (calcStats)
+ {
+ indicesMap[val]->push_back(i);
+ }
+ }
+ else
+ {
+ auto* v = new vector;
+ v->push_back(gsGeom);
+ shapeMap[val] = v;
+
+ if (calcStats)
+ {
+ auto* v2 = new vector;
+ v2->push_back(i);
+ indicesMap[val] = v2;
+ }
+ }
+ }
+ }
+
+ const bool isM = ShapeUtility::IsM(_shpfiletype);
+
+ // saving results
+ long count = 0; // number of shapes inserted
+ int shapeProcessed = 0; // for progress bar
+ percent = 0;
+ size = shapeMap.size();
+
+ VARIANT_BOOL vbretval;
+ auto p = shapeMap.begin();
+
+ ShpfileType targetType;
+ sf->get_ShapefileType(&targetType);
+
+ while (p != shapeMap.end())
+ {
+ CallbackHelper::Progress(_globalCallback, shapeProcessed, size, "Merging shapes...", _key, percent);
+
+ GEOSGeometry* gsGeom = GeosConverter::MergeGeometries(*p->second, nullptr, false, false);
+ delete p->second; // deleting the vector
+
+ if (gsGeom != nullptr)
+ {
+ std::vector vShapes;
+ if (GeosConverter::GeomToShapes(gsGeom, &vShapes, isM))
+ {
+ for (auto shp : vShapes)
+ {
+ if (shp != nullptr)
+ {
+ ShapeHelper::ForceProperShapeType(shp, targetType);
+
+ sf->EditInsertShape(shp, &count, &vbretval);
+ if (vbretval)
+ sf->EditCellValue(0, count, (VARIANT)p->first, &vbretval);
+
+ shp->Release();
+
+ if (calcStats)
+ {
+ std::vector* indices = indicesMap[p->first];
+ fieldMap[count] = indices;
+ }
+
+ count++;
+ }
+ }
+ }
+ GeosHelper::DestroyGeometry(gsGeom);
+ }
+ ++p;
+ shapeProcessed++;
+ }
+
+ if (calcStats)
+ {
+ CalculateFieldStats(fieldMap, operations, sf);
+
+ // delete indices map
+ auto p2 = indicesMap.begin();
+ while (p2 != indicesMap.end())
+ {
+ delete p2->second;
+ ++p2;
+ }
+ }
+
+ this->ClearCachedGeometries();
+ CallbackHelper::ProgressCompleted(_globalCallback, _key);
}
// *************************************************************
// DissolveClipper()
// *************************************************************
-void CShapefile::DissolveClipper(long FieldIndex, VARIANT_BOOL SelectedOnly, IFieldStatOperations* operations, IShapefile* sf)
+void CShapefile::DissolveClipper(long FieldIndex, VARIANT_BOOL SelectedOnly, IFieldStatOperations* operations,
+ IShapefile* sf)
{
- map *> fieldMap; // index in output, indices in input
- map *> indicesMap; // value in input, indices in input
- map shapeMap;
-
- CComVariant val; // VARIANT hasn't got comparison operators and therefore
- // can't be used with associative containers
- long percent = 0;
- int size = (int)_shapeData.size();
- // std::vector polygons;
- std::vector polygons;
- polygons.resize(size, NULL);
-
- ClipperConverter ogr(this);
-
- bool calcStats = false;
- if (operations)
- {
- int count;
- operations->get_Count(&count);
- calcStats = count > 0;
- }
-
- for(long i = 0; i < size; i++)
- {
- CallbackHelper::Progress(_globalCallback, i, size, "Merging shapes...", _key, percent);
-
- if (!ShapeAvailable(i, SelectedOnly))
- continue;
-
- IShape* shp = NULL;
- this->GetValidatedShape(i, &shp);
- if (!shp) continue;
-
- // ClipperLib::Polygons* poly = ogr.Shape2ClipperPolygon(shp);
- ClipperLib::Paths* poly = ogr.Shape2ClipperPolygon(shp);
- shp->Release();
-
- if (poly == NULL) continue;
-
- this->get_CellValue(FieldIndex, i, &val);
-
- if(shapeMap.find(val) != shapeMap.end())
- {
- // shapeMap[val]->AddPolygons(*poly, ClipperLib::ptClip);
- shapeMap[val]->AddPaths(*poly, ClipperLib::ptClip, true);
- polygons[i] = poly;
- if (calcStats) {
- indicesMap[val]->push_back(i);
- }
- }
- else
- {
- shapeMap[val] = new ClipperLib::Clipper();
- // shapeMap[val]->AddPolygons(*poly, ClipperLib::ptClip);
- shapeMap[val]->AddPaths(*poly, ClipperLib::ptClip, true);
- polygons[i] = poly;
-
- if (calcStats) {
- vector* v2 = new vector;
- v2->push_back(i);
- indicesMap[val] = v2;
- }
- }
- }
-
- // perform clipping and saving the results
- VARIANT_BOOL vbretval;
- long count = 0;
- map ::iterator p = shapeMap.begin();
- while(p != shapeMap.end())
- {
- IShape* shp = NULL;
- // ClipperLib::Polygons result;
- ClipperLib::Paths result;
- ClipperLib::Clipper* clip = p->second;
- if (clip)
- {
- clip->Execute(ClipperLib::ctUnion, result);
- shp = ogr.ClipperPolygon2Shape(&result);
-
- if (shp)
- {
- long numPoints;
- shp->get_NumPoints(&numPoints);
- if (numPoints > 0)
- {
- sf->EditInsertShape(shp, &count, &vbretval);
- if (vbretval)
- sf->EditCellValue(0, count, (VARIANT)p->first, &vbretval);
-
- if (calcStats)
- {
- std::vector* indices = indicesMap[p->first];
- fieldMap[count] = indices;
- }
-
- count++;
- }
- shp->Release();
- }
- delete p->second;
- }
- ++p;
- }
-
- // deleting the polygons
- for (int i = 0; i < size; i++)
- {
- if (polygons[i])
- {
- delete polygons[i];
- }
- }
-
- CallbackHelper::ProgressCompleted(_globalCallback, _key);
- shapeMap.clear();
-
- if (calcStats)
- {
- CalculateFieldStats(fieldMap, operations, sf);
-
- // delete indices map
- map *>::iterator p = indicesMap.begin();
- while(p != indicesMap.end())
- {
- delete p->second;
- ++p;
- }
- }
+ map*> fieldMap; // index in output, indices in input
+ map*> indicesMap; // value in input, indices in input
+ map shapeMap;
+
+ CComVariant val; // VARIANT hasn't got comparison operators and therefore
+ // can't be used with associative containers
+ long percent = 0;
+ const auto size = (int)_shapeData.size();
+ // std::vector polygons;
+ std::vector polygons;
+ polygons.resize(size, nullptr);
+
+ ClipperConverter ogr(this);
+
+ bool calcStats = false;
+ if (operations)
+ {
+ int count;
+ operations->get_Count(&count);
+ calcStats = count > 0;
+ }
+
+ for (long i = 0; i < size; i++)
+ {
+ CallbackHelper::Progress(_globalCallback, i, size, "Merging shapes...", _key, percent);
+
+ if (!ShapeAvailable(i, SelectedOnly))
+ continue;
+
+ IShape* shp = nullptr;
+ this->GetValidatedShape(i, &shp);
+ if (!shp) continue;
+
+ // ClipperLib::Polygons* poly = ogr.Shape2ClipperPolygon(shp);
+ ClipperLib::Paths* poly = ogr.Shape2ClipperPolygon(shp);
+ shp->Release();
+
+ if (poly == nullptr) continue;
+
+ this->get_CellValue(FieldIndex, i, &val);
+
+ if (shapeMap.find(val) != shapeMap.end())
+ {
+ // shapeMap[val]->AddPolygons(*poly, ClipperLib::ptClip);
+ shapeMap[val]->AddPaths(*poly, ClipperLib::ptClip, true);
+ polygons[i] = poly;
+ if (calcStats)
+ {
+ indicesMap[val]->push_back(i);
+ }
+ }
+ else
+ {
+ shapeMap[val] = new ClipperLib::Clipper();
+ // shapeMap[val]->AddPolygons(*poly, ClipperLib::ptClip);
+ shapeMap[val]->AddPaths(*poly, ClipperLib::ptClip, true);
+ polygons[i] = poly;
+
+ if (calcStats)
+ {
+ auto* v2 = new vector;
+ v2->push_back(i);
+ indicesMap[val] = v2;
+ }
+ }
+ }
+
+ // perform clipping and saving the results
+ VARIANT_BOOL vbretval;
+ long count = 0;
+ auto p = shapeMap.begin();
+ while (p != shapeMap.end())
+ {
+ // ClipperLib::Polygons result;
+ ClipperLib::Paths result;
+ ClipperLib::Clipper* clip = p->second;
+ if (clip)
+ {
+ clip->Execute(ClipperLib::ctUnion, result);
+ IShape* shp = ogr.ClipperPolygon2Shape(&result);
+
+ if (shp)
+ {
+ long numPoints;
+ shp->get_NumPoints(&numPoints);
+ if (numPoints > 0)
+ {
+ sf->EditInsertShape(shp, &count, &vbretval);
+ if (vbretval)
+ sf->EditCellValue(0, count, (VARIANT)p->first, &vbretval);
+
+ if (calcStats)
+ {
+ std::vector* indices = indicesMap[p->first];
+ fieldMap[count] = indices;
+ }
+
+ count++;
+ }
+ shp->Release();
+ }
+ delete p->second;
+ }
+ ++p;
+ }
+
+ // deleting the polygons
+ for (int i = 0; i < size; i++)
+ {
+ if (polygons[i])
+ {
+ delete polygons[i];
+ }
+ }
+
+ CallbackHelper::ProgressCompleted(_globalCallback, _key);
+ shapeMap.clear();
+
+ if (calcStats)
+ {
+ CalculateFieldStats(fieldMap, operations, sf);
+
+ // delete indices map
+ auto index = indicesMap.begin();
+ while (index != indicesMap.end())
+ {
+ delete index->second;
+ ++index;
+ }
+ }
}
// ********************************************************************
// AggregateShapesWithStats()
// ********************************************************************
-STDMETHODIMP CShapefile::AggregateShapesWithStats(VARIANT_BOOL SelectedOnly, LONG FieldIndex, IFieldStatOperations* statOperations, IShapefile** retval)
+STDMETHODIMP CShapefile::AggregateShapesWithStats(VARIANT_BOOL SelectedOnly, LONG FieldIndex,
+ IFieldStatOperations* statOperations, IShapefile** retval)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- AggregateShapesCore(SelectedOnly, FieldIndex, statOperations, retval);
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ AggregateShapesCore(SelectedOnly, FieldIndex, statOperations, retval);
+ return S_OK;
}
// ********************************************************************
@@ -1124,464 +1120,479 @@ STDMETHODIMP CShapefile::AggregateShapesWithStats(VARIANT_BOOL SelectedOnly, LON
// ********************************************************************
STDMETHODIMP CShapefile::AggregateShapes(VARIANT_BOOL SelectedOnly, LONG FieldIndex, IShapefile** retval)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- AggregateShapesCore(SelectedOnly, FieldIndex, NULL, retval);
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ AggregateShapesCore(SelectedOnly, FieldIndex, nullptr, retval);
+ return S_OK;
}
// ********************************************************************
// AggregateShapesCore()
// ********************************************************************
// Returns new shapefile instance.
-void CShapefile::AggregateShapesCore(VARIANT_BOOL SelectedOnly, LONG FieldIndex, IFieldStatOperations* operations, IShapefile** retval)
+void CShapefile::AggregateShapesCore(VARIANT_BOOL SelectedOnly, LONG FieldIndex, IFieldStatOperations* operations,
+ IShapefile** retval)
{
- long numFields;
- this->get_NumFields(&numFields);
-
- if( FieldIndex != -1 && !(FieldIndex >= 0 && FieldIndex < numFields))
- {
- ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
- return;
- }
-
- if(!ValidateInput(this, "AggregateShapes", "this", SelectedOnly))
- return;
-
- // ----------------------------------------------
- // Creating output
- // ----------------------------------------------
- ShpfileType targetType = _shpfiletype;
-
- // for points change to multi-point type, as there is no other way to group them
- if (targetType == SHP_POINT) targetType = SHP_MULTIPOINT;
- if (targetType == SHP_POINTZ) targetType = SHP_MULTIPOINTZ;
- if (targetType == SHP_POINTM) targetType = SHP_MULTIPOINTM;
-
- //ShapefileHelper::CloneNoFields(this, retval, targetType);
- // -----------------------------------------------
- // Creating output
- // -----------------------------------------------
- if (!ShapefileHelper::CloneNoFields(this, retval, targetType))
- {
- // Get errorcode and pass the source:
- long errorCode;
- (*retval)->get_LastErrorCode(&errorCode);
- *retval = NULL;
- ErrorMessage(errorCode);
- return;
- }
- long newFieldIndex = 0;
- CloneField(this, *retval, FieldIndex, newFieldIndex);
-
- // ----------------------------------------------
- // Building groups by field id
- // ----------------------------------------------
- VARIANT_BOOL vbretval;
- map *> fieldMap; // index in output, indices in input
- map *> indicesMap; // value in input, indices in input
- map *> shapeMap;
-
- CComVariant val;
-
- bool calcStats = false;
- if (operations)
- {
- int count;
- operations->get_Count(&count);
- calcStats = count > 0;
- }
+ long numFields;
+ this->get_NumFields(&numFields);
+
+ if (FieldIndex != -1 && !(FieldIndex >= 0 && FieldIndex < numFields))
+ {
+ ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
+ return;
+ }
+
+ if (!ValidateInput(this, "AggregateShapes", "this", SelectedOnly))
+ return;
+
+ // ----------------------------------------------
+ // Creating output
+ // ----------------------------------------------
+ ShpfileType targetType = _shpfiletype;
+
+ // for points change to multi-point type, as there is no other way to group them
+ if (targetType == SHP_POINT) targetType = SHP_MULTIPOINT;
+ if (targetType == SHP_POINTZ) targetType = SHP_MULTIPOINTZ;
+ if (targetType == SHP_POINTM) targetType = SHP_MULTIPOINTM;
+
+ //ShapefileHelper::CloneNoFields(this, retval, targetType);
+ // -----------------------------------------------
+ // Creating output
+ // -----------------------------------------------
+ if (!ShapefileHelper::CloneNoFields(this, retval, targetType))
+ {
+ // Get errorcode and pass the source:
+ long errorCode;
+ (*retval)->get_LastErrorCode(&errorCode);
+ *retval = nullptr;
+ ErrorMessage(errorCode);
+ return;
+ }
+ const long newFieldIndex = 0;
+ CloneField(this, *retval, FieldIndex, newFieldIndex);
+
+ // ----------------------------------------------
+ // Building groups by field id
+ // ----------------------------------------------
+ VARIANT_BOOL vbretval;
+ map*> fieldMap; // index in output, indices in input
+ map*> indicesMap; // value in input, indices in input
+ map*> shapeMap;
+
+ CComVariant val;
+
+ bool calcStats = false;
+ if (operations)
+ {
+ int count;
+ operations->get_Count(&count);
+ calcStats = count > 0;
+ }
+
+ long percent = 0;
+ auto size = (int)_shapeData.size();
+
+ for (long i = 0; i < size; i++)
+ {
+ CallbackHelper::Progress(_globalCallback, i, size, "Grouping shapes...", _key, percent);
+
+ if (!ShapeAvailable(i, SelectedOnly))
+ continue;
+
+ IShape* shp = nullptr;
+ this->GetValidatedShape(i, &shp);
+ if (!shp) continue;
+
+ if (FieldIndex != -1)
+ this->get_CellValue(FieldIndex, i, &val);
+
+ if (shapeMap.find(val) != shapeMap.end())
+ {
+ shapeMap[val]->push_back(shp);
+ if (calcStats)
+ {
+ indicesMap[val]->push_back(i);
+ }
+ }
+ else
+ {
+ auto* v = new vector;
+ v->push_back(shp);
+ shapeMap[val] = v;
+
+ if (calcStats)
+ {
+ auto* v2 = new vector;
+ v2->push_back(i);
+ indicesMap[val] = v2;
+ }
+ }
+ }
+
+ // ----------------------------------------------
+ // Merging groups
+ // ----------------------------------------------
+ long count = 0; // number of shapes inserted
+ int i = 0; // for progress bar
+ percent = 0;
+ size = shapeMap.size();
+ auto p = shapeMap.begin();
+
+ while (p != shapeMap.end())
+ {
+ CallbackHelper::Progress(_globalCallback, i, size, "Merging shapes...", _key, percent);
+
+ // merging shapes
+ vector* shapes = p->second;
+ long pntIndex = 0;
+ long partIndex = 0;
+
+ IShape* shpBase = nullptr;
+ for (unsigned int j = 0; j < shapes->size(); j++)
+ {
+ if (j == 0)
+ {
+ if (_isEditingShapes)
+ {
+ // in editing mode we share the shape with parent shapefile
+ // so a copy is needed to avoid conflicts
+ (*shapes)[0]->Clone(&shpBase);
+ (*shapes)[0]->Release();
+ }
+ else
+ {
+ // in the regular mode we are the sole owners of shape
+ shpBase = (*shapes)[0];
+ }
+ shpBase->get_NumPoints(&pntIndex);
+ shpBase->get_NumParts(&partIndex);
+
+ ShapeHelper::ForceProperShapeType(shpBase, targetType);
+ }
+ else
+ {
+ IShape* shp = (*shapes)[j];
+
+ if (ShapeUtility::Convert2D(targetType) == SHP_MULTIPOINT)
+ {
+ // in case of multi-point target type, simply copy all the points to base shape
+ // no need to deal with parts, multi-points don't have those
+ long numPoints = 0;
+ shp->get_NumPoints(&numPoints);
+ for (long n = 0; n < numPoints; n++)
+ {
+ CComPtr pnt = nullptr;
+ shp->get_Point(n, &pnt);
+ long pointCount;
+ shpBase->get_NumPoints(&pointCount);
+ shpBase->InsertPoint(pnt, &pointCount, &vbretval);
+ }
+ }
+ else
+ {
+ long numParts;
+ shp->get_NumParts(&numParts);
+
+ for (long part = 0; part < numParts; part++)
+ {
+ shpBase->InsertPart(pntIndex, &partIndex, &vbretval);
+
+ long start, end;
+ shp->get_Part(part, &start);
+ shp->get_EndOfPart(part, &end);
+
+ for (long point = start; point <= end; point++)
+ {
+ IPoint* pnt = nullptr;
+ shp->get_Point(point, &pnt);
+ if (pnt)
+ {
+ IPoint* pntNew = nullptr;
+ pnt->Clone(&pntNew);
+ shpBase->InsertPoint(pntNew, &pntIndex, &vbretval);
+ pntIndex++;
+ pntNew->Release();
+ pnt->Release();
+ }
+ }
+
+ partIndex++;
+ }
+ }
+ shp->Release();
+ }
+ }
+
+ shpBase->get_NumPoints(&pntIndex);
+ shpBase->get_NumParts(&partIndex);
+
+ if (partIndex >= 0 && pntIndex > 0)
+ {
+ (*retval)->EditInsertShape(shpBase, &count, &vbretval);
+ (*retval)->EditCellValue(newFieldIndex, count, p->first, &vbretval);
+
+ if (calcStats)
+ {
+ std::vector* indices = indicesMap[p->first];
+ fieldMap[count] = indices;
+ }
+ }
+
+ if (_isEditingShapes) // it was cloned in edit mode only
+ shpBase->Release();
+
+ delete p->second; // deleting the vector
+ count++;
+ ++p;
+ i++;
+ }
+
+ // ----------------------------------------------
+ // Calculation of stats
+ // ----------------------------------------------
+ if (calcStats)
+ {
+ CalculateFieldStats(fieldMap, operations, *retval);
+
+ // delete indices map
+ auto index = indicesMap.begin();
+ while (index != indicesMap.end())
+ {
+ delete index->second;
+ ++index;
+ }
+ }
+
+ // ----------------------------------------------
+ // Validating output
+ // ----------------------------------------------
+ CallbackHelper::ProgressCompleted(_globalCallback, _key);
+ ValidateOutput(retval, "AggregateShapes");
+ return;
+}
+#pragma endregion
- long percent = 0;
- int size = (int)_shapeData.size();
+#pragma region Buffer
- for(long i = 0; i < size; i++)
- {
- CallbackHelper::Progress(_globalCallback, i, size, "Grouping shapes...", _key, percent);
+// ********************************************************************
+// BufferByDistance()
+// ********************************************************************
+STDMETHODIMP CShapefile::BufferByDistance(double Distance, LONG nSegments, VARIANT_BOOL SelectedOnly,
+ VARIANT_BOOL MergeResults, IShapefile** sf)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+
+ if (MergeResults)
+ {
+ // ShapefileHelper::CloneNoFields(this, sf, SHP_POLYGON, true);
+ // -----------------------------------------------
+ // Creating output
+ // -----------------------------------------------
+ if (!ShapefileHelper::CloneNoFields(this, sf, SHP_POLYGON, true))
+ {
+ // Get errorcode and pass the source:
+ long errorCode;
+ (*sf)->get_LastErrorCode(&errorCode);
+ *sf = nullptr;
+ ErrorMessage(errorCode);
+ return S_OK;
+ }
+ }
+ else
+ {
+ // if not merging shapes, copy fields
+ ShapefileHelper::CloneCore(this, sf, SHP_POLYGON, false);
+ }
+
+ if (!BufferByDistanceCore(Distance, nSegments, SelectedOnly, MergeResults, *sf))
+ {
+ (*sf)->Release();
+ *sf = nullptr;
+ }
+
+ return S_OK;
+}
- if (!ShapeAvailable(i, SelectedOnly))
- continue;
+// ********************************************************************
+// BufferByDistance()
+// ********************************************************************
+VARIANT_BOOL CShapefile::BufferByDistanceCore(double Distance, LONG nSegments, VARIANT_BOOL SelectedOnly,
+ VARIANT_BOOL MergeResults, IShapefile* sf)
+{
+ // -------------------------------------------
+ // validating
+ // -------------------------------------------
+ if (!ValidateInput(this, "BufferByDistance", "this", SelectedOnly))
+ return VARIANT_FALSE;
+
+ // -------------------------------------------
+ // processing
+ // -------------------------------------------
+ VARIANT_BOOL vb;
+ const int size = _shapeData.size();
+ long count = 0;
+ long percent = 0;
+
+ std::vector results;
+ results.reserve(size);
+
+ ReadGeosGeometries(SelectedOnly);
+
+ const bool isM = ShapeUtility::IsM(_shpfiletype);
+
+ for (long i = 0; i < size; i++)
+ {
+ CallbackHelper::Progress(_globalCallback, i, size, "Buffering shapes...", _key, percent);
+
+ if (!ShapeAvailable(i, SelectedOnly))
+ continue;
+
+ GEOSGeometry* oGeom1 = this->GetGeosGeometry(i);
+ if (oGeom1)
+ {
+ GEOSGeometry* oGeom2 = GeosHelper::Buffer(oGeom1, Distance, (int)nSegments);
+
+ if (oGeom2 == nullptr) continue;
+
+ if (MergeResults)
+ {
+ results.push_back(oGeom2);
+ }
+ else
+ {
+ vector vShapes;
+
+ if (GeosConverter::GeomToShapes(oGeom2, &vShapes, isM))
+ {
+ this->InsertShapesVector(sf, vShapes, this, i, nullptr);
+ count += vShapes.size();
+ }
+ GeosHelper::DestroyGeometry(oGeom2);
+ }
+ }
+ }
+
+ // -------------------------------------------
+ // merging the results
+ // -------------------------------------------
+ if (MergeResults)
+ {
+ GEOSGeometry* gsGeom = GeosConverter::MergeGeometries(results, _globalCallback);
+ // geometries will be released in the process
+
+ if (gsGeom != nullptr) // the result should always be in g1
+ {
+ OGRGeometry* oGeom = GeosHelper::CreateFromGEOS(gsGeom);
+ GeosHelper::DestroyGeometry(gsGeom);
+
+ if (oGeom)
+ {
+ // bool isM = ShapeUtility::IsM(this->_shpfiletype);
+
+ const OGRwkbGeometryType type = oGeom->getGeometryType();
+ if (type == wkbMultiPolygon || type == wkbMultiPolygon25D)
+ {
+ std::vector polygons;
+
+ if (OgrConverter::MultiPolygon2Polygons(oGeom, &polygons))
+ {
+ for (auto& polygon : polygons)
+ {
+ IShape* shp = OgrConverter::GeometryToShape(polygon, isM);
+ if (shp)
+ {
+ sf->EditInsertShape(shp, &count, &vb);
+ shp->Release();
+ count++;
+ }
+ }
+ }
+ }
+ else
+ {
+ // Doesn't use any GEOS functions:
+ IShape* shp = OgrConverter::GeometryToShape(oGeom, isM);
+ if (shp)
+ {
+ sf->EditInsertShape(shp, &count, &vb);
+ shp->Release();
+ count++;
+ }
+ }
+ OGRGeometryFactory::destroyGeometry(oGeom);
+ }
+ }
+ }
+
+ this->ClearCachedGeometries();
+
+ // -------------------------------------------
+ // output validation
+ // -------------------------------------------
+ CallbackHelper::ProgressCompleted(_globalCallback, _key);
+ ValidateOutput(sf, "BufferByDistance");
+
+ return VARIANT_TRUE;
+}
- IShape* shp = NULL;
- this->GetValidatedShape(i, &shp);
- if (!shp) continue;
-
- if (FieldIndex != -1)
- this->get_CellValue(FieldIndex, i, &val);
+#pragma endregion
- if(shapeMap.find(val) != shapeMap.end())
- {
- shapeMap[val]->push_back(shp);
- if (calcStats) {
- indicesMap[val]->push_back(i);
- }
- }
- else
- {
- vector* v = new vector;
- v->push_back(shp);
- shapeMap[val] = v;
-
- if (calcStats) {
- vector* v2 = new vector;
- v2->push_back(i);
- indicesMap[val] = v2;
- }
- }
- }
-
- // ----------------------------------------------
- // Merging groups
- // ----------------------------------------------
- long count = 0; // number of shapes inserted
- int i = 0; // for progress bar
- percent = 0;
- size = shapeMap.size();
- map *>::iterator p = shapeMap.begin();
-
- while(p != shapeMap.end())
- {
- CallbackHelper::Progress(_globalCallback, i, size, "Merging shapes...", _key, percent);
-
- // merging shapes
- vector* shapes = p->second;
- long pntIndex = 0;
- long partIndex = 0;
-
- IShape* shpBase = NULL;
- for (unsigned int j = 0; j < shapes->size(); j++)
- {
- if (j == 0)
- {
- if (_isEditingShapes)
- {
- // in editing mode we share the shape with parent shapefile
- // so a copy is needed to avoid conflicts
- (*shapes)[0]->Clone(&shpBase);
- (*shapes)[0]->Release();
- }
- else
- {
- // in the regular mode we are the sole owners of shape
- shpBase = (*shapes)[0];
- }
- shpBase->get_NumPoints(&pntIndex);
- shpBase->get_NumParts(&partIndex);
-
- ShapeHelper::ForceProperShapeType(shpBase, targetType);
- }
- else
- {
- IShape* shp = (*shapes)[j];
-
- if (ShapeUtility::Convert2D(targetType) == SHP_MULTIPOINT)
- {
- // in case of multi-point target type, simply copy all the points to base shape
- // no need to deal with parts, multi-points don't have those
- long numPoints = 0;
- shp->get_NumPoints(&numPoints);
- for (long n = 0; n < numPoints; n++)
- {
- CComPtr pnt = NULL;
- shp->get_Point(n, &pnt);
- long pointCount;
- shpBase->get_NumPoints(&pointCount);
- shpBase->InsertPoint(pnt, &pointCount, &vbretval);
- }
- }
- else
- {
- long numParts;
- shp->get_NumParts(&numParts);
-
- for (long part = 0; part < numParts; part++)
- {
- shpBase->InsertPart(pntIndex, &partIndex, &vbretval);
-
- long start, end;
- shp->get_Part(part, &start);
- shp->get_EndOfPart(part, &end);
-
- for (long point = start; point <= end; point++)
- {
- IPoint* pnt = NULL;
- shp->get_Point(point, &pnt);
- if (pnt)
- {
- IPoint* pntNew = NULL;
- pnt->Clone(&pntNew);
- shpBase->InsertPoint(pntNew, &pntIndex, &vbretval);
- pntIndex++;
- pntNew->Release();
- pnt->Release();
- }
- }
-
- partIndex++;
- }
- }
- shp->Release();
- }
- }
-
- shpBase->get_NumPoints(&pntIndex);
- shpBase->get_NumParts(&partIndex);
-
- if (partIndex >= 0 && pntIndex > 0)
- {
- (*retval)->EditInsertShape(shpBase, &count, &vbretval);
- (*retval)->EditCellValue(newFieldIndex, count, p->first, &vbretval);
-
- if (calcStats)
- {
- std::vector* indices = indicesMap[p->first];
- fieldMap[count] = indices;
- }
- }
-
- if (_isEditingShapes) // it was cloned in edit mode only
- shpBase->Release();
-
- delete p->second; // deleting the vector
- count++;
- ++p;
- i++;
- }
-
- // ----------------------------------------------
- // Calculation of stats
- // ----------------------------------------------
- if (calcStats)
- {
- CalculateFieldStats(fieldMap, operations, *retval);
-
- // delete indices map
- map *>::iterator p = indicesMap.begin();
- while(p != indicesMap.end())
- {
- delete p->second;
- ++p;
- }
- }
-
- // ----------------------------------------------
- // Validating output
- // ----------------------------------------------
- CallbackHelper::ProgressCompleted(_globalCallback, _key);
- ValidateOutput(retval, "AggregateShapes");
- return;
-}
-#pragma endregion
-
-#pragma region Buffer
-
-// ********************************************************************
-// BufferByDistance()
-// ********************************************************************
-STDMETHODIMP CShapefile::BufferByDistance(double Distance, LONG nSegments, VARIANT_BOOL SelectedOnly, VARIANT_BOOL MergeResults, IShapefile** sf)
-{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
-
- if (MergeResults) {
- // ShapefileHelper::CloneNoFields(this, sf, SHP_POLYGON, true);
- // -----------------------------------------------
- // Creating output
- // -----------------------------------------------
- if (!ShapefileHelper::CloneNoFields(this, sf, SHP_POLYGON, true))
- {
- // Get errorcode and pass the source:
- long errorCode;
- (*sf)->get_LastErrorCode(&errorCode);
- *sf = NULL;
- ErrorMessage(errorCode);
- return S_OK;
- }
- }
- else {
- // if not merging shapes, copy fields
- ShapefileHelper::CloneCore(this, sf, SHP_POLYGON, false);
- }
-
- if (!BufferByDistanceCore(Distance, nSegments, SelectedOnly, MergeResults, *sf))
- {
- (*sf)->Release();
- *sf = NULL;
- }
-
- return S_OK;
-}
-
-// ********************************************************************
-// BufferByDistance()
-// ********************************************************************
-VARIANT_BOOL CShapefile::BufferByDistanceCore(double Distance, LONG nSegments, VARIANT_BOOL SelectedOnly, VARIANT_BOOL MergeResults, IShapefile* sf)
-{
- // -------------------------------------------
- // validating
- // -------------------------------------------
- if (!ValidateInput(this, "BufferByDistance", "this", SelectedOnly))
- return VARIANT_FALSE;
-
- // -------------------------------------------
- // processing
- // -------------------------------------------
- VARIANT_BOOL vb;
- int size = _shapeData.size();
- long count = 0;
- long percent = 0;
-
- std::vector results;
- results.reserve(size);
-
- ReadGeosGeometries(SelectedOnly);
-
- bool isM = ShapeUtility::IsM(_shpfiletype);
-
- for (long i = 0; i < size; i++)
- {
- CallbackHelper::Progress(_globalCallback, i, size, "Buffering shapes...", _key, percent);
-
- if (!ShapeAvailable(i, SelectedOnly))
- continue;
-
- GEOSGeometry* oGeom1 = this->GetGeosGeometry(i);
- if (oGeom1)
- {
- GEOSGeometry* oGeom2 = GeosHelper::Buffer(oGeom1, Distance, (int)nSegments);
-
- if (oGeom2 == NULL) continue;
-
- if (MergeResults)
- {
- results.push_back(oGeom2);
- }
- else
- {
- vector vShapes;
-
- if (GeosConverter::GeomToShapes(oGeom2, &vShapes, isM))
- {
- this->InsertShapesVector(sf, vShapes, this, i, NULL);
- count += vShapes.size();
- }
- GeosHelper::DestroyGeometry(oGeom2);
- }
- }
- }
-
- // -------------------------------------------
- // merging the results
- // -------------------------------------------
- if (MergeResults)
- {
- GEOSGeometry* gsGeom = GeosConverter::MergeGeometries(results, _globalCallback); // geometries will be released in the process
-
- if (gsGeom != NULL) // the result should always be in g1
- {
- OGRGeometry* oGeom = GeosHelper::CreateFromGEOS(gsGeom);
- GeosHelper::DestroyGeometry(gsGeom);
-
- if (oGeom)
- {
- bool isM = ShapeUtility::IsM(this->_shpfiletype);
-
- OGRwkbGeometryType type = oGeom->getGeometryType();
- if (type == wkbMultiPolygon || type == wkbMultiPolygon25D)
- {
- std::vector polygons;
-
- if (OgrConverter::MultiPolygon2Polygons(oGeom, &polygons))
- {
- for (unsigned int i = 0; i < polygons.size(); i++)
- {
- IShape* shp = OgrConverter::GeometryToShape(polygons[i], isM);
- if (shp)
- {
- sf->EditInsertShape(shp, &count, &vb);
- shp->Release();
- count++;
- }
- }
- }
- }
- else
- {
- // Doesn't use any GEOS functions:
- IShape* shp = OgrConverter::GeometryToShape(oGeom, isM);
- if (shp)
- {
- sf->EditInsertShape(shp, &count, &vb);
- shp->Release();
- count++;
- }
- }
- OGRGeometryFactory::destroyGeometry(oGeom);
- }
- }
- }
-
- this->ClearCachedGeometries();
-
- // -------------------------------------------
- // output validation
- // -------------------------------------------
- CallbackHelper::ProgressCompleted(_globalCallback, _key);
- ValidateOutput(sf, "BufferByDistance");
-
- return VARIANT_TRUE;
-}
-
-#pragma endregion
-
-#pragma region Clipping
-// ********************************************************************
-// GetDifference()
-// ********************************************************************
-STDMETHODIMP CShapefile::Difference(VARIANT_BOOL SelectedOnlySubject, IShapefile* sfOverlay, VARIANT_BOOL SelectedOnlyOverlay, IShapefile** retval)
-{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- DoClipOperation(SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, retval, clDifference);
- return S_OK;
-}
+#pragma region Clipping
+// ********************************************************************
+// GetDifference()
+// ********************************************************************
+STDMETHODIMP CShapefile::Difference(VARIANT_BOOL SelectedOnlySubject, IShapefile* sfOverlay,
+ VARIANT_BOOL SelectedOnlyOverlay, IShapefile** retval)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ DoClipOperation(SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, retval, clDifference);
+ return S_OK;
+}
// ********************************************************************
// Clip()
// ********************************************************************
-STDMETHODIMP CShapefile::Clip(VARIANT_BOOL SelectedOnlySubject, IShapefile* sfOverlay, VARIANT_BOOL SelectedOnlyOverlay, IShapefile** retval)
+STDMETHODIMP CShapefile::Clip(VARIANT_BOOL SelectedOnlySubject, IShapefile* sfOverlay, VARIANT_BOOL SelectedOnlyOverlay,
+ IShapefile** retval)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- DoClipOperation(SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, retval, clClip); // enumeration should be repaired
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ DoClipOperation(SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, retval, clClip);
+ // enumeration should be repaired
+ return S_OK;
}
// **********************************************************************
// * GetIntersection()
// **********************************************************************
STDMETHODIMP CShapefile::GetIntersection(VARIANT_BOOL SelectedOnlyOfThis, IShapefile* sf,
- VARIANT_BOOL SelectedOnly, ShpfileType fileType, ICallback* cBack, IShapefile** retval)
+ VARIANT_BOOL SelectedOnly, ShpfileType fileType, ICallback* cBack,
+ IShapefile** retval)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- DoClipOperation(SelectedOnlyOfThis, sf, SelectedOnly, retval, clIntersection, fileType);
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ DoClipOperation(SelectedOnlyOfThis, sf, SelectedOnly, retval, clIntersection, fileType);
+ return S_OK;
}
// ********************************************************************
// GetSymmDifference()
// ********************************************************************
-STDMETHODIMP CShapefile::SymmDifference(VARIANT_BOOL SelectedOnlySubject, IShapefile* sfOverlay, VARIANT_BOOL SelectedOnlyOverlay, IShapefile** retval)
+STDMETHODIMP CShapefile::SymmDifference(VARIANT_BOOL SelectedOnlySubject, IShapefile* sfOverlay,
+ VARIANT_BOOL SelectedOnlyOverlay, IShapefile** retval)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- DoClipOperation(SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, retval, clSymDifference); // enumeration should be repaired
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ DoClipOperation(SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, retval, clSymDifference);
+ // enumeration should be repaired
+ return S_OK;
}
// ********************************************************************
// GetUnion()
// ********************************************************************
-STDMETHODIMP CShapefile::Union(VARIANT_BOOL SelectedOnlySubject, IShapefile* sfOverlay, VARIANT_BOOL SelectedOnlyOverlay, IShapefile** retval)
+STDMETHODIMP CShapefile::Union(VARIANT_BOOL SelectedOnlySubject, IShapefile* sfOverlay,
+ VARIANT_BOOL SelectedOnlyOverlay, IShapefile** retval)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- DoClipOperation(SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, retval, clUnion);
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ DoClipOperation(SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, retval, clUnion);
+ return S_OK;
}
@@ -1591,50 +1602,46 @@ STDMETHODIMP CShapefile::Union(VARIANT_BOOL SelectedOnlySubject, IShapefile* sfO
// auto choosing the resulting type for intersection
ShpfileType GetClipOperationReturnType(ShpfileType type1, ShpfileType type2, tkClipOperation operation)
{
- switch (operation)
- {
- case clClip:
- case clIntersection:
- {
- bool isZ = ShapeUtility::IsZ(type1) || ShapeUtility::IsZ(type2);
- bool isM = ShapeUtility::IsM(type1) || ShapeUtility::IsM(type2);
-
- ShpfileType type2D = ShapeUtility::Convert2D(type1);
- ShpfileType type2D2 = ShapeUtility::Convert2D(type2);
-
- // return type is always has the lower dimension of two
- if (type2D == SHP_POINT || type2D2 == SHP_POINT)
- {
- return ShapeUtility::Get25DShapeType(SHP_POINT, isZ, isM);
- }
- else if (type2D == SHP_MULTIPOINT || type2D2 == SHP_MULTIPOINT)
- {
- return ShapeUtility::Get25DShapeType(SHP_MULTIPOINT, isZ, isM);
- }
- else if (type2D == SHP_POLYLINE && type2D2 == SHP_POLYLINE)
- {
- return ShapeUtility::Get25DShapeType(SHP_POINT, isZ, isM);
- }
- else if (type2D == SHP_POLYLINE || type2D2 == SHP_POLYLINE)
- {
- return ShapeUtility::Get25DShapeType(SHP_POLYLINE, isZ, isM);
- }
- else
- {
- return ShapeUtility::Get25DShapeType(SHP_POLYGON, isZ, isM);
- }
- }
- break;
- case clDifference:
- // the subject type remains intact
- return type1;
- case clSymDifference:
- case clUnion:
- // both types should be the same
- return type1;
- }
-
- return type1;
+ switch (operation)
+ {
+ case clClip:
+ case clIntersection:
+ {
+ const bool isZ = ShapeUtility::IsZ(type1) || ShapeUtility::IsZ(type2);
+ const bool isM = ShapeUtility::IsM(type1) || ShapeUtility::IsM(type2);
+
+ const ShpfileType type2D = ShapeUtility::Convert2D(type1);
+ const ShpfileType type2D2 = ShapeUtility::Convert2D(type2);
+
+ // return type is always has the lower dimension of two
+ if (type2D == SHP_POINT || type2D2 == SHP_POINT)
+ {
+ return ShapeUtility::Get25DShapeType(SHP_POINT, isZ, isM);
+ }
+ if (type2D == SHP_MULTIPOINT || type2D2 == SHP_MULTIPOINT)
+ {
+ return ShapeUtility::Get25DShapeType(SHP_MULTIPOINT, isZ, isM);
+ }
+ if (type2D == SHP_POLYLINE && type2D2 == SHP_POLYLINE)
+ {
+ return ShapeUtility::Get25DShapeType(SHP_POINT, isZ, isM);
+ }
+ if (type2D == SHP_POLYLINE || type2D2 == SHP_POLYLINE)
+ {
+ return ShapeUtility::Get25DShapeType(SHP_POLYLINE, isZ, isM);
+ }
+ return ShapeUtility::Get25DShapeType(SHP_POLYGON, isZ, isM);
+ }
+ case clDifference:
+ // the subject type remains intact
+ return type1;
+ case clSymDifference:
+ case clUnion:
+ // both types should be the same
+ return type1;
+ }
+
+ return type1;
}
// ********************************************************************
@@ -1642,262 +1649,285 @@ ShpfileType GetClipOperationReturnType(ShpfileType type1, ShpfileType type2, tkC
// ********************************************************************
CString GetClipOperationName(tkClipOperation operation)
{
- switch(operation)
- {
- case clDifference:
- return "Difference";
- case clIntersection:
- return "GetIntersection";
- case clSymDifference:
- return "SymmDifference";
- case clUnion:
- return "Union";
- case clClip:
- default:
- return "Clip";
- }
+ switch (operation)
+ {
+ case clDifference:
+ return "Difference";
+ case clIntersection:
+ return "GetIntersection";
+ case clSymDifference:
+ return "SymmDifference";
+ case clUnion:
+ return "Union";
+ case clClip:
+ default:
+ return "Clip";
+ }
}
// ********************************************************************
// DoClipOperarion()
// ********************************************************************
-bool CShapefile::ValidateClippingOutputType(ShpfileType type1, ShpfileType type2, ShpfileType returnType, tkClipOperation operation)
+bool CShapefile::ValidateClippingOutputType(ShpfileType type1, ShpfileType type2, ShpfileType returnType,
+ tkClipOperation operation)
{
- switch (operation)
- {
- case clSymDifference:
- case clUnion:
- if (type1 != type2) {
- CallbackHelper::ErrorMsg("Types of both input shapefiles for symmetrical difference and union operations must be the same.");
- return false;
- }
- break;
- case clDifference:
- if (type1 != returnType)
- {
- CallbackHelper::ErrorMsg("The type of output shapefile must be the same as in put for difference operation.");
- return false;
- }
- break;
- case clIntersection:
- case clClip:
- bool isM1 = ShapeUtility::IsM(type1);
- bool isM2 = ShapeUtility::IsM(type2);
- bool isM = ShapeUtility::IsM(returnType);
-
- bool isZ1 = ShapeUtility::IsZ(type1);
- bool isZ2 = ShapeUtility::IsZ(type2);
- bool isZ = ShapeUtility::IsZ(returnType);
-
- if ((isM1 != isM && isM2 != isM) ||
- isZ1 != isZ && isZ2 != isZ)
- {
- // there is no complete certainty how our conversion routines and GEOS will
- // handle Z, M values, so we let it pass with a warning to see what happens
- CallbackHelper::ErrorMsg("Suspicious output type for clipping operation (Z, M values must be preserved).");
- }
-
- ShpfileType type2D = ShapeUtility::Convert2D(type1);
- ShpfileType type2D2 = ShapeUtility::Convert2D(type2);
-
- switch (returnType)
- {
- case SHP_POLYGON:
- if (type2D != SHP_POLYGON || type2D2 != SHP_POLYGON)
- {
- ErrorMessage(tkINCOMPATIBLE_SHAPEFILE_TYPE);
- return false;
- }
- break;
- case SHP_POLYLINE:
- if ((type2D != SHP_POLYLINE && type2D != SHP_POLYGON) ||
- (type2D2 != SHP_POLYLINE && type2D2 != SHP_POLYGON))
- {
- ErrorMessage(tkINCOMPATIBLE_SHAPEFILE_TYPE);
- return false;
- }
- break;
- case SHP_POINT:
- case SHP_MULTIPOINT:
- // point can be received from any combination of types (even poly vs poly)
- // not sure how multipoints are handled - so put no limitations for the either
- break;
- }
-
- break;
- }
-
- return true;
+ switch (operation)
+ {
+ case clSymDifference:
+ case clUnion:
+ if (type1 != type2)
+ {
+ CallbackHelper::ErrorMsg(
+ "Types of both input shapefiles for symmetrical difference and union operations must be the same.");
+ return false;
+ }
+ break;
+ case clDifference:
+ if (type1 != returnType)
+ {
+ CallbackHelper::ErrorMsg(
+ "The type of output shapefile must be the same as in put for difference operation.");
+ return false;
+ }
+ break;
+ case clIntersection:
+ case clClip:
+ const bool isM1 = ShapeUtility::IsM(type1);
+ const bool isM2 = ShapeUtility::IsM(type2);
+ const bool isM = ShapeUtility::IsM(returnType);
+
+ const bool isZ1 = ShapeUtility::IsZ(type1);
+ const bool isZ2 = ShapeUtility::IsZ(type2);
+ const bool isZ = ShapeUtility::IsZ(returnType);
+
+ if (isM1 != isM && isM2 != isM ||
+ isZ1 != isZ && isZ2 != isZ)
+ {
+ // there is no complete certainty how our conversion routines and GEOS will
+ // handle Z, M values, so we let it pass with a warning to see what happens
+ CallbackHelper::ErrorMsg("Suspicious output type for clipping operation (Z, M values must be preserved).");
+ }
+
+ const ShpfileType type2D = ShapeUtility::Convert2D(type1);
+ const ShpfileType type2D2 = ShapeUtility::Convert2D(type2);
+
+ switch (returnType)
+ {
+ case SHP_POLYGON:
+ if (type2D != SHP_POLYGON || type2D2 != SHP_POLYGON)
+ {
+ ErrorMessage(tkINCOMPATIBLE_SHAPEFILE_TYPE);
+ return false;
+ }
+ break;
+ case SHP_POLYLINE:
+ if (type2D != SHP_POLYLINE && type2D != SHP_POLYGON ||
+ type2D2 != SHP_POLYLINE && type2D2 != SHP_POLYGON)
+ {
+ ErrorMessage(tkINCOMPATIBLE_SHAPEFILE_TYPE);
+ return false;
+ }
+ break;
+ case SHP_POINT:
+ case SHP_MULTIPOINT:
+ // point can be received from any combination of types (even poly vs poly)
+ // not sure how multipoints are handled - so put no limitations for the either
+ break;
+ case SHP_NULLSHAPE: break;
+ case SHP_POINTZ: break;
+ case SHP_POLYLINEZ: break;
+ case SHP_POLYGONZ: break;
+ case SHP_MULTIPOINTZ: break;
+ case SHP_POINTM: break;
+ case SHP_POLYLINEM: break;
+ case SHP_POLYGONM: break;
+ case SHP_MULTIPOINTM: break;
+ case SHP_MULTIPATCH: break;
+ default: ;
+ }
+
+ break;
+ }
+
+ return true;
}
// ********************************************************************
// DoClipOperarion()
// ********************************************************************
-void CShapefile::DoClipOperation(VARIANT_BOOL SelectedOnlySubject, IShapefile* sfOverlay,
- VARIANT_BOOL SelectedOnlyOverlay, IShapefile** retval,
- tkClipOperation operation, ShpfileType returnType)
+void CShapefile::DoClipOperation(VARIANT_BOOL SelectedOnlySubject, IShapefile* sfOverlay,
+ VARIANT_BOOL SelectedOnlyOverlay, IShapefile** retval,
+ tkClipOperation operation, ShpfileType returnType)
{
- // ----------------------------------------------
- // Validation
- // ----------------------------------------------
- if (!sfOverlay)
- {
- ErrorMessage(tkUNEXPECTED_NULL_PARAMETER);
- return;
- }
-
- ShpfileType type1, type2;
- type1 = _shpfiletype;
-
- sfOverlay->get_ShapefileType(&type2);
- bool canUseClipper = type1 == SHP_POLYGON && type2 == SHP_POLYGON;
-
- if (returnType == SHP_NULLSHAPE)
- {
- returnType = GetClipOperationReturnType(type1, type2, operation);
- }
-
- if (!ValidateClippingOutputType(type1, type2, returnType, operation)) {
- return;
- }
-
- if (!ValidateInput(this, GetClipOperationName(operation), "this", SelectedOnlySubject))
- return;
-
- if (!ValidateInput(sfOverlay, GetClipOperationName(operation), "sfOverlay", SelectedOnlyOverlay))
- {
- return;
- }
-
- // ----------------------------------------------
- // Creating output
- // ----------------------------------------------
- // creation of resulting shapefile
- // ShapefileHelper::CloneNoFields(this, retval, returnType);
- if (!ShapefileHelper::CloneNoFields(this, retval, returnType))
- {
- // Get errorcode and pass the source:
- long errorCode;
- (*retval)->get_LastErrorCode(&errorCode);
- *retval = NULL;
- ErrorMessage(errorCode);
- return;
- }
-
- // do field mapping
- std::map fieldMap;
-
- // fields from the overlay shapefile will be copied for the limited number of operation only
- IShapefile* sfCopy = (operation == clIntersection || operation == clSymDifference || operation == clUnion)? sfOverlay : NULL;
- GeoProcessing::CopyFields(this, sfCopy, *retval, fieldMap);
-
- // -------------------------------------------
- // processing
- // -------------------------------------------
- long numShapes1, numShapes2;
- numShapes1 = _shapeData.size();
- sfOverlay->get_NumShapes(&numShapes2);
-
- bool useClipper = (_geometryEngine == engineClipper && canUseClipper);
-
- if (_globalCallback)
- {
- _globalCallback->QueryInterface(IID_IStopExecution,(void**)&_stopExecution);
- }
-
- // building spatial index for the operation
- if(! ((CShapefile*)sfOverlay)->GenerateTempQTree(SelectedOnlyOverlay ? true: false) )
- {
- ErrorMessage(tkFAILED_TO_BUILD_SPATIAL_INDEX);
- goto cleaning;
- }
-
- if (operation == clSymDifference || operation == clUnion)
- {
- if (! this->GenerateTempQTree(SelectedOnlySubject ? true : false) )
- {
- ErrorMessage(tkFAILED_TO_BUILD_SPATIAL_INDEX);
- goto cleaning;
- }
- }
-
- if (useClipper)
- {
- // do calculation by Clipper
- switch (operation)
- {
- case clDifference:
- this->DifferenceClipper(this, SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, *retval);
- break;
- case clIntersection:
- this->IntersectionClipper(SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, *retval, &fieldMap);
- break;
- case clClip:
- this->ClipClipper(SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, *retval);
- break;
- case clSymDifference:
- this->DifferenceClipper(this, SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, *retval);
- this->DifferenceClipper(sfOverlay, SelectedOnlyOverlay, this, SelectedOnlySubject, *retval, &fieldMap);
- break;
- case clUnion:
- std::set shapesToSkipSubject;
- std::set shapesToSkipClipping;
- this->IntersectionClipper(SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, *retval, &fieldMap, &shapesToSkipSubject, &shapesToSkipClipping);
- this->DifferenceClipper(this, SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, *retval, NULL, &shapesToSkipSubject);
- this->DifferenceClipper(sfOverlay, SelectedOnlyOverlay, this, SelectedOnlySubject, *retval, &fieldMap, &shapesToSkipClipping);
- }
- }
- else {
- this->ReadGeosGeometries(SelectedOnlySubject);
- ((CShapefile*)sfOverlay)->ReadGeosGeometries(SelectedOnlyOverlay);
-
- // do calculation by GEOS
- switch (operation)
- {
- case clDifference:
- this->DifferenceGEOS(this, SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, *retval);
- break;
- case clIntersection:
- this->IntersectionGEOS(SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, *retval, &fieldMap);
- break;
- case clClip:
- this->ClipGEOS(SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, *retval);
- break;
- case clSymDifference:
- // 2 differences
- this->DifferenceGEOS(this, SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, *retval);
- this->DifferenceGEOS(sfOverlay, SelectedOnlyOverlay, this, SelectedOnlySubject, *retval, &fieldMap);
- break;
- case clUnion:
- // intersection + symmetrical difference
- std::set shapesToSkipSubject;
- std::set shapesToSkipClipping;
- this->IntersectionGEOS(SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, *retval, &fieldMap, &shapesToSkipSubject, &shapesToSkipClipping );
- this->DifferenceGEOS(this, SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, *retval, NULL, &shapesToSkipSubject);
- this->DifferenceGEOS(sfOverlay, SelectedOnlyOverlay, this, SelectedOnlySubject, *retval, &fieldMap, &shapesToSkipClipping);
- break;
- }
-
- this->ClearCachedGeometries();
- sfOverlay->ClearCachedGeometries();
- }
-
- // -------------------------------------------
- // cleaning
- // -------------------------------------------
-cleaning:
- CallbackHelper::ProgressCompleted(_globalCallback, _key);
-
- // clearing spatial index for the operation
- ((CShapefile*)sfOverlay)->ClearTempQTree();
- if (operation == clSymDifference || operation == clUnion) {
- this->ClearTempQTree();
- }
-
- // -------------------------------------------
- // output validation
- // -------------------------------------------
- ValidateOutput(retval, GetClipOperationName(operation));
+ // ----------------------------------------------
+ // Validation
+ // ----------------------------------------------
+ if (!sfOverlay)
+ {
+ ErrorMessage(tkUNEXPECTED_NULL_PARAMETER);
+ return;
+ }
+
+ ShpfileType type2;
+ const ShpfileType type1 = _shpfiletype;
+
+ sfOverlay->get_ShapefileType(&type2);
+ const bool canUseClipper = type1 == SHP_POLYGON && type2 == SHP_POLYGON;
+
+ if (returnType == SHP_NULLSHAPE)
+ {
+ returnType = GetClipOperationReturnType(type1, type2, operation);
+ }
+
+ if (!ValidateClippingOutputType(type1, type2, returnType, operation))
+ {
+ return;
+ }
+
+ if (!ValidateInput(this, GetClipOperationName(operation), "this", SelectedOnlySubject))
+ return;
+
+ if (!ValidateInput(sfOverlay, GetClipOperationName(operation), "sfOverlay", SelectedOnlyOverlay))
+ {
+ return;
+ }
+
+ // ----------------------------------------------
+ // Creating output
+ // ----------------------------------------------
+ // creation of resulting shapefile
+ // ShapefileHelper::CloneNoFields(this, retval, returnType);
+ if (!ShapefileHelper::CloneNoFields(this, retval, returnType))
+ {
+ // Get errorcode and pass the source:
+ long errorCode;
+ (*retval)->get_LastErrorCode(&errorCode);
+ *retval = nullptr;
+ ErrorMessage(errorCode);
+ return;
+ }
+
+ // do field mapping
+ std::map fieldMap;
+
+ // fields from the overlay shapefile will be copied for the limited number of operation only
+ IShapefile* sfCopy = operation == clIntersection || operation == clSymDifference || operation == clUnion
+ ? sfOverlay
+ : nullptr;
+ GeoProcessing::CopyFields(this, sfCopy, *retval, fieldMap);
+
+ // long numShapes1 = _shapeData.size();
+ long numShapes2;
+ sfOverlay->get_NumShapes(&numShapes2);
+
+ const bool useClipper = _geometryEngine == engineClipper && canUseClipper;
+
+ if (_globalCallback)
+ {
+ _globalCallback->QueryInterface(IID_IStopExecution, (void**)&_stopExecution);
+ }
+
+ // building spatial index for the operation
+ if (! ((CShapefile*)sfOverlay)->GenerateTempQTree(SelectedOnlyOverlay != 0))
+ {
+ ErrorMessage(tkFAILED_TO_BUILD_SPATIAL_INDEX);
+ goto cleaning;
+ }
+
+ if (operation == clSymDifference || operation == clUnion)
+ {
+ if (! this->GenerateTempQTree(SelectedOnlySubject != 0))
+ {
+ ErrorMessage(tkFAILED_TO_BUILD_SPATIAL_INDEX);
+ goto cleaning;
+ }
+ }
+
+ if (useClipper)
+ {
+ // do calculation by Clipper
+ switch (operation)
+ {
+ case clDifference:
+ this->DifferenceClipper(this, SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, *retval);
+ break;
+ case clIntersection:
+ this->IntersectionClipper(SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, *retval, &fieldMap);
+ break;
+ case clClip:
+ this->ClipClipper(SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, *retval);
+ break;
+ case clSymDifference:
+ this->DifferenceClipper(this, SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, *retval);
+ this->DifferenceClipper(sfOverlay, SelectedOnlyOverlay, this, SelectedOnlySubject, *retval, &fieldMap);
+ break;
+ case clUnion:
+ std::set shapesToSkipSubject;
+ std::set shapesToSkipClipping;
+ this->IntersectionClipper(SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, *retval, &fieldMap,
+ &shapesToSkipSubject, &shapesToSkipClipping);
+ this->DifferenceClipper(this, SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, *retval, nullptr,
+ &shapesToSkipSubject);
+ this->DifferenceClipper(sfOverlay, SelectedOnlyOverlay, this, SelectedOnlySubject, *retval, &fieldMap,
+ &shapesToSkipClipping);
+ }
+ }
+ else
+ {
+ this->ReadGeosGeometries(SelectedOnlySubject);
+ ((CShapefile*)sfOverlay)->ReadGeosGeometries(SelectedOnlyOverlay);
+
+ // do calculation by GEOS
+ switch (operation)
+ {
+ case clDifference:
+ this->DifferenceGEOS(this, SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, *retval);
+ break;
+ case clIntersection:
+ this->IntersectionGEOS(SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, *retval, &fieldMap);
+ break;
+ case clClip:
+ this->ClipGEOS(SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, *retval);
+ break;
+ case clSymDifference:
+ // 2 differences
+ this->DifferenceGEOS(this, SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, *retval);
+ this->DifferenceGEOS(sfOverlay, SelectedOnlyOverlay, this, SelectedOnlySubject, *retval, &fieldMap);
+ break;
+ case clUnion:
+ // intersection + symmetrical difference
+ std::set shapesToSkipSubject;
+ std::set shapesToSkipClipping;
+ this->IntersectionGEOS(SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, *retval, &fieldMap,
+ &shapesToSkipSubject, &shapesToSkipClipping);
+ this->DifferenceGEOS(this, SelectedOnlySubject, sfOverlay, SelectedOnlyOverlay, *retval, nullptr,
+ &shapesToSkipSubject);
+ this->DifferenceGEOS(sfOverlay, SelectedOnlyOverlay, this, SelectedOnlySubject, *retval, &fieldMap,
+ &shapesToSkipClipping);
+ break;
+ }
+
+ this->ClearCachedGeometries();
+ sfOverlay->ClearCachedGeometries();
+ }
+
+ // -------------------------------------------
+ // cleaning
+ // -------------------------------------------
+cleaning:
+ CallbackHelper::ProgressCompleted(_globalCallback, _key);
+
+ // clearing spatial index for the operation
+ ((CShapefile*)sfOverlay)->ClearTempQTree();
+ if (operation == clSymDifference || operation == clUnion)
+ {
+ this->ClearTempQTree();
+ }
+
+ // -------------------------------------------
+ // output validation
+ // -------------------------------------------
+ ValidateOutput(retval, GetClipOperationName(operation));
}
#pragma endregion
@@ -1905,241 +1935,234 @@ void CShapefile::DoClipOperation(VARIANT_BOOL SelectedOnlySubject, IShapefile* s
// ********************************************************************
// ClipGEOS()
// ********************************************************************
-void CShapefile::ClipGEOS(VARIANT_BOOL SelectedOnlySubject, IShapefile* sfOverlay, VARIANT_BOOL SelectedOnlyOverlay, IShapefile* sfResult)
+void CShapefile::ClipGEOS(VARIANT_BOOL SelectedOnlySubject, IShapefile* sfOverlay, VARIANT_BOOL SelectedOnlyOverlay,
+ IShapefile* sfResult)
{
- QTree* qTree = ((CShapefile*)sfOverlay)->GetTempQTree();
-
- long numShapesSubject, numShapesClip;
- this->get_NumShapes(&numShapesSubject);
- sfOverlay->get_NumShapes(&numShapesClip);
- bool isM = ShapeUtility::IsM(_shpfiletype);
-
- long percent = 0;
- for(long subjectId = 0; subjectId < numShapesSubject; subjectId++)
- {
- CallbackHelper::Progress(_globalCallback, subjectId, numShapesSubject, "Clipping shapes...", _key, percent);
-
- if (!ShapeAvailable(subjectId, SelectedOnlySubject))
- continue;
-
- vector shapeIds;
- double xMin, xMax, yMin, yMax;
- this->QuickExtentsCore(subjectId, &xMin, &yMin, &xMax, &yMax);
- shapeIds = qTree->GetNodes(QTreeExtent(xMin,xMax,yMax,yMin));
-
- if (shapeIds.size() > 0)
- {
- GEOSGeometry* gsGeom1 = this->GetGeosGeometry(subjectId);
- if (gsGeom1)
- {
- // iterating through clip geometries preparing their union
- vector vUnion;
- GEOSGeometry* gsGeom2 = NULL;
-
- for (int j = 0; j < (int)shapeIds.size(); j++)
- {
- // user can abort the operation in any time
- if (_stopExecution)
- {
- VARIANT_BOOL stop;
- _stopExecution->StopFunction(&stop);
- if (stop)
- {
- sfResult->EditClear(&stop);
- //GeosHelper::DestroyGeometry(gsGeom1);
- goto cleaning;
- }
- }
-
- // extracting clip geometry
- long clipId = shapeIds[j];
-
- if (!((CShapefile*)sfOverlay)->ShapeAvailable(clipId, SelectedOnlyOverlay))
- continue;
-
- GEOSGeometry* gsGeom2 = ((CShapefile*)sfOverlay)->GetGeosGeometry(clipId);
-
- if (GeosHelper::Intersects(gsGeom1, gsGeom2))
- {
- vUnion.push_back(gsGeom2);
- }
- }
-
- // merging (input geometries won't be destroyed)
- gsGeom2 = NULL;
- bool deleteNeeded = false;
-
- if ((int)vUnion.size() > 1)
- {
- gsGeom2 = GeosConverter::MergeGeometries(vUnion, NULL, false, false);
- deleteNeeded = true;
- }
- else if ((int)vUnion.size() == 1)
- {
- gsGeom2 = vUnion[0];
- }
-
- if (gsGeom2)
- {
- GEOSGeometry* gsResult = GeosHelper::Intersection(gsGeom1, gsGeom2);
- if (gsResult != NULL)
- {
- vector vShapes;
- bool result = GeosConverter::GeomToShapes(gsResult, &vShapes, isM);
- GeosHelper::DestroyGeometry(gsResult);
- this->InsertShapesVector(sfResult, vShapes, this, subjectId, NULL);
- }
-
- // clipping geometry should be deleted only in case it was build up from several parts
- if (deleteNeeded)
- GeosHelper::DestroyGeometry(gsGeom2);
- }
-
- // subject geometry should always be deleted
- //GeosHelper::DestroyGeometry(gsGeom1);
- }
- }
- }
-cleaning:
- CallbackHelper::ProgressCompleted(_globalCallback, _key);
+ QTree* qTree = ((CShapefile*)sfOverlay)->GetTempQTree();
+
+ long numShapesSubject, numShapesClip;
+ this->get_NumShapes(&numShapesSubject);
+ sfOverlay->get_NumShapes(&numShapesClip);
+ const bool isM = ShapeUtility::IsM(_shpfiletype);
+
+ long percent = 0;
+ for (long subjectId = 0; subjectId < numShapesSubject; subjectId++)
+ {
+ CallbackHelper::Progress(_globalCallback, subjectId, numShapesSubject, "Clipping shapes...", _key, percent);
+
+ if (!ShapeAvailable(subjectId, SelectedOnlySubject))
+ continue;
+
+ double xMin, xMax, yMin, yMax;
+ this->QuickExtentsCore(subjectId, &xMin, &yMin, &xMax, &yMax);
+ vector shapeIds = qTree->GetNodes(QTreeExtent(xMin, xMax, yMax, yMin));
+
+ if (!shapeIds.empty())
+ {
+ GEOSGeometry* gsGeom1 = this->GetGeosGeometry(subjectId);
+ if (gsGeom1)
+ {
+ // iterating through clip geometries preparing their union
+ vector vUnion;
+
+ for (long clipId : shapeIds)
+ {
+ // user can abort the operation in any time
+ if (_stopExecution)
+ {
+ VARIANT_BOOL stop;
+ _stopExecution->StopFunction(&stop);
+ if (stop)
+ {
+ sfResult->EditClear(&stop);
+ //GeosHelper::DestroyGeometry(gsGeom1);
+ goto cleaning;
+ }
+ }
+
+ // extracting clip geometry
+ if (!((CShapefile*)sfOverlay)->ShapeAvailable(clipId, SelectedOnlyOverlay))
+ continue;
+
+ GEOSGeometry* gsGeom2 = ((CShapefile*)sfOverlay)->GetGeosGeometry(clipId);
+
+ if (GeosHelper::Intersects(gsGeom1, gsGeom2))
+ {
+ vUnion.push_back(gsGeom2);
+ }
+ }
+
+ // merging (input geometries won't be destroyed)
+ GEOSGeometry* gsGeom2 = nullptr;
+ bool deleteNeeded = false;
+
+ if ((int)vUnion.size() > 1)
+ {
+ gsGeom2 = GeosConverter::MergeGeometries(vUnion, nullptr, false, false);
+ deleteNeeded = true;
+ }
+ else if ((int)vUnion.size() == 1)
+ {
+ gsGeom2 = vUnion[0];
+ }
+
+ if (gsGeom2)
+ {
+ GEOSGeometry* gsResult = GeosHelper::Intersection(gsGeom1, gsGeom2);
+ if (gsResult != nullptr)
+ {
+ vector vShapes;
+ GeosConverter::GeomToShapes(gsResult, &vShapes, isM);
+ GeosHelper::DestroyGeometry(gsResult);
+ this->InsertShapesVector(sfResult, vShapes, this, subjectId, nullptr);
+ }
+
+ // clipping geometry should be deleted only in case it was build up from several parts
+ if (deleteNeeded)
+ GeosHelper::DestroyGeometry(gsGeom2);
+ }
+
+ // subject geometry should always be deleted
+ //GeosHelper::DestroyGeometry(gsGeom1);
+ }
+ }
+ }
+cleaning:
+ CallbackHelper::ProgressCompleted(_globalCallback, _key);
}
// ********************************************************************
// ClipClipper()
// ********************************************************************
-void CShapefile::ClipClipper(VARIANT_BOOL SelectedOnlySubject, IShapefile* sfOverlay, VARIANT_BOOL SelectedOnlyOverlay, IShapefile* sfResult)
+void CShapefile::ClipClipper(VARIANT_BOOL SelectedOnlySubject, IShapefile* sfOverlay, VARIANT_BOOL SelectedOnlyOverlay,
+ IShapefile* sfResult)
{
- QTree* qTree = ((CShapefile*)sfOverlay)->GetTempQTree();
-
- long numShapesSubject, numShapesClip;
- this->get_NumShapes(&numShapesSubject);
- sfOverlay->get_NumShapes(&numShapesClip);
-
- // vector vPolygons; // we shall create vectors for both clipper and GEOS
- vector vPolygons; // we shall create vectors for both clipper and GEOS
- vPolygons.assign(numShapesClip, NULL); // this won't take much RAM or time
-
- ClipperLib::Clipper clp;
- ClipperConverter ogr(this);
-
- long percent = 0;
- for(long subjectId =0; subjectId < numShapesSubject; subjectId++)
- {
- CallbackHelper::Progress(_globalCallback, subjectId, numShapesSubject, "Clipping shapes...", _key, percent);
-
- if (!ShapeAvailable(subjectId, SelectedOnlySubject))
- continue;
-
- vector shapeIds;
- double xMin, xMax, yMin, yMax;
- this->QuickExtentsCore(subjectId, &xMin, &yMin, &xMax, &yMax);
- shapeIds = qTree->GetNodes(QTreeExtent(xMin,xMax,yMax,yMin));
-
- if (shapeIds.size() > 0)
- {
- // extracting subject polygon
- IShape* shp1 = NULL;
- this->GetValidatedShape(subjectId, &shp1);
- if (!shp1) continue;
- // ClipperLib::Polygons* poly1 = ogr.Shape2ClipperPolygon(shp1);
- ClipperLib::Paths* poly1 = ogr.Shape2ClipperPolygon(shp1);
- shp1->Release();
-
- if (poly1)
- {
- // extracting clipping polygons
- for (int j = 0; j < (int)shapeIds.size(); j++)
- {
- // user can abort the operation in any time
- if (_stopExecution)
- {
- VARIANT_BOOL stop;
- _stopExecution->StopFunction(&stop);
- if (stop)
- {
- sfResult->EditClear(&stop);
- delete poly1;
- goto cleaning;
- }
- }
-
- long clipId = shapeIds[j];
-
- if (!((CShapefile*)sfOverlay)->ShapeAvailable(clipId, SelectedOnlyOverlay))
- continue;
-
- vector vShapes;
-
- // ClipperLib::Polygons* poly2 = NULL;
- ClipperLib::Paths* poly2 = NULL;
- if (vPolygons[clipId] == NULL)
- {
- IShape* shp2 = NULL;
- ((CShapefile*)sfOverlay)->GetValidatedShape(clipId, &shp2);
- if (!shp2) continue;
- poly2 = ogr.Shape2ClipperPolygon(shp2);
- vPolygons[clipId] = poly2;
- shp2->Release();
- }
- else
- {
- poly2 = vPolygons[clipId];
- }
-
- if (poly2)
- {
- // clp.AddPolygons(*poly2, ClipperLib::ptClip);
- clp.AddPaths(*poly2, ClipperLib::ptClip, true);
- }
- }
-
- // in case there are several input polygons, they should be merged before clipping
- if (shapeIds.size() > 1)
- {
- // ClipperLib::Polygons polyUnion;
- ClipperLib::Paths polyUnion;
- clp.Execute(ClipperLib::ctUnion, polyUnion);
- clp.Clear();
- // clp.AddPolygons(polyUnion, ClipperLib::ptClip);
- clp.AddPaths(polyUnion, ClipperLib::ptClip, true);
- }
-
- // adding subject polygon
- if (poly1){
- // clp.AddPolygons(*poly1, ClipperLib::ptSubject);
- clp.AddPaths(*poly1, ClipperLib::ptSubject, true);
- }
-
- // do clipping
- // ClipperLib::Polygons polyResult;
- ClipperLib::Paths polyResult;
- if (clp.Execute(ClipperLib::ctIntersection, polyResult))
- {
- IShape* shp = ogr.ClipperPolygon2Shape(&polyResult);
- if (shp)
- {
- vector vShapes;
- vShapes.push_back(shp);
- this->InsertShapesVector(sfResult, vShapes, this, subjectId, NULL);
- }
- }
-
- delete poly1;
- clp.Clear();
- }
- }
- }
+ QTree* qTree = ((CShapefile*)sfOverlay)->GetTempQTree();
+
+ long numShapesSubject, numShapesClip;
+ this->get_NumShapes(&numShapesSubject);
+ sfOverlay->get_NumShapes(&numShapesClip);
+
+ // vector vPolygons; // we shall create vectors for both clipper and GEOS
+ vector vPolygons; // we shall create vectors for both clipper and GEOS
+ vPolygons.assign(numShapesClip, nullptr); // this won't take much RAM or time
+
+ ClipperLib::Clipper clp;
+ ClipperConverter ogr(this);
+
+ long percent = 0;
+ for (long subjectId = 0; subjectId < numShapesSubject; subjectId++)
+ {
+ CallbackHelper::Progress(_globalCallback, subjectId, numShapesSubject, "Clipping shapes...", _key, percent);
+
+ if (!ShapeAvailable(subjectId, SelectedOnlySubject))
+ continue;
+
+ double xMin, xMax, yMin, yMax;
+ this->QuickExtentsCore(subjectId, &xMin, &yMin, &xMax, &yMax);
+ vector shapeIds = qTree->GetNodes(QTreeExtent(xMin, xMax, yMax, yMin));
+
+ if (!shapeIds.empty())
+ {
+ // extracting subject polygon
+ IShape* shp1 = nullptr;
+ this->GetValidatedShape(subjectId, &shp1);
+ if (!shp1) continue;
+ // ClipperLib::Polygons* poly1 = ogr.Shape2ClipperPolygon(shp1);
+ ClipperLib::Paths* poly1 = ogr.Shape2ClipperPolygon(shp1);
+ shp1->Release();
+
+ if (poly1)
+ {
+ // extracting clipping polygons
+ for (long clipId : shapeIds)
+ {
+ // user can abort the operation in any time
+ if (_stopExecution)
+ {
+ VARIANT_BOOL stop;
+ _stopExecution->StopFunction(&stop);
+ if (stop)
+ {
+ sfResult->EditClear(&stop);
+ delete poly1;
+ goto cleaning;
+ }
+ }
+
+ if (!((CShapefile*)sfOverlay)->ShapeAvailable(clipId, SelectedOnlyOverlay))
+ continue;
+
+ vector vShapes;
+
+ // ClipperLib::Polygons* poly2 = nullptr;
+ ClipperLib::Paths* poly2;
+ if (vPolygons[clipId] == nullptr)
+ {
+ IShape* shp2 = nullptr;
+ ((CShapefile*)sfOverlay)->GetValidatedShape(clipId, &shp2);
+ if (!shp2) continue;
+ poly2 = ogr.Shape2ClipperPolygon(shp2);
+ vPolygons[clipId] = poly2;
+ shp2->Release();
+ }
+ else
+ {
+ poly2 = vPolygons[clipId];
+ }
+
+ if (poly2)
+ {
+ // clp.AddPolygons(*poly2, ClipperLib::ptClip);
+ clp.AddPaths(*poly2, ClipperLib::ptClip, true);
+ }
+ }
+
+ // in case there are several input polygons, they should be merged before clipping
+ if (shapeIds.size() > 1)
+ {
+ // ClipperLib::Polygons polyUnion;
+ ClipperLib::Paths polyUnion;
+ clp.Execute(ClipperLib::ctUnion, polyUnion);
+ clp.Clear();
+ // clp.AddPolygons(polyUnion, ClipperLib::ptClip);
+ clp.AddPaths(polyUnion, ClipperLib::ptClip, true);
+ }
+
+ // adding subject polygon
+ if (poly1)
+ {
+ // clp.AddPolygons(*poly1, ClipperLib::ptSubject);
+ clp.AddPaths(*poly1, ClipperLib::ptSubject, true);
+ }
+
+ // do clipping
+ // ClipperLib::Polygons polyResult;
+ ClipperLib::Paths polyResult;
+ if (clp.Execute(ClipperLib::ctIntersection, polyResult))
+ {
+ IShape* shp = ogr.ClipperPolygon2Shape(&polyResult);
+ if (shp)
+ {
+ vector vShapes;
+ vShapes.push_back(shp);
+ this->InsertShapesVector(sfResult, vShapes, this, subjectId, nullptr);
+ }
+ }
+
+ delete poly1;
+ clp.Clear();
+ }
+ }
+ }
cleaning:
- CallbackHelper::ProgressCompleted(_globalCallback, _key);
+ CallbackHelper::ProgressCompleted(_globalCallback, _key);
- for(int i = 0; i < (int)vPolygons.size(); i++)
- {
- if (vPolygons[i] !=NULL)
- {
- delete vPolygons[i];
- }
- }
+ for (auto& vPolygon : vPolygons)
+ {
+ delete vPolygon;
+ }
}
#pragma endregion
@@ -2150,318 +2173,310 @@ void CShapefile::ClipClipper(VARIANT_BOOL SelectedOnlySubject, IShapefile* sfOve
// ******************************************************************
// shapesToExclude - vector to return shapes sum of intersected results for those is equals to the initial area
// such shapes can be excluded from further calculation in case of union;
-void CShapefile::IntersectionGEOS(VARIANT_BOOL SelectedOnlySubject, IShapefile* sfClip, VARIANT_BOOL SelectedOnlyClip,
- IShapefile* sfResult, map* fieldMap,
- std::set* subjectShapesToSkip,
- std::set* clippingShapesToSkip)
+void CShapefile::IntersectionGEOS(VARIANT_BOOL SelectedOnlySubject, IShapefile* sfClip, VARIANT_BOOL SelectedOnlyClip,
+ IShapefile* sfResult, map* fieldMap,
+ std::set* subjectShapesToSkip,
+ std::set* clippingShapesToSkip)
{
- QTree* qTree = ((CShapefile*)sfClip)->GetTempQTree();
-
- long numShapesSubject, numShapesClip;
- this->get_NumShapes(&numShapesSubject);
- sfClip->get_NumShapes(&numShapesClip);
-
- bool isM = ShapeUtility::IsM(_shpfiletype);
-
- long percent = 0;
- for(long subjectId = 0; subjectId < numShapesSubject; subjectId++)
- {
- CallbackHelper::Progress(_globalCallback, subjectId, numShapesSubject, "Intersecting shapes...", _key, percent);
-
- if(!ShapeAvailable(subjectId, SelectedOnlySubject))
- continue;
-
- vector shapeIds;
- double xMin, xMax, yMin, yMax;
- this->QuickExtentsCore(subjectId, &xMin, &yMin, &xMax, &yMax);
- shapeIds = qTree->GetNodes(QTreeExtent(xMin,xMax,yMax,yMin));
-
- if (shapeIds.size() > 0)
- {
- GEOSGeometry* geom1 = GetGeosGeometry(subjectId);
-
- if (geom1)
- {
- double sumArea = 0.0;
-
- // iterating through clip geometries
- for (int j = 0; j < (int)shapeIds.size(); j++)
- {
- // user can abort the operation at any time
- if (_stopExecution)
- {
- VARIANT_BOOL stop;
- _stopExecution->StopFunction(&stop);
- if (stop)
- {
- sfResult->EditClear(&stop);
- //GeosHelper::DestroyGeometry(geom1);
- goto cleaning;
- }
- }
-
- // extracting clip geometry
- long clipId = shapeIds[j];
-
- if (!((CShapefile*)sfClip)->ShapeAvailable(clipId, SelectedOnlyClip))
- continue;
-
- GEOSGeometry* geom2 = ((CShapefile*)sfClip)->GetGeosGeometry(clipId);
-
- // calculating intersection
- GEOSGeometry* geom = GeosHelper::Intersection(geom1, geom2); // don't delete oGeom1 as it will be used on the next loops
- if (geom == NULL) continue;
-
- // saving the results
- vector vShapes;
- bool result = GeosConverter::GeomToShapes(geom, &vShapes, isM);
- GeosHelper::DestroyGeometry(geom);
-
- this->InsertShapesVector(sfResult, vShapes, this, subjectId, NULL, sfClip, clipId, fieldMap); // shapes are released here
- }
- //GeosHelper::DestroyGeometry(geom1);
- }
- }
- }
+ QTree* qTree = ((CShapefile*)sfClip)->GetTempQTree();
+
+ long numShapesSubject, numShapesClip;
+ this->get_NumShapes(&numShapesSubject);
+ sfClip->get_NumShapes(&numShapesClip);
+
+ const bool isM = ShapeUtility::IsM(_shpfiletype);
+
+ long percent = 0;
+ for (long subjectId = 0; subjectId < numShapesSubject; subjectId++)
+ {
+ CallbackHelper::Progress(_globalCallback, subjectId, numShapesSubject, "Intersecting shapes...", _key, percent);
+
+ if (!ShapeAvailable(subjectId, SelectedOnlySubject))
+ continue;
+
+ double xMin, xMax, yMin, yMax;
+ this->QuickExtentsCore(subjectId, &xMin, &yMin, &xMax, &yMax);
+ vector shapeIds = qTree->GetNodes(QTreeExtent(xMin, xMax, yMax, yMin));
+
+ if (!shapeIds.empty())
+ {
+ GEOSGeometry* geom1 = GetGeosGeometry(subjectId);
+
+ if (geom1)
+ {
+ // double sumArea = 0.0;
+
+ // iterating through clip geometries
+ for (long clipId : shapeIds)
+ {
+ // user can abort the operation at any time
+ if (_stopExecution)
+ {
+ VARIANT_BOOL stop;
+ _stopExecution->StopFunction(&stop);
+ if (stop)
+ {
+ sfResult->EditClear(&stop);
+ //GeosHelper::DestroyGeometry(geom1);
+ goto cleaning;
+ }
+ }
+
+ // extracting clip geometry
+ if (!((CShapefile*)sfClip)->ShapeAvailable(clipId, SelectedOnlyClip))
+ continue;
+
+ GEOSGeometry* geom2 = ((CShapefile*)sfClip)->GetGeosGeometry(clipId);
+
+ // calculating intersection
+ GEOSGeometry* geom = GeosHelper::Intersection(geom1, geom2);
+ // don't delete oGeom1 as it will be used on the next loops
+ if (geom == nullptr) continue;
+
+ // saving the results
+ vector vShapes;
+ GeosConverter::GeomToShapes(geom, &vShapes, isM);
+ GeosHelper::DestroyGeometry(geom);
+
+ this->InsertShapesVector(sfResult, vShapes, this, subjectId, nullptr, sfClip, clipId, fieldMap);
+ // shapes are released here
+ }
+ //GeosHelper::DestroyGeometry(geom1);
+ }
+ }
+ }
cleaning:
- CallbackHelper::ProgressCompleted(_globalCallback, _key);
+ CallbackHelper::ProgressCompleted(_globalCallback, _key);
}
// ******************************************************************
// IntersectionClipperNoAttributes()
// ******************************************************************
-IShapefile* CShapefile::IntersectionClipperNoAttributes(VARIANT_BOOL SelectedOnlySubject, IShapefile* sfClip, VARIANT_BOOL SelectedOnlyClip )
+IShapefile* CShapefile::IntersectionClipperNoAttributes(VARIANT_BOOL SelectedOnlySubject, IShapefile* sfClip,
+ VARIANT_BOOL SelectedOnlyClip)
{
- if (!sfClip)
- return NULL;
-
- IShapefile* sfResult = NULL;
- this->Clone(&sfResult);
-
- ClipperLib::Clipper clp;
- ClipperConverter::AddPolygons(this, clp, ClipperLib::PolyType::ptSubject, SelectedOnlySubject == VARIANT_TRUE);
- ClipperConverter::AddPolygons(sfClip, clp, ClipperLib::PolyType::ptClip, SelectedOnlyClip == VARIANT_TRUE);
-
- // ClipperLib::Polygons polyResult;
- ClipperLib::Paths polyResult;
- if (clp.Execute(ClipperLib::ClipType::ctIntersection, polyResult)) {
-
- ClipperConverter converter(sfResult);
- IShape* shp = converter.ClipperPolygon2Shape(&polyResult);
-
- VARIANT_BOOL vb;
- if (shp) {
- long index = 0;
- sfResult->EditInsertShape(shp, &index, &vb);
- shp->Release();
- }
- }
- return sfResult;
+ if (!sfClip)
+ return nullptr;
+
+ IShapefile* sfResult = nullptr;
+ this->Clone(&sfResult);
+
+ ClipperLib::Clipper clp;
+ ClipperConverter::AddPolygons(this, clp, ClipperLib::PolyType::ptSubject, SelectedOnlySubject == VARIANT_TRUE);
+ ClipperConverter::AddPolygons(sfClip, clp, ClipperLib::PolyType::ptClip, SelectedOnlyClip == VARIANT_TRUE);
+
+ // ClipperLib::Polygons polyResult;
+ ClipperLib::Paths polyResult;
+ if (clp.Execute(ClipperLib::ClipType::ctIntersection, polyResult))
+ {
+ ClipperConverter converter(sfResult);
+ IShape* shp = converter.ClipperPolygon2Shape(&polyResult);
+
+ VARIANT_BOOL vb;
+ if (shp)
+ {
+ long index = 0;
+ sfResult->EditInsertShape(shp, &index, &vb);
+ shp->Release();
+ }
+ }
+ return sfResult;
}
// ******************************************************************
// IntersectionClipper()
// ******************************************************************
-void CShapefile::IntersectionClipper( VARIANT_BOOL SelectedOnlySubject, IShapefile* sfClip, VARIANT_BOOL SelectedOnlyClip,
- IShapefile* sfResult, map* fieldMap,
- std::set* subjectShapesToSkip,
- std::set* clippingShapesToSkip)
+void CShapefile::IntersectionClipper(VARIANT_BOOL SelectedOnlySubject, IShapefile* sfClip,
+ VARIANT_BOOL SelectedOnlyClip,
+ IShapefile* sfResult, map* fieldMap,
+ std::set* subjectShapesToSkip,
+ std::set* clippingShapesToSkip)
{
- QTree* qTree = ((CShapefile*)sfClip)->GetTempQTree();
-
- long numShapesSubject, numShapesClip;
- this->get_NumShapes(&numShapesSubject);
- sfClip->get_NumShapes(&numShapesClip);
-
- // vector vPolygons; // we shall create vectors for both clipper and GEOS
- vector vPolygons; // we shall create vectors for both clipper and GEOS
- vPolygons.assign(numShapesClip, NULL); // this won't take much RAM or time
-
- ClipperLib::Clipper clp;
- ClipperConverter converter(this);
-
- IGeoProjection* projection = NULL;
- sfClip->get_GeoProjection(&projection);
- VARIANT_BOOL isGeographic = VARIANT_FALSE;
- if (projection)
- {
- projection->get_IsGeographic(&isGeographic);
- projection->Release();
- projection = NULL;
- }
- double AREA_TOLERANCE = m_globalSettings.GetMinPolygonArea(isGeographic) * 0.001;
-
- // initial areas areas of the clipping shapes
- std::vector initClipAreas;
- // areas of the clipping shapes that were passed to the result: (int)index of shapes -> (double)area
- std::vector resultClipAreas;
-
- ShpfileType shpType;
- sfClip->get_ShapefileType(&shpType);
-
- bool buildSkipLists = (subjectShapesToSkip != NULL && clippingShapesToSkip != NULL && m_globalSettings.shapefileFastUnion &&
- ShapeUtility::Convert2D(_shpfiletype) == SHP_POLYGON && ShapeUtility::Convert2D(shpType) == SHP_POLYGON);
-
- if (buildSkipLists)
- {
- initClipAreas.resize(numShapesClip, 0.0);
- resultClipAreas.resize(numShapesClip, 0.0);
- }
-
- long percent = 0;
- for(long subjectId =0; subjectId < numShapesSubject; subjectId++)
- {
- CallbackHelper::Progress(_globalCallback, subjectId, numShapesSubject, "Intersecting shapes...", _key, percent);
+ QTree* qTree = ((CShapefile*)sfClip)->GetTempQTree();
+
+ long numShapesSubject, numShapesClip;
+ this->get_NumShapes(&numShapesSubject);
+ sfClip->get_NumShapes(&numShapesClip);
+
+ // vector vPolygons; // we shall create vectors for both clipper and GEOS
+ vector vPolygons; // we shall create vectors for both clipper and GEOS
+ vPolygons.assign(numShapesClip, nullptr); // this won't take much RAM or time
+
+ ClipperLib::Clipper clp;
+ ClipperConverter converter(this);
+
+ VARIANT_BOOL isGeographic = VARIANT_FALSE;
+ sfResult->get_IsGeographicProjection(&isGeographic);
+
+ const double AREA_TOLERANCE = m_globalSettings.GetMinPolygonArea(isGeographic) * 0.001;
+
+ // initial areas areas of the clipping shapes
+ std::vector initClipAreas;
+ // areas of the clipping shapes that were passed to the result: (int)index of shapes -> (double)area
+ std::vector resultClipAreas;
+
+ ShpfileType shpType;
+ sfClip->get_ShapefileType(&shpType);
+
+ const bool buildSkipLists = subjectShapesToSkip != nullptr && clippingShapesToSkip != nullptr && m_globalSettings.
+ shapefileFastUnion &&
+ ShapeUtility::Convert2D(_shpfiletype) == SHP_POLYGON && ShapeUtility::Convert2D(shpType) == SHP_POLYGON;
+
+ if (buildSkipLists)
+ {
+ initClipAreas.resize(numShapesClip, 0.0);
+ resultClipAreas.resize(numShapesClip, 0.0);
+ }
+
+ long percent = 0;
+ for (long subjectId = 0; subjectId < numShapesSubject; subjectId++)
+ {
+ CallbackHelper::Progress(_globalCallback, subjectId, numShapesSubject, "Intersecting shapes...", _key, percent);
+
+ if (!this->ShapeAvailable(subjectId, SelectedOnlySubject))
+ continue;
+
+ double xMin, xMax, yMin, yMax;
+ this->QuickExtentsCore(subjectId, &xMin, &yMin, &xMax, &yMax);
+ vector shapeIds = qTree->GetNodes(QTreeExtent(xMin, xMax, yMax, yMin));
+
+ if (!shapeIds.empty())
+ {
+ // extracting subject polygon
+ IShape* shp1 = nullptr;
+ this->GetValidatedShape(subjectId, &shp1);
+ if (!shp1) continue;
+ // ClipperLib::Polygons* poly1 = converter.Shape2ClipperPolygon(shp1);
+ ClipperLib::Paths* poly1 = converter.Shape2ClipperPolygon(shp1);
+
+ double initArea = 0.0;
+ shp1->get_Area(&initArea);
+ shp1->Release();
+
+ if (poly1)
+ {
+ double sumArea = 0.0;
+
+ // extracting clipping polygons
+ for (long clipId : shapeIds)
+ {
+ // user can abort the operation in any time
+ if (_stopExecution)
+ {
+ VARIANT_BOOL stop;
+ _stopExecution->StopFunction(&stop);
+ if (stop)
+ {
+ sfResult->EditClear(&stop);
+ delete poly1;
+ goto cleaning;
+ }
+ }
+
+ if (!((CShapefile*)sfClip)->ShapeAvailable(clipId, SelectedOnlyClip))
+ continue;
+
+ // vector vShapes;
+
+ // Processing with Clipper
+ // ClipperLib::Polygons* poly2 = nullptr;
+ ClipperLib::Paths* poly2;
+
+ if (vPolygons[clipId] == nullptr)
+ {
+ IShape* shp2 = nullptr;
+ ((CShapefile*)sfClip)->GetValidatedShape(clipId, &shp2);
+ if (!shp2) continue;
+ poly2 = converter.Shape2ClipperPolygon(shp2);
+ vPolygons[clipId] = poly2;
+
+ if (buildSkipLists)
+ {
+ double tempArea = 0.0;
+ shp2->get_Area(&tempArea);
+ initClipAreas[clipId] = tempArea;
+ }
+
+ shp2->Release();
+ }
+ else
+ {
+ poly2 = vPolygons[clipId];
+ }
+
+ if (poly2)
+ {
+ if (poly1)
+ {
+ // clp.AddPolygons(*poly1, ClipperLib::ptSubject);
+ clp.AddPaths(*poly1, ClipperLib::ptSubject, true);
+ }
+ if (poly2)
+ {
+ // clp.AddPolygons(*poly2, ClipperLib::ptClip);
+ clp.AddPaths(*poly2, ClipperLib::ptClip, true);
+ }
+
+ // do clipping
+ // ClipperLib::Polygons polyResult;
+ ClipperLib::Paths polyResult;
+ if (clp.Execute(ClipperLib::ctIntersection, polyResult))
+ {
+ IShape* shp = converter.ClipperPolygon2Shape(&polyResult);
+ if (shp)
+ {
+ // sum of area to exclude shapes from difference
+ if (buildSkipLists)
+ {
+ double areaTemp;
+ shp->get_Area(&areaTemp);
+
+ // subject shape
+ sumArea += areaTemp;
+ resultClipAreas[clipId] += areaTemp;
+ }
+
+ vector vShapes;
+ vShapes.push_back(shp);
+ this->InsertShapesVector(sfResult, vShapes, this, subjectId, nullptr, sfClip, clipId,
+ fieldMap);
+ }
+ }
+ clp.Clear();
+ }
+ }
+ delete poly1;
+
+ if (buildSkipLists)
+ {
+ if (fabs(sumArea - initArea) < AREA_TOLERANCE)
+ {
+ subjectShapesToSkip->insert(subjectId);
+ }
+ }
+ }
+ }
+ }
+
+ // building the list of clipping shapes to skip
+ if (buildSkipLists)
+ {
+ for (int i = 0; i < numShapesClip; i++)
+ {
+ if (fabs(initClipAreas[i] - resultClipAreas[i]) < AREA_TOLERANCE && initClipAreas[i] != 0.0)
+ {
+ clippingShapesToSkip->insert(i);
+ }
+ }
+ }
- if(!this->ShapeAvailable(subjectId, SelectedOnlySubject))
- continue;
-
- vector shapeIds;
- double xMin, xMax, yMin, yMax;
- this->QuickExtentsCore(subjectId, &xMin, &yMin, &xMax, &yMax);
- shapeIds = qTree->GetNodes(QTreeExtent(xMin,xMax,yMax,yMin));
-
- if (shapeIds.size() > 0)
- {
- // extracting subject polygon
- IShape* shp1 = NULL;
- this->GetValidatedShape(subjectId, &shp1);
- if (!shp1) continue;
- // ClipperLib::Polygons* poly1 = converter.Shape2ClipperPolygon(shp1);
- ClipperLib::Paths* poly1 = converter.Shape2ClipperPolygon(shp1);
-
- double initArea = 0.0;
- shp1->get_Area(&initArea);
- shp1->Release();
-
- if (poly1)
- {
- double sumArea = 0.0;
-
- // extracting clipping polygons
- for (int j = 0; j < (int)shapeIds.size(); j++)
- {
- // user can abort the operation in any time
- if (_stopExecution)
- {
- VARIANT_BOOL stop;
- _stopExecution->StopFunction(&stop);
- if (stop)
- {
- sfResult->EditClear(&stop);
- delete poly1;
- goto cleaning;
- }
- }
-
- long clipId = shapeIds[j];
-
- if (!((CShapefile*)sfClip)->ShapeAvailable(clipId, SelectedOnlyClip))
- continue;
-
- vector vShapes;
-
- // Processing with Clipper
- // ClipperLib::Polygons* poly2 = NULL;
- ClipperLib::Paths* poly2 = NULL;
-
- if (vPolygons[clipId] == NULL)
- {
- IShape* shp2 = NULL;
- ((CShapefile*)sfClip)->GetValidatedShape(clipId, &shp2);
- if (!shp2) continue;
- poly2 = converter.Shape2ClipperPolygon(shp2);
- vPolygons[clipId] = poly2;
-
- if (buildSkipLists)
- {
- double tempArea = 0.0;
- shp2->get_Area(&tempArea);
- initClipAreas[clipId] = tempArea;
- }
-
- shp2->Release();
- }
- else
- {
- poly2 = vPolygons[clipId];
- }
-
- if (poly2)
- {
- if (poly1)
- {
- // clp.AddPolygons(*poly1, ClipperLib::ptSubject);
- clp.AddPaths(*poly1, ClipperLib::ptSubject, true);
- }
- if (poly2)
- {
- // clp.AddPolygons(*poly2, ClipperLib::ptClip);
- clp.AddPaths(*poly2, ClipperLib::ptClip, true);
- }
-
- // do clipping
- // ClipperLib::Polygons polyResult;
- ClipperLib::Paths polyResult;
- if (clp.Execute(ClipperLib::ctIntersection, polyResult))
- {
- IShape* shp = converter.ClipperPolygon2Shape(&polyResult);
- if (shp)
- {
- // sum of area to exclude shapes from difference
- if (buildSkipLists)
- {
- double areaTemp;
- shp->get_Area(&areaTemp);
-
- // subject shape
- sumArea += areaTemp;
- resultClipAreas[clipId] += areaTemp;
- }
-
- vector vShapes;
- vShapes.push_back(shp);
- this->InsertShapesVector(sfResult, vShapes, this, subjectId, NULL, sfClip, clipId, fieldMap);
- }
- }
- clp.Clear();
- }
- }
- delete poly1;
-
- if (buildSkipLists)
- {
- if (fabs(sumArea - initArea) < AREA_TOLERANCE)
- {
- subjectShapesToSkip->insert(subjectId);
- }
- }
- }
- }
- }
-
- // building the list of clipping shapes to skip
- if (buildSkipLists)
- {
- for (int i = 0; i < numShapesClip; i++)
- {
- if ( fabs(initClipAreas[i] - resultClipAreas[i]) < AREA_TOLERANCE && initClipAreas[i] != 0.0)
- {
- clippingShapesToSkip->insert(i);
- }
- }
- }
-
-cleaning:
- CallbackHelper::ProgressCompleted(_globalCallback, _key);
+cleaning:
+ CallbackHelper::ProgressCompleted(_globalCallback, _key);
- for(int i = 0; i < (int)vPolygons.size(); i++)
- {
- if (vPolygons[i] !=NULL)
- {
- delete vPolygons[i];
- }
- }
+ for (auto& vPolygon : vPolygons)
+ {
+ delete vPolygon;
+ }
}
#pragma endregion
@@ -2469,127 +2484,124 @@ void CShapefile::IntersectionClipper( VARIANT_BOOL SelectedOnlySubject, IShapefi
// ********************************************************************
// DifferenceGEOS()
// ********************************************************************
-void CShapefile::DifferenceGEOS(IShapefile* sfSubject, VARIANT_BOOL SelectedOnlySubject, IShapefile* sfOverlay, VARIANT_BOOL SelectedOnlyOverlay,
- IShapefile* sfResult, map* fieldMap, set* shapesToSkip)
+void CShapefile::DifferenceGEOS(IShapefile* sfSubject, VARIANT_BOOL SelectedOnlySubject, IShapefile* sfOverlay,
+ VARIANT_BOOL SelectedOnlyOverlay,
+ IShapefile* sfResult, map* fieldMap, set* shapesToSkip)
{
- QTree* qTree = ((CShapefile*)sfOverlay)->GetTempQTree();
+ QTree* qTree = ((CShapefile*)sfOverlay)->GetTempQTree();
+
+ long numShapesSubject, numShapesClip;
+ sfSubject->get_NumShapes(&numShapesSubject);
+ sfOverlay->get_NumShapes(&numShapesClip);
+
+ const bool isM = ShapeUtility::IsM(_shpfiletype);
+
+ long percent = 0;
+ for (long subjectId = 0; subjectId < numShapesSubject; subjectId++)
+ {
+ CallbackHelper::Progress(_globalCallback, subjectId, numShapesSubject, "Calculating difference...", _key,
+ percent);
+
+ if (!((CShapefile*)sfSubject)->ShapeAvailable(subjectId, SelectedOnlySubject))
+ continue;
+
+ // those shapes are marked to skip in the course of intersection
+ if (shapesToSkip != nullptr)
+ {
+ if (shapesToSkip->find(subjectId) != shapesToSkip->end())
+ continue;
+ }
+
+ double xMin, xMax, yMin, yMax;
+ ((CShapefile*)sfSubject)->QuickExtentsCore(subjectId, &xMin, &yMin, &xMax, &yMax);
+ vector shapeIds = qTree->GetNodes(QTreeExtent(xMin, xMax, yMax, yMin));
+
+ if (!shapeIds.empty())
+ {
+ GEOSGeometry* gsGeom1 = ((CShapefile*)sfSubject)->GetGeosGeometry(subjectId);
+ if (!gsGeom1) continue;
+
+ vector vClip;
+
+ // iterating through clip geometries, if the subject will stand this, we add it to the result
+ for (long clipId : shapeIds)
+ {
+ // user can abort the operation in any time
+ if (_stopExecution)
+ {
+ VARIANT_BOOL stop;
+ _stopExecution->StopFunction(&stop);
+ if (stop)
+ {
+ sfResult->EditClear(&stop);
+ //GeosHelper::DestroyGeometry(gsGeom1);
+ goto cleaning;
+ }
+ }
+
+ // extracting clip geometry
+ if (!((CShapefile*)sfOverlay)->ShapeAvailable(clipId, SelectedOnlyOverlay))
+ continue;
+
+ GEOSGeometry* gsGeom2 = ((CShapefile*)sfOverlay)->GetGeosGeometry(clipId);
+
+ if (gsGeom2 && GeosHelper::Intersects(gsGeom1, gsGeom2))
+ {
+ vClip.push_back(gsGeom2);
+ }
+ }
+
+ GEOSGeometry* gsClip = nullptr;
+ if (vClip.size() == 1)
+ {
+ gsClip = vClip[0];
+ }
+ else if (vClip.size() > 1)
+ {
+ // union of the clipping shapes
+ gsClip = GeosConverter::MergeGeometries(vClip, nullptr, false, false);
+ }
+
+ bool deleteNeeded = false;
+ if (gsClip)
+ {
+ gsGeom1 = GeosHelper::Difference(gsGeom1, gsClip);
+ deleteNeeded = true;
+
+ // if clip geometry was merged, we should delete it
+ if (vClip.size() > 1)
+ {
+ GeosHelper::DestroyGeometry(gsClip);
+ }
+ }
+
+ // saving what was left from the subject
+ if (gsGeom1 != nullptr)
+ {
+ vector vShapes;
+ GeosConverter::GeomToShapes(gsGeom1, &vShapes, isM);
+ if (deleteNeeded)
+ GeosHelper::DestroyGeometry(gsGeom1);
+ this->InsertShapesVector(sfResult, vShapes, sfSubject, subjectId, fieldMap); // shapes are released here
+ }
+ }
+ else
+ {
+ // insert the shape directly no other shapes intersects it
+ // TODO: it makes sense to rewrite it in more efficient way
+ IShape* shp1 = nullptr;
+ vector vShapes;
+ ((CShapefile*)sfSubject)->GetValidatedShape(subjectId, &shp1);
+ if (shp1)
+ {
+ vShapes.push_back(shp1);
+ this->InsertShapesVector(sfResult, vShapes, sfSubject, subjectId, fieldMap); // shapes are released here
+ }
+ }
+ }
- long numShapesSubject, numShapesClip;
- sfSubject->get_NumShapes(&numShapesSubject);
- sfOverlay->get_NumShapes(&numShapesClip);
-
- bool isM = ShapeUtility::IsM(_shpfiletype);
-
- long percent = 0;
- for(long subjectId = 0; subjectId < numShapesSubject; subjectId++)
- {
- CallbackHelper::Progress(_globalCallback, subjectId, numShapesSubject, "Calculating difference...", _key, percent);
-
- if(!((CShapefile*)sfSubject)->ShapeAvailable(subjectId, SelectedOnlySubject))
- continue;
-
- // those shapes are marked to skip in the course of intersection
- if (shapesToSkip != NULL)
- {
- if (shapesToSkip->find(subjectId) != shapesToSkip->end())
- continue;
- }
-
- vector shapeIds;
- double xMin, xMax, yMin, yMax;
- ((CShapefile*)sfSubject)->QuickExtentsCore(subjectId, &xMin, &yMin, &xMax, &yMax);
- shapeIds = qTree->GetNodes(QTreeExtent(xMin,xMax,yMax,yMin));
-
- if (shapeIds.size() > 0)
- {
- GEOSGeometry* gsGeom1 = ((CShapefile*)sfSubject)->GetGeosGeometry(subjectId);
- if (!gsGeom1) continue;
-
- vector vClip;
-
- // iterating through clip geometries, if the subject will stand this, we add it to the result
- for (int j = 0; j < (int)shapeIds.size(); j++)
- {
- // user can abort the operation in any time
- if (_stopExecution)
- {
- VARIANT_BOOL stop;
- _stopExecution->StopFunction(&stop);
- if (stop)
- {
- sfResult->EditClear(&stop);
- //GeosHelper::DestroyGeometry(gsGeom1);
- goto cleaning;
- }
- }
-
- // extracting clip geometry
- long clipId = shapeIds[j];
-
- if (!((CShapefile*)sfOverlay)->ShapeAvailable(clipId, SelectedOnlyOverlay))
- continue;
-
- GEOSGeometry* gsGeom2 = ((CShapefile*)sfOverlay)->GetGeosGeometry(clipId);
-
- if (gsGeom2 && GeosHelper::Intersects(gsGeom1, gsGeom2))
- {
- vClip.push_back(gsGeom2);
- }
- }
-
- GEOSGeometry* gsClip = NULL;
- if (vClip.size() == 1)
- {
- gsClip = vClip[0];
- }
- else if (vClip.size() > 1)
- {
- // union of the clipping shapes
- gsClip = GeosConverter::MergeGeometries(vClip, NULL, false, false);
- }
-
- bool deleteNeeded = false;
- if (gsClip)
- {
- GEOSGeometry* gsTemp = gsGeom1;
- gsGeom1 = GeosHelper::Difference(gsGeom1, gsClip);
- deleteNeeded = true;
- //GeosHelper::DestroyGeometry(gsTemp); // initial subject geometry isn't needed any more
-
- // if clip geometry was merged, we should delete it
- if (vClip.size() > 1)
- {
- GeosHelper::DestroyGeometry(gsClip);
- }
- }
-
- // saving what was left from the subject
- if (gsGeom1 != NULL)
- {
- vector vShapes;
- bool result = GeosConverter::GeomToShapes(gsGeom1, &vShapes, isM);
- if (deleteNeeded)
- GeosHelper::DestroyGeometry(gsGeom1);
- this->InsertShapesVector(sfResult, vShapes, sfSubject, subjectId, fieldMap); // shapes are released here
- }
- }
- else
- {
- // insert the shape directly no other shapes intersects it
- // TODO: it makes sense to rewrite it in more efficient way
- IShape* shp1 = NULL;
- vector vShapes;
- ((CShapefile*)sfSubject)->GetValidatedShape(subjectId, &shp1);
- if (shp1)
- {
- vShapes.push_back(shp1);
- this->InsertShapesVector(sfResult, vShapes, sfSubject, subjectId, fieldMap); // shapes are released here
- }
- }
- }
-
-cleaning:
- CallbackHelper::ProgressCompleted(_globalCallback, _key);
+cleaning:
+ CallbackHelper::ProgressCompleted(_globalCallback, _key);
}
#ifdef SERIALIZE_POLYGONS
@@ -2625,413 +2637,438 @@ void SerializePolygon(ofstream& out, ClipperLib::Polygons* poly)
// ******************************************************************
// DifferenceClipper()
// ******************************************************************
-void CShapefile::DifferenceClipper(IShapefile* sfSubject, VARIANT_BOOL SelectedOnlySubject, IShapefile* sfClip, VARIANT_BOOL SelectedOnlyClip,
- IShapefile* sfResult, map* fieldMap, set* shapesToSkip)
+void CShapefile::DifferenceClipper(IShapefile* sfSubject, VARIANT_BOOL SelectedOnlySubject, IShapefile* sfClip,
+ VARIANT_BOOL SelectedOnlyClip,
+ IShapefile* sfResult, map* fieldMap, set* shapesToSkip)
{
- QTree* qTree = ((CShapefile*)sfClip)->GetTempQTree();
-
- long numShapesSubject, numShapesClip;
- sfSubject->get_NumShapes(&numShapesSubject);
- sfClip->get_NumShapes(&numShapesClip);
-
- // vector vPolygons; // we shall create vectors for both clipper and GEOS
- vector vPolygons; // we shall create vectors for both clipper and GEOS
- vPolygons.assign(numShapesClip, NULL); // this won't take much RAM or time
-
- ClipperConverter ogr(sfSubject);
-
- long percent = 0;
- for(long subjectId =0; subjectId < numShapesSubject; subjectId++)
- {
- CallbackHelper::Progress(_globalCallback, subjectId, numShapesSubject, "Calculating difference...", _key, percent);
+ QTree* qTree = ((CShapefile*)sfClip)->GetTempQTree();
+
+ long numShapesSubject, numShapesClip;
+ sfSubject->get_NumShapes(&numShapesSubject);
+ sfClip->get_NumShapes(&numShapesClip);
+
+ // vector vPolygons; // we shall create vectors for both clipper and GEOS
+ vector vPolygons; // we shall create vectors for both clipper and GEOS
+ vPolygons.assign(numShapesClip, nullptr); // this won't take much RAM or time
+
+ ClipperConverter ogr(sfSubject);
+
+ long percent = 0;
+ for (long subjectId = 0; subjectId < numShapesSubject; subjectId++)
+ {
+ CallbackHelper::Progress(_globalCallback, subjectId, numShapesSubject, "Calculating difference...", _key,
+ percent);
+
+ if (!((CShapefile*)sfSubject)->ShapeAvailable(subjectId, SelectedOnlySubject))
+ continue;
+
+ if (shapesToSkip != nullptr)
+ {
+ if (shapesToSkip->find(subjectId) != shapesToSkip->end())
+ continue;
+ }
+
+ double xMin, xMax, yMin, yMax;
+ ((CShapefile*)sfSubject)->QuickExtentsCore(subjectId, &xMin, &yMin, &xMax, &yMax);
+ vector shapeIds = qTree->GetNodes(QTreeExtent(xMin, xMax, yMax, yMin));
+
+ if (!shapeIds.empty())
+ {
+ // extracting subject polygon
+ IShape* shp1 = nullptr;
+ ((CShapefile*)sfSubject)->GetValidatedShape(subjectId, &shp1);
+ if (!shp1) continue;
+ // ClipperLib::Polygons* poly1 = ogr.Shape2ClipperPolygon(shp1);
+ ClipperLib::Paths* poly1 = ogr.Shape2ClipperPolygon(shp1);
+ shp1->Release();
+
+ if (poly1)
+ {
+ auto* clp = new ClipperLib::Clipper;
+
+ // extracting clipping polygons
+ // ClipperLib::Polygons* poly2 = nullptr;
+ ClipperLib::Paths* poly2;
+ for (long clipId : shapeIds)
+ {
+ // user can abort the operation in any time
+ if (_stopExecution)
+ {
+ VARIANT_BOOL stop;
+ _stopExecution->StopFunction(&stop);
+ if (stop)
+ {
+ sfResult->EditClear(&stop);
+ delete clp;
+ goto cleaning;
+ }
+ }
+
+ if (!((CShapefile*)sfClip)->ShapeAvailable(clipId, SelectedOnlyClip))
+ continue;
+
+ vector vShapes;
+
+ // processng with Clipper
+ if (vPolygons[clipId] == nullptr)
+ {
+ IShape* shp2 = nullptr;
+ ((CShapefile*)sfClip)->GetValidatedShape(clipId, &shp2);
+ if (!shp2) continue;
+ poly2 = ogr.Shape2ClipperPolygon(shp2);
+ vPolygons[clipId] = poly2;
+ shp2->Release();
+ }
+ else
+ {
+ poly2 = vPolygons[clipId];
+ }
+
+ if (poly2)
+ {
+ // clp->AddPolygons(*poly2, ClipperLib::ptClip);
+ clp->AddPaths(*poly2, ClipperLib::ptClip, true);
+ }
- if(!((CShapefile*)sfSubject)->ShapeAvailable(subjectId, SelectedOnlySubject))
- continue;
-
- if (shapesToSkip != NULL)
- {
- if (shapesToSkip->find(subjectId) != shapesToSkip->end())
- continue;
- }
-
- vector shapeIds;
- double xMin, xMax, yMin, yMax;
- ((CShapefile*)sfSubject)->QuickExtentsCore(subjectId, &xMin, &yMin, &xMax, &yMax);
- shapeIds = qTree->GetNodes(QTreeExtent(xMin,xMax,yMax,yMin));
-
- if (shapeIds.size() > 0)
- {
- // extracting subject polygon
- IShape* shp1 = NULL;
- ((CShapefile*)sfSubject)->GetValidatedShape(subjectId, &shp1);
- if (!shp1) continue;
- // ClipperLib::Polygons* poly1 = ogr.Shape2ClipperPolygon(shp1);
- ClipperLib::Paths* poly1 = ogr.Shape2ClipperPolygon(shp1);
- shp1->Release();
-
- if (poly1)
- {
- ClipperLib::Clipper* clp = new ClipperLib::Clipper;
-
- // extracting clipping polygons
- // ClipperLib::Polygons* poly2 = NULL;
- ClipperLib::Paths* poly2 = NULL;
- for (int j = 0; j < (int)shapeIds.size(); j++)
- {
- // user can abort the operation in any time
- if (_stopExecution)
- {
- VARIANT_BOOL stop;
- _stopExecution->StopFunction(&stop);
- if (stop)
- {
- sfResult->EditClear(&stop);
- delete clp;
- goto cleaning;
- }
- }
-
- long clipId = shapeIds[j];
-
- if (!((CShapefile*)sfClip)->ShapeAvailable(clipId, SelectedOnlyClip))
- continue;
-
- vector vShapes;
-
- // processng with Clipper
- if (vPolygons[clipId] == NULL)
- {
- IShape* shp2 = NULL;
- ((CShapefile*)sfClip)->GetValidatedShape(clipId, &shp2);
- if (!shp2) continue;
- poly2 = ogr.Shape2ClipperPolygon(shp2);
- vPolygons[clipId] = poly2;
- shp2->Release();
- }
- else
- {
- poly2 = vPolygons[clipId];
- }
-
- if (poly2)
- {
- // clp->AddPolygons(*poly2, ClipperLib::ptClip);
- clp->AddPaths(*poly2, ClipperLib::ptClip, true);
- }
-
- #ifdef SERIALIZE_POLYGONS
+#ifdef SERIALIZE_POLYGONS
SerializePolygon(out, poly2);
- #endif
- }
-
- if (poly1)
- {
- // clp->AddPolygons(*poly1, ClipperLib::ptSubject);
- clp->AddPaths(*poly1, ClipperLib::ptSubject, true);
- }
-
- #ifdef SERIALIZE_POLYGONS
- SerializePolygon(out, poly1);
- #endif
-
- // do clipping
- // ClipperLib::Polygons polyResult;
- ClipperLib::Paths polyResult;
- if (clp->Execute(ClipperLib::ctDifference, polyResult))
- {
- IShape* shp = ogr.ClipperPolygon2Shape(&polyResult);
- if (shp)
- {
- vector vShapes;
- vShapes.push_back(shp);
- this->InsertShapesVector(sfResult, vShapes, sfSubject, subjectId, fieldMap);
- }
- }
-
- delete poly1;
- clp->Clear();
- delete clp;
- }
- }
- else
- {
- // insert the shape directly no other shapes intersects it
- // TODO: it makes sense to rewrite it in more efficient way
- IShape* shp1 = NULL;
- vector vShapes;
- ((CShapefile*)sfSubject)->GetValidatedShape(subjectId, &shp1);
- if (shp1)
- {
- VARIANT_BOOL editingShapes;
- sfSubject->get_EditingShapes(&editingShapes);
- IShape* shpCopy = NULL;
- if (editingShapes)
- {
- shp1->Clone(&shpCopy);
- shp1->Release();
- }
- else
- {
- shpCopy = shp1;
- }
- vShapes.push_back(shpCopy);
- this->InsertShapesVector(sfResult, vShapes, sfSubject, subjectId, fieldMap); // shapes are released here
- }
- }
- }
-
-cleaning:
- CallbackHelper::ProgressCompleted(_globalCallback, _key);
-
- for(int i = 0; i < (int)vPolygons.size(); i++)
- {
- if (vPolygons[i] !=NULL)
- {
- delete vPolygons[i];
- }
- }
-}
-#pragma endregion
-
-#pragma region Properties
-// ********************************************************************
-// GeometryEngine()
-// ********************************************************************
-STDMETHODIMP CShapefile::get_GeometryEngine(tkGeometryEngine* pVal)
-{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- *pVal = _geometryEngine;
- return S_OK;
-}
-
-STDMETHODIMP CShapefile::put_GeometryEngine(tkGeometryEngine newVal)
-{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- _geometryEngine = newVal;
- return S_OK;
-}
-
-#pragma endregion
-
-#pragma region PointInPolygon
-
-
-
-// ********************************************************************
-// PointInShape()
-// ********************************************************************
-STDMETHODIMP CShapefile::PointInShape(LONG ShapeIndex, DOUBLE x, DOUBLE y, VARIANT_BOOL* retval)
-{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
-
- if( ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size())
- {
- *retval = VARIANT_FALSE;
- ErrorMessage( tkINDEX_OUT_OF_BOUNDS );
- return S_OK;
- }
-
- long numParts, numPoints;
- long * Parts;
- Point2D * Points;
-
- if (_isEditingShapes)
- {
- if(_shpfiletype != SHP_POLYGON && _shpfiletype != SHP_POLYGONM && _shpfiletype != SHP_POLYGONZ)
- {
- *retval = VARIANT_FALSE;
- return S_OK;
- }
-
- double xMin, yMin, xMax, yMax;
- this->QuickExtentsCore(ShapeIndex, &xMin, &yMin, &xMax, &yMax);
-
- if(x < xMin || y < yMin || x > xMax || y > yMax)
- {
- *retval = VARIANT_FALSE;
- return S_OK;
- }
-
- // retrieving shapes from memory
- IShape * shp = _shapeData[ShapeIndex]->shape;
- shp->get_NumParts(&numParts);
- shp->get_NumPoints(&numPoints);
- Parts = new long[numParts + 1];
- Points = new Point2D[numPoints];
-
- for(int nPart = numParts - 1; nPart >= 0; nPart--)
- shp->get_Part(nPart, &Parts[nPart]);
-
- VARIANT_BOOL vbretval;
- for(int nPoint = numPoints - 1; nPoint >= 0; nPoint--)
- {
- shp->get_XY(nPoint, &Points[nPoint].x, &Points[nPoint].y, &vbretval);
- }
- Parts[numParts] = numPoints;
- }
- else
- {
- CSingleLock lock(&_readLock, TRUE);
-
- int shpType;
- fseek(_shpfile, _shpOffsets[ShapeIndex] + sizeof(int)*2, SEEK_SET);
- fread(&shpType, sizeof(int), 1, _shpfile);
-
- shpType = ShapeUtility::Convert2D((ShpfileType)shpType);
- if(shpType != SHP_POLYGON)
- {
- *retval = VARIANT_FALSE;
- return S_OK;
- }
-
- ShapeHeader shpHeader;
- fread(&shpHeader, sizeof(ShapeHeader), 1, _shpfile);
-
- // check the bounds
- if(x < shpHeader.MinX || y < shpHeader.MinY || x > shpHeader.MaxX || y > shpHeader.MaxY)
- {
- *retval = VARIANT_FALSE;
- return S_OK;
- }
-
- Parts = new long[shpHeader.NumParts + 1];
- Points = new Point2D[shpHeader.NumPoints];
-
- fread(Parts, sizeof(int), shpHeader.NumParts, _shpfile);
- fread(Points, sizeof(Point2D), shpHeader.NumPoints, _shpfile);
- Parts[shpHeader.NumParts] = shpHeader.NumPoints;
- numParts = shpHeader.NumParts;
- }
-
- int CrossCount = 0;
- for(int nPart = numParts - 1; nPart >= 0; nPart--)
- {
- int nPointMax = Parts[nPart+1] - 1;
- for(int nPoint = Parts[nPart]; nPoint < nPointMax; nPoint++)
- {
- double x1 = Points[nPoint].x - x;
- double y1 = Points[nPoint].y - y;
- double x2 = Points[nPoint+1].x - x;
- double y2 = Points[nPoint+1].y - y;
+#endif
+ }
- double y1y2 = y1*y2;
- if(y1y2 > 0.0) // If the signs are the same
- {
- // Then it does not cross
- continue;
- }
- else if(y1y2 == 0.0) // Then it has intesected a vertex
- {
- if(y1 == 0.0)
- {
- if( y2 > 0.0 )
- continue;
- }
- else if( y1 > 0.0 )
- continue;
- }
+ if (poly1)
+ {
+ // clp->AddPolygons(*poly1, ClipperLib::ptSubject);
+ clp->AddPaths(*poly1, ClipperLib::ptSubject, true);
+ }
- if( x1 > 0.0 && x2 > 0.0 )
- {
- CrossCount++;
- continue;
- }
+#ifdef SERIALIZE_POLYGONS
+ SerializePolygon(out, poly1);
+#endif
- // Calculate Intersection
- double dy = y2 - y1;
- double dx = x2 - x1;
+ // do clipping
+ // ClipperLib::Polygons polyResult;
+ ClipperLib::Paths polyResult;
+ if (clp->Execute(ClipperLib::ctDifference, polyResult))
+ {
+ IShape* shp = ogr.ClipperPolygon2Shape(&polyResult);
+ if (shp)
+ {
+ vector vShapes;
+ vShapes.push_back(shp);
+ this->InsertShapesVector(sfResult, vShapes, sfSubject, subjectId, fieldMap);
+ }
+ }
+
+ delete poly1;
+ clp->Clear();
+ delete clp;
+ }
+ }
+ else
+ {
+ // insert the shape directly no other shapes intersects it
+ // TODO: it makes sense to rewrite it in more efficient way
+ IShape* shp1 = nullptr;
+ vector vShapes;
+ ((CShapefile*)sfSubject)->GetValidatedShape(subjectId, &shp1);
+ if (shp1)
+ {
+ VARIANT_BOOL editingShapes;
+ sfSubject->get_EditingShapes(&editingShapes);
+ IShape* shpCopy = nullptr;
+ if (editingShapes)
+ {
+ shp1->Clone(&shpCopy);
+ shp1->Release();
+ }
+ else
+ {
+ shpCopy = shp1;
+ }
+ vShapes.push_back(shpCopy);
+ this->InsertShapesVector(sfResult, vShapes, sfSubject, subjectId, fieldMap); // shapes are released here
+ }
+ }
+ }
- // CDM March 2008 - if dy is zero (horiz line), this will be a bad idea...
- if (dy != 0)
- {
- if (x1 - y1*(dx/dy) > 0.0)
- CrossCount++;
- }
- }
- }
- delete [] Points;
- delete [] Parts;
+cleaning:
+ CallbackHelper::ProgressCompleted(_globalCallback, _key);
- *retval = CrossCount&1 ? VARIANT_TRUE : VARIANT_FALSE;
- return S_OK;
+ for (auto& vPolygon : vPolygons)
+ {
+ delete vPolygon;
+ }
}
#pragma endregion
-#pragma region PointInShapefile
+#pragma region Properties
// ********************************************************************
-// PointInShapefile()
+// GeometryEngine()
// ********************************************************************
-STDMETHODIMP CShapefile::PointInShapefile(DOUBLE x, DOUBLE y, LONG* ShapeIndex)
+STDMETHODIMP CShapefile::get_GeometryEngine(tkGeometryEngine* pVal)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
-
- int nShapeCount = _polySf.size();
- for(int nShape = nShapeCount - 1; nShape >= 0; nShape--)
- // for(int nShape = 0; nShape < ShapeCount; nShape++) see http://www.mapwindow.org/phorum/read.php?3,9745,9950#msg-9950
- {
- PolygonShapefile * sf = &_polySf[nShape];
-
- if(x < sf->shpHeader.MinX || y < sf->shpHeader.MinY || x > sf->shpHeader.MaxX || y > sf->shpHeader.MaxY)
- {
- continue;
- }
-
- int CrossCount = 0;
-
- for(int nPart = sf->shpHeader.NumParts - 1; nPart >= 0; nPart--)
- {
- int nPointMax = sf->Parts[nPart+1] - 1;
- for(int nPoint = sf->Parts[nPart]; nPoint < nPointMax; nPoint++)
- {
- double x1 = sf->Points[nPoint].x - x;
- double y1 = sf->Points[nPoint].y - y;
- double x2 = sf->Points[nPoint+1].x - x;
- double y2 = sf->Points[nPoint+1].y - y;
-
- double y1y2 = y1*y2;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ *pVal = _geometryEngine;
+ return S_OK;
+}
- if(y1y2 > 0.0) // If the signs are the same
- {
- // Then it does not cross
- continue;
- }
- else if(y1y2 == 0.0) // Then it has intesected a vertex
- {
- if(y1 == 0.0)
- {
- if( y2 > 0.0 )
- continue;
- }
- else if( y1 > 0.0 )
- continue;
- }
+STDMETHODIMP CShapefile::put_GeometryEngine(tkGeometryEngine newVal)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ _geometryEngine = newVal;
+ return S_OK;
+}
- if( x1 > 0.0 && x2 > 0.0 )
- {
- CrossCount++;
- continue;
- }
+#pragma endregion
- // Calculate Intersection
- double dy = y2 - y1;
- double dx = x2 - x1;
- double xint = x1 - y1*(dx/dy);
+#pragma region PointInPolygon
- if(xint > 0.0)
- CrossCount++;
- }
- }
- if(CrossCount&1)
- {
- *ShapeIndex = nShape;
- return S_OK;
- }
-
- }
+// ********************************************************************
+// PointInShape()
+// ********************************************************************
+STDMETHODIMP CShapefile::PointInShape(LONG ShapeIndex, DOUBLE x, DOUBLE y, VARIANT_BOOL* retval)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+
+ if (ShapeIndex < 0 || ShapeIndex >= (long)_shapeData.size())
+ {
+ *retval = VARIANT_FALSE;
+ ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
+ return S_OK;
+ }
+
+ long numParts, numPoints;
+ long* Parts;
+ Point2D* Points;
+
+ if (_isEditingShapes)
+ {
+ if (_shpfiletype != SHP_POLYGON && _shpfiletype != SHP_POLYGONM && _shpfiletype != SHP_POLYGONZ)
+ {
+ *retval = VARIANT_FALSE;
+ return S_OK;
+ }
+
+ double xMin, yMin, xMax, yMax;
+ this->QuickExtentsCore(ShapeIndex, &xMin, &yMin, &xMax, &yMax);
+
+ if (x < xMin || y < yMin || x > xMax || y > yMax)
+ {
+ *retval = VARIANT_FALSE;
+ return S_OK;
+ }
+
+ // retrieving shapes from memory
+ IShape* shp = _shapeData[ShapeIndex]->shape;
+ shp->get_NumParts(&numParts);
+ shp->get_NumPoints(&numPoints);
+ Parts = new long[numParts + 1];
+ Points = new Point2D[numPoints];
+
+ for (int nPart = numParts - 1; nPart >= 0; nPart--)
+ shp->get_Part(nPart, &Parts[nPart]);
+
+ VARIANT_BOOL vbretval;
+ for (int nPoint = numPoints - 1; nPoint >= 0; nPoint--)
+ {
+ shp->get_XY(nPoint, &Points[nPoint].x, &Points[nPoint].y, &vbretval);
+ }
+ Parts[numParts] = numPoints;
+ }
+ else
+ {
+ CSingleLock lock(&_readLock, TRUE);
+
+ int shpType;
+ fseek(_shpfile, _shpOffsets[ShapeIndex] + sizeof(int) * 2, SEEK_SET);
+ fread(&shpType, sizeof(int), 1, _shpfile);
+
+ shpType = ShapeUtility::Convert2D((ShpfileType)shpType);
+ if (shpType != SHP_POLYGON)
+ {
+ *retval = VARIANT_FALSE;
+ return S_OK;
+ }
+
+ ShapeHeader shpHeader{};
+ fread(&shpHeader, sizeof(ShapeHeader), 1, _shpfile);
+
+ // check the bounds
+ if (x < shpHeader.MinX || y < shpHeader.MinY || x > shpHeader.MaxX || y > shpHeader.MaxY)
+ {
+ *retval = VARIANT_FALSE;
+ return S_OK;
+ }
+
+ Parts = new long[shpHeader.NumParts + 1];
+ Points = new Point2D[shpHeader.NumPoints];
+
+ fread(Parts, sizeof(int), shpHeader.NumParts, _shpfile);
+ fread(Points, sizeof(Point2D), shpHeader.NumPoints, _shpfile);
+ Parts[shpHeader.NumParts] = shpHeader.NumPoints;
+ numParts = shpHeader.NumParts;
+ }
+
+ int CrossCount = 0;
+ // work backwards through Parts since we only know the first point of each Part
+ for (int nPart = numParts - 1; nPart >= 0; nPart--)
+ {
+ const int nPointMin = Parts[nPart];
+ const int nPointMax = Parts[nPart + 1] - 1;
+ int i, j;
+ // algorithm by W. Randolph Franklin; for a detailed explanation, see
+ // https://wrf.ecse.rpi.edu//Research/Short_Notes/pnpoly.html
+ // note that i starts at first point, while j starts at last point, then follows behind i
+ for (i = nPointMin, j = nPointMax - 1; i < nPointMax; j = i++)
+ {
+ if ( ((Points[i].y > y) != (Points[j].y > y)) &&
+ (x < (Points[j].x - Points[i].x) * (y - Points[i].y) / (Points[j].y - Points[i].y) + Points[i].x) )
+ // we have a crossing
+ CrossCount++;
+ }
+
+ //for (int nPoint = Parts[nPart]; nPoint < nPointMax; nPoint++)
+ //{
+ // const double x1 = Points[nPoint].x - x;
+ // const double y1 = Points[nPoint].y - y;
+ // const double x2 = Points[nPoint + 1].x - x;
+ // const double y2 = Points[nPoint + 1].y - y;
+
+ // const double y1y2 = y1 * y2;
+ // if (y1y2 > 0.0) // If the signs are the same
+ // {
+ // // Then it does not cross
+ // continue;
+ // }
+ // if (y1y2 == 0.0) // Then it has intesected a vertex
+ // {
+ // if (y1 == 0.0)
+ // {
+ // if (y2 > 0.0)
+ // continue;
+ // }
+ // else if (y1 > 0.0)
+ // continue;
+ // }
+
+ // if (x1 > 0.0 && x2 > 0.0)
+ // {
+ // CrossCount++;
+ // continue;
+ // }
+
+ // // Calculate Intersection
+ // const double dy = y2 - y1;
+ // const double dx = x2 - x1;
+
+ // // CDM March 2008 - if dy is zero (horiz line), this will be a bad idea...
+ // if (dy != 0)
+ // {
+ // if (x1 - y1 * (dx / dy) > 0.0)
+ // CrossCount++;
+ // }
+ //}
+ }
+ delete [] Points;
+ delete [] Parts;
+
+ *retval = CrossCount & 1 ? VARIANT_TRUE : VARIANT_FALSE;
+ return S_OK;
+}
+#pragma endregion
- *ShapeIndex = -1;
- return S_OK;
+#pragma region PointInShapefile
+// ********************************************************************
+// PointInShapefile()
+// ********************************************************************
+STDMETHODIMP CShapefile::PointInShapefile(DOUBLE x, DOUBLE y, LONG* ShapeIndex)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+
+ const int nShapeCount = _polySf.size();
+ for (int nShape = nShapeCount - 1; nShape >= 0; nShape--)
+ // for(int nShape = 0; nShape < ShapeCount; nShape++) see http://www.mapwindow.org/phorum/read.php?3,9745,9950#msg-9950
+ {
+ PolygonShapefile* sf = &_polySf[nShape];
+
+ if (x < sf->shpHeader.MinX || y < sf->shpHeader.MinY || x > sf->shpHeader.MaxX || y > sf->shpHeader.MaxY)
+ {
+ continue;
+ }
+
+ int CrossCount = 0;
+
+ int i, j;
+ // work backwards through Parts since we only know the first point of each Part
+ for (int nPart = sf->shpHeader.NumParts - 1; nPart >= 0; nPart--)
+ {
+ const int nPointMin = sf->Parts[nPart];
+ const int nPointMax = sf->Parts[nPart + 1] - 1;
+ // algorithm by W. Randolph Franklin; for a detailed explanation, see
+ // https://wrf.ecse.rpi.edu//Research/Short_Notes/pnpoly.html
+ // note that i starts at first point, while j starts at last point, then follows behind i
+ for (i = nPointMin, j = nPointMax - 1; i < nPointMax; j = i++)
+ {
+ if (((sf->Points[i].y > y) != (sf->Points[j].y > y)) &&
+ (x < (sf->Points[j].x - sf->Points[i].x) * (y - sf->Points[i].y) / (sf->Points[j].y - sf->Points[i].y) + sf->Points[i].x))
+ // we have a crossing
+ CrossCount++;
+ }
+ }
+ //for (int nPart = sf->shpHeader.NumParts - 1; nPart >= 0; nPart--)
+ //{
+ // const int nPointMax = sf->Parts[nPart + 1] - 1;
+ // for (int nPoint = sf->Parts[nPart]; nPoint < nPointMax; nPoint++)
+ // {
+ // const double x1 = sf->Points[nPoint].x - x;
+ // const double y1 = sf->Points[nPoint].y - y;
+ // const double x2 = sf->Points[nPoint + 1].x - x;
+ // const double y2 = sf->Points[nPoint + 1].y - y;
+
+ // const double y1y2 = y1 * y2;
+
+ // if (y1y2 > 0.0) // If the signs are the same
+ // {
+ // // Then it does not cross
+ // continue;
+ // }
+ // if (y1y2 == 0.0) // Then it has intesected a vertex
+ // {
+ // if (y1 == 0.0)
+ // {
+ // if (y2 > 0.0)
+ // continue;
+ // }
+ // else if (y1 > 0.0)
+ // continue;
+ // }
+
+ // if (x1 > 0.0 && x2 > 0.0)
+ // {
+ // CrossCount++;
+ // continue;
+ // }
+
+ // // Calculate Intersection
+ // const double dy = y2 - y1;
+ // const double dx = x2 - x1;
+ // const double xint = x1 - y1 * (dx / dy);
+
+ // if (xint > 0.0)
+ // CrossCount++;
+ // }
+ //}
+
+ if (CrossCount & 1)
+ {
+ *ShapeIndex = nShape;
+ return S_OK;
+ }
+ }
+
+ *ShapeIndex = -1;
+ return S_OK;
}
// ********************************************************************
@@ -3039,70 +3076,71 @@ STDMETHODIMP CShapefile::PointInShapefile(DOUBLE x, DOUBLE y, LONG* ShapeIndex)
// ********************************************************************
STDMETHODIMP CShapefile::BeginPointInShapefile(VARIANT_BOOL* retval)
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- if (_writing)
- {
- //AfxMessageBox("Can't read");
- *retval = VARIANT_FALSE;
- return S_OK;
- }
-
- if( _shpfiletype != SHP_POLYGON )
- {
- *retval = VARIANT_FALSE;
- ErrorMessage(tkUNEXPECTED_SHAPE_TYPE);
- return S_OK;
- }
-
- CSingleLock lock(&_readLock, TRUE);
-
- int size = _shapeData.size();
- _polySf.resize(size);
-
- for(int nShape = 0; nShape < size; nShape++)
- {
- fseek(_shpfile, _shpOffsets[nShape]+sizeof(int)*2, SEEK_SET);
- int shpType;
- fread(&shpType, sizeof(int), 1, _shpfile);
- if(shpType != SHP_POLYGON)
- {
- *retval = VARIANT_FALSE;
- ErrorMessage(tkUNEXPECTED_SHAPE_TYPE);
- return S_OK;
- }
-
- PolygonShapefile & sf = _polySf[nShape];
- fread(&sf.shpHeader, sizeof(ShapeHeader), 1, _shpfile);
-
- if (sf.shpHeader.NumPoints > 0 && sf.shpHeader.NumParts > 0)
- {
- sf.Points.resize(sf.shpHeader.NumPoints);
- sf.Parts.resize(sf.shpHeader.NumParts + 1);
- fread(&sf.Parts[0], sizeof(int), sf.shpHeader.NumParts, _shpfile);
- fread(&sf.Points[0], sizeof(Point2D), sf.shpHeader.NumPoints, _shpfile);
- sf.Parts[sf.shpHeader.NumParts] = sf.shpHeader.NumPoints;
- *retval = VARIANT_TRUE;
- }
- else
- {
- // this isn't a valid shape, we simply won't process it
- ErrorMessage(tkINVALID_SHAPE);
- *retval = VARIANT_FALSE;
- }
- }
- return S_OK;
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ if (_writing)
+ {
+ //AfxMessageBox("Can't read");
+ *retval = VARIANT_FALSE;
+ return S_OK;
+ }
+
+ // allow all polygon variations
+ if (_shpfiletype != SHP_POLYGON && _shpfiletype != SHP_POLYGONM && _shpfiletype != SHP_POLYGONZ)
+ {
+ *retval = VARIANT_FALSE;
+ ErrorMessage(tkUNEXPECTED_SHAPE_TYPE);
+ return S_OK;
+ }
+
+ CSingleLock lock(&_readLock, TRUE);
+
+ const int size = _shapeData.size();
+ _polySf.resize(size);
+
+ for (int nShape = 0; nShape < size; nShape++)
+ {
+ fseek(_shpfile, _shpOffsets[nShape] + sizeof(int) * 2, SEEK_SET);
+ int shpType;
+ fread(&shpType, sizeof(int), 1, _shpfile);
+ if (shpType != SHP_POLYGON && shpType != SHP_POLYGONM && shpType != SHP_POLYGONZ)
+ {
+ *retval = VARIANT_FALSE;
+ ErrorMessage(tkUNEXPECTED_SHAPE_TYPE);
+ return S_OK;
+ }
+
+ PolygonShapefile& sf = _polySf[nShape];
+ fread(&sf.shpHeader, sizeof(ShapeHeader), 1, _shpfile);
+
+ if (sf.shpHeader.NumPoints > 0 && sf.shpHeader.NumParts > 0)
+ {
+ sf.Points.resize(sf.shpHeader.NumPoints);
+ sf.Parts.resize(sf.shpHeader.NumParts + 1);
+ fread(&sf.Parts[0], sizeof(int), sf.shpHeader.NumParts, _shpfile);
+ fread(&sf.Points[0], sizeof(Point2D), sf.shpHeader.NumPoints, _shpfile);
+ sf.Parts[sf.shpHeader.NumParts] = sf.shpHeader.NumPoints;
+ *retval = VARIANT_TRUE;
+ }
+ else
+ {
+ // this isn't a valid shape, we simply won't process it
+ ErrorMessage(tkINVALID_SHAPE);
+ *retval = VARIANT_FALSE;
+ }
+ }
+ return S_OK;
}
// ********************************************************************
// EndPointInShapefile()
// ********************************************************************
-STDMETHODIMP CShapefile::EndPointInShapefile(void)
+STDMETHODIMP CShapefile::EndPointInShapefile()
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
- _polySf.clear();
+ _polySf.clear();
- return S_OK;
+ return S_OK;
}
#pragma endregion
@@ -3113,70 +3151,71 @@ STDMETHODIMP CShapefile::EndPointInShapefile(void)
// ********************************************************************
VARIANT_BOOL CShapefile::ExplodeShapesCore(VARIANT_BOOL SelectedOnly, IShapefile* result)
{
- // ----------------------------------------------
- // Validation
- // ----------------------------------------------
- if (!ValidateInput(this, "ExplodeShapes", "this", SelectedOnly)) {
- return VARIANT_FALSE;
- }
-
- // ----------------------------------------------
- // Processing
- // ----------------------------------------------
- VARIANT_BOOL vb;
- long count;
- CComVariant var;
- std::vector vShapes;
- long percent = 0;
-
- LONG numShapes;
- this->get_NumShapes(&numShapes);
-
- LONG numFields;
- this->get_NumFields(&numFields);
-
- for (long i = 0; i < numShapes; i++)
- {
- CallbackHelper::Progress(_globalCallback, i, numShapes, "Exploding...", _key, percent);
-
- if (!ShapeAvailable(i, SelectedOnly))
- continue;
-
- IShape* shp = NULL;
- GetValidatedShape(i, &shp);
- if (!shp) continue;
-
- if (((CShape*)shp)->ExplodeCore(vShapes))
- {
- for (long j = 0; j < (long)vShapes.size(); j++)
- {
- // all the shapes are copies of the initial ones, so no further cloning is needed
- result->get_NumShapes(&count);
- result->EditInsertShape(vShapes[j], &count, &vb);
-
- if (vb)
- {
- // copy attributes
- for (int iFld = 0; iFld < numFields; iFld++)
- {
- this->get_CellValue(iFld, i, &var);
- result->EditCellValue(iFld, count, var, &vb);
- }
- }
- vShapes[j]->Release(); // reference was added in EditInsertShape
- }
- }
-
- shp->Release();
- }
-
- // ----------------------------------------------
- // Output validation
- // ----------------------------------------------
- CallbackHelper::ProgressCompleted(_globalCallback, _key);
- ValidateOutput(result, "ExplodeShapes");
-
- return VARIANT_TRUE;
+ // ----------------------------------------------
+ // Validation
+ // ----------------------------------------------
+ if (!ValidateInput(this, "ExplodeShapes", "this", SelectedOnly))
+ {
+ return VARIANT_FALSE;
+ }
+
+ // ----------------------------------------------
+ // Processing
+ // ----------------------------------------------
+ VARIANT_BOOL vb;
+ long count;
+ CComVariant var;
+ std::vector