diff --git a/MapWinGisTests-net6/MapWinGisTests-net6.sln.DotSettings b/MapWinGisTests-net6/MapWinGisTests-net6.sln.DotSettings
new file mode 100644
index 00000000..2d72aa38
--- /dev/null
+++ b/MapWinGisTests-net6/MapWinGisTests-net6.sln.DotSettings
@@ -0,0 +1,2 @@
+
+ True
\ No newline at end of file
diff --git a/MapWinGisTests-net6/MapWinGisTests/FunctionalTests/GdalUtils/GdalUtilsTests.cs b/MapWinGisTests-net6/MapWinGisTests/FunctionalTests/GdalUtils/GdalUtilsTests.cs
index f39dfd97..75469f3e 100644
--- a/MapWinGisTests-net6/MapWinGisTests/FunctionalTests/GdalUtils/GdalUtilsTests.cs
+++ b/MapWinGisTests-net6/MapWinGisTests/FunctionalTests/GdalUtils/GdalUtilsTests.cs
@@ -90,8 +90,12 @@ public void Progress(string keyOfSender, int percent, string message)
public void Error(string keyOfSender, string errorMsg)
{
- _testOutputHelper.WriteLine($"Error of {keyOfSender}: {errorMsg}");
- }
+ try {
+ _testOutputHelper.WriteLine($"Error of {keyOfSender}: {errorMsg}");
+ } catch {
+ // ignore
+ }
+ }
#pragma warning restore xUnit1013
#endregion
}
diff --git a/MapWinGisTests-net6/MapWinGisTests/FunctionalTests/Projections/GeoProjectionsTests.cs b/MapWinGisTests-net6/MapWinGisTests/FunctionalTests/Projections/GeoProjectionsTests.cs
index af555020..695b31af 100644
--- a/MapWinGisTests-net6/MapWinGisTests/FunctionalTests/Projections/GeoProjectionsTests.cs
+++ b/MapWinGisTests-net6/MapWinGisTests/FunctionalTests/Projections/GeoProjectionsTests.cs
@@ -72,8 +72,10 @@ public void IsEmptyTest()
[Fact]
public void IsSameTest()
{
- // Setup:
- var geoProjection3857 = new GeoProjection();
+ System.Diagnostics.Debug.WriteLine("IsSameTest() start");
+
+ // Setup:
+ var geoProjection3857 = new GeoProjection();
geoProjection3857.ShouldNotBeNull();
var geoProjection28992 = new GeoProjection();
@@ -113,7 +115,9 @@ public void IsSameTest()
geoProjection3857.IsSame[geoProjectionPrj].ShouldBeFalse("GeoProjections should not be the same.");
geoProjection28992.IsSame[geoProjectionPrj].ShouldBeTrue("GeoProjections should be the same.");
geoProjectionPrj.IsSame[geoProjection28992].ShouldBeTrue("GeoProjections should be the same.");
- }
+
+ System.Diagnostics.Debug.WriteLine("IsSameTest() end");
+ }
[Fact]
public void ImportFromAutoDetectTest()
diff --git a/MapWinGisTests-net6/MapWinGisTests/FunctionalTests/Projections/UtilsProjectionTests.cs b/MapWinGisTests-net6/MapWinGisTests/FunctionalTests/Projections/UtilsProjectionTests.cs
index fed0e554..9eacc263 100644
--- a/MapWinGisTests-net6/MapWinGisTests/FunctionalTests/Projections/UtilsProjectionTests.cs
+++ b/MapWinGisTests-net6/MapWinGisTests/FunctionalTests/Projections/UtilsProjectionTests.cs
@@ -13,12 +13,13 @@ public UtilsProjectionTests(ITestOutputHelper testOutputHelper)
[Fact]
public void UtilsReprojectShapefileTest()
{
- // RD (Amersfoort, The Neterlands) to WGS84:
- // https://geodata.nationaalgeoregister.nl/locatieserver/v3/free?q=a325
- // "centroide_rd": "POINT(187816.756 433912.801)",
- // "centroide_ll": "POINT(5.86394184 51.89276528)"
+ System.Diagnostics.Debug.WriteLine("UtilsReprojectShapefileTest() start");
+ // RD (Amersfoort, The Neterlands) to WGS84:
+ // https://geodata.nationaalgeoregister.nl/locatieserver/v3/free?q=a325
+ // "centroide_rd": "POINT(187816.756 433912.801)",
+ // "centroide_ll": "POINT(5.86394184 51.89276528)"
- UtilsReprojectPointShapefile(187816.756, 433912.801, 5.86394184, 51.89276528, 0.0000001, 28992, 4326);
+ UtilsReprojectPointShapefile(187816.756, 433912.801, 5.86394184, 51.89276528, 0.0000001, 28992, 4326);
// The other way round:
UtilsReprojectPointShapefile(5.86394184, 51.89276528, 187816.756, 433912.801, 0.05, 4326, 28992);
@@ -26,6 +27,7 @@ public void UtilsReprojectShapefileTest()
UtilsReprojectPointShapefile(4.5703125, 51.944265, 4.5706292, 51.945227, 0.000001, 4258, 4289);
// Swap:
UtilsReprojectPointShapefile(4.5706292, 51.945227, 4.5703125, 51.944265, 0.000001, 4289, 4258);
+ System.Diagnostics.Debug.WriteLine("UtilsReprojectShapefileTest() end");
}
private void UtilsReprojectPointShapefile(double srcX, double srcY, double dstX, double dstY, double tolerance, int srcEpsgCode, int dstEpsgCode)
diff --git a/MapWinGisTests-net6/MapWinGisTests/Helpers.cs b/MapWinGisTests-net6/MapWinGisTests/Helpers.cs
index 5c0b9f99..4dd391bc 100644
--- a/MapWinGisTests-net6/MapWinGisTests/Helpers.cs
+++ b/MapWinGisTests-net6/MapWinGisTests/Helpers.cs
@@ -98,6 +98,19 @@ internal static Shapefile LoadSfUsingFileManager(string filename)
return sf;
}
+ internal static Shapefile CreateTestPolylineShapefile()
+ {
+ var sfPolyline = MakeShapefile(ShpfileType.SHP_POLYLINE);
+ AddShape(sfPolyline, "LINESTRING (330695.973322992 5914896.16305817, 330711.986129861 5914867.19586245, 330713.350435287 5914867.56644015, 330716.510827627 5914862.28973662, 330715.632568651 5914860.60107999, 330652.234582712 5914803.80510632, 330553.749382483 5914715.80328169, 330551.979355848 5914714.83347535, 330549.911988583 5914715.86502807, 330545.027807355 5914724.05916443, 330544.592985976 5914725.93531509, 330544.30963704 5914726.72754692, 330543.612620707 5914726.14904553, 330543.271515787 5914727.06633931, 330542.234090059 5914729.85597723, 330542.959654761 5914730.50411962, 330530.319252794 5914765.86064153, 330505.294840402 5914836.7930124, 330471.411812074 5914931.61558331, 330486.074748666 5914941.33795239, 330585.983154737 5915010.32749106, 330618.427962455 5915031.20447119, 330653.234601917 5914970.37328093, 330695.973322992 5914896.16305817)");
+
+ sfPolyline.NumShapes.ShouldBe(1);
+
+ // Set projection:
+ sfPolyline.GeoProjection = MakeProjection(28992);
+
+ return sfPolyline;
+ }
+
internal static Shapefile CreateTestPolygonShapefile()
{
var sfPolygon = MakeShapefile(ShpfileType.SHP_POLYGON);
@@ -153,7 +166,14 @@ internal static Shape MakeShape(ShpfileType shpType)
return shp;
}
- internal static void AddShape(Shapefile sf, string wktSting)
+ internal static Shape MakeShape(Point pt)
+ {
+ var shape = MakeShape(ShpfileType.SHP_POINT);
+ shape.AddPoint(pt.x, pt.y);
+ return shape;
+ }
+
+ internal static void AddShape(Shapefile sf, string wktSting)
{
// Create shape
var shp = new Shape();
diff --git a/MapWinGisTests-net6/MapWinGisTests/MapWinGisTests.csproj b/MapWinGisTests-net6/MapWinGisTests/MapWinGisTests.csproj
index 8fd0fc81..41d8d926 100644
--- a/MapWinGisTests-net6/MapWinGisTests/MapWinGisTests.csproj
+++ b/MapWinGisTests-net6/MapWinGisTests/MapWinGisTests.csproj
@@ -1,7 +1,7 @@
- net6.0-windows8.0
+ net8.0-windows8.0
MapWinGisTests
enable
@@ -35,15 +35,18 @@
-
-
-
-
-
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/MapWinGisTests-net6/MapWinGisTests/ShouldBeExtensions.cs b/MapWinGisTests-net6/MapWinGisTests/ShouldBeExtensions.cs
new file mode 100644
index 00000000..4407759d
--- /dev/null
+++ b/MapWinGisTests-net6/MapWinGisTests/ShouldBeExtensions.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using JetBrains.Annotations;
+
+namespace Shouldly
+{
+ public static class ShouldBeExtensions
+ {
+ //ContractAnnotation("actual:notnull => halt")]
+ public static void ShouldBeEqualWithin(this double? actual, double expected, double withinAmount, string? customMessage = null)
+ {
+ if(!actual.HasValue)
+ throw new ShouldAssertException("actual value is null");
+
+ if(Math.Abs(actual.Value - expected) > withinAmount)
+ throw new ShouldAssertException($"{actual.Value} is not equal to {expected} withing {withinAmount}");
+ }
+ }
+}
diff --git a/MapWinGisTests-net6/MapWinGisTests/UnitTests/CodeCoverageTests.cs b/MapWinGisTests-net6/MapWinGisTests/UnitTests/CodeCoverageTests.cs
index e479a32e..1d84996c 100644
--- a/MapWinGisTests-net6/MapWinGisTests/UnitTests/CodeCoverageTests.cs
+++ b/MapWinGisTests-net6/MapWinGisTests/UnitTests/CodeCoverageTests.cs
@@ -12,7 +12,7 @@ public CodeCoverageTests(ITestOutputHelper testOutputHelper)
_testOutputHelper = testOutputHelper;
}
- [Fact(Skip = "Unit test is not yet implemented")]
+ //[Fact(Skip = "Unit test is not yet implemented")]
public void CheckShapefileClass()
{
CheckTests(typeof(ShapefileClass), "Shapefile");
diff --git a/MapWinGisTests-net6/MapWinGisTests/UnitTests/ShapeTests.cs b/MapWinGisTests-net6/MapWinGisTests/UnitTests/ShapeTests.cs
index 06b6c849..70712426 100644
--- a/MapWinGisTests-net6/MapWinGisTests/UnitTests/ShapeTests.cs
+++ b/MapWinGisTests-net6/MapWinGisTests/UnitTests/ShapeTests.cs
@@ -1,4 +1,7 @@
-namespace MapWinGisTests.UnitTests;
+using System.Management;
+using Shouldly;
+
+namespace MapWinGisTests.UnitTests;
[Collection(nameof(NotThreadSafeResourceCollection))]
public class ShapeTests
@@ -99,80 +102,403 @@ public void ShapeKeyTest()
[Fact(Skip = "Unit test is not yet implemented")]
public void ShapeGlobalCallbackTest() { }
- [Fact(Skip = "Unit test is not yet implemented")]
- public void ShapeExtentsTest() { }
+ [Fact]
+ public void ShapeExtentsTest()
+ {
+ _firstShapePoint.ShouldNotBeNull();
+ var ext = _firstShapePoint.Extents;
+
+ var xMin = double.MaxValue;
+ var xMax = double.MinValue;
+ var yMin = double.MaxValue;
+ var yMax = double.MinValue;
+ for(var i = 0; i < _firstShapePoint.NumPoints; i++)
+ {
+ var pt = _firstShapePoint.Point[i];
+ if(pt.x < xMin)
+ xMin = pt.x;
+ if(pt.x > xMax)
+ xMax = pt.x;
+ if(pt.y < yMin)
+ yMin = pt.y;
+ if(pt.y > yMax)
+ yMax = pt.y;
+ }
+
+ ext.xMin.ShouldBe(xMin);
+ ext.xMax.ShouldBe(xMax);
+ ext.yMin.ShouldBe(yMin);
+ ext.yMax.ShouldBe(yMax);
+ }
- [Fact(Skip = "Unit test is not yet implemented")]
- public void ShapeCentroidTest() { }
+ [Fact]
+ public void ShapeCentroidTest()
+ {
+ var sfPolygon = Helpers.CreateTestPolygonShapefile();
+ sfPolygon.ShouldNotBeNull();
- [Fact(Skip = "Unit test is not yet implemented")]
- public void ShapeLengthTest() { }
+ var shape = sfPolygon.Shape[0];
+ var centroid = shape.Centroid;
+ centroid.ShouldNotBeNull();
- [Fact(Skip = "Unit test is not yet implemented")]
- public void ShapePerimeterTest() { }
+ var centroidShp = Helpers.MakeShape(centroid);
+ shape.Contains(centroidShp).ShouldBeTrue();
+ }
- [Fact(Skip = "Unit test is not yet implemented")]
- public void ShapeAreaTest() { }
+ [Fact]
+ public void ShapeLengthTest()
+ {
+ var sfPolyline = Helpers.CreateTestPolylineShapefile();
+ sfPolyline.ShouldNotBeNull();
- [Fact(Skip = "Unit test is not yet implemented")]
- public void ShapeIsValidTest() { }
+ var expectedLength = 828.9983624899301;
+ var shape = sfPolyline.Shape[0];
- [Fact(Skip = "Unit test is not yet implemented")]
- public void ShapeXyTest() { }
+ ((shape.Length - expectedLength) < 0.000001).ShouldBeTrue();
+ }
- [Fact(Skip = "Unit test is not yet implemented")]
- public void ShapePartIsClockWiseTest() { }
+ [Fact]
+ public void ShapePerimeterTest()
+ {
+ var sfPolygon = Helpers.CreateTestPolygonShapefile();
+ sfPolygon.ShouldNotBeNull();
- [Fact(Skip = "Unit test is not yet implemented")]
- public void ShapeCenterTest() { }
+ var expectedPerimeter = 828.9983624899301;
+ var shape = sfPolygon.Shape[0];
+ ((shape.Perimeter - expectedPerimeter) < 0.000001).ShouldBeTrue();
+ }
- [Fact(Skip = "Unit test is not yet implemented")]
- public void ShapeEndOfPartTest() { }
+ [Fact]
+ public void ShapeAreaTest()
+ {
+ var sfPolygon = Helpers.CreateTestPolygonShapefile();
+ sfPolygon.ShouldNotBeNull();
+
+ var expectedArea = 41521.544653236866;
+ var shape = sfPolygon.Shape[0];
+ var diff = Math.Abs(shape.Area - expectedArea);
+ diff.ShouldBeLessThan(0.0001);
+ }
+
+ [Fact]
+ public void ShapeIsValidTest()
+ {
+ var sfPolygon = Helpers.CreateTestPolygonShapefile();
+ sfPolygon.ShouldNotBeNull();
+
+ var shape = sfPolygon.Shape[0];
+ shape.IsValid.ShouldBeTrue();
+ }
+
+ [Fact]
+ public void ShapeXyTest()
+ {
+ var sfPolygon = Helpers.CreateTestPolygonShapefile();
+ sfPolygon.ShouldNotBeNull();
+
+ var shape = sfPolygon.Shape[0];
+ var pt = shape.Point[0];
+
+ double x = 0, y = 0;
+ shape.get_XY(0, ref x, ref y);
+ x.ShouldBe(pt.x);
+ y.ShouldBe(pt.y);
+
+ x += 15;
+ y += 10;
+
+ shape.put_XY(0, x, y);
+ pt = shape.Point[0];
+ x.ShouldBe(pt.x);
+ y.ShouldBe(pt.y);
+ }
- [Fact(Skip = "Unit test is not yet implemented")]
- public void ShapePartAsShapeTest() { }
+ [Fact]
+ public void ShapePartIsClockWiseTest()
+ {
+ var sfPolygon = Helpers.CreateTestPolygonShapefile();
+ sfPolygon.ShouldNotBeNull();
- [Fact(Skip = "Unit test is not yet implemented")]
- public void ShapeIsValidReasonTest() { }
+ var shape = sfPolygon.Shape[0];
- [Fact(Skip = "Unit test is not yet implemented")]
- public void ShapeInteriorPointTest() { }
+ shape.PartIsClockWise[0].ShouldBeTrue();
+ }
- [Fact(Skip = "Unit test is not yet implemented")]
- public void ShapeShapeType2DTest() { }
+ [Fact]
+ public void ShapeCenterTest()
+ {
+ var sfPolygon = Helpers.CreateTestPolygonShapefile();
+ sfPolygon.ShouldNotBeNull();
- [Fact(Skip = "Unit test is not yet implemented")]
- public void ShapeIsEmptyTest() { }
+ var shape = sfPolygon.Shape[0];
- [Fact(Skip = "Unit test is not yet implemented")]
- public void ShapePut_ZTest() { }
+ var center = shape.Center;
+ center.ShouldNotBeNull();
- [Fact(Skip = "Unit test is not yet implemented")]
- public void ShapeMTest() { }
+ var centerShp = Helpers.MakeShape(center);
+ shape.Contains(centerShp).ShouldBeTrue();
+ }
- [Fact(Skip = "Unit test is not yet implemented")]
- public void ShapeZTest() { }
+ [Fact]
+ public void ShapeEndOfPartTest()
+ {
+ var sfPolygon = Helpers.CreateTestPolygonShapefile();
+ sfPolygon.ShouldNotBeNull();
- [Fact(Skip = "Unit test is not yet implemented")]
- public void ShapeBufferWithParamsTest() { }
+ var shape = sfPolygon.Shape[0];
+ shape.EndOfPart[0].ShouldBeGreaterThan(0);
+ }
- [Fact(Skip = "Unit test is not yet implemented")]
- public void ShapeMoveTest() { }
+ [Fact]
+ public void ShapePartAsShapeTest()
+ {
+ var sfPolygon = Helpers.CreateTestPolygonShapefile();
+ sfPolygon.ShouldNotBeNull();
- [Fact(Skip = "Unit test is not yet implemented")]
- public void ShapeRotateTest() { }
+ var shape = sfPolygon.Shape[0];
+ var partShape = shape.PartAsShape[0];
+ partShape.ShouldNotBeNull();
+ }
- [Fact(Skip = "Unit test is not yet implemented")]
- public void ShapeSplitByPolylineTest() { }
+ [Fact]
+ public void ShapeIsValidReasonTest()
+ {
+ var sfPolygon = Helpers.CreateTestPolygonShapefile();
+ sfPolygon.ShouldNotBeNull();
- [Fact(Skip = "Unit test is not yet implemented")]
- public void ShapeClearTest() { }
+ var shape = sfPolygon.Shape[0];
+ shape.DeletePoint(shape.NumPoints - 1);
+ shape.IsValid.ShouldBeFalse();
+ if(!shape.IsValid)
+ shape.IsValidReason.ShouldNotBeEmpty();
+ }
- [Fact(Skip = "Unit test is not yet implemented")]
- public void ShapeFixUp2Test() { }
+ [Fact]
+ public void ShapeInteriorPointTest()
+ {
+ var sfPolygon = Helpers.CreateTestPolygonShapefile();
+ sfPolygon.ShouldNotBeNull();
- [Fact(Skip = "Unit test is not yet implemented")]
- public void ShapeInterpolatePointTest() { }
+ var shape = sfPolygon.Shape[0];
+ var x = (shape.Extents.xMax - shape.Extents.xMin) / 2.0 + shape.Extents.xMin;
+ var y = (shape.Extents.yMax - shape.Extents.yMin) / 2.0 + shape.Extents.yMin;
+
+ var interiorPoint = shape.InteriorPoint;
+ interiorPoint.ShouldNotBeNull();
+ (Math.Abs(interiorPoint.x - x) < 10).ShouldBeTrue();
+ (Math.Abs(interiorPoint.y - y) < 10).ShouldBeTrue();
+ }
+
+ [Fact]
+ public void ShapeShapeType2DTest()
+ {
+ var shape = Helpers.MakeShape(ShpfileType.SHP_POLYLINEZ);
+ shape.ShapeType2D.ShouldBe(ShpfileType.SHP_POLYLINE);
+
+ shape = Helpers.MakeShape(ShpfileType.SHP_POLYGONZ);
+ shape.ShapeType2D.ShouldBe(ShpfileType.SHP_POLYGON);
+
+ shape = Helpers.MakeShape(ShpfileType.SHP_POINTZ);
+ shape.ShapeType2D.ShouldBe(ShpfileType.SHP_POINT);
+ }
+
+ [Fact]
+ public void ShapeIsEmptyTest()
+ {
+ var shp = Helpers.MakeShapefile(ShpfileType.SHP_POLYLINEZ);
+ shp.ShouldNotBeNull();
+
+ var shape = Helpers.MakeShape(ShpfileType.SHP_POLYLINEZ);
+ shape.IsEmpty.ShouldBeTrue();
+
+ var sfPolygon = Helpers.CreateTestPolygonShapefile();
+ sfPolygon.ShouldNotBeNull();
+ shape = sfPolygon.Shape[0];
+ shape.IsEmpty.ShouldBeFalse();
+ }
+
+ [Fact]
+ public void ShapePut_ZTest()
+ {
+ Shape shape = new ShapeClass();
+ shape.ShapeType = ShpfileType.SHP_POINTZ;
+ shape.AddPoint(100, 100);
+
+ var z = 3.14;
+ shape.put_Z(0, z).ShouldBeTrue();
+
+ shape.get_Z(0, out var zValue);
+ zValue.ShouldBe(z);
+ }
+
+ [Fact]
+ public void ShapeMTest()
+ {
+ var sfPolygon = Helpers.CreateTestPolygonShapefile();
+ sfPolygon.ShouldNotBeNull();
+
+ var shape = sfPolygon.Shape[0];
+
+ var m = 3.1415;
+ shape.put_M(0, m).ShouldBeTrue();
+ shape.get_M(0, out var mValue).ShouldBeTrue();
+ mValue.ShouldBe(m);
+ }
+
+ [Fact]
+ public void ShapeZTest()
+ {
+ var sfPolygon = Helpers.CreateTestPolygonShapefile();
+ sfPolygon.ShouldNotBeNull();
+
+ var shape = sfPolygon.Shape[0];
+
+ var z = 3.1415;
+ shape.put_Z(0, z).ShouldBeTrue();
+ shape.get_Z(0, out var zValue).ShouldBeTrue();
+ zValue.ShouldBe(z);
+ }
+
+ [Fact]
+ public void ShapeBufferWithParamsTest()
+ {
+ var sfPolygon = Helpers.CreateTestPolygonShapefile();
+ sfPolygon.ShouldNotBeNull();
+
+ var shape = sfPolygon.Shape[0];
+ var dist = 10.0;
+ var newShape = shape.BufferWithParams(dist, 30, false, tkBufferCap.bcROUND, tkBufferJoin.bjROUND, 5.0);
+ newShape.ShouldNotBeNull();
+ (shape.Area < newShape.Area).ShouldBeTrue();
+ }
+
+ [Fact]
+ public void ShapeMoveTest()
+ {
+ var sfPolygon = Helpers.CreateTestPolygonShapefile();
+ sfPolygon.ShouldNotBeNull();
+
+ var shape = sfPolygon.Shape[0];
+ var xCenter = shape.Center.x;
+ var yCenter = shape.Center.y;
+
+ var xOffset = 15;
+ var yOffset = 20;
+ shape.Move(xOffset, yOffset);
+
+ var center = shape.Center;
+ var xDiff = center.x - xCenter;
+ var yDiff = center.y - yCenter;
+ xDiff.ShouldBe(xOffset);
+ yDiff.ShouldBe(yOffset);
+ }
+
+ [Fact]
+ public void ShapeRotateTest()
+ {
+ var sfPolygon = Helpers.CreateTestPolygonShapefile();
+ sfPolygon.ShouldNotBeNull();
+
+ var shape = sfPolygon.Shape[0];
+ var orgShape = shape.Clone();
+
+ var center = shape.Center;
+ shape.Rotate(center.x, center.y, 360);
+
+ shape.Area.ShouldBe(orgShape.Area);
+ shape.NumPoints.ShouldBe(orgShape.NumPoints);
+
+ for (var i = 0; i < shape.NumPoints; i++)
+ {
+ var pt0 = orgShape.Point[i];
+ var pt1 = shape.Point[i];
+ pt0.ShouldNotBeNull();
+ pt1.ShouldNotBeNull();
+ pt0.x.ShouldBe(pt1.x);
+ pt0.y.ShouldBe(pt1.y);
+ }
+ }
+
+ [Fact]
+ public void ShapeSplitByPolylineTest()
+ {
+ var sfPolygon = Helpers.CreateTestPolygonShapefile();
+ sfPolygon.ShouldNotBeNull();
+
+ var shape = sfPolygon.Shape[0];
+
+ var polyline = Helpers.MakeShape(ShpfileType.SHP_POLYLINE);
+ polyline.ShouldNotBeNull();
+ var wkt = "LineString (330431.80617637105751783 5914860.0969890458509326, 330766.5170847776462324 5914971.03695115447044373, 330766.5170847776462324 5914971.03695115447044373)";
+ polyline.ImportFromWKT(wkt).ShouldBeTrue();
+
+ object result = null;
+ shape.SplitByPolyline(polyline, ref result).ShouldBeTrue();
+
+ result.ShouldBeOfType(typeof(object[]));
+ var array = result as object[];
+ array.ShouldNotBeNull();
+ array.Length.ShouldBe(2);
+
+ IShape shape0 = array[0] as Shape;
+ shape0.ShouldNotBeNull();
+ shape0.IsValid.ShouldBeTrue();
+
+ IShape shape1 = array[1] as Shape;
+ shape1.ShouldNotBeNull();
+ shape1.IsValid.ShouldBeTrue();
+
+ var diff = Math.Abs((shape0.Area + shape1.Area) - shape.Area);
+ diff.ShouldBeLessThan(0.001);
+ }
+
+ [Fact]
+ public void ShapeClearTest()
+ {
+ var sfPolygon = Helpers.CreateTestPolygonShapefile();
+ sfPolygon.ShouldNotBeNull();
+
+ var shape = sfPolygon.Shape[0];
+ shape.ShouldNotBeNull();
+ shape.IsEmpty.ShouldBeFalse();
+
+ shape.Clear();
+ shape.IsEmpty.ShouldBeTrue();
+ }
+
+ [Fact]
+ public void ShapeFixUp2Test()
+ {
+ var sfPolygon = Helpers.CreateTestPolygonShapefile();
+ sfPolygon.ShouldNotBeNull();
+
+ var shape = sfPolygon.Shape[0];
+ var newShape = shape.FixUp2(tkUnitsOfMeasure.umMeters);
+ newShape.ShouldNotBeNull();
+
+ shape.DeletePoint(shape.NumPoints - 1);
+ shape.IsValid.ShouldBeFalse();
+
+ newShape = shape.FixUp2(tkUnitsOfMeasure.umMeters);
+ newShape.ShouldNotBeNull();
+ newShape.IsValid.ShouldBeTrue();
+ }
+
+ [Fact]
+ public void ShapeInterpolatePointTest()
+ {
+ var sfPolyline = Helpers.CreateTestPolylineShapefile();
+ sfPolyline.ShouldNotBeNull();
+
+ var shape = sfPolyline.Shape[0];
+ var pt = shape.InterpolatePoint(shape.Point[0], 0.5);
+ pt.ShouldNotBeNull();
+
+ var expectedX = 330696.21521950705;
+ var expectedY = 5914895.72546695;
+ ShouldBeExtensions.ShouldBeEqualWithin(pt.x, expectedX, 0.0001);
+ ShouldBeExtensions.ShouldBeEqualWithin(pt.y, expectedY, 0.0001);
+ }
[Fact(Skip = "Unit test is not yet implemented")]
public void ShapeProjectDistanceToTest() { }
diff --git a/src/COM classes/Field.cpp b/src/COM classes/Field.cpp
index 8853396d..e97b6101 100644
--- a/src/COM classes/Field.cpp
+++ b/src/COM classes/Field.cpp
@@ -237,6 +237,7 @@ STDMETHODIMP CField::Clone(/*[out, retval]*/ IField** retVal)
fld->put_Precision(_precision);
fld->put_Type(_type);
fld->put_Name(_name);
+ fld->put_Alias(_alias);
fld->put_Width(_width);
*retVal = fld;
return S_OK;
diff --git a/src/COM classes/GdalRasterBand.cpp b/src/COM classes/GdalRasterBand.cpp
index 5ccd0606..8c1ad946 100644
--- a/src/COM classes/GdalRasterBand.cpp
+++ b/src/COM classes/GdalRasterBand.cpp
@@ -65,6 +65,7 @@ STDMETHODIMP CGdalRasterBand::get_Minimum(DOUBLE* pVal)
if (!success)
{
+ // Not an error, the band has no minimum value
ErrorMessage("Failed to retrieve minimum.");
}
@@ -87,7 +88,9 @@ STDMETHODIMP CGdalRasterBand::get_Maximum(DOUBLE* pVal)
if (!success)
{
+ // Not an error, the band has no maximum value
ErrorMessage("Failed to retrieve maximum.");
+ *pVal = 255;
}
return S_OK;
diff --git a/src/COM classes/GeoProjection.cpp b/src/COM classes/GeoProjection.cpp
index ea7487dd..c0036367 100644
--- a/src/COM classes/GeoProjection.cpp
+++ b/src/COM classes/GeoProjection.cpp
@@ -415,6 +415,7 @@ STDMETHODIMP CGeoProjection::ImportFromWKT(const BSTR proj, VARIANT_BOOL* retVal
else
{
CString strProj(proj);
+ strProj = CorrectAxisOrder(strProj).c_str();
OGRErr result = OGRERR_NONE;
// use newer method importFromWkt(const char*)
@@ -449,6 +450,8 @@ STDMETHODIMP CGeoProjection::ImportFromAutoDetect(BSTR proj, VARIANT_BOOL* retVa
{
const CString s(proj);
*retVal = VARIANT_FALSE;
+ if(s.GetLength() == 0)
+ return S_OK;
const OGRErr err = _projection->SetFromUserInput(s);
@@ -529,6 +532,38 @@ STDMETHODIMP CGeoProjection::get_IsSame(IGeoProjection* proj, VARIANT_BOOL* pVal
return S_OK;
}
+ CComBSTR name1;
+ CComBSTR name2;
+ this->get_Name(&name1);
+ proj->get_Name(&name2);
+ if (name1 == name2)
+ {
+ *pVal = VARIANT_TRUE;
+ return S_OK;
+ }
+
+ CComBSTR projName1;
+ CComBSTR projName2;
+ this->get_ProjectionName(&projName1);
+ proj->get_ProjectionName(&projName2);
+ if (projName1 == projName2)
+ {
+ *pVal = VARIANT_TRUE;
+ return S_OK;
+ }
+
+ std::wstring pn1(projName1, SysStringLen(projName1));
+ std::wstring pn2(projName2, SysStringLen(projName2));
+ std::replace(pn1.begin(), pn1.end(), '-', ' ');
+ std::replace(pn2.begin(), pn2.end(), '-', ' ');
+ pn1.erase(std::remove(pn1.begin(), pn1.end(), '.'), pn1.end());
+ pn2.erase(std::remove(pn2.begin(), pn2.end(), '.'), pn2.end());
+ if (pn1 == pn2)
+ {
+ *pVal = VARIANT_TRUE;
+ return S_OK;
+ }
+
const OGRSpatialReference* const sr = dynamic_cast(proj)->get_SpatialReference();
// use OGRSpatialReference to test same-ness
*pVal = (_projection->IsSame(sr) == 0) ? VARIANT_FALSE : VARIANT_TRUE;
@@ -898,16 +933,20 @@ bool CGeoProjection::ReadFromFileCore(CStringW filename, bool esri)
// determine file length
fseek(prjFile, 0L, SEEK_END);
const int fileLen = ftell(prjFile);
- fseek(prjFile, 0L, SEEK_SET);
- // allocate buffer for file
- vector pszWKT = vector(fileLen, 0);
- // read the file
- fread(pszWKT.data(), sizeof(char), fileLen, prjFile);
- fclose(prjFile);
- // do the import
- err = _projection->SetFromUserInput(pszWKT.data());
- // clean up
- //delete pszWKT;
+ if (fileLen > 0) {
+ fseek(prjFile, 0L, SEEK_SET);
+ // allocate buffer for file
+ vector pszWKT = vector(fileLen, 0);
+ // read the file
+ fread(pszWKT.data(), sizeof(char), fileLen, prjFile);
+ fclose(prjFile);
+ // do the import
+ err = _projection->SetFromUserInput(pszWKT.data());
+ // clean up
+ //delete pszWKT;
+ }
+ else
+ err = OGRERR_NOT_ENOUGH_DATA;
}
if (err != OGRERR_NONE)
@@ -955,11 +994,6 @@ bool CGeoProjection::WriteToFileCore(CStringW filename, bool esri)
if (filename.CompareNoCase(L"") == 0)
return false;
- FILE* prjFile = _wfopen(filename, L"wb");
- if (!prjFile) {
- return false;
- }
-
CString proj;
CComBSTR bstr;
if (esri)
@@ -976,13 +1010,17 @@ bool CGeoProjection::WriteToFileCore(CStringW filename, bool esri)
if (proj.GetLength() != 0)
{
+ FILE* prjFile = _wfopen(filename, L"wb");
+ if (!prjFile) {
+ return false;
+ }
+
fputs((LPCSTR)proj, prjFile);
//fprintf(prjFile, "%s", (LPCSTR)proj);
+ fclose(prjFile);
+ prjFile = nullptr;
}
- fclose(prjFile);
- prjFile = nullptr;
-
return true;
}
@@ -1457,4 +1495,94 @@ bool CGeoProjection::ParseLinearUnits(CString s, tkUnitsOfMeasure& units)
Debug::WriteLine("Unrecognized linear units: %s", s);
return false;
+}
+
+std::string CGeoProjection::CorrectAxisOrder(CString wkt)
+{
+ std::string result;
+
+ std::vector dual_value;
+ dual_value.emplace_back("AUTHORITY");
+ dual_value.emplace_back("AXIS");
+ dual_value.emplace_back("PARAMETER");
+ dual_value.emplace_back("PRIMEM");
+ dual_value.emplace_back("UNIT");
+ std::string tripple_value = "SPHEROID";
+
+ std::vector lines;
+ std::string currentLine;
+ int openCount = 0; // [
+ int commaCount = 0;
+ for (size_t i = 0; i < wkt.GetLength(); i++)
+ {
+ auto ch = wkt[i];
+ if (ch == '\r' || ch == '\n')
+ continue;
+ else if (ch == '[')
+ openCount++;
+ else if (ch == ']')
+ openCount--;
+ else if (ch == ',')
+ {
+ currentLine += ch;
+ commaCount++;
+ auto len = currentLine.find('[');
+ auto tag = currentLine.substr(0, len);
+ // Trim left
+ tag.erase(tag.begin(), std::find_if(tag.begin(), tag.end(), [](unsigned char ch) {
+ return !std::isspace(ch);
+ }));
+
+ //tag = "AXIS";
+ std::vector match_array;
+ match_array.emplace_back(tag);
+
+ if (std::find_first_of(dual_value.begin(), dual_value.end(), match_array.begin(), match_array.end()) != dual_value.end())
+ {
+ if (commaCount < 2)
+ continue;
+ }
+
+ if (tripple_value == tag)
+ {
+ if (commaCount < 3)
+ continue;
+ }
+
+ lines.emplace_back(currentLine.c_str());
+ currentLine.clear();
+ commaCount = 0;
+ continue;
+ }
+
+ currentLine += ch;
+ }
+ lines.emplace_back(currentLine.c_str());
+
+ int position1 = -1;
+ int position2 = -1;
+ int pos = 0;
+ for (auto line : lines)
+ {
+ auto f1 = line.find("AXIS[\"Northing\"") != std::string::npos;
+ auto f2 = line.find("AXIS[\"Easting\"") != std::string::npos;
+ if (position1 == -1 && line.find("AXIS[\"Northing\"") != std::string::npos)
+ position1 = pos;
+ else if (position2 == -1 && line.find("AXIS[\"Easting\"") != std::string::npos)
+ position2 = pos;
+ pos++;
+ }
+
+ if (position1 < position2)
+ std::swap(lines[position1], lines[position2]);
+
+ for (auto line : lines)
+ {
+ if (line[0] == '\n')
+ line = line.substr(1, line.length() - 1);
+ result += line;
+ result += "\r\n";
+ }
+
+ return result;
}
\ No newline at end of file
diff --git a/src/COM classes/GeoProjection.h b/src/COM classes/GeoProjection.h
index 1adc508f..8fde6603 100644
--- a/src/COM classes/GeoProjection.h
+++ b/src/COM classes/GeoProjection.h
@@ -164,6 +164,7 @@ class ATL_NO_VTABLE CGeoProjection :
OGRSpatialReference* get_SpatialReference() noexcept { return _projection; }
void SetIsFrozen(bool frozen) noexcept { _isFrozen = frozen; }
void InjectSpatialReference(const gsl::not_null sr);
+ static std::string CorrectAxisOrder(CString wkt);
};
OBJECT_ENTRY_AUTO(__uuidof(GeoProjection), CGeoProjection)
diff --git a/src/COM classes/LabelClass.cpp b/src/COM classes/LabelClass.cpp
index 2f7a469c..ffee92fa 100644
--- a/src/COM classes/LabelClass.cpp
+++ b/src/COM classes/LabelClass.cpp
@@ -93,3 +93,62 @@ STDMETHODIMP CLabelClass::get_ScreenExtents(IExtents** retval)
}
return S_OK;
}
+
+
+// ***********************************************************
+// MapExtents
+// ***********************************************************
+STDMETHODIMP CLabelClass::get_MapExtents(double inversePixelPerProjection, IExtents** retVal)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ IExtents* ext = nullptr;
+ if(_label->horizontalFrame)
+ {
+ ComHelper::CreateExtents(&ext);
+
+ auto width2 = (_label->horizontalFrame->right - _label->horizontalFrame->left) * inversePixelPerProjection / 2.0;
+ auto height2 = (_label->horizontalFrame->bottom - _label->horizontalFrame->top) * inversePixelPerProjection / 2.0;
+ ext->SetBounds(_label->x - width2,
+ _label->y - height2,
+ 0.0,
+ _label->x + width2,
+ _label->y + height2,
+ 0.0);
+ *retVal = ext;
+ }
+ else if(_label->rotatedFrame)
+ {
+ ComHelper::CreateExtents(&ext);
+ CRect* rect = _label->rotatedFrame->BoundingBox();
+ auto width2 = (rect->right - rect->left) * inversePixelPerProjection / 2.0;
+ auto height2 = (rect->bottom - rect->top) * inversePixelPerProjection / 2.0;
+ ext->SetBounds(_label->x - width2,
+ _label->y - height2,
+ 0.0,
+ _label->x + width2,
+ _label->y + height2,
+ 0.0);
+ *retVal = ext;
+ }
+ else
+ *retVal = nullptr;
+ return S_OK;
+}
+
+// ************************************************************
+// get/put_Key()
+// ************************************************************
+STDMETHODIMP CLabelClass::get_Key(BSTR* pVal)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ *pVal = OLE2BSTR(_label->key);
+ return S_OK;
+}
+
+STDMETHODIMP CLabelClass::put_Key(BSTR newVal)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ SysFreeString(_label->key);
+ _label->key = OLE2BSTR(newVal);
+ return S_OK;
+}
diff --git a/src/COM classes/LabelClass.h b/src/COM classes/LabelClass.h
index 79f64514..13451928 100644
--- a/src/COM classes/LabelClass.h
+++ b/src/COM classes/LabelClass.h
@@ -105,6 +105,10 @@ class ATL_NO_VTABLE CLabelClass :
STDMETHOD(get_ScreenExtents)(IExtents** retval);
+ STDMETHOD(get_MapExtents)(double inversePixelPerProjection, IExtents** retVal);
+
+ STDMETHOD(get_Key)(/*[out, retval]*/ BSTR* pVal);
+ STDMETHOD(put_Key)(/*[in]*/ BSTR newVal);
private:
CLabelInfo* _label;
bool _canDelete; // CLabelInfo can be allocated locally, then we need to delete it
diff --git a/src/COM classes/Labels.cpp b/src/COM classes/Labels.cpp
index 592df6e0..26cc7a15 100644
--- a/src/COM classes/Labels.cpp
+++ b/src/COM classes/Labels.cpp
@@ -838,6 +838,44 @@ STDMETHODIMP CLabels::Select(IExtents* BoundingBox, long Tolerance, SelectMode S
return S_OK;
};
+// *****************************************************************
+// SelectNotDrawn()
+// *****************************************************************
+// Selection of not drawn labels which fall in the given bounding box
+STDMETHODIMP CLabels::SelectNotDrawn(IExtents* BoundingBox, VARIANT* LabelIndices, VARIANT* PartIndices, VARIANT_BOOL* retval)
+{
+ *retval = VARIANT_FALSE;
+ if (!BoundingBox) return S_OK;
+ double xMin, yMin, zMin, xMax, yMax, zMax;
+ BoundingBox->GetBounds(&xMin, &yMin, &zMin, &xMax, &yMax, &zMax);
+
+ vector indices;
+ vector parts;
+
+ for (unsigned long i = 0; i < _labels.size(); i++)
+ {
+ vector* labelParts = _labels[i];
+ for (unsigned long j = 0; j < labelParts->size(); j++)
+ {
+ CLabelInfo* lbl = labelParts->at(j);
+ if (lbl->horizontalFrame == nullptr && lbl->rotatedFrame == nullptr)
+ {
+ auto isInside = GeometryHelper::PointInExtent(xMin, yMin, xMax, yMax, lbl->x, lbl->y);
+ if (isInside)
+ {
+ indices.push_back(i);
+ parts.push_back(j);
+ }
+ }
+ }
+ }
+
+ bool result = Templates::Vector2SafeArray(&indices, VT_I4, LabelIndices);
+ *retval = Templates::Vector2SafeArray(&parts, VT_I4, PartIndices);
+ *retval = *retval && result;
+
+ return S_OK;
+}
// *******************************************************************
// put_ParentShapefile()
@@ -2909,3 +2947,29 @@ STDMETHODIMP CLabels::UpdateSizeField()
return S_OK;
}
+
+
+// *************************************************************
+// get_LabelDrawnInMap()
+// *************************************************************
+STDMETHODIMP CLabels::get_LabelDrawnInMap(long index, VARIANT_BOOL* pVal)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+
+ auto match = _drawnInMap.find(index);
+ *pVal = match != _drawnInMap.end();
+
+ return S_OK;
+}
+
+// *************************************************************
+// AddDrawnLabel()
+// *************************************************************
+void CLabels::AddDrawnLabel(long index)
+{
+ if (index == -1) // Reset
+ _drawnInMap.clear();
+ else
+ _drawnInMap.insert(index);
+}
+
diff --git a/src/COM classes/Labels.h b/src/COM classes/Labels.h
index a41b9143..ec1c7857 100644
--- a/src/COM classes/Labels.h
+++ b/src/COM classes/Labels.h
@@ -26,6 +26,7 @@
#pragma once
#include "LabelOptions.h"
#include "LabelCategory.h"
+#include
#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
@@ -164,6 +165,8 @@ class ATL_NO_VTABLE CLabels :
// selection
STDMETHOD(Select)(IExtents* BoundingBox, long Tolerance, SelectMode SelectMode, VARIANT* LabelIndices, VARIANT* PartIndices, VARIANT_BOOL* retval);
+ STDMETHOD(SelectNotDrawn)(IExtents* BoundingBox, VARIANT* LabelIndices, VARIANT* PartIndices, VARIANT_BOOL* retval);
+
// ------------------------------------------------------
// Class-specific properties
// ------------------------------------------------------
@@ -388,7 +391,8 @@ class ATL_NO_VTABLE CLabels :
STDMETHOD(get_LogScaleForSize)(VARIANT_BOOL* pVal);
STDMETHOD(put_LogScaleForSize)(VARIANT_BOOL newVal);
STDMETHOD(UpdateSizeField)();
-
+ STDMETHOD(get_LabelDrawnInMap)(long index, VARIANT_BOOL* pVal);
+
private:
int _sourceField;
@@ -454,6 +458,7 @@ class ATL_NO_VTABLE CLabels :
tkTextRenderingHint _textRenderingHint;
VARIANT_BOOL _synchronized;
+ std::set _drawnInMap;
private:
inline void ErrorMessage(long errorCode);
@@ -489,7 +494,8 @@ class ATL_NO_VTABLE CLabels :
void LoadLblOptions(CPLXMLNode* node);
bool RecalculateFontSize();
-
+
+ void AddDrawnLabel(long index);
};
diff --git a/src/COM classes/OgrLayer.cpp b/src/COM classes/OgrLayer.cpp
index 9a5698db..5f2273a8 100644
--- a/src/COM classes/OgrLayer.cpp
+++ b/src/COM classes/OgrLayer.cpp
@@ -171,27 +171,40 @@ void COgrLayer::UpdateShapefileFromOGRLoader()
{
shp->Create(shpType, &vb);
shp->ImportFromBinary(data[i]->Shape, &vb);
- _shapefile->EditInsertShape(shp, &count, &vb);
- tbl->UpdateTableRow(data[i]->Row, count);
+ ShpfileType shapeType;
+ shp->get_ShapeType(&shapeType);
+ auto compatible = shapeType == shpType
+ || ShapeUtility::Convert2D(shapeType) == ShapeUtility::Convert2D(shpType);
+ // Ignore incompatible shapes
+ if (compatible)
+ {
+ _shapefile->EditInsertShape(shp, &count, &vb);
+
+ tbl->UpdateTableRow(data[i]->Row, count);
+ }
data[i]->Row = NULL; // we no longer own it; it'll be cleared by Shapefile.EditClear
- // Preserve selection accross reloads:
- CComVariant pVal;
- tbl->get_CellValue(0, count, &pVal);
- bool wasSelected = false;
- for (size_t i = 0; i < selectedOgrFIDs.size(); i++)
- {
- if (selectedOgrFIDs[i] == pVal) {
- wasSelected = true;
- break;
- }
- }
- if (wasSelected)
- _shapefile->put_ShapeSelected(count, VARIANT_TRUE);
-
- if (hasFid)
- ((CShapefile*)_shapefile)->MapOgrFid2ShapeIndex(pVal.lVal, count);
+ if (compatible)
+ {
+ // Preserve selection accross reloads:
+ CComVariant pVal;
+ tbl->get_CellValue(0, count, &pVal);
+ bool wasSelected = false;
+ for (size_t i = 0; i < selectedOgrFIDs.size(); i++)
+ {
+ if (selectedOgrFIDs[i] == pVal) {
+ wasSelected = true;
+ break;
+ }
+ }
+ if (wasSelected)
+ _shapefile->put_ShapeSelected(count, VARIANT_TRUE);
+
+ if (hasFid)
+ ((CShapefile*)_shapefile)->MapOgrFid2ShapeIndex(pVal.lVal, count);
+ }
+
count++;
}
diff --git a/src/COM classes/PlacedLabels.cpp b/src/COM classes/PlacedLabels.cpp
new file mode 100644
index 00000000..1a5b66cd
--- /dev/null
+++ b/src/COM classes/PlacedLabels.cpp
@@ -0,0 +1,49 @@
+// PlacedLabels.cpp : Implementation of CPlacedLabels
+
+#include "stdafx.h"
+#include "PlacedLabels.h"
+
+// *****************************************************************
+// get_NumShapes()
+// *****************************************************************
+STDMETHODIMP CPlacedLabels::get_NumIndex(long* pVal)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ *pVal = static_cast(_indexes.size());
+ return S_OK;
+}
+
+
+// *****************************************************************
+// GetIndexes()
+// *****************************************************************
+STDMETHODIMP CPlacedLabels::GetIndexes(SAFEARRAY** retval)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ *retval = SafeArrayCreateVector(VT_I4, 0, static_cast(_indexes.size()));
+ SafeArrayLock((*retval));
+ auto pData = static_cast((*retval)->pvData);
+ for(size_t i = 0; i < _indexes.size(); i++)
+ {
+ pData[i] = _indexes[i];
+ }
+ SafeArrayUnlock((*retval));
+
+ return S_OK;
+}
+
+
+// *****************************************************************
+// GetIndexes()
+// *****************************************************************
+STDMETHODIMP CPlacedLabels::SetVector(int* indexes, const int length)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+
+ for(int i = 0; i < length; i++)
+ {
+ _indexes.push_back(indexes[i]);
+ }
+
+ return S_OK;
+}
\ No newline at end of file
diff --git a/src/COM classes/PlacedLabels.h b/src/COM classes/PlacedLabels.h
new file mode 100644
index 00000000..3c73f37d
--- /dev/null
+++ b/src/COM classes/PlacedLabels.h
@@ -0,0 +1,58 @@
+// PlacedLabels.h : Declaration of the CPlacedLabels
+#pragma once
+
+#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
+#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
+#endif
+
+using namespace ATL;
+
+// CPlacedLabels
+class ATL_NO_VTABLE CPlacedLabels :
+ public CComObjectRootEx,
+ public CComCoClass,
+ public IDispatchImpl
+{
+public:
+ CPlacedLabels()
+ {
+ _pUnkMarshaler = nullptr;
+ //_hotTracking = VARIANT_TRUE;
+ //_mode = imAllLayers;
+ //_color = RGB(255, 0, 0); //RGB(30, 144, 255);
+ //_activeLayer = -1;
+ }
+
+ DECLARE_REGISTRY_RESOURCEID(IDR_PLACEDLABELS)
+
+ BEGIN_COM_MAP(CPlacedLabels)
+ COM_INTERFACE_ENTRY(IPlacedLabels)
+ COM_INTERFACE_ENTRY(IDispatch)
+ COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, _pUnkMarshaler.p)
+ END_COM_MAP()
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ DECLARE_GET_CONTROLLING_UNKNOWN()
+
+ HRESULT FinalConstruct()
+ {
+ return CoCreateFreeThreadedMarshaler(GetControllingUnknown(), &_pUnkMarshaler.p);
+ }
+
+ void FinalRelease()
+ {
+ _pUnkMarshaler.Release();
+ }
+
+ CComPtr _pUnkMarshaler;
+
+public:
+ STDMETHOD(get_NumIndex)(/*[out, retval]*/ long* pVal);
+ STDMETHOD(GetIndexes)( /*[out, retval]*/ SAFEARRAY** retval);
+ STDMETHOD(SetVector)(int* indexes, int length);
+
+private:
+ std::vector _indexes;
+};
+OBJECT_ENTRY_AUTO(__uuidof(PlacedLabels), CPlacedLabels)
diff --git a/src/COM classes/PlacedLabels.rgs b/src/COM classes/PlacedLabels.rgs
new file mode 100644
index 00000000..e7efc3dc
--- /dev/null
+++ b/src/COM classes/PlacedLabels.rgs
@@ -0,0 +1,26 @@
+HKCR
+{
+ MapWinGIS.PlacedLabels.1 = s 'PlacedLabels Class'
+ {
+ CLSID = s '{92A8E8D4-617E-47A4-8180-82E24AD3C984}'
+ }
+ MapWinGIS.PlacedLabels = s 'PlacedLabels Class'
+ {
+ CLSID = s '{92A8E8D4-617E-47A4-8180-82E24AD3C984}'
+ CurVer = s 'MapWinGIS.PlacedLabels.1'
+ }
+ NoRemove CLSID
+ {
+ ForceRemove {92A8E8D4-617E-47A4-8180-82E24AD3C984} = s 'PlacedLabels Class'
+ {
+ ProgID = s 'MapWinGIS.PlacedLabels.1'
+ VersionIndependentProgID = s 'MapWinGIS.PlacedLabels'
+ ForceRemove 'Programmable'
+ InprocServer32 = s '%MODULE%'
+ {
+ val ThreadingModel = s 'Both'
+ }
+ 'TypeLib' = s '{C368D713-CC5F-40ED-9F53-F84FE197B96A}'
+ }
+ }
+}
diff --git a/src/COM classes/Shape.cpp b/src/COM classes/Shape.cpp
index b88356b8..12019a0e 100644
--- a/src/COM classes/Shape.cpp
+++ b/src/COM classes/Shape.cpp
@@ -61,6 +61,11 @@ CShape::CShape()
_labelRotation = 0;
gReferenceCounter.AddRef(tkInterface::idShape);
+#if DEBUG_ALLOCATED_OBJECTS
+ gReferenceCounter.AddRef(this);
+ if (ComHelper::GetBreak())
+ ::OutputDebugStringA("Break!");
+#endif
}
// **********************************************
@@ -80,6 +85,11 @@ CShape::~CShape()
}
gReferenceCounter.Release(tkInterface::idShape); // TODO: Fix compile warning
+#if DEBUG_ALLOCATED_OBJECTS
+ gReferenceCounter.Release(this);
+ if (ComHelper::GetBreak())
+ ::OutputDebugStringA("Break!");
+#endif
}
#pragma region DataConversions
@@ -259,6 +269,13 @@ STDMETHODIMP CShape::put_ShapeType(const ShpfileType newVal)
const ShapeWrapperType type = _shp->get_WrapperType();
const ShapeWrapperType newType = ShapeUtility::GetShapeWrapperType(newVal, !_useFastMode);
+ /*if ((newVal == SHP_POINT || newVal == SHP_POINTM || newVal == SHP_POINTZ) && ComHelper::GetBreak()) {
+ CString str;
+ str.Format("0x%016llx SHP_POINT", this);
+ const CComBSTR bstr(str);
+ put_Key(bstr);
+ } */
+
if (type == newType)
{
if (!_shp->put_ShapeType(newVal)) {
diff --git a/src/COM classes/ShapeDrawingOptions.cpp b/src/COM classes/ShapeDrawingOptions.cpp
index d9837fa9..579c6338 100644
--- a/src/COM classes/ShapeDrawingOptions.cpp
+++ b/src/COM classes/ShapeDrawingOptions.cpp
@@ -1164,7 +1164,7 @@ STDMETHODIMP CShapeDrawingOptions::put_LineWidth (float newVal)
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (newVal < 1) newVal = 1;
if (newVal > 20) newVal = 20;
- _options.lineWidth = newVal;
+ _options.lineWidth = newVal;
return S_OK;
}
diff --git a/src/COM classes/ShapeDrawingOptions.h b/src/COM classes/ShapeDrawingOptions.h
index 75a8c89c..b9dff9af 100644
--- a/src/COM classes/ShapeDrawingOptions.h
+++ b/src/COM classes/ShapeDrawingOptions.h
@@ -47,11 +47,13 @@ class ATL_NO_VTABLE CShapeDrawingOptions :
_isLineDecoration = false;
_pointRotationExpression = SysAllocString(L"");
gReferenceCounter.AddRef(tkInterface::idShapeDrawingOptions);
+ //gReferenceCounter.AddRef(this);
}
~CShapeDrawingOptions()
{
::SysFreeString(_pointRotationExpression);
gReferenceCounter.Release(tkInterface::idShapeDrawingOptions);
+ //gReferenceCounter.Release(this);
}
DECLARE_REGISTRY_RESOURCEID(IDR_SHAPEDRAWINGOPTIONS)
diff --git a/src/COM classes/ShapeEditor.cpp b/src/COM classes/ShapeEditor.cpp
index cace166e..b8561279 100644
--- a/src/COM classes/ShapeEditor.cpp
+++ b/src/COM classes/ShapeEditor.cpp
@@ -173,6 +173,10 @@ STDMETHODIMP CShapeEditor::get_ValidatedShape(IShape** retVal)
// *******************************************************
void CShapeEditor::CopyData(int firstIndex, int lastIndex, IShape* target )
{
+ ShpfileType shpType;
+ target->get_ShapeType(&shpType);
+ bool haveZ = ShapeUtility::IsZ(shpType);
+ bool haveM = ShapeUtility::HaveM(shpType);
long index, partCount = 0;
VARIANT_BOOL vb;
for(int i = firstIndex; i < lastIndex; i++)
@@ -180,6 +184,12 @@ void CShapeEditor::CopyData(int firstIndex, int lastIndex, IShape* target )
MeasurePoint* pnt = _activeShape->GetPoint(i);
if (pnt) {
target->AddPoint(pnt->Proj.x, pnt->Proj.y, &index);
+ IPoint* pt;
+ target->get_Point(index, &pt);
+ if (haveZ)
+ pt->put_Z(pnt->z);
+ if (haveM)
+ pt->put_M(pnt->m);
if (pnt->Part == PartBegin) {
target->InsertPart(i, &partCount, &vb);
partCount++;
@@ -345,11 +355,13 @@ STDMETHODIMP CShapeEditor::StartEdit(LONG LayerHandle, LONG ShapeIndex, VARIANT_
if (list) {
list->get_UndoCount(&_startingUndoCount);
}
-
+
+ _startedEditOnInvalidShape = false;
CComPtr shp = NULL;
sf->get_Shape(ShapeIndex, &shp);
if (shp)
{
+ _startedEditOnInvalidShape = !Validate(&shp);
put_EditorState(esEdit);
SetShape(shp);
_layerHandle = LayerHandle;
@@ -391,9 +403,12 @@ STDMETHODIMP CShapeEditor::SetShape( IShape* shp )
}
VARIANT_BOOL vb;
- double x, y;
+ double x, y, z, m;
shp->get_NumPoints(&numPoints);
+ bool haveZ = ShapeUtility::IsZ(shpType);
+ bool haveM = ShapeUtility::HaveM(shpType);
+
for(long i = 0; i < numPoints; i++)
{
PointPart part = PartNone;
@@ -401,7 +416,15 @@ STDMETHODIMP CShapeEditor::SetShape( IShape* shp )
if (endParts.find(i) != endParts.end()) part = PartEnd;
shp->get_XY(i, &x, &y, &vb);
- _activeShape->AddPoint(x, y, -1, -1, part);
+ if(haveZ)
+ shp->get_Z(i, &z, &vb);
+ else
+ z = 0.0;
+ if(haveM)
+ shp->get_M(i, &m, &vb);
+ else
+ m = 0.0;
+ _activeShape->AddPoint(x, y, z, m, -1, -1, part);
}
return S_OK;
}
@@ -717,11 +740,13 @@ STDMETHODIMP CShapeEditor::AddPoint(IPoint *newPoint, VARIANT_BOOL* retVal)
get_IsDigitizing(&digitizing);
tkCursorMode cursor = _mapCallback->_GetCursorMode();
if (digitizing) {
- double x, y;
+ double x, y, z, m;
newPoint->get_X(&x);
newPoint->get_Y(&y);
+ newPoint->get_Z(&z);
+ newPoint->get_Z(&m);
newPoint->Release();
- _activeShape->AddPoint(x, y, -1, -1, PartBegin);
+ _activeShape->AddPoint(x, y, z, m, -1, -1, PartBegin);
*retVal = VARIANT_TRUE;
return S_OK;
}
@@ -1167,6 +1192,8 @@ bool CShapeEditor::TryStop()
CComPtr shp = NULL;
get_ValidatedShape(&shp);
+ if (!shp && _startedEditOnInvalidShape ) // Invalid so get the invalid raw shape if we started with invalid shape (IK-379)
+ get_RawData(&shp);
switch (_state)
{
@@ -1183,8 +1210,9 @@ bool CShapeEditor::TryStop()
VARIANT_BOOL isEmpty;
get_IsEmpty(&isEmpty);
if (isEmpty) return true;
- if (!shp) return false;
- bool result = TrySaveShape(shp);
+ if (!shp && !_activeShape->AllowSaveInvalidGeometry) return false;
+ if( shp ) // Only try to save if we have a shape (IK-379)
+ bool result = TrySaveShape(shp);
SetRedrawNeeded(rtVolatileLayer);
break;
}
@@ -1277,8 +1305,9 @@ void CShapeEditor::HandleProjPointAdd(double projX, double projY)
{
double pixelX, pixelY;
_mapCallback->_ProjectionToPixel(projX, projY, &pixelX, &pixelY);
- _activeShape->AddPoint(projX, projY, pixelX, pixelY);
+ _activeShape->AddPoint(projX, projY, 0.0, 0.0, pixelX, pixelY);
_activeShape->ClearSnapPoint();
+ _mapCallback->_FireVertexAdded(&projX, &projY);
}
// ***************************************************************
@@ -1783,3 +1812,37 @@ STDMETHODIMP CShapeEditor::Deserialize(BSTR state, VARIANT_BOOL* retVal)
return S_OK;
}
+
+// ***************************************************************
+// EnableInsertVertex()
+// ***************************************************************
+STDMETHODIMP CShapeEditor::get_EnableInsertVertex(VARIANT_BOOL* pVal)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ *pVal = _activeShape->EnableInsertVertex;
+ return S_OK;
+}
+
+STDMETHODIMP CShapeEditor::put_EnableInsertVertex(VARIANT_BOOL newVal)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ _activeShape->EnableInsertVertex = newVal ? true : false;
+ return S_OK;
+}
+
+// ***************************************************************
+// AllowSaveInvalidGeometry()
+// ***************************************************************
+STDMETHODIMP CShapeEditor::get_AllowSaveInvalidGeometry(VARIANT_BOOL* pVal)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ *pVal = _activeShape->AllowSaveInvalidGeometry;
+ return S_OK;
+}
+
+STDMETHODIMP CShapeEditor::put_AllowSaveInvalidGeometry(VARIANT_BOOL newVal)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ _activeShape->AllowSaveInvalidGeometry = newVal ? true : false;
+ return S_OK;
+}
\ No newline at end of file
diff --git a/src/COM classes/ShapeEditor.h b/src/COM classes/ShapeEditor.h
index a384757f..66622108 100644
--- a/src/COM classes/ShapeEditor.h
+++ b/src/COM classes/ShapeEditor.h
@@ -162,6 +162,7 @@ class ATL_NO_VTABLE CShapeEditor :
double _snapTolerance;
tkLayerSelection _snapBehavior;
EditorBase* _activeShape;
+ bool _startedEditOnInvalidShape;
long _layerHandle;
long _shapeIndex;
long _lastErrorCode;
@@ -256,5 +257,10 @@ class ATL_NO_VTABLE CShapeEditor :
STDMETHOD(put_ShowLength)(VARIANT_BOOL newVal);
STDMETHOD(Serialize)(BSTR* retVal);
STDMETHOD(Deserialize)(BSTR state, VARIANT_BOOL* retVal);
+ STDMETHOD(get_EnableInsertVertex)(VARIANT_BOOL* pVal);
+ STDMETHOD(put_EnableInsertVertex)(VARIANT_BOOL newVal);
+ STDMETHOD(get_AllowSaveInvalidGeometry)(VARIANT_BOOL* pVal);
+ STDMETHOD(put_AllowSaveInvalidGeometry)(VARIANT_BOOL newVal);
+
};
OBJECT_ENTRY_AUTO(__uuidof(ShapeEditor), CShapeEditor)
diff --git a/src/COM classes/Shapefile.cpp b/src/COM classes/Shapefile.cpp
index 67c99c78..2f7e021d 100644
--- a/src/COM classes/Shapefile.cpp
+++ b/src/COM classes/Shapefile.cpp
@@ -35,6 +35,7 @@
#include "LabelsHelper.h"
#include "ShapeStyleHelper.h"
#include "TableClass.h"
+#include
#ifdef _DEBUG
#define new DEBUG_NEW
@@ -137,6 +138,7 @@ CShapefile::CShapefile()
ComHelper::CreateInstance(idUndoList, (IDispatch**)&_undoList);
gReferenceCounter.AddRef(tkInterface::idShapefile);
+ //gReferenceCounter.AddRef(this);
}
CShapefile::~CShapefile()
@@ -183,6 +185,7 @@ CShapefile::~CShapefile()
_undoList->Release();
}
gReferenceCounter.Release(tkInterface::idShapefile);
+ //gReferenceCounter.Release(this);
}
std::vector* CShapefile::get_ShapeVector()
@@ -1035,7 +1038,11 @@ STDMETHODIMP CShapefile::Close(VARIANT_BOOL* retval)
_categories->Clear();
}
*retval = VARIANT_TRUE;
-
+#if DEBUG
+ CString sError;
+ sError.AppendFormat("CShapefile::Close() returned: {0}\r\n", *retval);
+ ::OutputDebugStringA(sError.GetBuffer());
+#endif
return S_OK;
}
@@ -2280,6 +2287,8 @@ CPLXMLNode* CShapefile::SerializeCore(const VARIANT_BOOL saveSelection, CString
if (s != "")
Utility::CPLCreateXMLAttributeAndValue(psTree, "VisibilityExpression", s);
+ if (_sourceType == sstUninitialized)
+ Utility::CPLCreateXMLAttributeAndValue(psTree, "SourceType", "Uninitialized");
if (_useQTree != FALSE)
Utility::CPLCreateXMLAttributeAndValue(psTree, "UseQTree", CPLString().Printf("%d", _useQTree));
@@ -2316,6 +2325,10 @@ CPLXMLNode* CShapefile::SerializeCore(const VARIANT_BOOL saveSelection, CString
Utility::CPLCreateXMLAttributeAndValue(psTree, "SortAscending",
CPLString().Printf("%d", static_cast(_sortAscending)));
+ s = CString(_key);
+ if (s != "")
+ Utility::CPLCreateXMLAttributeAndValue(psTree, "Key", s);
+
// drawing options
CPLXMLNode* node = static_cast(_defaultDrawOpt)->SerializeCore("DefaultDrawingOptions");
if (node)
@@ -2765,6 +2778,23 @@ bool CShapefile::ReprojectCore(IGeoProjection* newProjection, LONG* reprojectedC
OGRSpatialReference* projSource = static_cast(_geoProjection)->get_SpatialReference();
OGRSpatialReference* projTarget = static_cast(newProjection)->get_SpatialReference();
+ char* pszWKT;
+ projSource->exportToPrettyWkt(&pszWKT);
+ auto srcWkt = CGeoProjection::CorrectAxisOrder(pszWKT);
+ auto ret1 = projSource->importFromWkt(srcWkt.c_str());
+ /*
+ ::OutputDebugStringA("\r\nprojSource:\r\n\r\n");
+ ::OutputDebugStringA(pszWKT); */
+
+ projTarget->exportToPrettyWkt(&pszWKT);
+ auto dstWkt = CGeoProjection::CorrectAxisOrder(pszWKT);
+ auto ret2 = projTarget->importFromWkt(dstWkt.c_str());
+ /*
+ ::OutputDebugStringA("\r\nprojTarget:\r\n");
+ ::OutputDebugStringA(pszWKT);
+ ::OutputDebugStringA("\r\n"); */
+
+
OGRCoordinateTransformation* transf = OGRCreateCoordinateTransformation(projSource, projTarget);
if (!transf)
{
diff --git a/src/COM classes/Shapefile_ReadWrite.cpp b/src/COM classes/Shapefile_ReadWrite.cpp
index 1b8f2cef..5e1a5471 100644
--- a/src/COM classes/Shapefile_ReadWrite.cpp
+++ b/src/COM classes/Shapefile_ReadWrite.cpp
@@ -1,1341 +1,1353 @@
-//********************************************************************************************************
-//File name: Shapefile.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");
-//you may not use this file except in compliance with the License. You may obtain a copy of the License at
-//http://www.mozilla.org/MPL/
-//Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
-//ANY KIND, either express or implied. See the License for the specific language governing rights and
-//limitations under the License.
-//
-//The Original Code is MapWindow Open Source.
-//
-//The Initial Developer of this version of the Original Code is Daniel P. Ames using portions created by
-//Utah State University and the Idaho National Engineering and Environmental Lab that were released as
-//public domain in March 2004.
-//
-//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
-
-#pragma once
-#include "stdafx.h"
-#include "Shapefile.h"
-#include "Shape.h"
-#include "ShapeWrapper.h"
-#include "ShapeHelper.h"
-
-#pragma region GetShape
-
-// ************************************************************
-// get_Shape()
-// ************************************************************
-STDMETHODIMP CShapefile::get_Shape(long shapeIndex, IShape **pVal)
-{
- AFX_MANAGE_STATE(AfxGetStaticModuleState())
- VARIANT_BOOL vbretval = VARIANT_FALSE;
-
- // out of bounds?
- if( shapeIndex < 0 || shapeIndex >= (long)_shapeData.size())
- {
- ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
- *pVal = NULL;
- return S_OK;
- }
-
- // last shape in the append mode is always in memory
- bool appendedShape = _appendMode && shapeIndex == _shapeData.size() - 1;
-
- // editing shapes?
- if (_isEditingShapes || appendedShape)
- {
- if (_shapeData[shapeIndex]->shape) {
- _shapeData[shapeIndex]->shape->AddRef();
- }
-
- *pVal = _shapeData[shapeIndex]->shape;
- return S_OK;
- }
-
- CSingleLock lock(&_readLock, TRUE);
-
- *pVal = _fastMode ? ReadFastModeShape(shapeIndex) : ReadComShape(shapeIndex);
-
- return S_OK;
-}
-
-// ************************************************************
-// ReadFastModeShape()
-// ************************************************************
-IShape* CShapefile::ReadFastModeShape(long shapeIndex)
-{
fseek(_shpfile, _shpOffsets[shapeIndex], SEEK_SET);
-
- // read the shp from disk
- int index = ShapeUtility::ReadIntBigEndian(_shpfile);
-
- if (index != shapeIndex + 1)
- {
- ErrorMessage(tkINVALID_SHP_FILE);
- return NULL;
- }
-
- int contentLength = ShapeUtility::ReadIntBigEndian(_shpfile) * 2;
-
- // *2: for conversion from 16-bit words to 8-bit words
- // -2: skip first 2 int - it's record number and content length;
- int length = contentLength; //- 2 * sizeof(int);
-
- char* data = new char[length];
- int count = (int)fread(data, sizeof(char), length, _shpfile);
-
- if (count != length)
- {
- delete[] data;
- return NULL;
- }
-
- IShape* shape = NULL;
-
- if (data != NULL)
- {
- ComHelper::CreateShape(&shape);
- shape->put_GlobalCallback(_globalCallback);
- ((CShape*)shape)->put_RawData(data, contentLength);
- delete[] data;
- }
-
- return shape;
-}
-
-// ************************************************************
-// ReadComShape()
-// ************************************************************
-IShape* CShapefile::ReadComShape(long shapeIndex)
-{
// read the shp from disk
- fseek(_shpfile, _shpOffsets[shapeIndex], SEEK_SET);
-
- int intbuf;
- fread(&intbuf, sizeof(int), 1, _shpfile);
- ShapeUtility::SwapEndian((char*)&intbuf, sizeof(int));
-
- // shape records are 1 based - Allow for a mistake
- if (intbuf != shapeIndex + 1 && intbuf != shapeIndex)
- {
- ErrorMessage(tkINVALID_SHP_FILE);
- return NULL;
- }
-
- fread(&intbuf, sizeof(int), 1, _shpfile);
- ShapeUtility::SwapEndian((char*)&intbuf, sizeof(int));
- int contentLength = intbuf * 2;//(32 bit words)
-
- fread(&intbuf, sizeof(int), 1, _shpfile);
-
- ShpfileType shpType = (ShpfileType)intbuf;
-
- IShape * shape = NULL;
- IPoint * pnt = NULL;
- VARIANT_BOOL vbretval;
-
-#pragma region Nullshape Or Mismatch
- // ------------------------------------------------------
- // Shape specific record contents
- // ------------------------------------------------------
-
- // MWGIS-91
- bool areEqualTypes = shpType == _shpfiletype;
- if (!areEqualTypes){
- areEqualTypes = ShapeUtility::Convert2D(shpType) == ShapeUtility::Convert2D(_shpfiletype);
- }
-
- if (_shpfiletype == SHP_NULLSHAPE)
- {
- if (shpType != SHP_NULLSHAPE)
- {
- ErrorMessage(tkINVALID_SHP_FILE);
- return NULL;
- }
- else
- {
- shape->Create(shpType, &vbretval);
- shape->put_GlobalCallback(_globalCallback);
- return shape;
- }
- }
- else if (shpType != SHP_NULLSHAPE && !areEqualTypes)
- {
- ErrorMessage(tkINVALID_SHP_FILE);
- return NULL;
- }
-#pragma endregion
-
-#pragma region Point
- // ------------------------------------------------------
- // SHP_POINT
- // ------------------------------------------------------
- else if (_shpfiletype == SHP_POINT)
- {
- ComHelper::CreateShape(&shape);
- shape->Create(shpType, &vbretval);
- shape->put_GlobalCallback(_globalCallback);
-
- // if (shpType == SHP_POINT)
- if (areEqualTypes)
- {
- ComHelper::CreatePoint(&pnt);
- pnt->put_GlobalCallback(_globalCallback);
-
- double x, y;
- fread(&x, sizeof(double), 1, _shpfile);
- fread(&y, sizeof(double), 1, _shpfile);
- pnt->put_X(x);
- pnt->put_Y(y);
-
- long pointIndex = 0;
- shape->InsertPoint(pnt, &pointIndex, &vbretval);
- if (vbretval == VARIANT_FALSE)
- {
- shape->Release();
- return NULL;
- }
- pnt->Release();
- }
- }
-
- // ------------------------------------------------------
- // SHP_POINTZ
- // ------------------------------------------------------
- else if (_shpfiletype == SHP_POINTZ)
- {
- ComHelper::CreateShape(&shape);
- shape->Create(shpType, &vbretval);
- shape->put_GlobalCallback(_globalCallback);
-
- // if (shpType == SHP_POINTZ)
- if (areEqualTypes)
- {
- ComHelper::CreatePoint(&pnt);
- pnt->put_GlobalCallback(_globalCallback);
-
- double x, y, z, m;
- fread(&x, sizeof(double), 1, _shpfile);
- fread(&y, sizeof(double), 1, _shpfile);
- fread(&z, sizeof(double), 1, _shpfile);
- fread(&m, sizeof(double), 1, _shpfile);
- pnt->put_X(x);
- pnt->put_Y(y);
- pnt->put_Z(z);
- pnt->put_M(m);
-
- long pointIndex = 0;
- shape->InsertPoint(pnt, &pointIndex, &vbretval);
- if (vbretval == VARIANT_FALSE)
- {
- shape->Release();
- return NULL;
- }
- pnt->Release();
- }
- }
-
- // ------------------------------------------------------
- // SHP_POINTM
- // ------------------------------------------------------
- else if (_shpfiletype == SHP_POINTM)
- {
- ComHelper::CreateShape(&shape);
- shape->Create(shpType, &vbretval);
- shape->put_GlobalCallback(_globalCallback);
-
- // if (shpType == SHP_POINTM)
- if (areEqualTypes)
- {
- ComHelper::CreatePoint(&pnt);
- pnt->put_GlobalCallback(_globalCallback);
-
- double x, y, m;
- fread(&x, sizeof(double), 1, _shpfile);
- fread(&y, sizeof(double), 1, _shpfile);
- fread(&m, sizeof(double), 1, _shpfile);
- pnt->put_X(x);
- pnt->put_Y(y);
- pnt->put_M(m);
-
- long pointIndex = 0;
- shape->InsertPoint(pnt, &pointIndex, &vbretval);
- if (vbretval == VARIANT_FALSE)
- {
- shape->Release();
- return NULL;
- }
- pnt->Release();
- }
- }
-#pragma endregion
-#pragma region Polyline
- // ------------------------------------------------------
- // SHP_POLYLINE
- // ------------------------------------------------------
- else if (_shpfiletype == SHP_POLYLINE)
- {
- ComHelper::CreateShape(&shape);
- shape->Create(shpType, &vbretval);
- shape->put_GlobalCallback(_globalCallback);
-
- // if (shpType == SHP_POLYLINE)
- if (areEqualTypes)
- {
- VARIANT_BOOL retval;
- double bx, by;
- int numParts;
- int numPoints;
- int part;
- double x, y;
-
- fread(&bx, sizeof(double), 1, _shpfile);
- fread(&by, sizeof(double), 1, _shpfile);
- fread(&bx, sizeof(double), 1, _shpfile);
- fread(&by, sizeof(double), 1, _shpfile);
-
- fread(&numParts, sizeof(int), 1, _shpfile);
- fread(&numPoints, sizeof(int), 1, _shpfile);
-
- long partIndex = 0;
- for (int i = 0; i < numParts; i++)
- {
- fread(&part, sizeof(int), 1, _shpfile);
- partIndex = i;
- shape->InsertPart(part, &partIndex, &retval);
- if (retval == VARIANT_FALSE)
- {
- shape->Release();
- return NULL;
- }
- }
-
- long pointIndex = 0;
- for (int j = 0; j < numPoints; j++)
- {
- ComHelper::CreatePoint(&pnt);
- pnt->put_GlobalCallback(_globalCallback);
- fread(&x, sizeof(double), 1, _shpfile);
- fread(&y, sizeof(double), 1, _shpfile);
- pnt->put_X(x);
- pnt->put_Y(y);
- pointIndex = j;
- shape->InsertPoint(pnt, &pointIndex, &retval);
- if (retval == VARIANT_FALSE)
- {
- shape->Release();
- return NULL;
- }
- pnt->Release();
- }
- }
- }
-
- // ------------------------------------------------------
- // SHP_POLYLINEZ
- // ------------------------------------------------------
- else if (_shpfiletype == SHP_POLYLINEZ)
- {
- ComHelper::CreateShape(&shape);
- shape->Create(shpType, &vbretval);
- shape->put_GlobalCallback(_globalCallback);
- // if (shpType == SHP_POLYLINEZ)
- if (areEqualTypes)
- {
- VARIANT_BOOL retval;
- double bx, by, bz, bm;
- int numParts;
- int numPoints;
- int part;
- double x, y, z, m;
-
- fread(&bx, sizeof(double), 1, _shpfile);
- fread(&by, sizeof(double), 1, _shpfile);
- fread(&bx, sizeof(double), 1, _shpfile);
- fread(&by, sizeof(double), 1, _shpfile);
-
- fread(&numParts, sizeof(int), 1, _shpfile);
- fread(&numPoints, sizeof(int), 1, _shpfile);
-
- long partIndex = 0;
- for (int i = 0; i < numParts; i++)
- {
- fread(&part, sizeof(int), 1, _shpfile);
- partIndex = i;
- shape->InsertPart(part, &partIndex, &retval);
- if (retval == VARIANT_FALSE)
- {
- shape->Release();
- return NULL;
- }
- }
-
- long pointIndex = 0;
- //Read the x, y part of the point
- for (int j = 0; j < numPoints; j++)
- {
- ComHelper::CreatePoint(&pnt);
- pnt->put_GlobalCallback(_globalCallback);
- fread(&x, sizeof(double), 1, _shpfile);
- fread(&y, sizeof(double), 1, _shpfile);
- pnt->put_X(x);
- pnt->put_Y(y);
- pointIndex = j;
- shape->InsertPoint(pnt, &pointIndex, &retval);
- if (retval == VARIANT_FALSE)
- {
- shape->Release();
- return NULL;
- }
- pnt->Release();
- }
-
- fread(&bz, sizeof(double), 1, _shpfile);
- fread(&bz, sizeof(double), 1, _shpfile);
-
- for (int k = 0; k < numPoints; k++)
- {
- fread(&z, sizeof(double), 1, _shpfile);
- pointIndex = k;
- IPoint * pnt = NULL;
- shape->get_Point(pointIndex, &pnt);
- if (pnt == NULL)
- {
- shape->Release();
- return NULL;
- }
- pnt->put_Z(z);
- pnt->Release();
- }
-
- fread(&bm, sizeof(double), 1, _shpfile);
- fread(&bm, sizeof(double), 1, _shpfile);
-
- for (int mc = 0; mc < numPoints; mc++)
- {
- fread(&m, sizeof(double), 1, _shpfile);
- pointIndex = mc;
- IPoint * pnt = NULL;
- shape->get_Point(pointIndex, &pnt);
- if (pnt == NULL)
- {
- shape->Release();
- return NULL;
- }
- pnt->put_M(m);
- //Rob Cairns 20-Dec-05
- pnt->Release();
- }
- }
- }
-
- // ------------------------------------------------------
- // SHP_POLYLINEM
- // ------------------------------------------------------
- else if (_shpfiletype == SHP_POLYLINEM)
- {
- ComHelper::CreateShape(&shape);
- shape->Create(shpType, &vbretval);
- shape->put_GlobalCallback(_globalCallback);
-
- // if (shpType == SHP_POLYLINEM)
- if (areEqualTypes)
- {
- VARIANT_BOOL retval;
- double bx, by, bm;
- int numParts;
- int numPoints;
- int part;
- double x, y, m;
-
- fread(&bx, sizeof(double), 1, _shpfile);
- fread(&by, sizeof(double), 1, _shpfile);
- fread(&bx, sizeof(double), 1, _shpfile);
- fread(&by, sizeof(double), 1, _shpfile);
-
- fread(&numParts, sizeof(int), 1, _shpfile);
- fread(&numPoints, sizeof(int), 1, _shpfile);
-
- long partIndex = 0;
- for (int i = 0; i < numParts; i++)
- {
- fread(&part, sizeof(int), 1, _shpfile);
- partIndex = i;
- shape->InsertPart(part, &partIndex, &retval);
- if (retval == VARIANT_FALSE)
- {
- shape->Release();
- return NULL;
- }
- }
-
- long pointIndex = 0;
- //Read the x, y part of the point
- for (int j = 0; j < numPoints; j++)
- {
- ComHelper::CreatePoint(&pnt);
- pnt->put_GlobalCallback(_globalCallback);
- fread(&x, sizeof(double), 1, _shpfile);
- fread(&y, sizeof(double), 1, _shpfile);
- pnt->put_X(x);
- pnt->put_Y(y);
- pointIndex = j;
- shape->InsertPoint(pnt, &pointIndex, &retval);
- if (retval == VARIANT_FALSE)
- {
- shape->Release();
- return NULL;
- }
- pnt->Release();
- }
-
- fread(&bm, sizeof(double), 1, _shpfile);
- fread(&bm, sizeof(double), 1, _shpfile);
-
- for (int mc = 0; mc < numPoints; mc++)
- {
- fread(&m, sizeof(double), 1, _shpfile);
- pointIndex = mc;
- IPoint * pnt = NULL;
- shape->get_Point(pointIndex, &pnt);
- if (pnt == NULL)
- {
- shape->Release();
- return NULL;
- }
- pnt->put_M(m);
- pnt->Release();
-
- }
- }
- }
-#pragma endregion
-#pragma region Polygon
- // ------------------------------------------------------
- // SHP_POLYGON
- // ------------------------------------------------------
- else if (_shpfiletype == SHP_POLYGON)
- {
- ComHelper::CreateShape(&shape);
- shape->Create(shpType, &vbretval);
- shape->put_GlobalCallback(_globalCallback);
-
- // if (shpType == SHP_POLYGON)
- if (areEqualTypes)
- {
- VARIANT_BOOL retval;
- double bx, by;
- int numParts;
- int numPoints;
- int part;
- double x, y;
-
- fread(&bx, sizeof(double), 1, _shpfile);
- fread(&by, sizeof(double), 1, _shpfile);
- fread(&bx, sizeof(double), 1, _shpfile);
- fread(&by, sizeof(double), 1, _shpfile);
-
- fread(&numParts, sizeof(int), 1, _shpfile);
- fread(&numPoints, sizeof(int), 1, _shpfile);
-
- long partIndex = 0;
- for (int i = 0; i < numParts; i++)
- {
- fread(&part, sizeof(int), 1, _shpfile);
- partIndex = i;
- shape->InsertPart(part, &partIndex, &retval);
- if (retval == VARIANT_FALSE)
- {
- shape->Release();
- return NULL;
- }
- }
-
- long pointIndex = 0;
- for (int j = 0; j < numPoints; j++)
- {
- ComHelper::CreatePoint(&pnt);
- pnt->put_GlobalCallback(_globalCallback);
- fread(&x, sizeof(double), 1, _shpfile);
- fread(&y, sizeof(double), 1, _shpfile);
- pnt->put_X(x);
- pnt->put_Y(y);
- pointIndex = j;
- shape->InsertPoint(pnt, &pointIndex, &retval);
- if (retval == VARIANT_FALSE)
- {
- shape->Release();
- return NULL;
- }
- pnt->Release();
- }
- }
- }
-
- // ------------------------------------------------------
- // SHP_POLYGONZ
- // ------------------------------------------------------
- else if (_shpfiletype == SHP_POLYGONZ)
- {
- ComHelper::CreateShape(&shape);
- shape->Create(shpType, &vbretval);
- shape->put_GlobalCallback(_globalCallback);
- // if (shpType == SHP_POLYGONZ)
- if (areEqualTypes)
- {
- VARIANT_BOOL retval;
- double bx, by, bz, bm;
- int numParts;
- int numPoints;
- int part;
- double x, y, z, m;
-
- fread(&bx, sizeof(double), 1, _shpfile);
- fread(&by, sizeof(double), 1, _shpfile);
- fread(&bx, sizeof(double), 1, _shpfile);
- fread(&by, sizeof(double), 1, _shpfile);
-
- fread(&numParts, sizeof(int), 1, _shpfile);
- fread(&numPoints, sizeof(int), 1, _shpfile);
-
- long partIndex = 0;
- for (int i = 0; i < numParts; i++)
- {
- fread(&part, sizeof(int), 1, _shpfile);
- partIndex = i;
- shape->InsertPart(part, &partIndex, &retval);
- if (retval == VARIANT_FALSE)
- {
- shape->Release();
- return NULL;
- }
- }
-
- //Read the x, y part of the point
- long pointIndex = 0;
- for (int j = 0; j < numPoints; j++)
- {
- ComHelper::CreatePoint(&pnt);
- pnt->put_GlobalCallback(_globalCallback);
- fread(&x, sizeof(double), 1, _shpfile);
- fread(&y, sizeof(double), 1, _shpfile);
- pnt->put_X(x);
- pnt->put_Y(y);
- pointIndex = j;
- shape->InsertPoint(pnt, &pointIndex, &retval);
- if (retval == VARIANT_FALSE)
- {
- shape->Release();
- return NULL;
- }
- pnt->Release();
- }
-
- fread(&bz, sizeof(double), 1, _shpfile);
- fread(&bz, sizeof(double), 1, _shpfile);
-
+//********************************************************************************************************
+//File name: Shapefile.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");
+//you may not use this file except in compliance with the License. You may obtain a copy of the License at
+//http://www.mozilla.org/MPL/
+//Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
+//ANY KIND, either express or implied. See the License for the specific language governing rights and
+//limitations under the License.
+//
+//The Original Code is MapWindow Open Source.
+//
+//The Initial Developer of this version of the Original Code is Daniel P. Ames using portions created by
+//Utah State University and the Idaho National Engineering and Environmental Lab that were released as
+//public domain in March 2004.
+//
+//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
+
+#pragma once
+#include "stdafx.h"
+#include "Shapefile.h"
+#include "Shape.h"
+#include "ShapeWrapper.h"
+#include "ShapeHelper.h"
+
+#pragma region GetShape
+
+// ************************************************************
+// get_Shape()
+// ************************************************************
+STDMETHODIMP CShapefile::get_Shape(long shapeIndex, IShape **pVal)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState())
+ VARIANT_BOOL vbretval = VARIANT_FALSE;
+
+ // out of bounds?
+ if( shapeIndex < 0 || shapeIndex >= (long)_shapeData.size())
+ {
+ ErrorMessage(tkINDEX_OUT_OF_BOUNDS);
+ *pVal = NULL;
+ return S_OK;
+ }
+
+ // last shape in the append mode is always in memory
+ bool appendedShape = _appendMode && shapeIndex == _shapeData.size() - 1;
+
+ // editing shapes?
+ if (_isEditingShapes || appendedShape)
+ {
+ if (_shapeData[shapeIndex]->shape) {
+ _shapeData[shapeIndex]->shape->AddRef();
+ }
+
+ *pVal = _shapeData[shapeIndex]->shape;
+ return S_OK;
+ }
+
+ CSingleLock lock(&_readLock, TRUE);
+
+ *pVal = _fastMode ? ReadFastModeShape(shapeIndex) : ReadComShape(shapeIndex);
+
+ return S_OK;
+}
+
+// ************************************************************
+// ReadFastModeShape()
+// ************************************************************
+IShape* CShapefile::ReadFastModeShape(long shapeIndex)
+{
+ fseek(_shpfile, _shpOffsets[shapeIndex], SEEK_SET);
+
+ // read the shp from disk
+ int index = ShapeUtility::ReadIntBigEndian(_shpfile);
+
+ if (index != shapeIndex + 1)
+ {
+ ErrorMessage(tkINVALID_SHP_FILE);
+ return NULL;
+ }
+
+ int contentLength = ShapeUtility::ReadIntBigEndian(_shpfile) * 2;
+
+ // *2: for conversion from 16-bit words to 8-bit words
+ // -2: skip first 2 int - it's record number and content length;
+ int length = contentLength; //- 2 * sizeof(int);
+
+ char* data = new char[length];
+ int count = (int)fread(data, sizeof(char), length, _shpfile);
+
+ if (count != length)
+ {
+ delete[] data;
+ return NULL;
+ }
+
+ IShape* shape = NULL;
+
+ if (data != NULL)
+ {
+ ComHelper::CreateShape(&shape);
+ shape->put_GlobalCallback(_globalCallback);
+ ((CShape*)shape)->put_RawData(data, contentLength);
+ delete[] data;
+ }
+
+ return shape;
+}
+
+// ************************************************************
+// ReadComShape()
+// ************************************************************
+IShape* CShapefile::ReadComShape(long shapeIndex)
+{
+ // read the shp from disk
+ fseek(_shpfile, _shpOffsets[shapeIndex], SEEK_SET);
+
+ int intbuf;
+ fread(&intbuf, sizeof(int), 1, _shpfile);
+ ShapeUtility::SwapEndian((char*)&intbuf, sizeof(int));
+
+ // shape records are 1 based - Allow for a mistake
+ if (intbuf != shapeIndex + 1 && intbuf != shapeIndex)
+ {
+ ErrorMessage(tkINVALID_SHP_FILE);
+ return NULL;
+ }
+
+ fread(&intbuf, sizeof(int), 1, _shpfile);
+ ShapeUtility::SwapEndian((char*)&intbuf, sizeof(int));
+ int contentLength = intbuf * 2;//(32 bit words)
+
+ fread(&intbuf, sizeof(int), 1, _shpfile);
+
+ ShpfileType shpType = (ShpfileType)intbuf;
+
+ IShape * shape = NULL;
+ IPoint * pnt = NULL;
+ VARIANT_BOOL vbretval;
+
+#pragma region Nullshape Or Mismatch
+ // ------------------------------------------------------
+ // Shape specific record contents
+ // ------------------------------------------------------
+
+ // MWGIS-91
+ bool areEqualTypes = shpType == _shpfiletype;
+ if (!areEqualTypes){
+ areEqualTypes = ShapeUtility::Convert2D(shpType) == ShapeUtility::Convert2D(_shpfiletype);
+ }
+
+ if (_shpfiletype == SHP_NULLSHAPE)
+ {
+ if (shpType != SHP_NULLSHAPE)
+ {
+ ErrorMessage(tkINVALID_SHP_FILE);
+ return NULL;
+ }
+ else
+ {
+ shape->Create(shpType, &vbretval);
+ shape->put_GlobalCallback(_globalCallback);
+ return shape;
+ }
+ }
+ else if (shpType != SHP_NULLSHAPE && !areEqualTypes)
+ {
+ ErrorMessage(tkINVALID_SHP_FILE);
+ return NULL;
+ }
+#pragma endregion
+
+#pragma region Point
+ // ------------------------------------------------------
+ // SHP_POINT
+ // ------------------------------------------------------
+ else if (_shpfiletype == SHP_POINT)
+ {
+ ComHelper::CreateShape(&shape);
+ shape->Create(shpType, &vbretval);
+ shape->put_GlobalCallback(_globalCallback);
+
+ // if (shpType == SHP_POINT)
+ if (areEqualTypes)
+ {
+ ComHelper::CreatePoint(&pnt);
+ pnt->put_GlobalCallback(_globalCallback);
+
+ double x, y;
+ fread(&x, sizeof(double), 1, _shpfile);
+ fread(&y, sizeof(double), 1, _shpfile);
+ pnt->put_X(x);
+ pnt->put_Y(y);
+
+ long pointIndex = 0;
+ shape->InsertPoint(pnt, &pointIndex, &vbretval);
+ if (vbretval == VARIANT_FALSE)
+ {
+ shape->Release();
+ return NULL;
+ }
+ pnt->Release();
+ }
+ }
+
+ // ------------------------------------------------------
+ // SHP_POINTZ
+ // ------------------------------------------------------
+ else if (_shpfiletype == SHP_POINTZ)
+ {
+ ComHelper::CreateShape(&shape);
+ shape->Create(shpType, &vbretval);
+ shape->put_GlobalCallback(_globalCallback);
+
+ // if (shpType == SHP_POINTZ)
+ if (areEqualTypes)
+ {
+ ComHelper::CreatePoint(&pnt);
+ pnt->put_GlobalCallback(_globalCallback);
+
+ double x, y, z, m;
+ fread(&x, sizeof(double), 1, _shpfile);
+ fread(&y, sizeof(double), 1, _shpfile);
+ fread(&z, sizeof(double), 1, _shpfile);
+ fread(&m, sizeof(double), 1, _shpfile);
+ pnt->put_X(x);
+ pnt->put_Y(y);
+ pnt->put_Z(z);
+ pnt->put_M(m);
+
+ long pointIndex = 0;
+ shape->InsertPoint(pnt, &pointIndex, &vbretval);
+ if (vbretval == VARIANT_FALSE)
+ {
+ shape->Release();
+ return NULL;
+ }
+ pnt->Release();
+ }
+ }
+
+ // ------------------------------------------------------
+ // SHP_POINTM
+ // ------------------------------------------------------
+ else if (_shpfiletype == SHP_POINTM)
+ {
+ ComHelper::CreateShape(&shape);
+ shape->Create(shpType, &vbretval);
+ shape->put_GlobalCallback(_globalCallback);
+
+ // if (shpType == SHP_POINTM)
+ if (areEqualTypes)
+ {
+ ComHelper::CreatePoint(&pnt);
+ pnt->put_GlobalCallback(_globalCallback);
+
+ double x, y, m;
+ fread(&x, sizeof(double), 1, _shpfile);
+ fread(&y, sizeof(double), 1, _shpfile);
+ fread(&m, sizeof(double), 1, _shpfile);
+ pnt->put_X(x);
+ pnt->put_Y(y);
+ pnt->put_M(m);
+
+ long pointIndex = 0;
+ shape->InsertPoint(pnt, &pointIndex, &vbretval);
+ if (vbretval == VARIANT_FALSE)
+ {
+ shape->Release();
+ return NULL;
+ }
+ pnt->Release();
+ }
+ }
+#pragma endregion
+#pragma region Polyline
+ // ------------------------------------------------------
+ // SHP_POLYLINE
+ // ------------------------------------------------------
+ else if (_shpfiletype == SHP_POLYLINE)
+ {
+ ComHelper::CreateShape(&shape);
+ shape->Create(shpType, &vbretval);
+ shape->put_GlobalCallback(_globalCallback);
+
+ // if (shpType == SHP_POLYLINE)
+ if (areEqualTypes)
+ {
+ VARIANT_BOOL retval;
+ double bx, by;
+ int numParts;
+ int numPoints;
+ int part;
+ double x, y;
+
+ fread(&bx, sizeof(double), 1, _shpfile);
+ fread(&by, sizeof(double), 1, _shpfile);
+ fread(&bx, sizeof(double), 1, _shpfile);
+ fread(&by, sizeof(double), 1, _shpfile);
+
+ fread(&numParts, sizeof(int), 1, _shpfile);
+ fread(&numPoints, sizeof(int), 1, _shpfile);
+
+ long partIndex = 0;
+ for (int i = 0; i < numParts; i++)
+ {
+ fread(&part, sizeof(int), 1, _shpfile);
+ partIndex = i;
+ shape->InsertPart(part, &partIndex, &retval);
+ if (retval == VARIANT_FALSE)
+ {
+ shape->Release();
+ return NULL;
+ }
+ }
+
+ long pointIndex = 0;
+ for (int j = 0; j < numPoints; j++)
+ {
+ ComHelper::CreatePoint(&pnt);
+ pnt->put_GlobalCallback(_globalCallback);
+ fread(&x, sizeof(double), 1, _shpfile);
+ fread(&y, sizeof(double), 1, _shpfile);
+ pnt->put_X(x);
+ pnt->put_Y(y);
+ pointIndex = j;
+ shape->InsertPoint(pnt, &pointIndex, &retval);
+ if (retval == VARIANT_FALSE)
+ {
+ shape->Release();
+ return NULL;
+ }
+ pnt->Release();
+ }
+ }
+ }
+
+ // ------------------------------------------------------
+ // SHP_POLYLINEZ
+ // ------------------------------------------------------
+ else if (_shpfiletype == SHP_POLYLINEZ)
+ {
+ ComHelper::CreateShape(&shape);
+ shape->Create(shpType, &vbretval);
+ shape->put_GlobalCallback(_globalCallback);
+ // if (shpType == SHP_POLYLINEZ)
+ if (areEqualTypes)
+ {
+ VARIANT_BOOL retval;
+ double bx, by, bz, bm;
+ int numParts;
+ int numPoints;
+ int part;
+ double x, y, z, m;
+
+ fread(&bx, sizeof(double), 1, _shpfile);
+ fread(&by, sizeof(double), 1, _shpfile);
+ fread(&bx, sizeof(double), 1, _shpfile);
+ fread(&by, sizeof(double), 1, _shpfile);
+
+ fread(&numParts, sizeof(int), 1, _shpfile);
+ fread(&numPoints, sizeof(int), 1, _shpfile);
+
+ long partIndex = 0;
+ for (int i = 0; i < numParts; i++)
+ {
+ fread(&part, sizeof(int), 1, _shpfile);
+ partIndex = i;
+ shape->InsertPart(part, &partIndex, &retval);
+ if (retval == VARIANT_FALSE)
+ {
+ shape->Release();
+ return NULL;
+ }
+ }
+
+ long pointIndex = 0;
+ //Read the x, y part of the point
+ for (int j = 0; j < numPoints; j++)
+ {
+ ComHelper::CreatePoint(&pnt);
+ pnt->put_GlobalCallback(_globalCallback);
+ fread(&x, sizeof(double), 1, _shpfile);
+ fread(&y, sizeof(double), 1, _shpfile);
+ pnt->put_X(x);
+ pnt->put_Y(y);
+ pointIndex = j;
+ shape->InsertPoint(pnt, &pointIndex, &retval);
+ if (retval == VARIANT_FALSE)
+ {
+ shape->Release();
+ return NULL;
+ }
+ pnt->Release();
+ }
+
+ fread(&bz, sizeof(double), 1, _shpfile);
+ fread(&bz, sizeof(double), 1, _shpfile);
+
for (int k = 0; k < numPoints; k++)
- {
- fread(&z, sizeof(double), 1, _shpfile);
- pointIndex = k;
- IPoint * pnt = NULL;
- shape->get_Point(pointIndex, &pnt);
- if (pnt == NULL)
- {
- shape->Release();
- return NULL;
- }
- pnt->put_Z(z);
- pnt->Release();
- }
-
- fread(&bm, sizeof(double), 1, _shpfile);
- fread(&bm, sizeof(double), 1, _shpfile);
-
- for (int mc = 0; mc < numPoints; mc++)
- {
- fread(&m, sizeof(double), 1, _shpfile);
- pointIndex = mc;
- IPoint * pnt = NULL;
- shape->get_Point(pointIndex, &pnt);
- if (pnt == NULL)
- {
- shape->Release();
- return NULL;
- }
- pnt->put_M(m);
- pnt->Release();
- }
- }
- }
-
- // ------------------------------------------------------
- // SHP_POLYGONM
- // ------------------------------------------------------
- else if (_shpfiletype == SHP_POLYGONM)
- {
- ComHelper::CreateShape(&shape);
- shape->Create(shpType, &vbretval);
- shape->put_GlobalCallback(_globalCallback);
- // if (shpType == SHP_POLYGONM)
- if (areEqualTypes)
- {
- VARIANT_BOOL retval;
- double bx, by, bm;
- int numParts;
- int numPoints;
- int part;
- double x, y, m;
-
- fread(&bx, sizeof(double), 1, _shpfile);
- fread(&by, sizeof(double), 1, _shpfile);
- fread(&bx, sizeof(double), 1, _shpfile);
- fread(&by, sizeof(double), 1, _shpfile);
-
- fread(&numParts, sizeof(int), 1, _shpfile);
- fread(&numPoints, sizeof(int), 1, _shpfile);
-
- long partIndex = 0;
- for (int i = 0; i < numParts; i++)
- {
- fread(&part, sizeof(int), 1, _shpfile);
- partIndex = i;
- shape->InsertPart(part, &partIndex, &retval);
- if (retval == VARIANT_FALSE)
- {
- shape->Release();
- return NULL;
- }
- }
-
- //Read the x, y part of the point
- long pointIndex = 0;
- for (int j = 0; j < numPoints; j++)
- {
- ComHelper::CreatePoint(&pnt);
- pnt->put_GlobalCallback(_globalCallback);
- fread(&x, sizeof(double), 1, _shpfile);
- fread(&y, sizeof(double), 1, _shpfile);
- pnt->put_X(x);
- pnt->put_Y(y);
- pointIndex = j;
- shape->InsertPoint(pnt, &pointIndex, &retval);
- if (retval == VARIANT_FALSE)
- {
- shape->Release();
- return NULL;
- }
- pnt->Release();
- }
-
- // M range
- fread(&bm, sizeof(double), 1, _shpfile);
- fread(&bm, sizeof(double), 1, _shpfile);
-
- for (int mc = 0; mc < numPoints; mc++)
- {
- fread(&m, sizeof(double), 1, _shpfile);
- pointIndex = mc;
- IPoint * pnt = NULL;
- shape->get_Point(pointIndex, &pnt);
- if (pnt == NULL)
- {
- shape->Release();
- return NULL;
- }
- pnt->put_M(m);
- pnt->Release();
- }
- }
- }
-#pragma endregion
-#pragma region Multipoint
- // ------------------------------------------------------
- // SHP_MULTIPOINT
- // ------------------------------------------------------
- else if (_shpfiletype == SHP_MULTIPOINT)
- {
- ComHelper::CreateShape(&shape);
- shape->Create(shpType, &vbretval);
- shape->put_GlobalCallback(_globalCallback);
-
- // if (shpType == SHP_MULTIPOINT)
- if (areEqualTypes)
- {
- VARIANT_BOOL retval;
- double bx, by;
- int numPoints;
- double x, y;
-
- fread(&bx, sizeof(double), 1, _shpfile);
- fread(&by, sizeof(double), 1, _shpfile);
- fread(&bx, sizeof(double), 1, _shpfile);
- fread(&by, sizeof(double), 1, _shpfile);
-
- fread(&numPoints, sizeof(int), 1, _shpfile);
-
- long pointIndex = 0;
- for (int j = 0; j < numPoints; j++)
- {
- ComHelper::CreatePoint(&pnt);
- pnt->put_GlobalCallback(_globalCallback);
- fread(&x, sizeof(double), 1, _shpfile);
- fread(&y, sizeof(double), 1, _shpfile);
- pnt->put_X(x);
- pnt->put_Y(y);
- pointIndex = j;
- shape->InsertPoint(pnt, &pointIndex, &retval);
- if (retval == VARIANT_FALSE)
- {
- shape->Release();
- return NULL;
- }
- pnt->Release();
- }
- }
- }
-
- // ------------------------------------------------------
- // SHP_MULTIPOINTZ
- // ------------------------------------------------------
- else if (_shpfiletype == SHP_MULTIPOINTZ)
- {
- ComHelper::CreateShape(&shape);
- shape->Create(shpType, &vbretval);
- shape->put_GlobalCallback(_globalCallback);
-
- // if (shpType == SHP_MULTIPOINTZ)
- if (areEqualTypes)
- {
- VARIANT_BOOL retval;
- double bx, by, bz, bm;
- int numPoints;
- double x, y, z, m;
-
- fread(&bx, sizeof(double), 1, _shpfile);
- fread(&by, sizeof(double), 1, _shpfile);
- fread(&bx, sizeof(double), 1, _shpfile);
- fread(&by, sizeof(double), 1, _shpfile);
-
- fread(&numPoints, sizeof(int), 1, _shpfile);
-
- long pointIndex = 0;
- for (int j = 0; j < numPoints; j++)
- {
- ComHelper::CreatePoint(&pnt);
- pnt->put_GlobalCallback(_globalCallback);
- fread(&x, sizeof(double), 1, _shpfile);
- fread(&y, sizeof(double), 1, _shpfile);
- pnt->put_X(x);
- pnt->put_Y(y);
- pointIndex = j;
- shape->InsertPoint(pnt, &pointIndex, &retval);
- if (retval == VARIANT_FALSE)
- {
- shape->Release();
- return NULL;
- }
- pnt->Release();
- }
-
- fread(&bz, sizeof(double), 1, _shpfile);
- fread(&bz, sizeof(double), 1, _shpfile);
-
- for (int k = 0; k < numPoints; k++)
- {
- fread(&z, sizeof(double), 1, _shpfile);
- pointIndex = k;
- IPoint * pnt = NULL;
- shape->get_Point(pointIndex, &pnt);
- if (pnt == NULL)
- {
- shape->Release();
- return NULL;
- }
- pnt->put_Z(z);
- pnt->Release();
- }
-
- fread(&bm, sizeof(double), 1, _shpfile);
- fread(&bm, sizeof(double), 1, _shpfile);
-
- for (int mc = 0; mc < numPoints; mc++)
- {
- fread(&m, sizeof(double), 1, _shpfile);
- pointIndex = mc;
- IPoint * pnt = NULL;
- shape->get_Point(pointIndex, &pnt);
- if (pnt == NULL)
- {
- shape->Release();
- return NULL;
- }
- pnt->put_M(m);
- pnt->Release();
- }
- }
- }
-
- // ------------------------------------------------------
- // SHP_MULTIPOINTM
- // ------------------------------------------------------
- else if (_shpfiletype == SHP_MULTIPOINTM)
- {
- ComHelper::CreateShape(&shape);
- shape->Create(shpType, &vbretval);
- shape->put_GlobalCallback(_globalCallback);
-
- // if (shpType == SHP_MULTIPOINTM)
- if (areEqualTypes)
- {
- VARIANT_BOOL retval;
- double bx, by, bm;
- int numPoints;
- double x, y, m;
-
- fread(&bx, sizeof(double), 1, _shpfile);
- fread(&by, sizeof(double), 1, _shpfile);
- fread(&bx, sizeof(double), 1, _shpfile);
- fread(&by, sizeof(double), 1, _shpfile);
-
- fread(&numPoints, sizeof(int), 1, _shpfile);
-
- long pointIndex = 0;
- for (int j = 0; j < numPoints; j++)
- {
- ComHelper::CreatePoint(&pnt);
- pnt->put_GlobalCallback(_globalCallback);
- fread(&x, sizeof(double), 1, _shpfile);
- fread(&y, sizeof(double), 1, _shpfile);
- pnt->put_X(x);
- pnt->put_Y(y);
- pointIndex = j;
- shape->InsertPoint(pnt, &pointIndex, &retval);
- if (retval == VARIANT_FALSE)
- {
- shape->Release();
- return NULL;
- }
- pnt->Release();
- }
-
- fread(&bm, sizeof(double), 1, _shpfile);
- fread(&bm, sizeof(double), 1, _shpfile);
-
- for (int mc = 0; mc < numPoints; mc++)
- {
- fread(&m, sizeof(double), 1, _shpfile);
- pointIndex = mc;
- IPoint * pnt = NULL;
- shape->get_Point(pointIndex, &pnt);
- if (pnt == NULL)
- {
- shape->Release();
- return NULL;
- }
- pnt->put_M(m);
- pnt->Release();
- }
- }
- }
-#pragma endregion
-
- return shape;
-}
-#pragma endregion
-
-#pragma region ShxReadingWriting
-
-// **************************************************************
-// ReadShx()
-// **************************************************************
-BOOL CShapefile::ReadShx()
-{
// guaranteed that .shx file is open
- rewind(_shxfile);
- _shpOffsets.clear();
-
- // file code
- int intbuf;
- fread(&intbuf,sizeof(int),1,_shxfile);
- ShapeUtility::SwapEndian((char*)&intbuf,sizeof(int));
- if( intbuf != FILE_CODE )
- return FALSE;
-
- // unused
- int unused = UNUSEDVAL;
- for(int i=0; i < UNUSEDSIZE; i++)
- {
- fread(&intbuf,sizeof(int),1,_shxfile);
- ShapeUtility::SwapEndian((char*)&intbuf,sizeof(int));
- if( intbuf != unused )
- return FALSE;
- }
-
- // file length (16 bit words)
- fread(&intbuf,sizeof(int),1,_shxfile);
- ShapeUtility::SwapEndian((char*)&intbuf,sizeof(int));
- int filelength = intbuf;
-
- // version
- fread(&intbuf,sizeof(int),1,_shxfile);
- if( intbuf != VERSION )
- return FALSE;
-
- // shapefile type
- fread(&intbuf,sizeof(int),1,_shxfile);
- _shpfiletype = (ShpfileType)intbuf;
-
- // bounds
- fread(&_minX,sizeof(double),1,_shxfile);
- fread(&_minY,sizeof(double),1,_shxfile);
- fread(&_maxX,sizeof(double),1,_shxfile);
- fread(&_maxY,sizeof(double),1,_shxfile);
- fread(&_minZ,sizeof(double),1,_shxfile);
- fread(&_maxZ,sizeof(double),1,_shxfile);
- fread(&_minM,sizeof(double),1,_shxfile);
- fread(&_maxM,sizeof(double),1,_shxfile);
-
- int readLength = HEADER_BYTES_16;
- while( readLength < filelength )
- {
- // offset
- fread(&intbuf,sizeof(int),1,_shxfile);
- ShapeUtility::SwapEndian((char*)&intbuf,sizeof(int));
- _shpOffsets.push_back(intbuf*2); // convert to (32 bit words)
-
- // content length
- fread(&intbuf,sizeof(int),1,_shxfile);
- ShapeUtility::SwapEndian((char*)&intbuf,sizeof(int));
- readLength += 4;
- }
-
- rewind(_shxfile);
- return TRUE;
-}
-
-// **************************************************************
-// AppendToShx()
-// **************************************************************
-bool CShapefile::AppendToShx(FILE* shx, IShape* shp, int offset)
-{
if (!shx || !shp) return false;
-
- _shpOffsets.push_back(offset);
-
- int success = fseek(shx, 0, SEEK_END);
-
- ShapeUtility::WriteBigEndian(shx, offset / 2);
-
- int contentLength = ShapeHelper::GetContentLength(shp);
- ShapeUtility::WriteBigEndian(shx, contentLength / 2);
-
- fflush(shx);
-
- return true;
-}
-
-// **************************************************************
-// WriteShx()
-// **************************************************************
-BOOL CShapefile::WriteShx(FILE * shx, ICallback * cBack)
-{
ICallback* callback = cBack ? cBack : _globalCallback;
-
- // guaranteed that .shx file is open
- rewind(shx);
-
- // FILE CODE
- ShapeUtility::WriteBigEndian(shx, FILE_CODE);
-
- // unused
- for(int j = 0; j < UNUSEDSIZE; j++)
- {
- ShapeUtility::WriteBigEndian(shx, UNUSEDVAL);
- }
-
- // FILELENGTH (16 bit words)
- int fileLength = HEADER_BYTES_16 + (int)_shapeData.size() * 4;
- ShapeUtility::WriteBigEndian(shx, fileLength);
-
- //VERSION
- int version = VERSION;
- fwrite(&version, sizeof(int),1,shx);
-
- //SHAPEFILE TYPE
- int tmpshapefiletype = (short)_shpfiletype;
- fwrite(&tmpshapefiletype, sizeof(int),1,shx);
-
- //BOUNDS
- WriteBounds(shx);
-
- int offset = HEADER_BYTES_32;
- long numPoints = 0;
- long numParts = 0;
- ShpfileType shptype;
- IShape * shape = NULL;
-
- long percent = 0, newpercent = 0;
-
- _shpOffsets.clear();
- int size = (int)_shapeData.size();
- for( int i = 0; i < size; i++)
- {
- // convert to (32 bit words)
- _shpOffsets.push_back(offset);
-
- ShapeUtility::WriteBigEndian(shx, offset / 2);
-
- get_Shape(i,&shape);
- shape->get_NumPoints(&numPoints);
- shape->get_NumParts(&numParts);
- shape->get_ShapeType(&shptype);
-
- int contentLength = ShapeUtility::get_ContentLength(shptype, numPoints, numParts);
-
- offset = offset + RECORD_HEADER_LENGTH_32 + contentLength;
-
- ShapeUtility::WriteBigEndian(shx, contentLength / 2);
-
- shape->Release();
-
- CallbackHelper::Progress(callback, i, size, "Writing .shx file", _key, percent);
- }
-
- CallbackHelper::ProgressCompleted(callback, _key);
-
- fflush(shx);
-
- return TRUE;
-}
-#pragma endregion
-
-#pragma region ShpReadingWriting
-
-// **************************************************************
-// GetWriteFileLength()
-// **************************************************************
-int CShapefile::GetWriteFileLength()
-{
IShape * sh = NULL;
- long numPoints = 0;
- long numParts = 0;
- long part = 0;
- ShpfileType shptype;
-
- int filelength = HEADER_BYTES_32;
-
- int size = (int)_shapeData.size();
- for (int i = 0; i < size; i++)
- {
- this->get_Shape(i, &sh);
- sh->get_NumPoints(&numPoints);
- sh->get_NumParts(&numParts);
- sh->get_ShapeType(&shptype);
-
- int contentLength = ShapeUtility::get_ContentLength(shptype, numPoints, numParts);
- filelength = filelength + RECORD_HEADER_LENGTH_32 + contentLength;
-
- sh->Release();
- }
- return filelength;
-}
-
-// **************************************************************
-// AppendToShpFile()
-// **************************************************************
-bool CShapefile::AppendToShpFile(FILE* shp, IShapeWrapper* wrapper)
-{
if (!shp || !wrapper) return false;
-
- int length = wrapper->get_ContentLength();
-
- // write record header
- ShapeUtility::WriteBigEndian(shp, _shapeData.size());
- ShapeUtility::WriteBigEndian(shp, length / 2);
-
- // write content
- wrapper->RefreshBounds();
- int* data = wrapper->get_RawData();
- if (data)
- {
- fseek(shp, 0, SEEK_END);
- size_t size = fwrite(data, sizeof(char), length, shp);
- fflush(shp);
-
- delete[] data;
-
- return true;
- }
-
- return false;
-}
-
-// **************************************************************
-// WriteShp()
-// **************************************************************
-void CShapefile::WriteBounds(FILE * shp)
-{
double ShapefileBounds[8];
- ShapefileBounds[0] = _minX;
- ShapefileBounds[1] = _minY;
- ShapefileBounds[2] = _maxX;
- ShapefileBounds[3] = _maxY;
- ShapefileBounds[4] = _minZ;
- ShapefileBounds[5] = _maxZ;
- ShapefileBounds[6] = _minM;
- ShapefileBounds[7] = _maxM;
- fwrite(ShapefileBounds, sizeof(double), 8, shp);
-}
-
-// **************************************************************
-// WriteShp()
-// **************************************************************
-BOOL CShapefile::WriteShp(FILE * shp, ICallback * cBack)
-{
// guaranteed that .shp file is open
- rewind(shp);
-
- //FILE_CODE
- ShapeUtility::WriteBigEndian(shp, FILE_CODE);
-
- //UNUSED
- for(int j = 0; j < UNUSEDSIZE; j++)
- {
- ShapeUtility::WriteBigEndian(shp, UNUSEDVAL);
- }
-
- //FILELENGTH (32 bit words)
- int fileLength = GetWriteFileLength();
- ShapeUtility::WriteBigEndian(shp, fileLength / 2);
-
- //VERSION
- int version = VERSION;
- fwrite(&version, sizeof(int),1,shp);
-
- //SHAPEFILE TYPE
- int tmpshapefiletype = (short)_shpfiletype;
- fwrite(&tmpshapefiletype, sizeof(int),1,shp);
-
- //BOUNDS
- WriteBounds(shp);
-
- long percent = 0, newpercent = 0;
-
- ICallback* callback = _globalCallback ? _globalCallback : cBack;
-
- long numPoints = 0;
- long numParts = 0;
- long part = 0;
- IShape * sh = NULL;
-
- int size = _shapeData.size();
-
- for( int k = 0; k < size; k++)
- {
- get_Shape(k,&sh);
- CShape* shape = (CShape*)sh;
-
- IShapeWrapper* wrapper = shape->get_ShapeWrapper();
- int length = wrapper->get_ContentLength();
-
- //Write the Record Header
- ShapeUtility::WriteBigEndian(shp, k + 1);
- ShapeUtility::WriteBigEndian(shp, length / 2);
-
- if ( _fastMode && _isEditingShapes)
- {
- wrapper->RefreshBounds();
- int* data = wrapper->get_RawData();
- fwrite(data, sizeof(char), length, shp);
- delete[] data;
- }
- else
- {
- // disk based mode
- // disk-based + fast data (probably a bit faster procedure can be devised)
- // in-memory mode (COM points)
- ShpfileType shptype = wrapper->get_ShapeType();
- ShpfileType shptype2D = wrapper->get_ShapeType2D();
- numPoints = wrapper->get_PointCount();
- numParts = wrapper->get_PartCount();
-
- //Write the Record
- if( shptype2D == SHP_NULLSHAPE )
- {
- int ishptype = shptype;
- fwrite(&shptype, sizeof(int), 1, shp);
- }
- else if( shptype2D == SHP_POINT )
- {
- int ishptype = shptype;
- fwrite(&ishptype,sizeof(int),1,shp);
- switch (shptype)
- {
- case SHP_POINT:
- ShapeUtility::WritePointXY(wrapper, 0, shp);
- break;
- case SHP_POINTZ:
- ShapeUtility::WritePointXYZ(wrapper, 0, shp);
- break;
- case SHP_POINTM:
- ShapeUtility::WritePointXYM(wrapper, 0, shp);
- break;
- }
- }
- else if( shptype2D == SHP_POLYLINE || shptype2D == SHP_POLYGON || shptype2D == SHP_MULTIPOINT )
- {
- int ishptype = shptype;
- fwrite(&ishptype,sizeof(int),1,shp);
-
- ShapeUtility::WriteExtentsXY(wrapper, shp);
-
- if (shptype2D != SHP_MULTIPOINT) // parts should be written for both polylines and polygons
- fwrite(&numParts,sizeof(int),1,shp);
-
- fwrite(&numPoints,sizeof(int),1,shp);
-
- if (shptype2D != SHP_MULTIPOINT) // parts should be written for both polylines and polygons
- {
- for( int p = 0; p < numParts; p++ )
- {
- shape->get_Part(p,&part);
- fwrite(&part,sizeof(int),1,shp);
- }
- }
-
- // xy
- for (int i = 0; i < numPoints; i++) {
- ShapeUtility::WritePointXY(wrapper, i, shp);
- }
-
- // z
- if (shptype == SHP_POLYLINEZ || shptype == SHP_POLYGONZ || shptype == SHP_MULTIPOINTZ)
- {
- ShapeUtility::WriteExtentsZ(wrapper, shp);
-
- for (int i = 0; i < numPoints; i++) {
- ShapeUtility::WritePointZ(wrapper, i, shp);
- }
- }
-
- // m
- if (shptype != SHP_POLYLINE && shptype != SHP_POLYGON && shptype != SHP_MULTIPOINT) // writing for both M and Z
- {
- ShapeUtility::WriteExtentsM(wrapper, shp);
-
- for (int i = 0; i < numPoints; i++) {
- ShapeUtility::WritePointM(wrapper, i, shp);
- }
- }
- }
- }
-
- shape->Release();
-
- CallbackHelper::Progress(callback, k, size, "Writing .shp file", _key, percent);
- }
-
- CallbackHelper::ProgressCompleted(callback, _key);
-
- fflush(shp);
- return TRUE;
-}
-#pragma endregion
+ {
+ fread(&z, sizeof(double), 1, _shpfile);
+ pointIndex = k;
+ IPoint * pnt = NULL;
+ shape->get_Point(pointIndex, &pnt);
+ if (pnt == NULL)
+ {
+ shape->Release();
+ return NULL;
+ }
+ pnt->put_Z(z);
+ pnt->Release();
+ }
+
+ fread(&bm, sizeof(double), 1, _shpfile);
+ fread(&bm, sizeof(double), 1, _shpfile);
+
+ for (int mc = 0; mc < numPoints; mc++)
+ {
+ fread(&m, sizeof(double), 1, _shpfile);
+ pointIndex = mc;
+ IPoint * pnt = NULL;
+ shape->get_Point(pointIndex, &pnt);
+ if (pnt == NULL)
+ {
+ shape->Release();
+ return NULL;
+ }
+ pnt->put_M(m);
+ //Rob Cairns 20-Dec-05
+ pnt->Release();
+ }
+ }
+ }
+
+ // ------------------------------------------------------
+ // SHP_POLYLINEM
+ // ------------------------------------------------------
+ else if (_shpfiletype == SHP_POLYLINEM)
+ {
+ ComHelper::CreateShape(&shape);
+ shape->Create(shpType, &vbretval);
+ shape->put_GlobalCallback(_globalCallback);
+
+ // if (shpType == SHP_POLYLINEM)
+ if (areEqualTypes)
+ {
+ VARIANT_BOOL retval;
+ double bx, by, bm;
+ int numParts;
+ int numPoints;
+ int part;
+ double x, y, m;
+
+ fread(&bx, sizeof(double), 1, _shpfile);
+ fread(&by, sizeof(double), 1, _shpfile);
+ fread(&bx, sizeof(double), 1, _shpfile);
+ fread(&by, sizeof(double), 1, _shpfile);
+
+ fread(&numParts, sizeof(int), 1, _shpfile);
+ fread(&numPoints, sizeof(int), 1, _shpfile);
+
+ long partIndex = 0;
+ for (int i = 0; i < numParts; i++)
+ {
+ fread(&part, sizeof(int), 1, _shpfile);
+ partIndex = i;
+ shape->InsertPart(part, &partIndex, &retval);
+ if (retval == VARIANT_FALSE)
+ {
+ shape->Release();
+ return NULL;
+ }
+ }
+
+ long pointIndex = 0;
+ //Read the x, y part of the point
+ for (int j = 0; j < numPoints; j++)
+ {
+ ComHelper::CreatePoint(&pnt);
+ pnt->put_GlobalCallback(_globalCallback);
+ fread(&x, sizeof(double), 1, _shpfile);
+ fread(&y, sizeof(double), 1, _shpfile);
+ pnt->put_X(x);
+ pnt->put_Y(y);
+ pointIndex = j;
+ shape->InsertPoint(pnt, &pointIndex, &retval);
+ if (retval == VARIANT_FALSE)
+ {
+ shape->Release();
+ return NULL;
+ }
+ pnt->Release();
+ }
+
+ fread(&bm, sizeof(double), 1, _shpfile);
+ fread(&bm, sizeof(double), 1, _shpfile);
+
+ for (int mc = 0; mc < numPoints; mc++)
+ {
+ fread(&m, sizeof(double), 1, _shpfile);
+ pointIndex = mc;
+ IPoint * pnt = NULL;
+ shape->get_Point(pointIndex, &pnt);
+ if (pnt == NULL)
+ {
+ shape->Release();
+ return NULL;
+ }
+ pnt->put_M(m);
+ pnt->Release();
+
+ }
+ }
+ }
+#pragma endregion
+#pragma region Polygon
+ // ------------------------------------------------------
+ // SHP_POLYGON
+ // ------------------------------------------------------
+ else if (_shpfiletype == SHP_POLYGON)
+ {
+ ComHelper::CreateShape(&shape);
+ shape->Create(shpType, &vbretval);
+ shape->put_GlobalCallback(_globalCallback);
+
+ // if (shpType == SHP_POLYGON)
+ if (areEqualTypes)
+ {
+ VARIANT_BOOL retval;
+ double bx, by;
+ int numParts;
+ int numPoints;
+ int part;
+ double x, y;
+
+ fread(&bx, sizeof(double), 1, _shpfile);
+ fread(&by, sizeof(double), 1, _shpfile);
+ fread(&bx, sizeof(double), 1, _shpfile);
+ fread(&by, sizeof(double), 1, _shpfile);
+
+ fread(&numParts, sizeof(int), 1, _shpfile);
+ fread(&numPoints, sizeof(int), 1, _shpfile);
+
+ long partIndex = 0;
+ for (int i = 0; i < numParts; i++)
+ {
+ fread(&part, sizeof(int), 1, _shpfile);
+ partIndex = i;
+ shape->InsertPart(part, &partIndex, &retval);
+ if (retval == VARIANT_FALSE)
+ {
+ shape->Release();
+ return NULL;
+ }
+ }
+
+ long pointIndex = 0;
+ for (int j = 0; j < numPoints; j++)
+ {
+ ComHelper::CreatePoint(&pnt);
+ pnt->put_GlobalCallback(_globalCallback);
+ fread(&x, sizeof(double), 1, _shpfile);
+ fread(&y, sizeof(double), 1, _shpfile);
+ pnt->put_X(x);
+ pnt->put_Y(y);
+ pointIndex = j;
+ shape->InsertPoint(pnt, &pointIndex, &retval);
+ if (retval == VARIANT_FALSE)
+ {
+ shape->Release();
+ return NULL;
+ }
+ pnt->Release();
+ }
+ }
+ }
+
+ // ------------------------------------------------------
+ // SHP_POLYGONZ
+ // ------------------------------------------------------
+ else if (_shpfiletype == SHP_POLYGONZ)
+ {
+ ComHelper::CreateShape(&shape);
+ shape->Create(shpType, &vbretval);
+ shape->put_GlobalCallback(_globalCallback);
+ // if (shpType == SHP_POLYGONZ)
+ if (areEqualTypes)
+ {
+ VARIANT_BOOL retval;
+ double bx, by, bz, bm;
+ int numParts;
+ int numPoints;
+ int part;
+ double x, y, z, m;
+
+ fread(&bx, sizeof(double), 1, _shpfile);
+ fread(&by, sizeof(double), 1, _shpfile);
+ fread(&bx, sizeof(double), 1, _shpfile);
+ fread(&by, sizeof(double), 1, _shpfile);
+
+ fread(&numParts, sizeof(int), 1, _shpfile);
+ fread(&numPoints, sizeof(int), 1, _shpfile);
+
+ long partIndex = 0;
+ for (int i = 0; i < numParts; i++)
+ {
+ fread(&part, sizeof(int), 1, _shpfile);
+ partIndex = i;
+ shape->InsertPart(part, &partIndex, &retval);
+ if (retval == VARIANT_FALSE)
+ {
+ shape->Release();
+ return NULL;
+ }
+ }
+
+ //Read the x, y part of the point
+ long pointIndex = 0;
+ for (int j = 0; j < numPoints; j++)
+ {
+ ComHelper::CreatePoint(&pnt);
+ pnt->put_GlobalCallback(_globalCallback);
+ fread(&x, sizeof(double), 1, _shpfile);
+ fread(&y, sizeof(double), 1, _shpfile);
+ pnt->put_X(x);
+ pnt->put_Y(y);
+ pointIndex = j;
+ shape->InsertPoint(pnt, &pointIndex, &retval);
+ if (retval == VARIANT_FALSE)
+ {
+ shape->Release();
+ return NULL;
+ }
+ pnt->Release();
+ }
+
+ fread(&bz, sizeof(double), 1, _shpfile);
+ fread(&bz, sizeof(double), 1, _shpfile);
+
+ for (int k = 0; k < numPoints; k++)
+ {
+ fread(&z, sizeof(double), 1, _shpfile);
+ pointIndex = k;
+ IPoint * pnt = NULL;
+ shape->get_Point(pointIndex, &pnt);
+ if (pnt == NULL)
+ {
+ shape->Release();
+ return NULL;
+ }
+ pnt->put_Z(z);
+ pnt->Release();
+ }
+
+ fread(&bm, sizeof(double), 1, _shpfile);
+ fread(&bm, sizeof(double), 1, _shpfile);
+
+ for (int mc = 0; mc < numPoints; mc++)
+ {
+ fread(&m, sizeof(double), 1, _shpfile);
+ pointIndex = mc;
+ IPoint * pnt = NULL;
+ shape->get_Point(pointIndex, &pnt);
+ if (pnt == NULL)
+ {
+ shape->Release();
+ return NULL;
+ }
+ pnt->put_M(m);
+ pnt->Release();
+ }
+ }
+ }
+
+ // ------------------------------------------------------
+ // SHP_POLYGONM
+ // ------------------------------------------------------
+ else if (_shpfiletype == SHP_POLYGONM)
+ {
+ ComHelper::CreateShape(&shape);
+ shape->Create(shpType, &vbretval);
+ shape->put_GlobalCallback(_globalCallback);
+ // if (shpType == SHP_POLYGONM)
+ if (areEqualTypes)
+ {
+ VARIANT_BOOL retval;
+ double bx, by, bm;
+ int numParts;
+ int numPoints;
+ int part;
+ double x, y, m;
+
+ fread(&bx, sizeof(double), 1, _shpfile);
+ fread(&by, sizeof(double), 1, _shpfile);
+ fread(&bx, sizeof(double), 1, _shpfile);
+ fread(&by, sizeof(double), 1, _shpfile);
+
+ fread(&numParts, sizeof(int), 1, _shpfile);
+ fread(&numPoints, sizeof(int), 1, _shpfile);
+
+ long partIndex = 0;
+ for (int i = 0; i < numParts; i++)
+ {
+ fread(&part, sizeof(int), 1, _shpfile);
+ partIndex = i;
+ shape->InsertPart(part, &partIndex, &retval);
+ if (retval == VARIANT_FALSE)
+ {
+ shape->Release();
+ return NULL;
+ }
+ }
+
+ //Read the x, y part of the point
+ long pointIndex = 0;
+ for (int j = 0; j < numPoints; j++)
+ {
+ ComHelper::CreatePoint(&pnt);
+ pnt->put_GlobalCallback(_globalCallback);
+ fread(&x, sizeof(double), 1, _shpfile);
+ fread(&y, sizeof(double), 1, _shpfile);
+ pnt->put_X(x);
+ pnt->put_Y(y);
+ pointIndex = j;
+ shape->InsertPoint(pnt, &pointIndex, &retval);
+ if (retval == VARIANT_FALSE)
+ {
+ shape->Release();
+ return NULL;
+ }
+ pnt->Release();
+ }
+
+ // M range
+ fread(&bm, sizeof(double), 1, _shpfile);
+ fread(&bm, sizeof(double), 1, _shpfile);
+
+ for (int mc = 0; mc < numPoints; mc++)
+ {
+ fread(&m, sizeof(double), 1, _shpfile);
+ pointIndex = mc;
+ IPoint * pnt = NULL;
+ shape->get_Point(pointIndex, &pnt);
+ if (pnt == NULL)
+ {
+ shape->Release();
+ return NULL;
+ }
+ pnt->put_M(m);
+ pnt->Release();
+ }
+ }
+ }
+#pragma endregion
+#pragma region Multipoint
+ // ------------------------------------------------------
+ // SHP_MULTIPOINT
+ // ------------------------------------------------------
+ else if (_shpfiletype == SHP_MULTIPOINT)
+ {
+ ComHelper::CreateShape(&shape);
+ shape->Create(shpType, &vbretval);
+ shape->put_GlobalCallback(_globalCallback);
+
+ // if (shpType == SHP_MULTIPOINT)
+ if (areEqualTypes)
+ {
+ VARIANT_BOOL retval;
+ double bx, by;
+ int numPoints;
+ double x, y;
+
+ fread(&bx, sizeof(double), 1, _shpfile);
+ fread(&by, sizeof(double), 1, _shpfile);
+ fread(&bx, sizeof(double), 1, _shpfile);
+ fread(&by, sizeof(double), 1, _shpfile);
+
+ fread(&numPoints, sizeof(int), 1, _shpfile);
+
+ long pointIndex = 0;
+ for (int j = 0; j < numPoints; j++)
+ {
+ ComHelper::CreatePoint(&pnt);
+ pnt->put_GlobalCallback(_globalCallback);
+ fread(&x, sizeof(double), 1, _shpfile);
+ fread(&y, sizeof(double), 1, _shpfile);
+ pnt->put_X(x);
+ pnt->put_Y(y);
+ pointIndex = j;
+ shape->InsertPoint(pnt, &pointIndex, &retval);
+ if (retval == VARIANT_FALSE)
+ {
+ shape->Release();
+ return NULL;
+ }
+ pnt->Release();
+ }
+ }
+ }
+
+ // ------------------------------------------------------
+ // SHP_MULTIPOINTZ
+ // ------------------------------------------------------
+ else if (_shpfiletype == SHP_MULTIPOINTZ)
+ {
+ ComHelper::CreateShape(&shape);
+ shape->Create(shpType, &vbretval);
+ shape->put_GlobalCallback(_globalCallback);
+
+ // if (shpType == SHP_MULTIPOINTZ)
+ if (areEqualTypes)
+ {
+ VARIANT_BOOL retval;
+ double bx, by, bz, bm;
+ int numPoints;
+ double x, y, z, m;
+
+ fread(&bx, sizeof(double), 1, _shpfile);
+ fread(&by, sizeof(double), 1, _shpfile);
+ fread(&bx, sizeof(double), 1, _shpfile);
+ fread(&by, sizeof(double), 1, _shpfile);
+
+ fread(&numPoints, sizeof(int), 1, _shpfile);
+
+ long pointIndex = 0;
+ for (int j = 0; j < numPoints; j++)
+ {
+ ComHelper::CreatePoint(&pnt);
+ pnt->put_GlobalCallback(_globalCallback);
+ fread(&x, sizeof(double), 1, _shpfile);
+ fread(&y, sizeof(double), 1, _shpfile);
+ pnt->put_X(x);
+ pnt->put_Y(y);
+ pointIndex = j;
+ shape->InsertPoint(pnt, &pointIndex, &retval);
+ if (retval == VARIANT_FALSE)
+ {
+ shape->Release();
+ return NULL;
+ }
+ pnt->Release();
+ }
+
+ fread(&bz, sizeof(double), 1, _shpfile);
+ fread(&bz, sizeof(double), 1, _shpfile);
+
+ for (int k = 0; k < numPoints; k++)
+ {
+ fread(&z, sizeof(double), 1, _shpfile);
+ pointIndex = k;
+ IPoint * pnt = NULL;
+ shape->get_Point(pointIndex, &pnt);
+ if (pnt == NULL)
+ {
+ shape->Release();
+ return NULL;
+ }
+ pnt->put_Z(z);
+ pnt->Release();
+ }
+
+ fread(&bm, sizeof(double), 1, _shpfile);
+ fread(&bm, sizeof(double), 1, _shpfile);
+
+ for (int mc = 0; mc < numPoints; mc++)
+ {
+ fread(&m, sizeof(double), 1, _shpfile);
+ pointIndex = mc;
+ IPoint * pnt = NULL;
+ shape->get_Point(pointIndex, &pnt);
+ if (pnt == NULL)
+ {
+ shape->Release();
+ return NULL;
+ }
+ pnt->put_M(m);
+ pnt->Release();
+ }
+ }
+ }
+
+ // ------------------------------------------------------
+ // SHP_MULTIPOINTM
+ // ------------------------------------------------------
+ else if (_shpfiletype == SHP_MULTIPOINTM)
+ {
+ ComHelper::CreateShape(&shape);
+ shape->Create(shpType, &vbretval);
+ shape->put_GlobalCallback(_globalCallback);
+
+ // if (shpType == SHP_MULTIPOINTM)
+ if (areEqualTypes)
+ {
+ VARIANT_BOOL retval;
+ double bx, by, bm;
+ int numPoints;
+ double x, y, m;
+
+ fread(&bx, sizeof(double), 1, _shpfile);
+ fread(&by, sizeof(double), 1, _shpfile);
+ fread(&bx, sizeof(double), 1, _shpfile);
+ fread(&by, sizeof(double), 1, _shpfile);
+
+ fread(&numPoints, sizeof(int), 1, _shpfile);
+
+ long pointIndex = 0;
+ for (int j = 0; j < numPoints; j++)
+ {
+ ComHelper::CreatePoint(&pnt);
+ pnt->put_GlobalCallback(_globalCallback);
+ fread(&x, sizeof(double), 1, _shpfile);
+ fread(&y, sizeof(double), 1, _shpfile);
+ pnt->put_X(x);
+ pnt->put_Y(y);
+ pointIndex = j;
+ shape->InsertPoint(pnt, &pointIndex, &retval);
+ if (retval == VARIANT_FALSE)
+ {
+ shape->Release();
+ return NULL;
+ }
+ pnt->Release();
+ }
+
+ fread(&bm, sizeof(double), 1, _shpfile);
+ fread(&bm, sizeof(double), 1, _shpfile);
+
+ for (int mc = 0; mc < numPoints; mc++)
+ {
+ fread(&m, sizeof(double), 1, _shpfile);
+ pointIndex = mc;
+ IPoint * pnt = NULL;
+ shape->get_Point(pointIndex, &pnt);
+ if (pnt == NULL)
+ {
+ shape->Release();
+ return NULL;
+ }
+ pnt->put_M(m);
+ pnt->Release();
+ }
+ }
+ }
+#pragma endregion
+
+ return shape;
+}
+#pragma endregion
+
+#pragma region ShxReadingWriting
+
+// **************************************************************
+// ReadShx()
+// **************************************************************
+BOOL CShapefile::ReadShx()
+{
+ // guaranteed that .shx file is open
+ rewind(_shxfile);
+ _shpOffsets.clear();
+
+ // file code
+ int intbuf;
+ fread(&intbuf,sizeof(int),1,_shxfile);
+ ShapeUtility::SwapEndian((char*)&intbuf,sizeof(int));
+ if( intbuf != FILE_CODE )
+ return FALSE;
+
+ // unused
+ int unused = UNUSEDVAL;
+ for(int i=0; i < UNUSEDSIZE; i++)
+ {
+ fread(&intbuf,sizeof(int),1,_shxfile);
+ ShapeUtility::SwapEndian((char*)&intbuf,sizeof(int));
+ if( intbuf != unused )
+ return FALSE;
+ }
+
+ // file length (16 bit words)
+ fread(&intbuf,sizeof(int),1,_shxfile);
+ ShapeUtility::SwapEndian((char*)&intbuf,sizeof(int));
+ int filelength = intbuf;
+
+ // version
+ fread(&intbuf,sizeof(int),1,_shxfile);
+ if( intbuf != VERSION )
+ return FALSE;
+
+ // shapefile type
+ fread(&intbuf,sizeof(int),1,_shxfile);
+ _shpfiletype = (ShpfileType)intbuf;
+
+ // bounds
+ fread(&_minX,sizeof(double),1,_shxfile);
+ fread(&_minY,sizeof(double),1,_shxfile);
+ fread(&_maxX,sizeof(double),1,_shxfile);
+ fread(&_maxY,sizeof(double),1,_shxfile);
+ fread(&_minZ,sizeof(double),1,_shxfile);
+ fread(&_maxZ,sizeof(double),1,_shxfile);
+ fread(&_minM,sizeof(double),1,_shxfile);
+ fread(&_maxM,sizeof(double),1,_shxfile);
+
+ int readLength = HEADER_BYTES_16;
+ while( readLength < filelength )
+ {
+ // offset
+ fread(&intbuf,sizeof(int),1,_shxfile);
+ ShapeUtility::SwapEndian((char*)&intbuf,sizeof(int));
+ _shpOffsets.push_back(intbuf*2); // convert to (32 bit words)
+
+ // content length
+ fread(&intbuf,sizeof(int),1,_shxfile);
+ ShapeUtility::SwapEndian((char*)&intbuf,sizeof(int));
+ readLength += 4;
+ }
+
+ rewind(_shxfile);
+ return TRUE;
+}
+
+// **************************************************************
+// AppendToShx()
+// **************************************************************
+bool CShapefile::AppendToShx(FILE* shx, IShape* shp, int offset)
+{
+ if (!shx || !shp) return false;
+
+ _shpOffsets.push_back(offset);
+
+ int success = fseek(shx, 0, SEEK_END);
+
+ ShapeUtility::WriteBigEndian(shx, offset / 2);
+
+ int contentLength = ShapeHelper::GetContentLength(shp);
+ ShapeUtility::WriteBigEndian(shx, contentLength / 2);
+
+ fflush(shx);
+
+ return true;
+}
+
+// **************************************************************
+// WriteShx()
+// **************************************************************
+BOOL CShapefile::WriteShx(FILE * shx, ICallback * cBack)
+{
+ ICallback* callback = cBack ? cBack : _globalCallback;
+
+ // guaranteed that .shx file is open
+ rewind(shx);
+
+ // FILE CODE
+ ShapeUtility::WriteBigEndian(shx, FILE_CODE);
+
+ // unused
+ for(int j = 0; j < UNUSEDSIZE; j++)
+ {
+ ShapeUtility::WriteBigEndian(shx, UNUSEDVAL);
+ }
+
+ // FILELENGTH (16 bit words)
+ int fileLength = HEADER_BYTES_16 + (int)_shapeData.size() * 4;
+ ShapeUtility::WriteBigEndian(shx, fileLength);
+
+ //VERSION
+ int version = VERSION;
+ fwrite(&version, sizeof(int),1,shx);
+
+ //SHAPEFILE TYPE
+ int tmpshapefiletype = (short)_shpfiletype;
+ fwrite(&tmpshapefiletype, sizeof(int),1,shx);
+
+ //BOUNDS
+ WriteBounds(shx);
+
+ int offset = HEADER_BYTES_32;
+ long numPoints = 0;
+ long numParts = 0;
+ ShpfileType shptype;
+ IShape * shape = NULL;
+
+ long percent = 0, newpercent = 0;
+
+ _shpOffsets.clear();
+ int size = (int)_shapeData.size();
+ for( int i = 0; i < size; i++)
+ {
+ // convert to (32 bit words)
+ _shpOffsets.push_back(offset);
+
+ ShapeUtility::WriteBigEndian(shx, offset / 2);
+
+ get_Shape(i,&shape);
+ shape->get_NumPoints(&numPoints);
+ shape->get_NumParts(&numParts);
+ shape->get_ShapeType(&shptype);
+
+ int contentLength = ShapeUtility::get_ContentLength(shptype, numPoints, numParts);
+
+ offset = offset + RECORD_HEADER_LENGTH_32 + contentLength;
+
+ ShapeUtility::WriteBigEndian(shx, contentLength / 2);
+
+ shape->Release();
+
+ long percent = static_cast(static_cast(i + 1) / size * 100);
+
+ if (percent % 10 == 0)
+ CallbackHelper::Progress(callback, i, size, "Writing .shx file", _key, percent);
+ }
+
+ CallbackHelper::ProgressCompleted(callback, _key);
+
+ fflush(shx);
+
+ return TRUE;
+}
+#pragma endregion
+
+#pragma region ShpReadingWriting
+
+// **************************************************************
+// GetWriteFileLength()
+// **************************************************************
+int CShapefile::GetWriteFileLength()
+{
+ IShape * sh = NULL;
+ long numPoints = 0;
+ long numParts = 0;
+ long part = 0;
+ ShpfileType shptype;
+
+ int filelength = HEADER_BYTES_32;
+
+ int size = (int)_shapeData.size();
+ for (int i = 0; i < size; i++)
+ {
+ this->get_Shape(i, &sh);
+ sh->get_NumPoints(&numPoints);
+ sh->get_NumParts(&numParts);
+ sh->get_ShapeType(&shptype);
+
+ int contentLength = ShapeUtility::get_ContentLength(shptype, numPoints, numParts);
+ filelength = filelength + RECORD_HEADER_LENGTH_32 + contentLength;
+
+ sh->Release();
+ }
+ return filelength;
+}
+
+// **************************************************************
+// AppendToShpFile()
+// **************************************************************
+bool CShapefile::AppendToShpFile(FILE* shp, IShapeWrapper* wrapper)
+{
+ if (!shp || !wrapper) return false;
+
+ int length = wrapper->get_ContentLength();
+
+ // write record header
+ ShapeUtility::WriteBigEndian(shp, _shapeData.size());
+ ShapeUtility::WriteBigEndian(shp, length / 2);
+
+ // write content
+ wrapper->RefreshBounds();
+ int* data = wrapper->get_RawData();
+ if (data)
+ {
+ fseek(shp, 0, SEEK_END);
+ size_t size = fwrite(data, sizeof(char), length, shp);
+ fflush(shp);
+
+ delete[] data;
+
+ return true;
+ }
+
+ return false;
+}
+
+// **************************************************************
+// WriteShp()
+// **************************************************************
+void CShapefile::WriteBounds(FILE * shp)
+{
+ double ShapefileBounds[8];
+ ShapefileBounds[0] = _minX;
+ ShapefileBounds[1] = _minY;
+ ShapefileBounds[2] = _maxX;
+ ShapefileBounds[3] = _maxY;
+ ShapefileBounds[4] = _minZ;
+ ShapefileBounds[5] = _maxZ;
+ ShapefileBounds[6] = _minM;
+ ShapefileBounds[7] = _maxM;
+ fwrite(ShapefileBounds, sizeof(double), 8, shp);
+}
+
+// **************************************************************
+// WriteShp()
+// **************************************************************
+BOOL CShapefile::WriteShp(FILE * shp, ICallback * cBack)
+{
+ // guaranteed that .shp file is open
+ rewind(shp);
+
+ //FILE_CODE
+ ShapeUtility::WriteBigEndian(shp, FILE_CODE);
+
+ //UNUSED
+ for(int j = 0; j < UNUSEDSIZE; j++)
+ {
+ ShapeUtility::WriteBigEndian(shp, UNUSEDVAL);
+ }
+
+ //FILELENGTH (32 bit words)
+ int fileLength = GetWriteFileLength();
+ ShapeUtility::WriteBigEndian(shp, fileLength / 2);
+
+ //VERSION
+ int version = VERSION;
+ fwrite(&version, sizeof(int),1,shp);
+
+ //SHAPEFILE TYPE
+ int tmpshapefiletype = (short)_shpfiletype;
+ fwrite(&tmpshapefiletype, sizeof(int),1,shp);
+
+ //BOUNDS
+ WriteBounds(shp);
+
+ long percent = 0, newpercent = 0;
+
+ ICallback* callback = _globalCallback ? _globalCallback : cBack;
+
+ long numPoints = 0;
+ long numParts = 0;
+ long part = 0;
+ IShape * sh = NULL;
+
+ int size = _shapeData.size();
+
+ for( int k = 0; k < size; k++)
+ {
+ get_Shape(k,&sh);
+ CShape* shape = (CShape*)sh;
+
+ IShapeWrapper* wrapper = shape->get_ShapeWrapper();
+ int length = wrapper->get_ContentLength();
+
+ //Write the Record Header
+ ShapeUtility::WriteBigEndian(shp, k + 1);
+ ShapeUtility::WriteBigEndian(shp, length / 2);
+
+ if ( _fastMode && _isEditingShapes)
+ {
+ wrapper->RefreshBounds();
+ int* data = wrapper->get_RawData();
+ fwrite(data, sizeof(char), length, shp);
+ delete[] data;
+ }
+ else
+ {
+ // disk based mode
+ // disk-based + fast data (probably a bit faster procedure can be devised)
+ // in-memory mode (COM points)
+ ShpfileType shptype = wrapper->get_ShapeType();
+ ShpfileType shptype2D = wrapper->get_ShapeType2D();
+ numPoints = wrapper->get_PointCount();
+ numParts = wrapper->get_PartCount();
+
+ //Write the Record
+ if( shptype2D == SHP_NULLSHAPE )
+ {
+ int ishptype = shptype;
+ fwrite(&shptype, sizeof(int), 1, shp);
+ }
+ else if( shptype2D == SHP_POINT )
+ {
+ int ishptype = shptype;
+ fwrite(&ishptype,sizeof(int),1,shp);
+ switch (shptype)
+ {
+ case SHP_POINT:
+ ShapeUtility::WritePointXY(wrapper, 0, shp);
+ break;
+ case SHP_POINTZ:
+ ShapeUtility::WritePointXYZ(wrapper, 0, shp);
+ break;
+ case SHP_POINTM:
+ ShapeUtility::WritePointXYM(wrapper, 0, shp);
+ break;
+ }
+ }
+ else if( shptype2D == SHP_POLYLINE || shptype2D == SHP_POLYGON || shptype2D == SHP_MULTIPOINT )
+ {
+ int ishptype = shptype;
+ fwrite(&ishptype,sizeof(int),1,shp);
+
+ ShapeUtility::WriteExtentsXY(wrapper, shp);
+
+ if (shptype2D != SHP_MULTIPOINT) // parts should be written for both polylines and polygons
+ fwrite(&numParts,sizeof(int),1,shp);
+
+ fwrite(&numPoints,sizeof(int),1,shp);
+
+ if (shptype2D != SHP_MULTIPOINT) // parts should be written for both polylines and polygons
+ {
+ for( int p = 0; p < numParts; p++ )
+ {
+ shape->get_Part(p,&part);
+ fwrite(&part,sizeof(int),1,shp);
+ }
+ }
+
+ // xy
+ for (int i = 0; i < numPoints; i++) {
+ ShapeUtility::WritePointXY(wrapper, i, shp);
+ }
+
+ // z
+ if (shptype == SHP_POLYLINEZ || shptype == SHP_POLYGONZ || shptype == SHP_MULTIPOINTZ)
+ {
+ ShapeUtility::WriteExtentsZ(wrapper, shp);
+
+ for (int i = 0; i < numPoints; i++) {
+ ShapeUtility::WritePointZ(wrapper, i, shp);
+ }
+ }
+
+ // m
+ if (shptype != SHP_POLYLINE && shptype != SHP_POLYGON && shptype != SHP_MULTIPOINT) // writing for both M and Z
+ {
+ ShapeUtility::WriteExtentsM(wrapper, shp);
+
+ for (int i = 0; i < numPoints; i++) {
+ ShapeUtility::WritePointM(wrapper, i, shp);
+ }
+ }
+ }
+ }
+
+ shape->Release();
+
+ CallbackHelper::Progress(callback, k, size, "Writing .shp file", _key, percent);
+ }
+
+ CallbackHelper::ProgressCompleted(callback, _key);
+
+ fflush(shp);
+ return TRUE;
+}
+#pragma endregion
diff --git a/src/COM classes/Shapefile_Selection.cpp b/src/COM classes/Shapefile_Selection.cpp
index 15fbf084..382438e2 100644
--- a/src/COM classes/Shapefile_Selection.cpp
+++ b/src/COM classes/Shapefile_Selection.cpp
@@ -80,7 +80,14 @@ bool CShapefile::SelectShapesCore(Extent& extents, const double tolerance, const
// build GEOSGeom for comparison
IShape* shpExt = nullptr;
+#if DEBUG_ALLOCATED_OBJECTS
+ auto currentBrake = ComHelper::GetBreak();
+ ComHelper::SetBreak(false);
+#endif
ComHelper::CreateShape(&shpExt);
+#if DEBUG_ALLOCATED_OBJECTS
+ ComHelper::SetBreak(currentBrake);
+#endif
const bool bPtSelection = bMinX == bMaxX && bMinY == bMaxY;
int localNumShapes = static_cast(_shapeData.size());
@@ -158,6 +165,8 @@ bool CShapefile::SelectShapesCore(Extent& extents, const double tolerance, const
shpExt->AddPoint(bMinX, bMinY, &idx);
// convert input point to GEOS
GEOSGeom geosPoint = GeosConverter::ShapeToGeom(shpExt); // TODO: Fix compile warning
+ shpExt->Release();
+ shpExt = nullptr;
if (shpType2D == SHP_POLYGON)
{
@@ -216,6 +225,8 @@ bool CShapefile::SelectShapesCore(Extent& extents, const double tolerance, const
shpExt->AddPoint(bMinX, bMinY, &idx);
// convert extent to GEOS
GEOSGeom geosExtent = GeosConverter::ShapeToGeom(shpExt); // TODO: Fix compile warning
+ shpExt->Release();
+ shpExt = nullptr;
for (i = 0; i < localNumShapes; i++)
{
diff --git a/src/COM classes/Shapefile_SpatialIndex.cpp b/src/COM classes/Shapefile_SpatialIndex.cpp
index c4d31df5..03815588 100644
--- a/src/COM classes/Shapefile_SpatialIndex.cpp
+++ b/src/COM classes/Shapefile_SpatialIndex.cpp
@@ -197,6 +197,7 @@ STDMETHODIMP CShapefile::get_CanUseSpatialIndex(IExtents* pArea, VARIANT_BOOL* p
if (_shpfileName.GetLength() <= 3)
{
+ // dhe, Noisy error?
ErrorMessage(tkINVALID_FOR_INMEMORY_OBJECT);
return S_OK;
}
diff --git a/src/COM classes/TableClass.cpp b/src/COM classes/TableClass.cpp
index 2093976b..b8b45880 100644
--- a/src/COM classes/TableClass.cpp
+++ b/src/COM classes/TableClass.cpp
@@ -782,7 +782,9 @@ bool CTableClass::SaveToFile(const CStringW& dbfFilename, bool updateFileInPlace
}
}
- DBFAddField(newdbfHandle, OLE2CA(fname), (DBFFieldType)type, width, precision);
+ int ret = DBFAddField(newdbfHandle, OLE2CA(fname), (DBFFieldType)type, width, precision);
+ if (ret == -1)
+ ErrorMessage(tkDBF_CANT_ADD_DBF_FIELD);
field->Release();
}
@@ -822,6 +824,15 @@ bool CTableClass::SaveToFile(const CStringW& dbfFilename, bool updateFileInPlace
if (!updateFileInPlace)
DBFClose(newdbfHandle);
+ // Set byte 29 to 0x00 in the .dbf file (Codepage mark)
+ FILE* dbfFile = _wfopen(dbfFilename, L"r+");
+ if (dbfFile != NULL) {
+ fseek(dbfFile, 29, SEEK_SET);
+ fputc('\0', dbfFile);
+ fflush(dbfFile);
+ fclose(dbfFile);
+ }
+
return true;
}
@@ -863,6 +874,9 @@ STDMETHODIMP CTableClass::SaveAs(BSTR dbfFilename, ICallback *cBack, VARIANT_BOO
// **************************************************************
void CTableClass::ClearFields()
{
+ //if(_triggerDebug)
+ //DebugBreak();
+
for (int i = 0; i < FieldCount(); i++)
{
if (_fields[i]->field != NULL)
@@ -884,6 +898,9 @@ STDMETHODIMP CTableClass::Close(VARIANT_BOOL *retval)
*retval = VARIANT_TRUE;
+ //if(_triggerDebug)
+ //DebugBreak();
+
StopAllJoins();
ClearFields();
@@ -1474,7 +1491,9 @@ bool CTableClass::WriteRecord(DBFInfo* dbfHandle, long fromRowIndex, long toRowI
if (val.vt == VT_BSTR)
{
nonstackString = Utility::ConvertBSTRToLPSTR(val.bstrVal, (isUTF8 ? CP_UTF8 : CP_ACP)); // ((LPCSTR)Utility::ConvertToUtf8(val.bstrVal)); // Utility::SYS2A(val.bstrVal);
+ int fieldCount = DBFGetFieldCount(dbfHandle);
DBFWriteStringAttribute(dbfHandle, toRowIndex, i, nonstackString);
+ //::OutputDebugString("DBFWriteStringAttribute() done!");
delete[] nonstackString;
nonstackString = NULL;
}
@@ -1764,7 +1783,7 @@ STDMETHODIMP CTableClass::EditCellValue(long FieldIndex, long RowIndex, VARIANT
// Darrel Brown, 10/16/2003 Added support for null cell values
// jf, 2/17/2018, added support for Dates and Booleans
- if (newVal.vt != VT_I4 && newVal.vt != VT_R8 && newVal.vt != VT_BSTR && newVal.vt != VT_DATE && newVal.vt != VT_BOOL && newVal.vt != VT_NULL)
+ if (newVal.vt != VT_I4 && newVal.vt != VT_R8 && newVal.vt != VT_BSTR && newVal.vt != VT_DATE && newVal.vt != VT_BOOL && newVal.vt != VT_NULL && newVal.vt != VT_EMPTY)
{
ErrorMessage(tkINCORRECT_VARIANT_TYPE);
return S_OK;
@@ -3296,7 +3315,7 @@ STDMETHODIMP CTableClass::StopJoin(int joinIndex, VARIANT_BOOL* retVal)
STDMETHODIMP CTableClass::get_IsJoined(VARIANT_BOOL* retVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
- for (size_t i = _fields.size() - 1; i >= 0; i--)
+ for (size_t i = _fields.size() - 1; i >= 0 && _fields.size() > i; i--)
{
if (_fields[i]->Joined()) {
*retVal = VARIANT_TRUE;
diff --git a/src/COM classes/TableClass.h b/src/COM classes/TableClass.h
index 4a1bd217..ed3009cc 100644
--- a/src/COM classes/TableClass.h
+++ b/src/COM classes/TableClass.h
@@ -46,6 +46,7 @@ class ATL_NO_VTABLE CTableClass :
_pUnkMarshaler = NULL;
_key = SysAllocString(L"");
_lastRecordIndex = -1;
+ _triggerDebug = false;
gReferenceCounter.AddRef(tkInterface::idTable);
}
@@ -194,6 +195,7 @@ class ATL_NO_VTABLE CTableClass :
int _lastRecordIndex; // last index accessed with get_CellValue
bool _appendMode;
int _appendStartShapeCount;
+ bool _triggerDebug;
public:
bool m_needToSaveAsNewFile;
diff --git a/src/COM classes/Utils_OGR.cpp b/src/COM classes/Utils_OGR.cpp
index c2b19aa9..d2efcd71 100644
--- a/src/COM classes/Utils_OGR.cpp
+++ b/src/COM classes/Utils_OGR.cpp
@@ -2,6 +2,7 @@
//File name: Utils_OGR.cpp
//Description: Implementation of CUtils.
//********************************************************************************************************
+#include "stdafx.h"
#include
#include
#include "cpl_conv.h"
@@ -16,6 +17,7 @@
#include "vrtdataset.h"
#pragma warning(disable:4996)
+#define DISABLE_OGR2OGR 1
int CPL_STDCALL GDALProgressCallback(double dfComplete, const char* pszMessage, void* pData);
@@ -47,6 +49,7 @@ typedef struct
} AssociatedLayers;
+#if GDAL_VERSION_MAJOR >= 3
static int TranslateLayer(TargetLayerInfo* psInfo,
GDALDataset* poSrcDS,
OGRLayer* poSrcLayer,
@@ -54,9 +57,9 @@ static int TranslateLayer(TargetLayerInfo* psInfo,
int bTransform,
int bWrapDateline,
const char* pszDateLineOffset,
- OGRSpatialReference* poOutputSRS,
+ const OGRSpatialReference* poOutputSRS,
int bNullifyOutputSRS,
- OGRSpatialReference* poUserSourceSRS,
+ const OGRSpatialReference* poUserSourceSRS,
OGRCoordinateTransformation* poGCPCoordTrans,
int eGType,
int bPromoteToMulti,
@@ -71,7 +74,7 @@ static int TranslateLayer(TargetLayerInfo* psInfo,
GIntBig* pnReadFeatureCount,
GDALProgressFunc pfnProgress,
void* pProgressArg);
-
+#endif
/* -------------------------------------------------------------------- */
/* CheckDestDataSourceNameConsistency() */
@@ -802,10 +805,10 @@ class GCPCoordTransformation final : public OGRCoordinateTransformation
poSRS->Dereference();
}
- OGRSpatialReference* GetSourceCS() override { return poSRS; }
- OGRSpatialReference* GetTargetCS() override { return poSRS; }
+ const OGRSpatialReference* GetSourceCS() const { return poSRS; }
+ const OGRSpatialReference* GetTargetCS() const { return poSRS; }
- int Transform(int nCount,
+ int Transform(size_t nCount,
double* x, double* y, double* z,
double* /* t */,
int* pabSuccess) override
@@ -887,8 +890,8 @@ class GCPCoordTransformation : public OGRCoordinateTransformation
poSRS->Dereference();
}
- virtual OGRSpatialReference* GetSourceCS() { return poSRS; }
- virtual OGRSpatialReference* GetTargetCS() { return poSRS; }
+ virtual const OGRSpatialReference* GetSourceCS() { return poSRS; }
+ virtual const OGRSpatialReference* GetTargetCS() { return poSRS; }
virtual int Transform(int nCount,
double* x, double* y, double* z) override
@@ -1053,8 +1056,8 @@ static TargetLayerInfo* SetupTargetLayer(CPL_UNUSED GDALDataset* poSrcDS,
}
}
- OGRSpatialReference* poOutputSRS = poOutputSRSIn;
- if (poOutputSRS == NULL && !bNullifyOutputSRS)
+ const OGRSpatialReference* poOutputSRS = poOutputSRSIn;
+ if (poOutputSRS == nullptr && !bNullifyOutputSRS)
{
if (nSrcGeomFieldCount == 1 || anRequestedGeomFields.size() == 0)
poOutputSRS = poSrcLayer->GetSpatialRef();
@@ -1572,6 +1575,7 @@ __declspec(deprecated("This is a deprecated function, use CGdalUtils::GdalVector
STDMETHODIMP CUtils::OGR2OGR(BSTR bstrSrcFilename, BSTR bstrDstFilename,
BSTR bstrOptions, ICallback* cBack, VARIANT_BOOL* retval)
{
+#if !DISABLE_OGR2OGR
USES_CONVERSION;
struct CallbackParams params(GetCallback(), "Converting");
@@ -3062,6 +3066,10 @@ STDMETHODIMP CUtils::OGR2OGR(BSTR bstrSrcFilename, BSTR bstrDstFilename,
* retval = nRetCode == 0 ? VARIANT_TRUE : VARIANT_FALSE;
return ResetConfigOptions(tkNO_ERROR);
+#else
+ *retval = VARIANT_FALSE;
+ return 0;
+#endif
}
/************************************************************************/
@@ -3165,19 +3173,19 @@ class CompositeCT final : public OGRCoordinateTransformation
return new CompositeCT(*this);
}
- OGRSpatialReference* GetSourceCS() override
+ const OGRSpatialReference* GetSourceCS() const override
{
return poCT1 ? poCT1->GetSourceCS() :
poCT2 ? poCT2->GetSourceCS() : nullptr;
}
- OGRSpatialReference* GetTargetCS() override
+ const OGRSpatialReference* GetTargetCS() const override
{
return poCT2 ? poCT2->GetTargetCS() :
poCT1 ? poCT1->GetTargetCS() : nullptr;
}
- int Transform(int nCount,
+ int Transform(size_t nCount,
double* x, double* y, double* z,
double* t,
int* pabSuccess) override
@@ -3215,7 +3223,7 @@ class CompositeCT : public OGRCoordinateTransformation
}
- virtual OGRSpatialReference* GetSourceCS()
+ virtual const OGRSpatialReference* GetSourceCS()
{
return poCT1 ? poCT1->GetSourceCS() :
poCT2 ? poCT2->GetSourceCS() : NULL;
@@ -3261,9 +3269,9 @@ static int SetupCT(TargetLayerInfo* psInfo,
int bTransform,
int bWrapDateline,
const char* pszDateLineOffset,
- OGRSpatialReference* poUserSourceSRS,
+ const OGRSpatialReference* poUserSourceSRS,
OGRFeature* poFeature,
- OGRSpatialReference* poOutputSRS,
+ const OGRSpatialReference* poOutputSRS,
OGRCoordinateTransformation* poGCPCoordTrans)
{
OGRLayer* poDstLayer = psInfo->poDstLayer;
@@ -3273,9 +3281,9 @@ static int SetupCT(TargetLayerInfo* psInfo,
/* -------------------------------------------------------------------- */
/* Setup coordinate transformation if we need it. */
/* -------------------------------------------------------------------- */
- OGRSpatialReference* poSourceSRS = NULL;
- OGRCoordinateTransformation* poCT = NULL;
- char** papszTransformOptions = NULL;
+ const OGRSpatialReference* poSourceSRS = nullptr;
+ OGRCoordinateTransformation* poCT = nullptr;
+ char** papszTransformOptions = nullptr;
int iSrcGeomField;
if (psInfo->iRequestedSrcGeomField >= 0)
@@ -3301,7 +3309,7 @@ static int SetupCT(TargetLayerInfo* psInfo,
if (psInfo->nFeaturesRead == 0)
{
poSourceSRS = poUserSourceSRS;
- if (poSourceSRS == NULL)
+ if (poSourceSRS == nullptr)
{
if (iSrcGeomField > 0)
poSourceSRS = poSrcLayer->GetLayerDefn()->
@@ -3310,7 +3318,7 @@ static int SetupCT(TargetLayerInfo* psInfo,
poSourceSRS = poSrcLayer->GetSpatialRef();
}
}
- if (poSourceSRS == NULL)
+ if (poSourceSRS == nullptr)
{
OGRGeometry* poSrcGeometry =
poFeature->GetGeomFieldRef(iSrcGeomField);
@@ -3422,7 +3430,7 @@ static int TranslateLayer(TargetLayerInfo* psInfo,
int bTransform,
int bWrapDateline,
const char* pszDateLineOffset,
- OGRSpatialReference* poOutputSRS,
+ const OGRSpatialReference* poOutputSRS,
int bNullifyOutputSRS,
OGRSpatialReference* poUserSourceSRS,
OGRCoordinateTransformation* poGCPCoordTrans,
diff --git a/src/COM classes/WmsLayer.cpp b/src/COM classes/WmsLayer.cpp
index b8a17536..c6635d30 100644
--- a/src/COM classes/WmsLayer.cpp
+++ b/src/COM classes/WmsLayer.cpp
@@ -823,3 +823,46 @@ STDMETHODIMP CWmsLayer::put_Styles(BSTR newVal)
return S_OK;
}
+
+// ********************************************************
+// BoundingBoxOrder()
+// ********************************************************
+STDMETHODIMP CWmsLayer::get_BoundingBoxOrder(tkWmsBoundingBoxOrder* pVal)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+
+ *pVal = _provider->get_BoundingBoxOrder();
+
+ return S_OK;
+}
+
+STDMETHODIMP CWmsLayer::put_BoundingBoxOrder(tkWmsBoundingBoxOrder newVal)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+
+ _provider->set_BoundingBoxOrder(newVal);
+
+ return S_OK;
+}
+
+
+// ********************************************************
+// TileSize()
+// ********************************************************
+STDMETHODIMP CWmsLayer::get_TileSize(LONG* pVal)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+
+ *pVal = _provider->get_TileSize();
+
+ return S_OK;
+}
+
+STDMETHODIMP CWmsLayer::put_TileSize(LONG newVal)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+
+ _provider->set_TileSize(newVal);
+
+ return S_OK;
+}
\ No newline at end of file
diff --git a/src/COM classes/WmsLayer.h b/src/COM classes/WmsLayer.h
index 035d0b7d..a18384ef 100644
--- a/src/COM classes/WmsLayer.h
+++ b/src/COM classes/WmsLayer.h
@@ -99,8 +99,12 @@ class ATL_NO_VTABLE CWmsLayer :
STDMETHOD(put_Version)(tkWmsVersion newVal);
STDMETHOD(get_Styles)(BSTR* pVal);
STDMETHOD(put_Styles)(BSTR newVal);
+ STDMETHOD(get_BoundingBoxOrder)(tkWmsBoundingBoxOrder* pVal);
+ STDMETHOD(put_BoundingBoxOrder)(tkWmsBoundingBoxOrder newVal);
+ STDMETHOD(get_TileSize)(LONG* pVal);
+ STDMETHOD(put_TileSize)(LONG newVal);
-private:
+private:
BSTR _key;
long _lastErrorCode;
WmsCustomProvider* _provider;
diff --git a/src/ComHelpers/CallbackHelper.cpp b/src/ComHelpers/CallbackHelper.cpp
index 439d2c59..74094e53 100644
--- a/src/ComHelpers/CallbackHelper.cpp
+++ b/src/ComHelpers/CallbackHelper.cpp
@@ -122,6 +122,7 @@ void CallbackHelper::ErrorMsg(const CString className, ICallback* localCback, BS
if (callback || Debug::IsDebugMode())
{
if (strcmp(message, "No Error") == 0) return;
+ if (strcmp(message, "The method isn't applicable to the in-memory object") == 0) return;
TCHAR buffer[1024];
va_list args;
diff --git a/src/ComHelpers/SelectionHelper.cpp b/src/ComHelpers/SelectionHelper.cpp
index 9ed2372c..489d8b1b 100644
--- a/src/ComHelpers/SelectionHelper.cpp
+++ b/src/ComHelpers/SelectionHelper.cpp
@@ -209,23 +209,60 @@ bool SelectionHelper::SelectSingleShape(IShapefile* sf, Extent& box, long& shape
{
return SelectSingleShape(sf, box, SelectMode::INTERSECTION, shapeIndex);
}
+
bool SelectionHelper::SelectSingleShape(IShapefile* sf, Extent& box, SelectMode mode, long& shapeIndex)
{
vector results;
+ bool foundMatch = false;
+ double minDistance = (std::numeric_limits::max)();
if (SelectShapes(sf, box, mode, results))
{
- for (int i = results.size() - 1; i >= 0; i--)
+ auto center = box.GetCenter();
+ IShape* ptShp = nullptr;
+ ComHelper::CreateShape(&ptShp);
+ ptShp->put_ShapeType(SHP_POINT);
+ IPoint* pnt;
+ ComHelper::CreatePoint(&pnt);
+ pnt->put_X(center.x);
+ pnt->put_Y(center.y);
+ VARIANT_BOOL retVal;
+ long pointIndex = 0;
+ ptShp->InsertPoint(pnt, &pointIndex, &retVal);
+ pnt->Release();
+ for (int i = static_cast(results.size()) - 1; i >= 0; i--)
{
VARIANT_BOOL visible;
sf->get_ShapeRendered(results[i], &visible);
if (visible)
{
- shapeIndex = results[i];
- return true;
+ IShape* shp;
+ sf->get_Shape(results[i], &shp);
+ ShpfileType shpfileType;
+ shp->get_ShapeType(&shpfileType);
+ double distance;
+ if (shpfileType == SHP_POLYGON || shpfileType == SHP_POLYGONZ || shpfileType == SHP_POLYGONM)
+ {
+ // Measure distance to polygons boundary to allow selection of inner shape, (IK-384)
+ IShape* boundary;
+ shp->Boundary(&boundary);
+ boundary->Distance(ptShp, &distance);
+ boundary->Release();
+ }
+ else
+ shp->Distance(ptShp, &distance);
+
+
+ if (minDistance > distance)
+ {
+ minDistance = distance;
+ shapeIndex = results[i];
+ foundMatch = true;
+ }
}
}
+ ptShp->Release();
}
- return false;
+ return foundMatch;
}
/***********************************************************************/
diff --git a/src/ComHelpers/ShapeHelper.cpp b/src/ComHelpers/ShapeHelper.cpp
index a3896df2..227bc385 100644
--- a/src/ComHelpers/ShapeHelper.cpp
+++ b/src/ComHelpers/ShapeHelper.cpp
@@ -428,3 +428,108 @@ int ShapeHelper::GetContentLength(IShape* shp)
return ShapeUtility::get_ContentLength(shpType, numPoints, numParts);
}
+
+// *************************************************************
+// DebugDump()
+// *************************************************************
+void ShapeHelper::DebugDump(IShape* shp)
+{
+ long numPoints, numParts;
+ ShpfileType shpType;
+
+ shp->get_NumPoints(&numPoints);
+ shp->get_NumParts(&numParts);
+ shp->get_ShapeType(&shpType);
+
+ if (numParts > 1) {
+ ::OutputDebugStringA("Not support NumParts > 1");
+ return;
+ }
+
+ if (numPoints <= 10 || numPoints > 15)
+ return;
+
+ HRESULT hr;
+ IPoint* pnt = nullptr;
+ CString sOutput;
+ double x, y, z, m;
+ switch (shpType)
+ {
+ case SHP_NULLSHAPE:
+ ::OutputDebugStringA("ShapeHelper::DebugDump(): NULLSHAPE");
+ break;
+
+ case SHP_POINT:
+ case SHP_POINTZ:
+ hr = shp->get_Point(0, &pnt);
+ if (FAILED(hr)) {
+ CString sError;
+ sError.AppendFormat("ShapeHelper::DebugDump() Failed in get_Point(1, ..)\r\n");
+ ::OutputDebugStringA(sError.GetBuffer());
+ return;
+ }
+ pnt->get_X(&x);
+ pnt->get_Y(&y);
+
+ if (shpType == SHP_POINT)
+ sOutput.AppendFormat("Point N: %f E: %f\r\n", y, x);
+ else {
+ pnt->get_Z(&z);
+ pnt->get_M(&m);
+ sOutput.AppendFormat("Point N: %f E: %f Z: %f M: %f\r\n", y, x, z, m);
+ }
+ break;
+
+
+ case SHP_POLYLINE:
+ case SHP_POLYLINEZ:
+ for (int i = 0; i < numPoints; i++) {
+ hr = shp->get_Point(i, &pnt);
+ if (FAILED(hr)) {
+ CString sError;
+ sError.AppendFormat("ShapeHelper::DebugDump() Failed in get_Point(%d, ..)\r\n", i);
+ ::OutputDebugStringA(sError.GetBuffer());
+ return;
+ }
+ pnt->get_X(&x);
+ pnt->get_Y(&y);
+ if (shpType == SHP_POLYLINE)
+ sOutput.AppendFormat("Point# %d X: %f Y: %f\r\n", i, x, y);
+ else {
+ pnt->get_Z(&z);
+ pnt->get_M(&m);
+ sOutput.AppendFormat("Point# %d N: %f E: %f Z: %f M: %f\r\n", i, y, x, z, m);
+ }
+ }
+ break;
+
+ case SHP_POLYGON:
+ case SHP_POLYGONZ:
+ for (int i = 0; i < numPoints; i++) {
+ hr = shp->get_Point(i, &pnt);
+ if (FAILED(hr)) {
+ CString sError;
+ sError.AppendFormat("ShapeHelper::DebugDump() Failed in get_Point(%d, ..)\r\n", i);
+ ::OutputDebugStringA(sError.GetBuffer());
+ return;
+ }
+ pnt->get_X(&x);
+ pnt->get_Y(&y);
+ if (shpType == SHP_POLYGON)
+ sOutput.AppendFormat("Point# %d X: %f Y: %f\r\n", i, x, y);
+ else {
+ pnt->get_Z(&z);
+ pnt->get_M(&m);
+ sOutput.AppendFormat("Point# %d N: %f E: %f Z: %f M: %f\r\n", i, y, x, z, m);
+ }
+ }
+ break;
+
+ default:
+ ::OutputDebugStringA("ShapeHelper::DebugDump(): Shape Type: Unknown");
+ break;
+ }
+ sOutput.Append("\r\n");
+ ::OutputDebugStringA(sOutput.GetBuffer());
+}
+
diff --git a/src/ComHelpers/ShapeHelper.h b/src/ComHelpers/ShapeHelper.h
index a3e3783d..5666ea81 100644
--- a/src/ComHelpers/ShapeHelper.h
+++ b/src/ComHelpers/ShapeHelper.h
@@ -19,5 +19,6 @@ class ShapeHelper
static void AddLabelToShape(IShape* shp, ILabels* labels, BSTR text, tkLabelPositioning method, tkLineLabelOrientation orientation, double offsetX, double offsetY);
static IShape* CenterAsShape(IShape* shp);
static int GetContentLength(IShape* shp);
+ static void DebugDump(IShape* shp);
};
diff --git a/src/ComHelpers/ShapefileHelper.cpp b/src/ComHelpers/ShapefileHelper.cpp
index 9b85fa09..f4c3da65 100644
--- a/src/ComHelpers/ShapefileHelper.cpp
+++ b/src/ComHelpers/ShapefileHelper.cpp
@@ -403,13 +403,13 @@ bool tryGetCloserPointForShape(IShape* shp, IShape* ptShp, double& minDist, doub
// Get the distance
double distance;
resShp->get_Length(&distance);
+ resShp->Release();
- // Check if this is allowed and/or smaller than the previous found point:
+ // Check if this is allowed and/or smaller than the previous found point:
if (distance < minDist && distance < maxDistance) {
fx = xPnt;
fy = yPnt;
minDist = distance;
- resShp->Release();
return true;
}
}
@@ -488,6 +488,11 @@ bool ShapefileHelper::GetClosestSnapPosition(IShapefile* sf, double x, double y,
else if (shptype == SHP_POLYGONZ)
partShp->put_ShapeType(SHP_POLYLINEZ);
+ /*CString str;
+ str.Format("0x%016llx\r\n", shp);
+ const CComBSTR bstr(str);
+ partShp->put_Key(bstr); */
+
// Insert part
long part = 0;
VARIANT_BOOL vbretval;
diff --git a/src/CopyTamasFiles.bat b/src/CopyTamasFiles.bat
index 84f9bbf4..726ef8b3 100644
--- a/src/CopyTamasFiles.bat
+++ b/src/CopyTamasFiles.bat
@@ -10,6 +10,7 @@ REM * Paul Meems, update for ecw dll, June 2015 *
REM * Paul Meems, update for ecw dll to v5.3, Aug 2017 *
REM * Paul Meems, update for xerces and lti_dsdk dll, Aug 2018 *
REM * Paul Meems, update for GDAL v3+, Jan 2022 *
+REM * Daniel Hedén, update for GDAL v3.10.3, proj9 *
REM * Usage to test: *
REM * CopyTamasFiles.bat D:\dev\MapwinGIS\GitHub\support\GDAL_SDK\v140\bin\win32 D:\dev\MapwinGIS\GitHub\src\bin\Win32\
REM *************************************************************
@@ -19,7 +20,7 @@ set _to_dir=%2
if '%_from_dir%'=='' if '%_to_dir%'=='' GOTO usage
REM Copy gdal plugins:
-FOR %%G IN (gdal_MrSID.dll gdal_netCDF.dll gdal_HDF4.dll gdal_HDF4Image.dll gdal_HDF5.dll gdal_HDF5Image.dll gdal_ECW_JP2ECW.dll gdal_MG4Lidar.dll) DO (
+FOR %%G IN (gdal_ECW_JP2ECW.dll gdal_FITS.dll gdal_GEOR.dll gdal_GIF.dll gdal_HDF4.dll gdal_HDF5.dll gdal_KEA.dll gdal_MG4Lidar.dll gdal_MrSID.dll gdal_PDF.dll gdal_netCDF.dll ogr_OCI.dll ogr_ODBC.dll) DO (
IF EXIST %_from_dir%\gdal\plugins\%%G (
xcopy /v /c /r /y %_from_dir%\gdal\plugins\%%G %_to_dir%gdalplugins\
)
@@ -37,13 +38,25 @@ xcopy /v /c /r /y %_from_dir%\gdal-data\*.* %_to_dir%gdal-data\
REM xcopy /v /c /r /y %_from_dir%\proj\SHARE\*.* %_to_dir%..\PROJ_NAD\
REM Copy Proj7 data. TODO: Check if copied to correct location:
-xcopy /v /c /r /y %_from_dir%\proj7\share\*.* %_to_dir%proj7\share\
+rem xcopy /v /c /r /y %_from_dir%\proj7\share\*.* %_to_dir%proj7\share\
+
+REM Copy Proj9 data. TODO: Check if copied to correct location:
+xcopy /v /c /r /y %_from_dir%\proj9\share\*.* %_to_dir%proj9\share\
+
+REM Copy gdal plugins
+xcopy /v /c /r /y %_from_dir%\gdal\plugins\*.* %_to_dir%gdal\plugins\
+
+REM Copy gdal plugins-external
+xcopy /v /c /r /y %_from_dir%\gdal\plugins-external\*.* %_to_dir%gdal\plugins-external\
+
+REM Copy gdal plugins-external
+xcopy /v /c /r /y %_from_dir%\gdal\plugins-optional\*.* %_to_dir%gdal\plugins-optional\
REM Copy needed Tamas binaries:
-FOR %%G IN (cfitsio.dll freexl.dll geos.dll geos_c.dll hdf.dll hdf5.dll hdf5_hl.dll hdf5_cpp.dll hdf5_hl_cpp.dll libcrypto-1_1.dll libcrypto-1_1-x64.dll
- libcurl.dll libexpat.dll tiff.dll tiffxx.dll ogdi.dll mfhdf.dll
- iconv-2.dll libmysql.dll libpng16.dll libpq.dll libssl-1_1.dll libssl-1_1-x64.dll libxml2.dll lti_lidar_dsdk_1.1.dll netcdf.dll
- openjp2.dll spatialite.dll sqlite3.dll szip.dll tbb.dll xdr.dll zlib.dll
+FOR %%G IN (cfitsio.dll freexl.dll geos.dll geos_c.dll hdf.dll hdf5.dll hdf5_hl.dll hdf5_cpp.dll hdf5_hl_cpp.dll libcrypto-1_1.dll libcrypto-1_1-x64.dll libcrypto-3-x64.dll
+ libcurl.dll libexpat.dll tiff.dll tiffxx.dll ogdi.dll mfhdf.dll pcre.dll
+ iconv-2.dll libmysql.dll libpng16.dll libpq.dll libssl-1_1.dll libssl-1_1-x64.dll libssl-3-x64.dll libxml2.dll lti_lidar_dsdk_1.1.dll netcdf.dll
+ openjp2.dll proj_9.dll spatialite.dll sqlite3.dll szip.dll tbb.dll xdr.dll zlib.dll zstd.dll
NCSEcw.dll) DO (
IF EXIST %_from_dir%\%%G (
xcopy /v /c /r /y %_from_dir%\%%G %_to_dir%
@@ -51,8 +64,8 @@ FOR %%G IN (cfitsio.dll freexl.dll geos.dll geos_c.dll hdf.dll hdf5.dll hdf5_hl.
)
REM gdal contains the version number, so use a wildcard:
-del /f /q %_to_dir%\gdal*.dll
-xcopy /v /c /r /y %_from_dir%\gdal3*.dll %_to_dir%
+rem del /f /q %_to_dir%\gdal*.dll
+rem xcopy /v /c /r /y %_from_dir%\gdal3*.dll %_to_dir%
REM xerces contains a version number, so use a wildcard:
del /f /q %_to_dir%\xerces-c*.dll
@@ -63,10 +76,18 @@ del /f /q %_to_dir%\lti_dsdk*.dll
xcopy /v /c /r /y %_from_dir%\lti_dsdk*.dll %_to_dir%
REM Updates for GDAL v3:
-del /f /q %_to_dir%\gdal3*.dll
-xcopy /v /c /r /y %_from_dir%\gdal3*.dll %_to_dir%
-del /f /q %_to_dir%\proj_7*.dll
-xcopy /v /c /r /y %_from_dir%\proj_7*.dll %_to_dir%
+rem del /f /q %_to_dir%\gdal3*.dll
+rem xcopy /v /c /r /y %_from_dir%\gdal3*.dll %_to_dir%
+rem del /f /q %_to_dir%\proj_7*.dll
+rem xcopy /v /c /r /y %_from_dir%\proj_7*.dll %_to_dir%
+
+REM gdal witout the version number:
+del /f /q %_to_dir%\gdal.dll
+xcopy /v /c /r /y %_from_dir%\gdal.dll %_to_dir%
+
+REM msvcp140*
+rem xcopy /v /c /r /y %_from_dir%\msvcp140.dll %_to_dir%
+xcopy /v /c /r /y %_from_dir%\msvcp140*.dll %_to_dir%
REM Copy licenses:
xcopy /v /c /r /y %_from_dir%\..\..\..\licenses\*.rtf %_to_dir%..\Licenses\
diff --git a/src/Drawing/LabelDrawing.cpp b/src/Drawing/LabelDrawing.cpp
index 8ac833ce..6c9ca90c 100644
--- a/src/Drawing/LabelDrawing.cpp
+++ b/src/Drawing/LabelDrawing.cpp
@@ -54,7 +54,7 @@ void CLabelDrawer::InitSettings(LabelSettings& settings, ILabels* labels, IShape
settings.scaleFactor = GetScaleFactor(labels);
- settings.autoOffset = GetAutoOffset(labels, sf);
+ settings.autoOffset = sf != nullptr ? GetAutoOffset(labels, sf) : false;
settings.numLabels = LabelsHelper::GetCount(labels);
@@ -121,6 +121,8 @@ void CLabelDrawer::DrawLabels(ILabels* labels)
gdi.InitDc(_graphics);
}
+ lbs->AddDrawnLabel(-1); // Reset collection
+
// ---------------------------------------------------------------
// drawing categories - we'll start from the categories
// with the higher priority, therefore reverse order
@@ -173,7 +175,7 @@ void CLabelDrawer::DrawLabels(ILabels* labels)
if ((lbl->category == categoryIndex) || (categoryIndex == -1 && (lbl->category < 0 || lbl->category >= settings.numCategories))) {}
else continue; /* Wrong category */
-
+
// blocking the labels with the text already displayed
if (settings.removeDuplicates)
{
@@ -221,6 +223,7 @@ void CLabelDrawer::DrawLabels(ILabels* labels)
continue;
}
+ lbs->AddDrawnLabel(k);
// actual drawing
if (useGdiPlus) {
gdiPlus.DrawLabel(options, rect, piX, piY, angle);
@@ -248,6 +251,401 @@ void CLabelDrawer::DrawLabels(ILabels* labels)
}
}
+int* CLabelDrawer::PlaceLabels(ILabels* labels)
+{
+ if (!CheckVisibility(labels))
+ return NULL;
+
+ CLabels* lbs = static_cast(labels);
+ vector*>* labelData = lbs->get_LabelData();
+
+ IShapefile* sf = lbs->get_ParentShapefile();
+ std::vector* shapeData = NULL;
+ if (sf) {
+ shapeData = ((CShapefile*)sf)->get_ShapeVector();
+ }
+
+ // ---------------------------------
+ // settings, filter and sorting
+ // ---------------------------------
+ LabelSettings settings;
+ InitSettings(settings, labels, sf);
+
+ vector visibilityMask(settings.numLabels, false);
+ GetVisibilityMask(labels, sf, shapeData, visibilityMask);
+
+ // sort them if sort field is specified
+ vector* indices = NULL;
+ if (sf) {
+ ((CShapefile*)sf)->GetSorting(&indices);
+ }
+
+ if (indices && indices->size() != settings.numLabels) {
+ indices = NULL;
+ }
+
+ // ---------------------------------
+ // preparing to (not) draw
+ // ---------------------------------
+ GdiLabelDrawer gdi;
+ GdiPlusLabelDrawer gdiPlus;
+ CRect rect(0, 0, 0, 0);
+ std::set uniqueValues;
+
+ bool useGdiPlus = GetUseGdiPlus(labels);
+ if (useGdiPlus) {
+ gdiPlus.InitGraphics(_graphics, labels);
+ }
+ else {
+ gdi.InitDc(_graphics);
+ }
+
+ // ---------------------------------------------------------------
+ // drawing categories - we'll start from the categories
+ // with the higher priority, therefore reverse order
+ // ---------------------------------------------------------------
+ for (int categoryIndex = settings.numCategories - 1; categoryIndex >= -1; categoryIndex--)
+ {
+ CLabelOptions* options = GetCategoryOptions(labels, categoryIndex);
+
+ if (!options || !options->visible) continue;
+
+
+ // ---------------------------------------------------------------
+ // place labels
+ // ---------------------------------------------------------------
+ for (long k = 0; k < settings.numLabels; k++)
+ {
+ long i = indices ? (*indices)[k] : k;
+
+ if (!visibilityMask[i]) {
+ continue;
+ }
+
+ vector* parts = (*labelData)[i];
+ for (int j = 0; j < (int)parts->size(); j++)
+ {
+ CLabelInfo* lbl = (*parts)[j];
+
+ if (lbl->x < _extents->left) continue;
+ if (lbl->x > _extents->right) continue;
+ if (lbl->y < _extents->bottom) continue;
+ if (lbl->y > _extents->top) continue;
+ if (lbl->text.GetLength() <= 0) continue;
+
+ if ((lbl->category == categoryIndex) || (categoryIndex == -1 && (lbl->category < 0 || lbl->category >= settings.numCategories))) {}
+ else continue; /* Wrong category */
+
+ // blocking the labels with the text already displayed
+ if (settings.removeDuplicates)
+ {
+ if (uniqueValues.find(lbl->text) != uniqueValues.end())
+ continue;
+ else
+ uniqueValues.insert(lbl->text);
+ }
+
+ // measuring label
+ if (useGdiPlus) {
+ gdiPlus.MeasureString(lbl, rect);
+ }
+ else {
+ gdi.MeasureString(lbl, rect);
+ }
+
+ // rotation angle
+ double angle, angleRad;
+ LabelDrawingHelper::CalcRotation(lbl, _mapRotation, angle);
+ angleRad = AngleHelper::ToRad(angle);
+
+ // calculating screen rectangle
+ double piX, piY;
+
+ // Fix for MWGIS-79:
+ int shapeSize = 0;
+ if (sf)
+ shapeSize = (*shapeData)[i]->size;
+ CalcScreenRectangle(options, lbl, settings.autoOffset, shapeSize, rect, piX, piY);
+
+ // do we have overlaps?
+ if (!TryAvoidCollisions(lbl, settings.avoidCollisions, rect, piX, piY, settings.buffer, angleRad)) {
+ continue;
+ }
+
+ lbs->AddDrawnLabel(k);
+ // actual drawing
+ if (useGdiPlus) {
+ gdiPlus.DrawLabel(options, rect, piX, piY, angle);
+ }
+ else {
+ gdi.DrawLabel(options, lbl, rect, angleRad, piX, piY);
+ }
+ }
+ } // label
+ }
+}
+
+CRect CLabelDrawer::GetLabelExtents(ILabels* labels, long index)
+{
+ auto lbs = static_cast(labels);
+ //CLabels* lbs = static_cast(labels);
+ vector*>* labelData = lbs->get_LabelData();
+
+ vector* parts = (*labelData)[index];
+ CLabelInfo* lbl = (*parts)[0];
+
+ CLabelOptions* options = GetCategoryOptions(labels, index);
+
+ //CRect rect(0, 0, 0, 0);
+ //double piX, piY;
+ //CalcScreenRectangle(options, lbl, false, 0, rect, piX, piY);
+
+
+ LabelSettings settings;
+ InitSettings(settings, labels, nullptr);
+
+ // ---------------------------------
+ // preparing to draw
+ // ---------------------------------
+ GdiLabelDrawer gdi;
+ GdiPlusLabelDrawer gdiPlus;
+ CRect rect(0, 0, 0, 0);
+ std::set uniqueValues;
+
+ bool useGdiPlus = GetUseGdiPlus(labels);
+ if(useGdiPlus)
+ gdiPlus.InitGraphics(_graphics, labels);
+ else
+ gdi.InitDc(_graphics);
+
+ if(useGdiPlus)
+ {
+ // we create separate pens/brushes for each drawing method
+ gdiPlus.InitFromCategory(options, settings.hasRotation);
+
+ // choosing appropriate font
+ gdiPlus.SelectFont(options, lbl, settings.scaleFactor);
+
+ // measuring label
+ gdiPlus.MeasureString(lbl, rect);
+
+ gdiPlus.ReleaseForCategory(settings.useVariableFontSize);
+ }
+ else
+ {
+ // we create separate pens/brushes for each drawing method
+ gdi.InitFromCategory(options);
+
+ // choosing appropriate font
+ gdi.SelectFont(options, lbl, settings.scaleFactor);
+
+ // measuring label
+ gdi.MeasureString(lbl, rect);
+
+ gdi.ReleaseForCategory(settings.useVariableFontSize);
+ }
+
+ double piX, piY;
+ if(_spatiallyReferenced)
+ ProjectionToPixel(lbl->x, lbl->y, piX, piY);
+ else
+ {
+ piX = lbl->x;
+ piY = lbl->y;
+ }
+
+ rect.left += static_cast(piX);
+ rect.right += static_cast(piX);
+ rect.bottom += static_cast(piY);
+ rect.top += static_cast(piY);
+
+ return rect;
+}
+
+// *********************************************************************
+// PlaceAllMapLabels()
+// *********************************************************************
+vector CLabelDrawer::PlaceAllMapLabels(ILabels* labels)
+{
+ std:vector indexes;
+
+ if (!CheckVisibility(labels))
+ return indexes;
+
+ auto lbs = static_cast(labels);
+ vector*>* labelData = lbs->get_LabelData();
+
+ IShapefile* sf = lbs->get_ParentShapefile();
+ std::vector* shapeData = nullptr;
+ if (sf) {
+ shapeData = ((CShapefile*)sf)->get_ShapeVector();
+ }
+
+ // ---------------------------------
+ // settings, filter and sorting
+ // ---------------------------------
+ LabelSettings settings;
+ InitSettings(settings, labels, sf);
+
+ vector visibilityMask(settings.numLabels, false);
+ GetVisibilityMask(labels, sf, shapeData, visibilityMask);
+
+ // sort them if sort field is specified
+ vector* indices = nullptr;
+ if (sf) {
+ ((CShapefile*)sf)->GetSorting(&indices);
+ }
+
+ if (indices && indices->size() != settings.numLabels) {
+ indices = nullptr;
+ }
+
+ // ---------------------------------
+ // preparing to draw
+ // ---------------------------------
+ GdiLabelDrawer gdi;
+ GdiPlusLabelDrawer gdiPlus;
+ CRect rect(0, 0, 0, 0);
+ std::set uniqueValues;
+
+ bool useGdiPlus = GetUseGdiPlus(labels);
+ if (useGdiPlus) {
+ gdiPlus.InitGraphics(_graphics, labels);
+ }
+ else {
+ gdi.InitDc(_graphics);
+ }
+
+
+ // ---------------------------------------------------------------
+ // drawing categories - we'll start from the categories
+ // with the higher priority, therefore reverse order
+ // ---------------------------------------------------------------
+ for (int categoryIndex = settings.numCategories - 1; categoryIndex >= -1; categoryIndex--)
+ {
+ CLabelOptions* options = GetCategoryOptions(labels, categoryIndex);
+ if (!options || !options->visible) continue;
+
+ // we create separate pens/brushes for each drawing method
+ if (useGdiPlus)
+ gdiPlus.InitFromCategory(options, settings.hasRotation);
+ else
+ gdi.InitFromCategory(options);
+
+ if (!settings.useVariableFontSize)
+ {
+ if (useGdiPlus)
+ gdiPlus.SelectFont(options, options->fontSize, settings.scaleFactor);
+ else
+ gdi.SelectFont(options, options->fontSize, settings.scaleFactor);
+ }
+
+ // ---------------------------------------------------------------
+ // drawing labels within category
+ // ---------------------------------------------------------------
+ for (long k = 0; k < settings.numLabels; k++)
+ {
+ long i = indices ? (*indices)[k] : k;
+
+ if (!visibilityMask[i]) {
+ continue;
+ }
+
+ vector* parts = (*labelData)[i];
+ for (int j = 0; j < static_cast(parts->size()); j++)
+ {
+ CLabelInfo* lbl = (*parts)[j];
+
+ if (lbl->x < _extents->left) continue;
+ if (lbl->x > _extents->right) continue;
+ if (lbl->y < _extents->bottom) continue;
+ if (lbl->y > _extents->top) continue;
+ if (lbl->text.GetLength() <= 0) continue;
+
+ if ((lbl->category == categoryIndex) || (categoryIndex == -1 && (lbl->category < 0 || lbl->category >= settings.numCategories))) {}
+ else continue; /* Wrong category */
+
+ // blocking the labels with the text already displayed
+ if (settings.removeDuplicates)
+ {
+ if (uniqueValues.find(lbl->text) != uniqueValues.end())
+ continue;
+
+ uniqueValues.insert(lbl->text);
+ }
+
+ // choosing appropriate font
+ if (settings.useVariableFontSize)
+ {
+ if (useGdiPlus) {
+ gdiPlus.SelectFont(options, lbl, settings.scaleFactor);
+ }
+ else {
+ gdi.SelectFont(options, lbl, settings.scaleFactor);
+ }
+ }
+
+ // measuring label
+ if (useGdiPlus) {
+ gdiPlus.MeasureString(lbl, rect);
+ }
+ else {
+ gdi.MeasureString(lbl, rect);
+ }
+
+ // rotation angle
+ double angle, angleRad;
+ LabelDrawingHelper::CalcRotation(lbl, _mapRotation, angle);
+ angleRad = AngleHelper::ToRad(angle);
+
+ // calculating screen rectangle
+ double piX, piY;
+
+ // Fix for MWGIS-79:
+ int shapeSize = 0;
+ if (sf)
+ shapeSize = (*shapeData)[i]->size;
+ CalcScreenRectangle(options, lbl, settings.autoOffset, shapeSize, rect, piX, piY);
+
+ // do we have overlaps?
+ if (!TryAvoidCollisions(lbl, settings.avoidCollisions, rect, piX, piY, settings.buffer, angleRad))
+ continue;
+
+ indexes.push_back(k);
+ /*lbs->AddDrawnLabel(k);
+ // actual drawing
+ if (useGdiPlus) {
+ gdiPlus.DrawLabel(options, rect, piX, piY, angle);
+ }
+ else {
+ gdi.DrawLabel(options, lbl, rect, angleRad, piX, piY);
+ } */
+ }
+ } // label
+
+ if (useGdiPlus) {
+ gdiPlus.ReleaseForCategory(settings.useVariableFontSize);
+ }
+ else {
+ gdi.ReleaseForCategory(settings.useVariableFontSize);
+ }
+ } // category
+
+ // restoring rendering options
+ if (useGdiPlus) {
+ gdiPlus.RestoreGraphics();
+ }
+ else {
+ gdi.ReleaseDc();
+ }
+
+ return indexes;
+ /*auto pArray = new int[indexes.size()];
+ copy(indexes.begin(), indexes.end(), pArray);
+ return pArray;*/
+}
+
+
// *********************************************************************
// GetCategoryOptions()
// *********************************************************************
diff --git a/src/Drawing/LabelDrawing.h b/src/Drawing/LabelDrawing.h
index 28be4999..4463d9fa 100644
--- a/src/Drawing/LabelDrawing.h
+++ b/src/Drawing/LabelDrawing.h
@@ -67,7 +67,7 @@ class CLabelDrawer: public CBaseDrawer
_graphics = graphics;
}
- ~CLabelDrawer(void){};
+ ~CLabelDrawer(void){}
private:
struct LabelSettings {
@@ -82,7 +82,7 @@ class CLabelDrawer: public CBaseDrawer
bool useVariableFontSize;
};
-private:
+private:
HDC _hdc;
double _currentScale;
int _currentZoom;
@@ -90,7 +90,7 @@ class CLabelDrawer: public CBaseDrawer
CCollisionList* _collisionList;
bool _spatiallyReferenced;
bool _printing;
-
+
private:
void InitSettings(LabelSettings& settings, ILabels* labels, IShapefile* sf);
bool HaveCollision(CRotatedRectangle& rect);
@@ -108,5 +108,8 @@ class CLabelDrawer: public CBaseDrawer
public:
void DrawLabels(ILabels* LabelsClass);
+ int* PlaceLabels(ILabels* LabelsClass);
+ vector PlaceAllMapLabels(ILabels* labels);
+ CRect GetLabelExtents(ILabels* labels, long index);
};
diff --git a/src/Drawing/LabelOptions.h b/src/Drawing/LabelOptions.h
index 4d9bc995..39278b31 100644
--- a/src/Drawing/LabelOptions.h
+++ b/src/Drawing/LabelOptions.h
@@ -211,6 +211,7 @@ struct CLabelInfo
rotatedFrame = NULL;
horizontalFrame = NULL;
isDrawn = VARIANT_FALSE;
+ key = SysAllocString(L"");
}
~CLabelInfo()
{
@@ -232,5 +233,6 @@ struct CLabelInfo
long category;
VARIANT_BOOL isDrawn;
short fontSize;
+ BSTR key;
};
diff --git a/src/Drawing/LayerDrawer.cpp b/src/Drawing/LayerDrawer.cpp
index a1a0a1df..91b5b271 100644
--- a/src/Drawing/LayerDrawer.cpp
+++ b/src/Drawing/LayerDrawer.cpp
@@ -45,3 +45,24 @@ void LayerDrawer::DrawLabels(Layer* layer, CLabelDrawer& drawer, tkVerticalPosit
}
}
+// ****************************************************************
+// PlaceLabels()
+// ****************************************************************
+int* LayerDrawer::PlaceLabels(Layer* layer, CLabelDrawer& drawer, tkVerticalPosition position)
+{
+ if (!layer) return NULL;
+ int* ret = NULL;
+ ILabels* labels = layer->get_Labels();
+ if (labels != NULL)
+ {
+ tkVerticalPosition vertPos;
+ labels->get_VerticalPosition(&vertPos);
+ if (vertPos == position)
+ {
+ ret = drawer.PlaceLabels(labels);
+ }
+ labels->Release();
+ labels = NULL;
+ }
+ return ret;
+}
\ No newline at end of file
diff --git a/src/Drawing/LayerDrawer.h b/src/Drawing/LayerDrawer.h
index 578ed54c..e5b81bbd 100644
--- a/src/Drawing/LayerDrawer.h
+++ b/src/Drawing/LayerDrawer.h
@@ -9,5 +9,6 @@ class LayerDrawer
public:
static void DrawCharts(Layer* layer, CChartDrawer& drawer, tkVerticalPosition position);
static void DrawLabels(Layer* layer, CLabelDrawer& drawer, tkVerticalPosition position);
+ static int* PlaceLabels(Layer* layer, CLabelDrawer& drawer, tkVerticalPosition position);
};
diff --git a/src/Drawing/ShapefileDrawing.cpp b/src/Drawing/ShapefileDrawing.cpp
index 3801854f..f1e47309 100644
--- a/src/Drawing/ShapefileDrawing.cpp
+++ b/src/Drawing/ShapefileDrawing.cpp
@@ -408,7 +408,8 @@ bool CShapefileDrawer::Draw(const CRect& rcBounds, IShapefile* sf)
}
}
}
- else
+ // Always draw selected objects, so the selection drawing can be drawn on top.
+ //else
{
long catIndex = (*_shapeData)[offset]->category;
diff --git a/src/Drawing/TilesDrawer.cpp b/src/Drawing/TilesDrawer.cpp
index 0453ba30..1d9c072c 100644
--- a/src/Drawing/TilesDrawer.cpp
+++ b/src/Drawing/TilesDrawer.cpp
@@ -17,7 +17,10 @@
**************************************************************************************
* Contributor(s):
* (Open source contributors should list themselves and their modifications here). */
- #include "stdafx.h"
+#include "stdafx.h"
+#define DEBUG_TILES_DRAWER 1
+#include
+#include
#include "TilesDrawer.h"
#include "TileHelper.h"
#include "CustomProjection.h"
@@ -33,6 +36,32 @@ void TilesDrawer::DrawTiles( TileManager* manager, IGeoProjection* mapProjection
{
if (!manager) return;
+#if LOG_TILE_DRAWING
+ if (_pTileLog != nullptr)
+ _pTileLog->close();
+
+ CString fileName;
+ auto t = std::time(nullptr);
+ auto tm = *std::localtime(&t);
+ std::ostringstream oss;
+ //oss << std::put_time(&tm, "%Y-%m-%d_%H%M%S");
+ oss << std::put_time(&tm, "%Y-%m-%d_%H%M%S");
+ auto timeStr = oss.str();
+ fileName.Empty();
+ auto nr = GetTileDrawCount();
+ fileName.Format(R"(C:\Temp\tiles\tilesLog_%hs_%d.txt)", timeStr.c_str(), nr);
+ struct stat buffer;
+ /*auto exist = stat(fileName.GetString(), &buffer) == 0;
+ if (exist)
+ {
+ // if file exists, append to it
+ fileName.AppendFormat("_%d.txt", 1);
+ }*/
+
+ _pTileLog = new std::ofstream();
+ _pTileLog->open(fileName.GetString(), std::ios::out | std::ios::app);
+#endif
+
BaseProvider* provider = manager->get_Provider();
if (!provider) return;
@@ -42,12 +71,32 @@ void TilesDrawer::DrawTiles( TileManager* manager, IGeoProjection* mapProjection
InitImageAttributes(manager, attr);
bool isSame = IsSameProjection(mapProjection, provider);
-
+
// copy to temporary vector, for not lock the original one for the whole length of drawing
std::vector tiles;
manager->CopyBuffer(tiles);
+#if DEBUG_TILES_DRAWER
+ CString sOutput;
+ sOutput.AppendFormat("TilesDrawer::DrawTiles() isSame: %s, tiles.Count: %llu\r\n", isSame ? "True" : "False", tiles.size());
+ ::OutputDebugStringA(sOutput.GetBuffer());
+#if LOG_TILE_DRAWING
+ _pTileLog->write(sOutput.GetString(), sOutput.GetLength());
+#endif
+#endif
// per tile drawing
+
+ auto minTileY = 100000;
+ auto maxTileY = -100000;
+ for (size_t i = 0; i < tiles.size(); i++)
+ {
+ const auto tileY = tiles[i]->tileY();
+ if (tileY < minTileY)
+ minTileY = tileY;
+ if (tileY > maxTileY)
+ maxTileY = tileY;
+ }
+
for (size_t i = 0; i < tiles.size();i++)
{
TileCore* tile = tiles[i];
@@ -61,7 +110,11 @@ void TilesDrawer::DrawTiles( TileManager* manager, IGeoProjection* mapProjection
continue;
}
+#if SQUARE_TILES
+ DrawOverlays(tile, minTileY, maxTileY, screenBounds, attr);
+#else
DrawOverlays(tile, screenBounds, attr);
+#endif
if (drawGrid) {
DrawGrid(tile, screenBounds);
@@ -75,6 +128,11 @@ void TilesDrawer::DrawTiles( TileManager* manager, IGeoProjection* mapProjection
{
DrawWmsBounds(provider);
}
+#if LOG_TILE_DRAWING
+ _pTileLog->flush();
+ _pTileLog->close();
+ _pTileLog = nullptr;
+#endif
}
// ***************************************************************
@@ -108,8 +166,17 @@ void TilesDrawer::InitImageAttributes(TileManager* manager, ImageAttributes& att
// ***************************************************************
// DrawOverlays()
// ***************************************************************
+#if SQUARE_TILES
+void TilesDrawer::DrawOverlays(TileCore* tile, int minTileY, int maxTileY, RectF screenBounds, ImageAttributes& attr)
+#else
void TilesDrawer::DrawOverlays(TileCore* tile, RectF screenBounds, ImageAttributes& attr)
+#endif
{
+ CString sOutput;
+#if DEBUG_TILES_DRAWER
+ sOutput.AppendFormat("TilesDrawer::DrawOverlays() tileX: %d screenBounds: %f x %f tile->Overlays.size: %llu \r\n", tile->tileX(), screenBounds.Width, screenBounds.Height, tile->Overlays.size());
+ ::OutputDebugStringA(sOutput.GetBuffer());
+#endif
for (size_t i = 0; i < tile->Overlays.size(); i++)
{
Bitmap* bmp = tile->get_Bitmap(i)->m_bitmap;
@@ -121,18 +188,113 @@ void TilesDrawer::DrawOverlays(TileCore* tile, RectF screenBounds, ImageAttribut
Status status;
double ROUNDING_TOLERANCE = 0.1;
-
+
double dx = abs(screenBounds.Width - bmp->GetWidth());
double dy = abs(screenBounds.Height - bmp->GetHeight());
+#if !SQUARE_TILES
if (dx < ROUNDING_TOLERANCE && dy < ROUNDING_TOLERANCE)
{
// TODO: better to check that all tiles have the same size and apply this rendering only then
status = _graphics->DrawImage(bmp, Utility::Rint(screenBounds.X), Utility::Rint(screenBounds.Y));
+
+#else
+ auto aspectRatio = screenBounds.Width / screenBounds.Height; // aspect ratio of the tile size
+ // How much the tile size differs from the screen bounds
+ auto dxyDiff = abs(dx - dy);
+
+ /*if(i == 0)
+ {
+ CLSID pngClsid;
+ CString encoder = L"image/png";
+ USES_CONVERSION;
+ Utility::GetEncoderClsid(A2OLE(encoder), &pngClsid);
+ bmp->Save(L"c:\\tmp\\tile_bmp.png", &pngClsid, nullptr);
+ } */
+
+ //sOutput.Format("DrawOverlays(%d, %d) screenBounds: %f, %f, %f, %f\r\n", tile->tileX(), tile->tileY(), screenBounds.X, screenBounds.Y, screenBounds.Width, screenBounds.Height);
+ //::OutputDebugStringA(sOutput.GetBuffer());
+
+ if (dxyDiff > 2.5) // Tow much difference between tile size and screen bounds size (aspect ratio)
+ {
+ // If the tile size is too different from the screen bounds, we draw it with only the top-left corner to prevent stretching of the image
+ // TODO: better to check that all tiles have the same size and apply this rendering only then
+ //status = _graphics->DrawImage(bmp, Utility::Rint(screenBounds.X), Utility::Rint(screenBounds.Y));
+
+ auto diff = screenBounds.Height - screenBounds.Width;
+ auto srcy = 0.0f;
+ const auto tilesDown = maxTileY - tile->tileY();
+ const auto tilesUpp = tile->tileY() - minTileY;
+
+ if (aspectRatio < 1)
+ {
+ screenBounds.Height = screenBounds.Width;
+ //screenBounds.Y += diff;
+ //screenBounds.Y += diff / 2.0f; // center the image vertically
+
+ if (tile->tileX() == 234 && tile->tileY() == 28)
+ ::OutputDebugStringA("\r\n");
+
+ //if (tilesDown > 0)
+#if RELEASE_MODE
+ screenBounds.Y += (diff / 2.0) * (tilesUpp + 1);
+#endif
+ //screenBounds.Y += (diff / 1.0) * (tilesDown - 1);
+
+ CLSID pngClsid;
+ const CString encoder = L"image/png";
+ USES_CONVERSION;
+ Utility::GetEncoderClsid(A2OLE(encoder), &pngClsid);
+ CStringW fileName;
+ fileName.Format(L"C:\\tmp\\tiles\\live\\tile_bmp_%d_%d.png", tile->tileX(), tile->tileY());
+ bmp->Save(fileName.GetBuffer(), &pngClsid, nullptr);
+
+#if DEBUG_TILES_DRAWER
+ //DumpTile(tile, bmp);
+ sOutput.Format("DrawImage(%d, %d) screenBounds.Height: %f, bmp.Height: %u, tilesDown: %d, tilesUpp: %d\r\n", tile->tileX(), tile->tileY(), screenBounds.Height, bmp->GetHeight(), tilesDown, tilesUpp);
+#if LOG_TILE_DRAWING
+ if (_pTileLog != nullptr)
+ {
+ _pTileLog->write(sOutput.GetString(), sOutput.GetLength());
+ _pTileLog->flush();
+ }
+#endif
+ ::OutputDebugStringA(sOutput.GetBuffer());
+#endif
+ }
+ else
+ {
+ ::OutputDebugStringA("aspectRatio >= 1 ");
+ //screenBounds.Width = screenBounds.Height;
+ }
+
+ //sOutput.Format("DrawImage() screenBounds.Height: %f, bmp.Height: %u, diff: %f\r\n", screenBounds.Height, bmp->GetHeight(), diff);
+ //::OutputDebugStringA(sOutput.GetBuffer());
+ //screenBounds.Width = bmp->GetWidth();
+ //screenBounds.Height = bmp->GetHeight();
+ //if (tilesUpp == 0)
+ status = _graphics->DrawImage(bmp, screenBounds, 0.0f, srcy, (REAL)bmp->GetWidth(), (REAL)bmp->GetHeight(), UnitPixel, &attr);
+
+#endif
+
+
+
+#if DEBUG_TILES_DRAWER
+ sOutput.Format("DrawImage(%f, %f, %f, %f, %d, %d) \r\n", screenBounds.X, screenBounds.Y, screenBounds.Width, screenBounds.Height, bmp->GetWidth(), bmp->GetHeight());
+ ::OutputDebugStringA(sOutput.GetBuffer());
+#endif
}
else
{
+ DumpTile(tile, bmp);
status = _graphics->DrawImage(bmp, screenBounds, 0.0f, 0.0f, (REAL)bmp->GetWidth(), (REAL)bmp->GetHeight(), UnitPixel, &attr);
+#if DEBUG_TILES_DRAWER
+ if (dxyDiff > 2.5)
+ {
+ sOutput.Format("DrawImage(%f, %f, %f, %f, %d, %d) \r\n", screenBounds.X, screenBounds.Y, screenBounds.Width, screenBounds.Height, bmp->GetWidth(), bmp->GetHeight());
+ ::OutputDebugStringA(sOutput.GetBuffer());
+ }
+#endif
}
if (status != Gdiplus::Status::Ok)
@@ -140,6 +302,8 @@ void TilesDrawer::DrawOverlays(TileCore* tile, RectF screenBounds, ImageAttribut
Debug::WriteLine("Failed to draw tile.");
}
}
+ else
+ ::OutputDebugStringA("TilesDrawer::DrawOverlays() bmp is null \r\n");
}
}
@@ -148,11 +312,13 @@ void TilesDrawer::DrawOverlays(TileCore* tile, RectF screenBounds, ImageAttribut
// ***************************************************************
void TilesDrawer::DumpTile(TileCore* tile, Bitmap* bmp)
{
- if (tile->tileX() == 0)
+ //if (tile->tileX() == 0)
{
CLSID clsid;
Utility::GetEncoderClsid(L"image/png", &clsid);
- bmp->Save(L"D:\\buffer.png", &clsid, NULL);
+ CStringW sFileName;
+ sFileName.Format(L"C:\\Temp\\tiles\\tile_%d_%d.png", tile->tileX(), tile->tileY());
+ bmp->Save(sFileName, &clsid, nullptr);
}
}
@@ -222,10 +388,24 @@ bool TilesDrawer::CalculateScreenBounds(TileCore* tile, RectF& screenBounds)
return false;
}
+#if DEBUG_TILES_DRAWER
+ CString text;
+ text.Format("CalculateScreenBounds(%d, %d) %f, %f, %f, %f\r\n", tile->tileX(), tile->tileY(), bounds->xLng, bounds->yLat, bounds->WidthLng, bounds->HeightLat);
+#if LOG_TILE_DRAWING
+ if (_pTileLog != nullptr)
+ {
+ _pTileLog->write(text.GetString(), text.GetLength());
+ _pTileLog->flush();
+ }
+#endif
+ ::OutputDebugStringA(text.GetBuffer());
+#endif
+
screenBounds.X = static_cast(x);
screenBounds.Y = static_cast(y);
screenBounds.Width = static_cast(width);
screenBounds.Height = static_cast(height);
+ //screenBounds.Height = static_cast(width);
return true;
}
diff --git a/src/Drawing/TilesDrawer.h b/src/Drawing/TilesDrawer.h
index 62147d34..a108421a 100644
--- a/src/Drawing/TilesDrawer.h
+++ b/src/Drawing/TilesDrawer.h
@@ -21,6 +21,8 @@
#include "basedrawer.h"
#include "TileManager.h"
+static int _tileDrawCount;
+
class TilesDrawer : public CBaseDrawer
{
public:
@@ -29,6 +31,10 @@ class TilesDrawer : public CBaseDrawer
: _graphics(g), _transfomation(transform)
{
_dc = NULL;
+#if LOG_TILE_DRAWING
+ _pTileLog = nullptr;
+#endif
+ _tileDrawCount = 0;
_extents = extents;
_pixelPerProjectionX = pixelPerProjectionX;
_pixelPerProjectionY = pixelPerProjectionY;
@@ -41,16 +47,23 @@ class TilesDrawer : public CBaseDrawer
Gdiplus::Graphics* _graphics;
IGeoProjection* _transfomation;
double _pixelPerMapUnit;
-
+#if LOG_TILE_DRAWING
+ std::ofstream* _pTileLog;
+#endif
public:
// properties
IGeoProjection* get_Transform() { return _transfomation; } // WGS84 to map transformation
+ int GetTileDrawCount() { return _tileDrawCount++; }
private:
bool IsSameProjection(IGeoProjection* mapProjection, BaseProvider* provider);
bool UpdateTileBounds(TileCore* tile, bool isSameProjection, int projectionChangeCount);
void DrawGrid(TileCore* tile, Gdiplus::RectF& screenRect);
+#if SQUARE_TILES
+ void DrawOverlays(TileCore* tile, int minTileY, int maxTileY, Gdiplus::RectF screenBounds, Gdiplus::ImageAttributes& attr);
+#else
void DrawOverlays(TileCore* tile, Gdiplus::RectF screenBounds, Gdiplus::ImageAttributes& attr);
+#endif
bool CalculateScreenBounds(TileCore* tile, Gdiplus::RectF& screenBounds);
void DrawGridText(TileCore* tile, Gdiplus::RectF& screenRect);
void InitImageAttributes(TileManager* manager, Gdiplus::ImageAttributes& attr);
diff --git a/src/Editor/ActiveShape.cpp b/src/Editor/ActiveShape.cpp
index f1e0c13c..06edd382 100644
--- a/src/Editor/ActiveShape.cpp
+++ b/src/Editor/ActiveShape.cpp
@@ -677,7 +677,7 @@ bool ActiveShape::HandlePointAdd(const double screenX, const double screenY, con
PixelToProj(screenX, screenY, projX, projY);
}
- AddPoint(projX, projY, screenX, screenY);
+ AddPoint(projX, projY, 0.0, 0.0, screenX, screenY);
UpdatePolyCloseState(true, closePointIndex);
@@ -687,7 +687,7 @@ bool ActiveShape::HandlePointAdd(const double screenX, const double screenY, con
// *******************************************************
// AddPoint()
// *******************************************************
-void ActiveShape::AddPoint(const double xProj, const double yProj, const double xScreen, const double yScreen, const PointPart part)
+void ActiveShape::AddPoint(const double xProj, const double yProj, const double z, const double m, const double xScreen, const double yScreen, const PointPart part)
{
ClearIfStopped();
@@ -697,6 +697,8 @@ void ActiveShape::AddPoint(const double xProj, const double yProj, const double
MeasurePoint* pnt = new MeasurePoint(); // TODO: Fix compile warning
pnt->Proj.x = xProj;
pnt->Proj.y = yProj;
+ pnt->z = z;
+ pnt->m = m;
pnt->Part = part;
_points.push_back(pnt);
@@ -712,7 +714,7 @@ void ActiveShape::AddPoint(const double xProj, const double yProj)
{
double xScreen, yScreen;
ProjToPixel(xProj, yProj, xScreen, yScreen);
- AddPoint(xProj, yProj, xScreen, yScreen);
+ AddPoint(xProj, yProj, 0.0, 0.0, xScreen, yScreen);
}
// **************************************************************
diff --git a/src/Editor/ActiveShape.h b/src/Editor/ActiveShape.h
index 8eb2747b..41a1d924 100644
--- a/src/Editor/ActiveShape.h
+++ b/src/Editor/ActiveShape.h
@@ -53,6 +53,7 @@ class ActiveShape : public GeoShape
ShowLength = true;
ShowTotalLength = true;
ShowArea = true;
+ EnableInsertVertex = true;
};
virtual ~ActiveShape() {
@@ -117,6 +118,8 @@ class ActiveShape : public GeoShape
tkAreaDisplayMode AreaDisplayMode;
tkBearingType BearingType;
tkAngleFormat AngleFormat;
+ bool EnableInsertVertex;
+ bool AllowSaveInvalidGeometry;
OLE_COLOR FillColor;
OLE_COLOR LineColor;
@@ -155,7 +158,7 @@ class ActiveShape : public GeoShape
virtual bool UndoPoint();
virtual bool GetPartStartAndEnd(int partIndex, MixedShapePart whichPoints, int& startIndex, int& endIndex);
ShapeInputMode GetInputMode() const { return _inputMode; }
- void AddPoint(double xProj, double yProj, double xScreen, double yScreen, PointPart part = PartNone);
+ void AddPoint(double xProj, double yProj, const double z, const double m, double xScreen, double yScreen, PointPart part = PartNone);
void AddPoint(double xProj, double yProj);
bool HandlePointAdd(double screenX, double screenY, bool ctrl);
int GetPointCount() const { return gsl::narrow_cast(_points.size()); }
diff --git a/src/Editor/MeasuringBase.cpp b/src/Editor/MeasuringBase.cpp
index 9b9e92aa..ea57229c 100644
--- a/src/Editor/MeasuringBase.cpp
+++ b/src/Editor/MeasuringBase.cpp
@@ -77,7 +77,7 @@ void MeasuringBase::HandleProjPointAdd(double projX, double projY)
{
double pixelX, pixelY;
_mapCallback->_ProjectionToPixel(projX, projY, &pixelX, &pixelY);
- AddPoint(projX, projY, pixelX, pixelY);
+ AddPoint(projX, projY, 0.0, 0.0, pixelX, pixelY);
}
// *******************************************************
diff --git a/src/Image/GdalRaster.cpp b/src/Image/GdalRaster.cpp
index a362fece..4f298e11 100644
--- a/src/Image/GdalRaster.cpp
+++ b/src/Image/GdalRaster.cpp
@@ -362,6 +362,19 @@ bool GdalRaster::ReadGeoTransform()
double adfGeoTransform[6];
bool success = _dataset->GetGeoTransform(adfGeoTransform) == CE_None;
+ if (!success) {
+ // IK-82, try to convert from GCP to GeoTransform, with looser tolerances (ApproxOK = True) (if we have GCP)
+ auto count = _dataset->GetGCPCount();
+ if (count > 0)
+ {
+ auto gcps = _dataset->GetGCPs();
+ success = CPL_TO_BOOL(GDALGCPsToGeoTransform(count, gcps, adfGeoTransform, TRUE));
+ CString sOutput;
+ sOutput.AppendFormat("GDALGCPsToGeoTransform(%d,..,TRUE): return: %s\r\n", count, success ? "true" : "false");
+ ::OutputDebugStringA(sOutput.GetBuffer());
+ }
+ }
+
m_globalSettings.SetGdalUtf8(false);
if (!success) return false;
diff --git a/src/MapControl/DispIds.h b/src/MapControl/DispIds.h
index 5b418dfe..05183f53 100644
--- a/src/MapControl/DispIds.h
+++ b/src/MapControl/DispIds.h
@@ -3,6 +3,8 @@ enum { //{{AFX_DISP_ID(CMapView)
// NOTE: ClassWizard will add and remove enumeration elements here
// DO NOT EDIT what you see in these blocks of generated code !
// **ClassWizard is a thing of the past... feel free to edit this code.
+ dispidGetDrawingLabelExtents = 270L,
+ dispidPlaceAllMapLabels = 269L,
dispidShowCoordinatesBackground = 268L,
dispidSetLatitudeLongitude = 267L,
dispidStartNewBoundShapeEx = 266L,
@@ -19,7 +21,7 @@ enum { //{{AFX_DISP_ID(CMapView)
dispidZoomToNext = 255L,
dispidShowCoordinatesFormat = 254L,
dispidLayerExtents = 253L,
- dispidCustomDrawingFlags = 252L,
+ dispidCustomDrawingFlags = 252L,
dispidFocusRectangle = 251L,
dispidIdentifiedShapes = 250L,
@@ -303,6 +305,7 @@ enum { //{{AFX_DISP_ID(CMapView)
eventidLayerReprojectedIncomplete = 39L,
eventidBeforeVertexDigitized = 40L,
eventidSnapPointRequested = 41L,
- eventidSnapPointFound = 42L
+ eventidSnapPointFound = 42L,
+ eventidFireVertexAdded = 43L
//}}AFX_DISP_ID
};
diff --git a/src/MapControl/GlobalSettingsInfo.h b/src/MapControl/GlobalSettingsInfo.h
index 3f9ba2a7..97d9dc5d 100644
--- a/src/MapControl/GlobalSettingsInfo.h
+++ b/src/MapControl/GlobalSettingsInfo.h
@@ -108,7 +108,7 @@ struct GlobalSettingsInfo
cacheDbfRecords = true;
overrideLocalCallback = true;
proxyAuthentication = asBasic;
- httpUserAgent = "MapWinGIS/5.4"; // TODO Use VERSION Macros
+ httpUserAgent = "MapWinGIS/5.5"; // TODO Use VERSION Macros
hereAppId = "";
hereAppCode = "";
bingApiKey = "";
@@ -180,7 +180,7 @@ struct GlobalSettingsInfo
shortUnitStrings[lsMeters] = L"m";
shortUnitStrings[lsKilometers] = L"km";
shortUnitStrings[lsSquareKilometers] = L"sq.km";
- shortUnitStrings[lsSquareMeters] = L"sq.m";
+ shortUnitStrings[lsSquareMeters] = L"m²";
shortUnitStrings[lsMapUnits] = L"mu";
shortUnitStrings[lsSquareMapUnits] = L"sq.mu";
shortUnitStrings[lsMiles] = L"mi";
diff --git a/src/MapControl/Map.cpp b/src/MapControl/Map.cpp
index c7090e5a..ef3202dd 100644
--- a/src/MapControl/Map.cpp
+++ b/src/MapControl/Map.cpp
@@ -146,9 +146,11 @@ BEGIN_EVENT_MAP(CMapView, COleControl)
EVENT_CUSTOM_ID("BeforeLayers", eventidBeforeLayers, FireBeforeLayers, VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4)
EVENT_CUSTOM_ID("AfterLayers", eventidAfterLayers, FireAfterLayers, VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4)
EVENT_CUSTOM_ID("LayerReprojectedIncomplete", eventidLayerReprojectedIncomplete, FireLayerReprojectedIncomplete, VTS_I4 VTS_I4 VTS_I4)
- EVENT_CUSTOM_ID("BeforeVertexDigitized", eventidBeforeVertexDigitized, FireBeforeVertexDigitized, VTS_PR8 VTS_PR8)
+ EVENT_CUSTOM_ID("BeforeVertexDigitized", eventidBeforeVertexDigitized, FireBeforeVertexDigitized, VTS_PR8 VTS_PR8 VTS_I4)
EVENT_CUSTOM_ID("SnapPointRequested", eventidSnapPointRequested, FireSnapPointRequested, VTS_R8 VTS_R8 VTS_PR8 VTS_PR8 VTS_PI4 VTS_PI4)
EVENT_CUSTOM_ID("SnapPointFound", eventidSnapPointFound, FireSnapPointFound, VTS_R8 VTS_R8 VTS_PR8 VTS_PR8)
+ EVENT_CUSTOM_ID("VertexAdded", eventidFireVertexAdded, FireVertexAdded, VTS_R8 VTS_R8)
+
EVENT_STOCK_DBLCLICK()
//}}AFX_EVENT_MAP
diff --git a/src/MapControl/Map.h b/src/MapControl/Map.h
index fcc01f71..b56f0287 100644
--- a/src/MapControl/Map.h
+++ b/src/MapControl/Map.h
@@ -632,6 +632,9 @@ class CMapView : public COleControl, IMapViewCallback
afx_msg VARIANT_BOOL GetRecenterMapOnZoom();
afx_msg void SetShowCoordinatesBackground(VARIANT_BOOL nNewValue);
afx_msg VARIANT_BOOL GetShowCoordinatesBackground();
+ afx_msg IPlacedLabels* PlaceAllMapLabels(long layerHandle);
+ afx_msg IExtents* GetDrawingLabelExtents(VARIANT* values); // long layerHandle, long index
+
#pragma endregion
//}}AFX_DISPATCH
@@ -707,9 +710,13 @@ class CMapView : public COleControl, IMapViewCallback
{
FireEvent(eventidValidateShape, EVENT_PARAM(VTS_I4 VTS_DISPATCH VTS_PI4), LayerHandle, Shape, Cancel);
}
- void FireBeforeVertexDigitized(DOUBLE* pointX, DOUBLE* pointY)
+ void FireBeforeVertexDigitized(DOUBLE* pointX, DOUBLE* pointY, long selectedVertex)
+ {
+ FireEvent(eventidBeforeVertexDigitized, EVENT_PARAM(VTS_PR8 VTS_PR8 VTS_I4), pointX, pointY, selectedVertex);
+ }
+ void FireVertexAdded(DOUBLE* pointX, DOUBLE* pointY)
{
- FireEvent(eventidBeforeVertexDigitized, EVENT_PARAM(VTS_PR8 VTS_PR8), pointX, pointY);
+ FireEvent(eventidFireVertexAdded, EVENT_PARAM(VTS_PR8 VTS_PR8), pointX, pointY);
}
void FireSnapPointRequested(DOUBLE pointX, DOUBLE pointY, DOUBLE* snappedX, DOUBLE* snappedY, tkMwBoolean* isFound, tkMwBoolean* isFinal)
{
@@ -1052,6 +1059,7 @@ class CMapView : public COleControl, IMapViewCallback
CString Crypt(CString str);
bool VerifySerial(CString str);
void DrawLayers(const CRect& rcBounds, Gdiplus::Graphics* graphics, bool layerBuffer = true);
+ int* PlaceLabels(const CRect& rcBounds, Gdiplus::Graphics* graphics, bool layerBuffer);
bool HasImages();
bool HasHotTracking();
bool HasVolatileShapefiles();
@@ -1158,6 +1166,7 @@ class CMapView : public COleControl, IMapViewCallback
void SetTempExtents(double left, double right, double top, double bottom, long Width, long Height);
void RestoreExtents();
void SetNewExtentsWithForcedZooming(Extent ext, bool zoomIn);
+ void SetNewExtentsWithZoomOut(Extent ext);
IExtents* GetMaxExtents();
DOUBLE DegreesPerMapUnit();
double UnitsPerPixel();
@@ -1360,7 +1369,8 @@ class CMapView : public COleControl, IMapViewCallback
virtual void _FireValidateShape(const LONG layerHandle, IDispatch* shape, tkMwBoolean* cancel) { FireValidateShape(layerHandle, shape, cancel); }
virtual void _FireAfterShapeEdit(const tkUndoOperation newShape, const LONG layerHandle, const LONG shapeIndex) { FireAfterShapeEdit(newShape, layerHandle, shapeIndex); }
virtual void _FireShapeValidationFailed(const LPCTSTR errorMessage) { FireShapeValidationFailed(errorMessage); }
- virtual void _FireBeforeVertexDigitized(DOUBLE* pointX, DOUBLE* pointY) { FireBeforeVertexDigitized(pointX, pointY); }
+ virtual void _FireBeforeVertexDigitized(DOUBLE* pointX, DOUBLE* pointY, long selectedVertex) { FireBeforeVertexDigitized(pointX, pointY, selectedVertex); }
+ virtual void _FireVertexAdded(DOUBLE* pointX, DOUBLE* pointY) { FireVertexAdded(pointX, pointY); }
virtual void _ZoomToEditor() { ZoomToEditor(); }
virtual void _SetMapCursor(const tkCursorMode mode, bool clearEditor) { UpdateCursor(mode, false); }
virtual void _Redraw(const tkRedrawType redrawType, const bool updateTiles, const bool atOnce) { RedrawCore(redrawType, atOnce, updateTiles); };
diff --git a/src/MapControl/MapViewCallback.h b/src/MapControl/MapViewCallback.h
index 53245955..2be2f24f 100644
--- a/src/MapControl/MapViewCallback.h
+++ b/src/MapControl/MapViewCallback.h
@@ -18,7 +18,8 @@ class IMapViewCallback
virtual void _FireValidateShape(LONG LayerHandle, IDispatch* Shape, tkMwBoolean* Cancel) = 0;
virtual void _FireAfterShapeEdit(tkUndoOperation action, LONG LayerHandle, LONG ShapeIndex) = 0;
virtual void _FireShapeValidationFailed(LPCTSTR ErrorMessage) = 0;
- virtual void _FireBeforeVertexDigitized(DOUBLE* pointX, DOUBLE* pointY) = 0;
+ virtual void _FireBeforeVertexDigitized(DOUBLE* pointX, DOUBLE* pointY, long selectedVertex) = 0;
+ virtual void _FireVertexAdded(DOUBLE* pointX, DOUBLE* pointY) = 0;
virtual void _ZoomToEditor() = 0;
virtual void _SetMapCursor(tkCursorMode mode, bool clearEditor) = 0;
virtual void _Redraw(tkRedrawType redrawType, bool updateTiles, bool atOnce) = 0;
diff --git a/src/MapControl/Map_DispatchMap.cpp b/src/MapControl/Map_DispatchMap.cpp
index c24edce6..a2c34800 100644
--- a/src/MapControl/Map_DispatchMap.cpp
+++ b/src/MapControl/Map_DispatchMap.cpp
@@ -295,7 +295,9 @@ BEGIN_DISPATCH_MAP(CMapView, COleControl)
DISP_FUNCTION_ID(CMapView, "RestartBackgroundLoading", dispidRestartBackgroundLoading, RestartBackgroundLoading, VT_EMPTY, VTS_I4)
DISP_FUNCTION_ID(CMapView, "StartNewBoundShape", dispidStartNewBoundShape, StartNewBoundShape, VT_BOOL, VTS_R8 VTS_R8)
DISP_FUNCTION_ID(CMapView, "StartNewBoundShapeEx", dispidStartNewBoundShapeEx, StartNewBoundShapeEx, VT_BOOL, VTS_I4)
- DISP_PROPERTY_EX_ID(CMapView, "ShowCoordinatesBackground", dispidShowCoordinatesBackground, GetShowCoordinatesBackground, SetShowCoordinatesBackground, VT_BOOL)
+ DISP_PROPERTY_EX_ID(CMapView, "ShowCoordinatesBackground", dispidShowCoordinatesBackground, GetShowCoordinatesBackground, SetShowCoordinatesBackground, VT_BOOL)
+ DISP_FUNCTION_ID(CMapView, "PlaceAllMapLabels", dispidPlaceAllMapLabels, PlaceAllMapLabels, VT_DISPATCH, VTS_I4)
+ DISP_FUNCTION_ID(CMapView, "GetDrawingLabelExtents", dispidGetDrawingLabelExtents, GetDrawingLabelExtents, VT_DISPATCH, VTS_VARIANT)
END_DISPATCH_MAP()
//}}AFX_DISPATCH_MAP
diff --git a/src/MapControl/Map_Drawing.cpp b/src/MapControl/Map_Drawing.cpp
index ed041839..f6977d94 100644
--- a/src/MapControl/Map_Drawing.cpp
+++ b/src/MapControl/Map_Drawing.cpp
@@ -124,8 +124,13 @@ void CMapView::HandleNewDrawing(CDC* pdc, const CRect& rcBounds, const CRect& rc
// passing main buffer to client for custom drawing
FireOnDrawbackBufferCore(g, _isSnapshot ? NULL : _bufferBitmap);
}
-
+#if DEBUG_ALLOCATED_OBJECTS
+ ComHelper::SetBreak(false);
+#endif
RedrawTools(g, rcBounds);
+#if DEBUG_ALLOCATED_OBJECTS
+ ComHelper::SetBreak(false);
+#endif
// redraw time and logo
DWORD endTick = GetTickCount();
@@ -336,6 +341,8 @@ void CMapView::RedrawWmsLayers(Gdiplus::Graphics* g)
gWms->Clear(Gdiplus::Color::Transparent);
}
+ //manager->VerifyLayers();
+
TilesDrawer drawer(gWms, &_extents, _pixelPerProjectionX, _pixelPerProjectionY, PixelsPerMapUnit(), GetWgs84ToMapTransform());
drawer.DrawTiles(manager, GetMapProjection(), _isSnapshot, _projectionChangeCount);
@@ -1047,7 +1054,11 @@ void CMapView::DrawImageLayer(const CRect& rcBounds, Layer* l, Gdiplus::Graphics
iimg->get_OriginalWidth(&width);
iimg->get_OriginalHeight(&height);
+#if BIG_TILE_SIZE
+ if ((width == 512 && height == 512) || _isSnapshot)
+#else
if ((width == 256 && height == 256) || _isSnapshot)
+#endif
{
// it's tiles, I don't want to cache bitmap here to avoid seams
// the same thing with Snapshot calls
@@ -1477,7 +1488,155 @@ void CloseMapRotation()
// TODO: implement
}
+// ******************************************************************
+// PlaceLabels()
+// ******************************************************************
+int* CMapView::PlaceLabels(const CRect& rcBounds, Gdiplus::Graphics* graphics, bool layerBuffer)
+{
+ if (_lockCount > 0 && !_isSnapshot)
+ return nullptr;
+
+ // clear extents of drawn labels and charts
+ this->ClearLabelFrames();
+
+ long endcondition = _activeLayers.size();
+ // nothing to draw
+ if (endcondition == 0)
+ return nullptr;
+
+ register int i;
+ long startcondition = 0;
+
+ // prepare for placing
+
+ // ------------------------------------------------------------------
+ // Check whether some layers are completely concealed by images
+ // no need to draw them then
+ // ------------------------------------------------------------------
+ bool* isConcealed = new bool[endcondition];
+ memset(isConcealed, 0, endcondition * sizeof(bool));
+
+ double scale = GetCurrentScale();
+ int zoom;
+ _tiles->get_CurrentZoom(&zoom);
+
+ if (layerBuffer)
+ CheckForConcealedImages(isConcealed, startcondition, endcondition, scale, zoom);
+
+ double currentScale = this->GetCurrentScale();
+
+ // collision avoidance
+ _collisionList.Clear();
+ CCollisionList collisionListLabels;
+ CCollisionList collisionListCharts;
+
+ CCollisionList* chosenListLabels = m_globalSettings.commonCollisionListForLabels ? (&_collisionList) : (&collisionListLabels);;
+ CCollisionList* chosenListCharts = m_globalSettings.commonCollisionListForCharts ? (&_collisionList) : (&collisionListCharts);;
+
+ // initializing classes for drawing
+ bool forceGdiplus = this->_rotateAngle != 0.0f || _isSnapshot;
+
+ CShapefileDrawer sfDrawer(graphics, &_extents, _pixelPerProjectionX, _pixelPerProjectionY, &_collisionList, this->GetCurrentScale(), this->GetCurrentZoom(), forceGdiplus);
+ CLabelDrawer lblDrawer(graphics, &_extents, _pixelPerProjectionX, _pixelPerProjectionY, currentScale, _currentZoom, chosenListLabels, _rotateAngle, _isSnapshot);
+
+ // mark all shapes as not drawn
+ for (int i = startcondition; i < endcondition; i++)
+ {
+ Layer* l = _allLayers[_activeLayers[i]];
+ if (l->IsShapefile() && l->wasRendered) // if it's hidden don't clear every time
+ {
+ CComPtr sf = NULL;
+ // don't mark as 'undrawn' if we're not going to redraw it
+ if (l->QueryShapefile(&sf) && ShapefileHelper::IsVolatile(sf) != layerBuffer)
+ {
+ ShapefileHelper::Cast(sf)->MarkUndrawn();
+ }
+ }
+ }
+
+ // run drawing
+ int shapeCount = 0;
+ for (int i = startcondition; i < endcondition; i++)
+ {
+ long layerHandle = _activeLayers[i];
+ Layer* l = _allLayers[layerHandle];
+ if (!l || !l->get_Object()) continue;
+
+ bool visible = l->IsVisible(scale, zoom) && !isConcealed[i];
+ l->wasRendered = visible;
+
+ if (visible)
+ {
+ if (l->IsImage())
+ {
+ if (!layerBuffer) continue;
+
+ LayerDrawer::DrawLabels(l, lblDrawer, vpAboveParentLayer);
+ }
+ else if (l->IsShapefile() || l->IsDynamicOgrLayer())
+ {
+
+ CComPtr sf = NULL;
+ if (l->IsDynamicOgrLayer())
+ {
+ // Try to get the data loaded so far & update labels & categories
+ l->UpdateShapefile();
+
+ // Get the shapefile
+ l->QueryShapefile(&sf);
+ }
+ else
+ {
+ // grab extents from shapefile in case they changed
+ l->UpdateExtentsFromDatasource();
+
+ if (!l->extents.Intersects(_extents))
+ continue;
+
+ // Update labels & categories
+ l->UpdateShapefile();
+ }
+
+ // layerBuffer == true indicates we're drawing the non-Volatile layers
+ if (l->QueryShapefile(&sf) && ShapefileHelper::IsVolatile(sf) == layerBuffer)
+ continue;
+
+ //LayerDrawer::DrawLabels(l, lblDrawer, vpAboveParentLayer);
+ auto ret = LayerDrawer::PlaceLabels(l, lblDrawer, vpAboveParentLayer);
+ }
+ }
+ }
+
+ shapeCount = sfDrawer.GetShapeCount();
+
+ if (layerBuffer)
+ _shapeCountInView = shapeCount;
+
+ if (!layerBuffer && shapeCount > _shapeCountInView)
+ _shapeCountInView = shapeCount;
+
+ // drawing labels and charts above the layers
+ for (i = 0; i < (int)_activeLayers.size(); i++)
+ {
+ Layer* l = _allLayers[_activeLayers[i]];
+
+ if (!l || !l->get_Object()) continue;
+
+ if (!l->IsVisible(scale, zoom)) continue;
+
+ CComPtr sf = NULL;
+ if (l->QueryShapefile(&sf) && ShapefileHelper::IsVolatile(sf) == layerBuffer)
+ continue;
+
+ //LayerDrawer::DrawLabels(l, lblDrawer, vpAboveAllLayers);
+ auto ret = LayerDrawer::PlaceLabels(l, lblDrawer, vpAboveAllLayers);
+ //LayerDrawer::DrawCharts(l, chartDrawer, vpAboveAllLayers);
+ }
+
+ if (isConcealed)
+ delete[] isConcealed;
+}
diff --git a/src/MapControl/Map_DrawingLayer.cpp b/src/MapControl/Map_DrawingLayer.cpp
index 15cd2ae5..23215868 100644
--- a/src/MapControl/Map_DrawingLayer.cpp
+++ b/src/MapControl/Map_DrawingLayer.cpp
@@ -5,6 +5,7 @@
#include "stdafx.h"
#include "Map.h"
#include "LabelDrawing.h"
+#include "Labels.h"
// ***************************************************************
// IsValidDrawList()
@@ -1005,6 +1006,85 @@ void CMapView::SetDrawingLabels(long DrawingLayerIndex, ILabels* newVal)
else
ErrorMessage(tkINVALID_DRAW_HANDLE);
}
-#pragma endregion
+// ***************************************************************
+// PlaceAllMapLabels
+// ***************************************************************
+IPlacedLabels* CMapView::PlaceAllMapLabels(long layerHandle)
+{
+ ::OutputDebugStringA("PlaceAllMapLabels");
+ auto currentScale = this->GetCurrentScale();
+ CCollisionList collisionListLabels;
+ CCollisionList* chosenListLabels = m_globalSettings.commonCollisionListForLabels ? (&_collisionList) : (&collisionListLabels);
+
+ Gdiplus::Graphics* graphics = Gdiplus::Graphics::FromImage(_layerBitmap);
+ graphics->Clear(Gdiplus::Color::Transparent);
+ graphics->SetCompositingMode(Gdiplus::CompositingModeSourceOver);
+
+ auto maxExtents = GetMaxExtents();
+ auto extents = new Extent(maxExtents);
+ CLabelDrawer lblDrawer(graphics, extents, _pixelPerProjectionX, _pixelPerProjectionY, currentScale, _currentZoom, chosenListLabels, _rotateAngle, _isSnapshot);
+
+ Layer* layer = _allLayers[layerHandle];
+ auto labels = layer->get_Labels();
+ auto array = lblDrawer.PlaceAllMapLabels(labels);
+ IPlacedLabels* placedLabels;
+ ComHelper::CreateInstance(idPlacedLabels, (IDispatch**)&placedLabels);
+
+ auto indexes = array.data();
+ placedLabels->SetVector(indexes, array.size());
+
+ return placedLabels;
+}
+
+// ***************************************************************
+// GetLabelExtents
+// ***************************************************************
+IExtents* CMapView::GetDrawingLabelExtents(VARIANT* variant) //long layerHandle, long index)
+{
+ SAFEARRAY* sar = *variant->pparray;
+ auto values = static_cast(sar->pvData);
+ auto layerHandle = values[0];
+ auto index = values[1];
+ auto currentScale = this->GetCurrentScale();
+ CCollisionList collisionListLabels;
+ CCollisionList* chosenListLabels = m_globalSettings.commonCollisionListForLabels ? (&_collisionList) : (&collisionListLabels);
+
+ Gdiplus::Graphics* graphics = Gdiplus::Graphics::FromImage(_layerBitmap);
+ graphics->Clear(Gdiplus::Color::Transparent);
+ graphics->SetCompositingMode(Gdiplus::CompositingModeSourceOver);
+
+ auto maxExtents = GetMaxExtents();
+ auto extents = new Extent(maxExtents);
+ CLabelDrawer lblDrawer(graphics, extents, _pixelPerProjectionX, _pixelPerProjectionY, currentScale, _currentZoom, chosenListLabels, _rotateAngle, _isSnapshot);
+
+ IExtents* box;
+ ComHelper::CreateExtents(&box);
+ ILabels* labels = nullptr;
+ if(IsValidDrawList(layerHandle))
+ {
+ _allDrawLists[layerHandle]->m_labels->AddRef();
+ labels = _allDrawLists[layerHandle]->m_labels;
+
+ auto rect = lblDrawer.GetLabelExtents(labels, index);
+ box->SetBounds(rect.left, rect.bottom, 0.0, rect.right, rect.top, 0.0);
+ }
+
+ /*CLabels* lbs = static_cast(labels);
+ vector*>* labelData = lbs->get_LabelData();
+ vector* parts = (*labelData)[index];
+ CLabelInfo* lbl = (*parts)[0]; */
+
+ /*ILabel* pLabel;
+ ComHelper::CreateInstance(idLabel, reinterpret_cast(&pLabel));
+ labels->get_Label(index, 0, &pLabel);
+ *pLabel-> */
+
+
+ //box->SetBounds(layer->extents.left, layer->extents.bottom, 0.0, layer->extents.right, layer->extents.top, 0.0);
+
+ return box;
+}
+
+#pragma endregion
diff --git a/src/MapControl/Map_Dynamic.cpp b/src/MapControl/Map_Dynamic.cpp
index a5358118..06e4a6e7 100644
--- a/src/MapControl/Map_Dynamic.cpp
+++ b/src/MapControl/Map_Dynamic.cpp
@@ -145,7 +145,7 @@ void CMapView::DrawShapeEditor( Gdiplus::Graphics* g, bool dynamicBuffer )
// ****************************************************************
void CMapView::DrawZoombox(Gdiplus::Graphics* g)
{
- bool zooming = m_cursorMode == cmZoomIn && _dragging.Operation == DragZoombox;
+ bool zooming = (m_cursorMode == cmZoomIn || m_cursorMode == cmZoomOut ) && _dragging.Operation == DragZoombox;
bool selection = m_cursorMode == cmSelection && _dragging.Operation == DragSelectionBox;
bool drawZoombox = _leftButtonDown && _dragging.Start != _dragging.Move && (zooming || selection);
@@ -153,7 +153,7 @@ void CMapView::DrawZoombox(Gdiplus::Graphics* g)
{
CRect r = _dragging.GetRectangle();
Gdiplus::Rect rect(r.left, r.top, r.right - r.left, r.bottom - r.top);
-
+
g->SetPixelOffsetMode(Gdiplus::PixelOffsetMode::PixelOffsetModeHighQuality);
if (selection)
{
diff --git a/src/MapControl/Map_Edit.cpp b/src/MapControl/Map_Edit.cpp
index d34ba7f3..b9f17391 100644
--- a/src/MapControl/Map_Edit.cpp
+++ b/src/MapControl/Map_Edit.cpp
@@ -32,6 +32,9 @@ bool CMapView::HandleLButtonUpDragVertexOrShape(UINT nFlags)
bool shift = (nFlags & MK_SHIFT) != 0;
bool alt = GetKeyState(VK_MENU) < 0 ? true : false;
+ // dhe
+ alt = true;
+
if (SnappingIsOn(shift))
{
VARIANT_BOOL result = this->FindSnapPointCore(_dragging.Move.x, _dragging.Move.y, &x2, &y2);
@@ -39,8 +42,11 @@ bool CMapView::HandleLButtonUpDragVertexOrShape(UINT nFlags)
return true; // can't proceed without snapping in this mode
}
+ int selectedVertex;
+ auto ret = _shapeEditor->get_SelectedVertex(&selectedVertex);
+
if (alt) { // user wants to intercept coordinates and possibly modify them
- this->FireBeforeVertexDigitized(&x2, &y2);
+ this->FireBeforeVertexDigitized(&x2, &y2, selectedVertex);
}
GetEditorBase()->MoveVertex(x2, y2); // don't save state; it's already saved at the beginning of operation
@@ -88,8 +94,18 @@ bool CMapView::HandleOnMouseMoveShapeEditor(int x, int y, long nFlags)
// get Snap setting
_shapeEditor->get_SnapBehavior(&snapBehavior);
+#if DEBUG_ALLOCATED_OBJECTS
+ ComHelper::SetBreak(false);
+ auto preCount = gReferenceCounter.GetReferenceCount();
+#endif
double projX, projY;
VARIANT_BOOL snapped = FindSnapPointCore(x, y, &projX, &projY);
+#if DEBUG_ALLOCATED_OBJECTS
+ auto postCount = gReferenceCounter.GetReferenceCount();
+ if (preCount < postCount)
+ ::OutputDebugStringA("Increased!");
+ ComHelper::SetBreak(false);
+#endif
if (!snapped) {
PixelToProjection(x, y, projX, projY);
GetEditorBase()->ClearSnapPoint();
diff --git a/src/MapControl/Map_Events.cpp b/src/MapControl/Map_Events.cpp
index 69108b35..a3db8a2b 100644
--- a/src/MapControl/Map_Events.cpp
+++ b/src/MapControl/Map_Events.cpp
@@ -551,15 +551,15 @@ void CMapView::OnLButtonDown(UINT nFlags, CPoint point)
if (m_cursorMode == cmAddShape) {
if (StartNewBoundShape(projX, projY) != VARIANT_TRUE) return;
}
-
if (alt) { // user wants to intercept coordinates and possibly modify them
- this->FireBeforeVertexDigitized(&projX, &projY);
+ this->FireBeforeVertexDigitized(&projX, &projY, -1);
}
if (Digitizer::OnMouseDown(_shapeEditor, projX, projY, ctrl)) {
+ //this->FireVertexAdded(&projX, &projY);
UpdateShapeEditor();
}
-
+
return;
}
@@ -568,13 +568,29 @@ void CMapView::OnLButtonDown(UINT nFlags, CPoint point)
{
case cmEditShape:
{
+ if( m_sendMouseDown == TRUE )
+ this->FireMouseDown(MK_LBUTTON, (short)vbflags, x, y);
if (!VertexEditor::OnMouseDown(this, _shapeEditor, projX, projY, ctrl, shift))
{
+#if DEBUG_ALLOCATED_OBJECTS
+ ComHelper::SetBreak(true);
+ auto preCount = gReferenceCounter.GetReferenceCount();
+#endif
long layerHandle, shapeIndex;
if (SelectShapeForEditing(x, y, layerHandle, shapeIndex))
{
VertexEditor::StartEdit(_shapeEditor, layerHandle, shapeIndex);
}
+#if DEBUG_ALLOCATED_OBJECTS
+ auto postCount = gReferenceCounter.GetReferenceCount();
+ if (preCount < postCount)
+ {
+ ::OutputDebugStringA("Increased!");
+ auto report = gReferenceCounter.GetReferenceReport();
+ ::OutputDebugStringA(report.GetBuffer());
+ }
+ ComHelper::SetBreak(false);
+#endif
}
UpdateShapeEditor();
}
@@ -631,7 +647,9 @@ void CMapView::OnLButtonDown(UINT nFlags, CPoint point)
break;
case cmZoomOut:
{
- ZoomToCursorPosition(false);
+ //ZoomToCursorPosition(false);
+ this->SetCapture();
+ _dragging.Operation = DragZoombox;
break;
}
case cmPan:
@@ -694,12 +712,14 @@ void CMapView::OnLButtonDblClk(UINT nFlags, CPoint point)
bool alt = GetKeyState(VK_MENU) < 0 ? true : false;
if (alt) { // user wants to intercept coordinates and possibly modify them
- this->FireBeforeVertexDigitized(&projX, &projY);
+ this->FireBeforeVertexDigitized(&projX, &projY, -1);
}
if (_shapeEditor->GetClosestPoint(projX, projY, projX, projY))
{
- if (_shapeEditor->InsertVertex(projX, projY)) {
+ VARIANT_BOOL enableInsertVertex;
+ _shapeEditor->get_EnableInsertVertex(&enableInsertVertex);
+ if (enableInsertVertex && _shapeEditor->InsertVertex(projX, projY)) {
RedrawCore(tkRedrawType::RedrawSkipDataLayers, true);
return;
}
@@ -785,7 +805,13 @@ void CMapView::OnLButtonUp(UINT nFlags, CPoint point)
case DragZoombox:
case DragSelectionBox:
{
+#if DEBUG_ALLOCATED_OBJECTS
+ ComHelper::SetBreak(false);
+#endif
HandleLButtonUpZoomBox(vbflags, point.x, point.y);
+#if DEBUG_ALLOCATED_OBJECTS
+ ComHelper::SetBreak(false);
+#endif
}
break;
}
@@ -955,6 +981,9 @@ void CMapView::HandleLButtonUpZoomBox(long vbflags, long x, long y)
case cmZoomIn:
ZoomToCursorPosition(true);
break;
+ case cmZoomOut:
+ ZoomToCursorPosition(false);
+ break;
case cmSelection:
if (sf || selectingSelectable)
{
@@ -1077,6 +1106,9 @@ void CMapView::HandleLButtonUpZoomBox(long vbflags, long x, long y)
case cmZoomIn:
SetNewExtentsWithForcedZooming(box, true);
break;
+ case cmZoomOut:
+ SetNewExtentsWithZoomOut(box);
+ break;
case cmSelection:
if (sf)
{
@@ -1416,6 +1448,9 @@ void CMapView::OnMouseMove(UINT nFlags, CPoint point)
if (updateHotTracking && _dragging.Operation == DragNone)
{
LayerShape info;
+#if DEBUG_ALLOCATED_OBJECTS
+ ComHelper::SetBreak(false);
+#endif
HotTrackingResult result = RecalcHotTracking(point, info);
switch (result)
{
@@ -1432,6 +1467,9 @@ void CMapView::OnMouseMove(UINT nFlags, CPoint point)
// do nothing
break;
}
+#if DEBUG_ALLOCATED_OBJECTS
+ ComHelper::SetBreak(false);
+#endif
}
if (_showCoordinates != cdmNone) {
@@ -1514,8 +1552,14 @@ void CMapView::OnRButtonDown(UINT nFlags, CPoint point)
long vbflags = ParseKeyboardEventFlags(nFlags);
+#if DEBUG_ALLOCATED_OBJECTS
+ ComHelper::SetBreak(false);
+#endif
if( m_sendMouseDown == TRUE )
this->FireMouseDown( MK_RBUTTON, (short)vbflags, point.x, point.y );
+#if DEBUG_ALLOCATED_OBJECTS
+ ComHelper::SetBreak(false);
+#endif
if (_doTrapRMouseDown)
{
diff --git a/src/MapControl/Map_Scale.cpp b/src/MapControl/Map_Scale.cpp
index 82cb59cc..68f03e4a 100644
--- a/src/MapControl/Map_Scale.cpp
+++ b/src/MapControl/Map_Scale.cpp
@@ -293,6 +293,32 @@ void CMapView::SetNewExtentsWithForcedZooming(Extent ext, bool zoomIn)
SetExtentsCore(Extent(cLeft, cRight, cBottom, cTop));
}
+// ****************************************************
+// SetNewExtentsWithZoomOut()
+// ****************************************************
+// Sets new extents by zooming out using given extent (drawn rectangle)
+void CMapView::SetNewExtentsWithZoomOut(Extent ext)
+{
+ auto extent = GetExtents();
+ if (extent == NULL) return;
+
+ double width, height;
+ extent->get_Width(&width);
+ extent->get_Height(&height);
+
+ auto const pt = ext.GetCenter();
+ auto const widthFactor = width / ext.Width();
+ auto const heightFactor = height / ext.Height();
+ width *= widthFactor;
+ height *= heightFactor;
+
+ double zMin, zMax;
+ extent->get_zMin(&zMin);
+ extent->get_zMax(&zMax);
+ extent->SetBounds(pt.x - width / 2, pt.y - height / 2, zMin, pt.x + width / 2, pt.y + height / 2, zMax);
+ SetExtents(extent);
+}
+
// ****************************************************
// SetExtentsCore()
// ****************************************************
@@ -466,7 +492,9 @@ VARIANT_BOOL CMapView::SetGeographicExtents(IExtents* extents)
if (_transformationMode == tmNotDefined)
{
+#if RELEASE_MODE
this->ErrorMessage(tkTRANSFORMATIONMODE_NOT_DEFINED);
+#endif
return VARIANT_FALSE;
}
@@ -556,6 +584,11 @@ IExtents* CMapView::GetGeographicExtents()
// ***************************************************************
bool CMapView::GetGeographicExtentsInternal(bool clipForTiles, Extent* clipExtents, Extent& result)
{
+ if (clipExtents != nullptr)
+ {
+ ::OutputDebugStringA(clipExtents->ToString());
+ ::OutputDebugStringA("\r\n");
+ }
// we don't want to have coordinates outside world bounds, as it breaks tiles loading
IExtents* ext = GetGeographicExtentsCore(clipForTiles, clipExtents);
if (!ext) return false;
@@ -564,6 +597,8 @@ bool CMapView::GetGeographicExtentsInternal(bool clipForTiles, Extent* clipExten
ext->Release();
result = bounds;
+ ::OutputDebugStringA(result.ToString());
+ ::OutputDebugStringA("\r\n");
return true;
}
@@ -855,7 +890,8 @@ void CMapView::ZoomToMaxVisibleExtents(void)
{
const double xrange = l->extents.right - l->extents.left;
const double yrange = l->extents.top - l->extents.bottom;
- if (xrange == 0 && yrange == 0 && l->extents.right == 0 && l->extents.top == 0)
+ if ((xrange == 0 && yrange == 0 && l->extents.right == 0 && l->extents.top == 0) ||
+ std::isinf(xrange) || std::isinf(yrange) || std::isinf(l->extents.right) || std::isinf(l->extents.top))
continue;
if (extentsSet == false)
@@ -972,6 +1008,10 @@ void CMapView::CalculateVisibleExtents(Extent e, bool MapSizeChanged)
double bottom = MIN(e.bottom, e.top);
double top = MAX(e.bottom, e.top);
+ CString sOutput;
+ sOutput.AppendFormat("CalculateVisibleExtents() left: %.2f, right: %.2f, bottom: %.2f, top: : %.2f\r\n", left, right, bottom, top);
+ ::OutputDebugStringA(sOutput.GetBuffer());
+
if (left == right) // lsu 26 jul 2009 for zooming to single point
{
left -= 0.5;
diff --git a/src/MapControl/Map_Tiles.cpp b/src/MapControl/Map_Tiles.cpp
index 848cea75..8e835970 100644
--- a/src/MapControl/Map_Tiles.cpp
+++ b/src/MapControl/Map_Tiles.cpp
@@ -86,7 +86,15 @@ int CMapView::ChooseZoom(BaseProvider* provider, Extent ext, double scalingRatio
tileSize *= PixelsPerMapUnit();
+#if BIG_TILE_SIZE
+ auto tileImageSize = 512;
+ auto customProvider = reinterpret_cast(provider);
+ if (customProvider != nullptr)
+ tileImageSize = static_cast(customProvider->get_TileSize());
+ int minSize = (int)(tileImageSize * scalingRatio * ratio);
+#else
int minSize = (int)(256 * scalingRatio * ratio);
+#endif
if (tileSize < minSize) {
break;
}
diff --git a/src/MapWinGIS-toolset142.sln b/src/MapWinGIS-toolset142.sln
new file mode 100644
index 00000000..f6ff325f
--- /dev/null
+++ b/src/MapWinGIS-toolset142.sln
@@ -0,0 +1,33 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MapWinGIS", "MapWinGIS-toolset142.vcxproj", "{1AB93398-2DE6-4043-BF6D-D438A794FB86}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ VLD|Win32 = VLD|Win32
+ VLD|x64 = VLD|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {1AB93398-2DE6-4043-BF6D-D438A794FB86}.Debug|Win32.ActiveCfg = Debug|Win32
+ {1AB93398-2DE6-4043-BF6D-D438A794FB86}.Debug|Win32.Build.0 = Debug|Win32
+ {1AB93398-2DE6-4043-BF6D-D438A794FB86}.Debug|x64.ActiveCfg = Debug|x64
+ {1AB93398-2DE6-4043-BF6D-D438A794FB86}.Debug|x64.Build.0 = Debug|x64
+ {1AB93398-2DE6-4043-BF6D-D438A794FB86}.Release|Win32.ActiveCfg = Release|Win32
+ {1AB93398-2DE6-4043-BF6D-D438A794FB86}.Release|Win32.Build.0 = Release|Win32
+ {1AB93398-2DE6-4043-BF6D-D438A794FB86}.Release|x64.ActiveCfg = Release|x64
+ {1AB93398-2DE6-4043-BF6D-D438A794FB86}.Release|x64.Build.0 = Release|x64
+ {1AB93398-2DE6-4043-BF6D-D438A794FB86}.VLD|Win32.ActiveCfg = VLD|Win32
+ {1AB93398-2DE6-4043-BF6D-D438A794FB86}.VLD|Win32.Build.0 = VLD|Win32
+ {1AB93398-2DE6-4043-BF6D-D438A794FB86}.VLD|x64.ActiveCfg = Debug|x64
+ {1AB93398-2DE6-4043-BF6D-D438A794FB86}.VLD|x64.Build.0 = Debug|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/src/MapWinGIS-toolset142.vcxproj b/src/MapWinGIS-toolset142.vcxproj
new file mode 100644
index 00000000..f7f38e0f
--- /dev/null
+++ b/src/MapWinGIS-toolset142.vcxproj
@@ -0,0 +1,957 @@
+
+
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+ VLD
+ Win32
+
+
+ VLD
+ x64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+
+ {1AB93398-2DE6-4043-BF6D-D438A794FB86}
+ MapWinGIS
+ MFCProj
+ 10.0.17134.0
+ MapWinGIS
+
+
+
+ DynamicLibrary
+ false
+ false
+ MultiByte
+ v142
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+ $(SolutionDir)bin\$(Platform)\
+ $(Configuration)\$(Platform)\
+ false
+ false
+ AllRules.ruleset
+
+
+ .ocx
+ true
+
+
+ false
+ false
+
+
+
+
+ Copying executables...
+ $(ProjectDir)CopyTamasFiles.bat $(ProjectDir)..\Support\GDAL_SDK\$(PlatformToolset)\bin\$(Platform) $(TargetDir)
+
+
+
+
+
+
+ %(Outputs)
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ %(AdditionalIncludeDirectories)
+ 3
+ true
+ false
+ true
+ false
+
+
+
+ /MP %(AdditionalOptions)
+ Disabled
+ false
+ Default
+ false
+ Speed
+ true
+ true
+ $(ProjectDir)..\Support\include;$(ProjectDir)..\Support\include\atlhttp;$(ProjectDir)..\support\include\ShapeLib;$(ProjectDir);$(ProjectDir)\COM classes;$(ProjectDir)\ComHelpers;$(ProjectDir)\MapControl;$(ProjectDir)\Drawing;$(ProjectDir)\Grid;$(ProjectDir)\Image;$(ProjectDir)\Processing;$(ProjectDir)\Shapefile;$(ProjectDir)\ShapeNetwork;$(ProjectDir)\Structures;$(ProjectDir)\Tin;$(ProjectDir)\Utilities;$(ProjectDir)\Grid\fip;$(ProjectDir)\Utilities\SpatialIndex;$(ProjectDir)\Tiles;$(ProjectDir)\Tiles\Providers;$(ProjectDir)\Tiles\Caching;$(ProjectDir)\Tiles\Loaders;$(ProjectDir)\Tiles\Projections;$(ProjectDir)\Tiles\Http;$(ProjectDir)\Utilities\SQLite;$(ProjectDir)..\Support\GDAL_SDK\$(PlatformToolset)\include\$(Platform);$(ProjectDir)..\Support\GDAL_SDK\$(PlatformToolset)\include\$(Platform)\curl;$(ProjectDir)\Ogr;$(ProjectDir)\Editor;C:\SWDEV\Projects\Lib\MapWinGIS_org\src\vcpkg_installed\x64-windows\include;%(AdditionalIncludeDirectories)
+ _NDBGSYMBOLS;_WINDOWS;_USRDLL;_AFXDLL;_CRT_SECURE_NO_WARNINGS;GEOS_NEW;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)
+ false
+ false
+ Sync
+ Default
+ MultiThreadedDLL
+ false
+ false
+ Use
+ stdafx.h
+ $(IntDir)$(TargetName).pch
+ $(IntDir)
+ $(IntDir)
+ $(IntDir)
+ false
+ Level3
+ true
+ ProgramDatabase
+ Default
+ false
+ false
+ 4503
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ 0x0409
+ %(AdditionalIncludeDirectories);$(intdir)
+
+
+
+
+
+ true
+ /ignore:4099 /Ignore:4254 %(AdditionalOptions)
+ cqlib.lib;GdiPlus.lib;gdal_i.lib;version.lib;Crypt32.lib;Dbghelp.lib;SpatialIndex-mw.lib;geos_c.lib;libtiff_i.lib;ShapeLib.lib;libcurl_imp.lib;%(AdditionalDependencies)
+ NotSet
+ $(OutDir)MapWinGIS.ocx
+ true
+ $(ProjectDir)..\Support\GDAL_SDK\$(PlatformToolset)\lib\$(Platform);$(ProjectDir)..\Support\lib\$(PlatformToolset)\$(Platform)\Release;%(AdditionalLibraryDirectories)
+ false
+ LIBC.lib;%(IgnoreSpecificDefaultLibraries)
+
+
+ %(DelayLoadDLLs)
+ true
+ $(OutDir)MapWinGIS.pdb
+ Windows
+ Default
+ false
+
+
+ $(IntDir)MapWinGIS.lib
+ $(IntDir)MapWinGIS.tlb
+ 2
+
+
+ $(IntDir)$(ProjectName).bsc
+
+
+ if $(PlatformName) == Win32 setx MapWinGISBin32 $(OutputPath)
+if $(PlatformName) == x64 setx MapWinGISBin64 $(OutputPath)
+
+
+
+
+
+ Win32
+
+
+ WIN32;%(PreprocessorDefinitions)
+ false
+
+
+ /MACHINE:I386 %(AdditionalOptions)
+ MachineX86
+
+
+
+
+
+ x64
+
+
+ WIN64;%(PreprocessorDefinitions)
+ stdcpp20
+
+
+ /MACHINE:x64 %(AdditionalOptions)
+ MachineX64
+
+
+
+
+
+ VLD_FORCE_ENABLE;%(PreprocessorDefinitions)
+
+
+ false
+
+
+
+
+
+ Full
+ false
+ RELEASE_MODE;%(PreprocessorDefinitions)
+ false
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Create
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MapWinGIS_i.h
+ MapWinGIS_i.c
+ $(IntDir)MapWinGIS.tlb
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/MapWinGIS.cpp b/src/MapWinGIS.cpp
index c8987529..6a7e9b37 100644
--- a/src/MapWinGIS.cpp
+++ b/src/MapWinGIS.cpp
@@ -31,12 +31,15 @@ static char THIS_FILE[] = __FILE__;
const GUID CDECL BASED_CODE _tlid = { 0xc368d713, 0xcc5f, 0x40ed, { 0x9f, 0x53, 0xf8, 0x4f, 0xe1, 0x97, 0xb9, 0x6a } };
const WORD _wVerMajor = 5;
-const WORD _wVerMinor = 4;
+const WORD _wVerMinor = 5;
CMapWinGISApp NEAR theApp;
CMapWinGISModule _AtlModule; // this one is from ATL7 (used by all ATL co-classes)
CComModule _Module; // this one is from ATL3 (used for ShapefileColorScheme and ShapefileColorBreak)
GlobalClassFactory m_factory; // make sure that this one is initialized after the _Module above
+#if DEBUG_ALLOCATED_OBJECTS
+bool _break;
+#endif
// ******************************************************
// CMapWinGISApp::InitInstance - DLL initialization
diff --git a/src/MapWinGIS.h b/src/MapWinGIS.h
index 127ceb67..3b85cf55 100644
--- a/src/MapWinGIS.h
+++ b/src/MapWinGIS.h
@@ -11,7 +11,7 @@
#include "GlobalClassFactory.h"
#define VERSION_MAJOR 5
-#define VERSION_MINOR 4
+#define VERSION_MINOR 5
extern const GUID CDECL _tlid;
extern const WORD _wVerMajor;
@@ -31,6 +31,9 @@ class CMapWinGISApp : public COleControlModule
};
extern GlobalClassFactory m_factory;
+#if DEBUG_ALLOCATED_OBJECTS
+extern bool _break;
+#endif
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
\ No newline at end of file
diff --git a/src/MapWinGIS.idl b/src/MapWinGIS.idl
index b8d95aff..98f759d4 100644
--- a/src/MapWinGIS.idl
+++ b/src/MapWinGIS.idl
@@ -69,6 +69,7 @@ interface IFunction;
interface IExpression;
interface IWmsLayer;
interface IGdalUtils;
+interface IPlacedLabels;
/************************** tkWmsVersion Enumeration **********************/
typedef
@@ -98,6 +99,21 @@ enum tkWmsBoundingBoxOrder
bboLatLong = 2,
} tkWmsBoundingBoxOrder;
+
+/************************** tkWmsTileSize Enumeration **********************/
+typedef
+[
+ uuid(5A91B5E6-A6BE-45F5-B2A1-B0ACC8F152BA),
+ helpstring("tkWmsTileSize"),
+]
+enum tkWmsTileSize
+{
+ sizeFullScreen = -100,
+ size256x256 = 256,
+ size512x512 = 512,
+ size1024x1024 = 1024,
+} tkWmsTileSize;
+
/************************** tkCallbackVerbosity Enumeration **********************/
typedef
[
@@ -621,6 +637,7 @@ enum tkAreaDisplayMode
admMetric = 0,
admHectars = 1,
admAmerican = 2,
+ admMetricMeters = 3,
} tkAreaDisplayMode;
/************************** tkCustomState Enumeration **********************/
@@ -1193,7 +1210,9 @@ enum tkInterface
idFunction = 50,
idExpression = 51,
idWmsLayer = 52,
- idGdalUtils = 53
+ idGdalUtils = 53,
+ idPlacedLabels = 54
+
} tkInterface;
typedef
@@ -3717,6 +3736,10 @@ interface IShapeEditor : IDispatch {
[id(62)] HRESULT AddPoint([in] IPoint* newPoint, [out, retval] VARIANT_BOOL* retVal);
[propget, id(63)] HRESULT SnapMode([out, retval] tkSnapMode* pVal);
[propput, id(63)] HRESULT SnapMode([in] tkSnapMode newVal);
+ [propget, id(64)] HRESULT EnableInsertVertex([out, retval] VARIANT_BOOL* pVal);
+ [propput, id(64)] HRESULT EnableInsertVertex([in] VARIANT_BOOL newVal);
+ [propget, id(65)] HRESULT AllowSaveInvalidGeometry([out, retval] VARIANT_BOOL* pVal);
+ [propput, id(65)] HRESULT AllowSaveInvalidGeometry([in] VARIANT_BOOL newVal);
};
@@ -5054,6 +5077,12 @@ interface ILabel : IDispatch {
[propget, id(10), helpstring("property OffsetY")] HRESULT OffsetY([out, retval] double* retval);
[propput, id(10), helpstring("property OffsetY")] HRESULT OffsetY([in] double newVal);
+
+ [propget, id(11), helpstring("property MapExtents")] HRESULT MapExtents(double inversePixelPerProjection, [out, retval] IExtents** retval);
+
+ [propget, id(12)] HRESULT Key([out, retval]BSTR* retVal);
+ [propput, id(12)] HRESULT Key([in]BSTR newVal);
+
};
// *********************************** Labels Interface *******************************
@@ -5329,6 +5358,15 @@ interface ILabels : IDispatch {
[propget, id(107), helpstring("property OffsetYField")] HRESULT OffsetYField([out, retval] long* retval);
[propput, id(107), helpstring("property OffsetYField")] HRESULT OffsetYField([in] long newVal);
[id(108)] HRESULT ApplyLabelExpression();
+ [propget, id(109), helpstring("property LabelDrawnInMap")] HRESULT LabelDrawnInMap([in]long Index, [out, retval] VARIANT_BOOL* pVal);
+
+ midl_pragma warning(disable:2402)
+ // function effectively requires the LabelIndices and PartIndices parameters,
+ // they were made optional only because they follow other optional parameters,
+ // and cannot reasonably be changed without breaking the interface.
+ // this pragma disables the warning only for this (and similar) functions.
+ [id(110), helpstring("method SelectNotDrawn")] HRESULT SelectNotDrawn([in]IExtents* BoundingBox, [in, optional, out]VARIANT* LabelIndices, [in, optional, out]VARIANT* PartIndices, [out, retval]VARIANT_BOOL* retval);
+ midl_pragma warning(enable:2402)
};
// ******************************* LabelCategory Interface *****************************
@@ -6725,6 +6763,10 @@ interface IWmsLayer : IDispatch {
[propput, id(27)] HRESULT Version([in] tkWmsVersion newVal);
[propget, id(28)] HRESULT Styles([out, retval] BSTR* pVal);
[propput, id(28)] HRESULT Styles([in] BSTR newVal);
+ [propget, id(29)] HRESULT BoundingBoxOrder([out, retval] tkWmsBoundingBoxOrder* pVal);
+ [propput, id(29)] HRESULT BoundingBoxOrder([in] tkWmsBoundingBoxOrder newVal);
+ [propget, id(30)] HRESULT TileSize([out, retval] LONG* pVal);
+ [propput, id(30)] HRESULT TileSize([in] LONG newVal);
};
/**************************** Gdal Utils Interface ***********************/
@@ -6752,7 +6794,20 @@ interface IGdalUtils : IDispatch {
}
[
- uuid(C368D713-CC5F-40ED-9F53-F84FE197B96A), version(5.4),
+ object,
+ uuid(399E8B54-795C-4C7F-84CF-4B127DD4DF5B),
+ dual,
+ nonextensible,
+ pointer_default(unique)
+]
+interface IPlacedLabels : IDispatch {
+ [propget, id(1), helpstring("property NumIndex")] HRESULT NumIndex([out, retval] long* pVal);
+ [id(2), helpstring("method GetIndexes")] HRESULT GetIndexes([out, retval] SAFEARRAY(long)* retval);
+ [id(3), helpstring("method SetVector")] HRESULT SetVector([in] int* indexes, int length);
+};
+
+[
+ uuid(C368D713-CC5F-40ED-9F53-F84FE197B96A), version(5.5),
helpfile("MapWinGIS.chm"),
helpstring("MapWinGIS Components"),
control
@@ -6774,7 +6829,7 @@ library MapWinGIS
// Primary dispatch interface for CMap
[uuid(1D077739-E866-46A0-B256-8AECC04F2312),
- helpstring("Dispatch interface for MapWinGIS Map Control"), version(5.4), hidden
+ helpstring("Dispatch interface for MapWinGIS Map Control"), version(5.5), hidden
]
dispinterface _DMap
{
@@ -6839,13 +6894,16 @@ library MapWinGIS
//[id(17), propput, nonbrowsable] void Extents(IExtents* nNewValue);
//[id(17), propget, nonbrowsable] IExtents* Extents();
-#define REDRAW_API
-#ifdef REDRAW_API
+#define REDRAW_API
+#ifdef REDRAW_API
[id(21)] void Redraw();
[id(42)] void LockWindow(tkLockMode LockMode);
[id(220)] void Redraw2(tkRedrawType redrawType);
[id(260)] void Redraw3(tkRedrawType redrawType, VARIANT_BOOL reloadTiles);
-#endif
+ [id(269)] IPlacedLabels* PlaceAllMapLabels(long LayerHandle);
+ [id(270)] IExtents* GetDrawingLabelExtents(VARIANT* values);
+ //long LayerHandle, long index);
+#endif
#define COORDINATES_API
#ifdef COORDINATES_API
@@ -7297,9 +7355,10 @@ library MapWinGIS
[id(37)] void BeforeLayers(long hdc, long xMin, long xMax, long yMin, long yMax, tkMwBoolean* Handled);
[id(38)] void AfterLayers(long hdc, long xMin, long xMax, long yMin, long yMax, tkMwBoolean* Handled);
[id(39)] void LayerReprojectedIncomplete(LONG LayerHandle, Long NumReprojected, Long NumShapes);
- [id(40)] void BeforeVertexDigitized(DOUBLE* pointX, DOUBLE* pointY);
+ [id(40)] void BeforeVertexDigitized(DOUBLE* pointX, DOUBLE* pointY, LONG selectedVertex);
[id(41)] void SnapPointRequested(DOUBLE pointX, DOUBLE pointY, DOUBLE* snappedX, DOUBLE* snappedY, tkMwBoolean* isFound, tkMwBoolean* isFinal);
[id(42)] void SnapPointFound(DOUBLE pointX, DOUBLE pointY, DOUBLE* snappedX, DOUBLE* snappedY);
+ [id(43)] void VertexAdded(DOUBLE pointX, DOUBLE pointY);
//}}AFX_ODL_EVENT
};
@@ -7706,6 +7765,7 @@ library MapWinGIS
{
[default] interface IIdentifier;
};
+
[
uuid(85EA46DF-FCB8-44A2-BFB0-2F5B0162768D)
]
@@ -7785,4 +7845,12 @@ library MapWinGIS
{
[default] interface IGdalUtils;
};
+
+ [
+ uuid(92A8E8D4-617E-47A4-8180-82E24AD3C984)
+ ]
+ coclass PlacedLabels
+ {
+ [default] interface IPlacedLabels;
+ };
};
diff --git a/src/MapWinGIS.rc b/src/MapWinGIS.rc
index a7daaf85..e14daf13 100644
--- a/src/MapWinGIS.rc
+++ b/src/MapWinGIS.rc
@@ -78,6 +78,7 @@ IDR_GDALDRIVERMANAGER REGISTRY "COM Classes/GdalDriverManager.r
IDR_FUNCTION REGISTRY "COM Classes/Function.rgs"
IDR_EXPRESSION REGISTRY "COM Classes/Expression.rgs"
IDR_WmsLayer REGISTRY "COM Classes/WmsLayer.rgs"
+IDR_PLACEDLABELS REGISTRY "COM Classes/PlacedLabels.rgs"
IDR_GdalUtils REGISTRY "COM Classes/GdalUtils.rgs"
#ifdef APSTUDIO_INVOKED
@@ -112,8 +113,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 5,4,0,0
- PRODUCTVERSION 5,4,0,0
+ FILEVERSION 5,5,0,5
+ PRODUCTVERSION 5,5,0,5
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -131,13 +132,13 @@ BEGIN
VALUE "Comments", "This control includes a mapping component and objects for reading and writing shapefiles and various triangulated irregular network and grid files. It also has extensive label and chart options and includes projection routines."
VALUE "CompanyName", "MapWindow OSS Team - www.mapwindow.org"
VALUE "FileDescription", "MapWinGIS ActiveX Control"
- VALUE "FileVersion", "5.4.0.0"
+ VALUE "FileVersion", "5.5.0.5"
VALUE "InternalName", "MapWinGIS ActiveX Control"
VALUE "LegalCopyright", "Copyright (C) 2004-2022 MapWindow OSS Team"
VALUE "LegalTrademarks", "MapWindow GIS is a trademark of Daniel P. Ames, 2005-2022"
VALUE "OriginalFilename", "MapWinGIS.ocx"
VALUE "ProductName", "MapWinGIS ActiveX Control"
- VALUE "ProductVersion", "5.4.0.0"
+ VALUE "ProductVersion", "5.5.0.5"
END
END
BLOCK "VarFileInfo"
diff --git a/src/MapWinGIS.sln b/src/MapWinGIS.sln
index 0a9eacc5..998b80ca 100644
--- a/src/MapWinGIS.sln
+++ b/src/MapWinGIS.sln
@@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2013
-VisualStudioVersion = 12.0.31101.0
+# Visual Studio Version 17
+VisualStudioVersion = 17.14.36203.30 d17.14
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MapWinGIS", "MapWinGIS.vcxproj", "{1AB93398-2DE6-4043-BF6D-D438A794FB86}"
EndProject
@@ -30,4 +30,7 @@ Global
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {B34A6D21-D737-4E10-B091-38D589393B00}
+ EndGlobalSection
EndGlobal
diff --git a/src/MapWinGIS.sln.DotSettings b/src/MapWinGIS.sln.DotSettings
index 1f61fb03..b5da44bb 100644
--- a/src/MapWinGIS.sln.DotSettings
+++ b/src/MapWinGIS.sln.DotSettings
@@ -1,5 +1,9 @@

<NamingElement Priority="1"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="__interface" /><type Name="class" /><type Name="struct" /></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></NamingElement>
<NamingElement Priority="8"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="global function" /></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></NamingElement>
+ <NamingElement Priority="8" Title="Global functions"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="global function" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aaBb" /></NamingElement>
+ <NamingElement Priority="1" Title="Classes and structs"><Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"><type Name="__interface" /><type Name="class" /><type Name="struct" /></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /></NamingElement>
+ True
True
+ True
True
\ No newline at end of file
diff --git a/src/MapWinGIS.vcxproj b/src/MapWinGIS.vcxproj
index 295e5150..c8c0153a 100644
--- a/src/MapWinGIS.vcxproj
+++ b/src/MapWinGIS.vcxproj
@@ -38,7 +38,7 @@
false
false
MultiByte
- v142
+ v143
@@ -170,17 +170,17 @@ echo in after $(CustomBuildAfterTargets)
true
/ignore:4099 /Ignore:4254 %(AdditionalOptions)
- GdiPlus.lib;gdal_i.lib;version.lib;Crypt32.lib;Dbghelp.lib;geos_c.lib;tiff.lib;libcurl_imp.lib;cqlib.lib;ShapeLib.lib;%(AdditionalDependencies)
+ GdiPlus.lib;gdal_i.lib;version.lib;Crypt32.lib;Dbghelp.lib;geos_c.lib;tiff.lib;libcurl_imp.lib;ShapeLib.lib;%(AdditionalDependencies)
NotSet
$(OutDir)MapWinGIS.ocx
true
- $(ProjectDir)..\Support\GDAL_SDK\$(PlatformToolset)\lib\$(Platform);$(ProjectDir)..\Support\lib\$(PlatformToolset)\$(Platform)\Release;$(ProjectDir)\vcpkg_installed\$(VcpkgTriplet)\$(VcpkgHostTriplet)\lib;$(ProjectDir)\vcpkg_installed\$(VCPKG_DEFAULT_TRIPLET)\lib;%(AdditionalLibraryDirectories)
+ $(ProjectDir)..\Support\GDAL_SDK\$(PlatformToolset)\lib\$(Platform);$(ProjectDir)..\Support\lib\$(PlatformToolset)\$(Platform)\Release;$(ProjectDir)\vcpkg_installed\$(VcpkgTriplet)\$(VcpkgHostTriplet)\lib;$(ProjectDir)\vcpkg_installed\$(VCPKG_DEFAULT_TRIPLET)\lib;$(ProjectDir)vcpkg\vcpkg\buildtrees\libgeotiff\x64-windows-rel\lib;%(AdditionalLibraryDirectories)
false
LIBC.lib;%(IgnoreSpecificDefaultLibraries)
%(DelayLoadDLLs)
- true
+ DebugFull
$(OutDir)MapWinGIS.pdb
Windows
Default
@@ -241,7 +241,7 @@ if $(PlatformName) == x64 (
x64
- WIN64;%(PreprocessorDefinitions)
+ WIN64;SQUARE_TILES;BIG_TILE_SIZE;DEBUG_ALLOCATED_OBJECTS_OFF;%(PreprocessorDefinitions)
stdc11
stdcpp14
true
@@ -249,7 +249,8 @@ if $(PlatformName) == x64 (
/MACHINE:x64 %(AdditionalOptions)
MachineX64
- spatialindex-64.lib;%(AdditionalDependencies)
+ spatialindex-64.lib;ShapeLib-toolset142.lib;xtiff.lib;%(AdditionalDependencies)
+ false
echo "In Pre-Link event"
@@ -304,7 +305,7 @@ if $(PlatformName) == x64 (
Full
false
- RELEASE_MODE;%(PreprocessorDefinitions)
+ RELEASE_MODE;SQUARE_TILES;%(PreprocessorDefinitions)
false
stdcpp14
stdc11
@@ -313,7 +314,8 @@ if $(PlatformName) == x64 (
true
- false
+ true
+ false
echo "In Pre-Link event"
@@ -462,6 +464,7 @@ if $(PlatformName) == x64 (
+
@@ -678,6 +681,7 @@ if $(PlatformName) == x64 (
+
@@ -1037,6 +1041,7 @@ if $(PlatformName) == x64 (
+
diff --git a/src/MapWinGIS.vcxproj.filters b/src/MapWinGIS.vcxproj.filters
index ce4cd171..36ce8bcf 100644
--- a/src/MapWinGIS.vcxproj.filters
+++ b/src/MapWinGIS.vcxproj.filters
@@ -1130,6 +1130,9 @@
+
+ COM classes
+
@@ -1956,6 +1959,9 @@
+
+ COM classes
+
@@ -2180,5 +2186,8 @@
+
+ COM classes
+
\ No newline at end of file
diff --git a/src/MapWinGIS.vcxproj.user b/src/MapWinGIS.vcxproj.user
index 18bc6f32..5b64e465 100644
--- a/src/MapWinGIS.vcxproj.user
+++ b/src/MapWinGIS.vcxproj.user
@@ -10,7 +10,9 @@
WindowsLocalDebugger
- $(MSBuildProjectDirectory)\..\MapWinGisTests-net6\WinFormsApp1\bin\$(Platform)\Debug\net6.0-windows\WinFormsApp1.exe
+ C:\Projects\Intrasis_WinGIS\Intrasis\Applications\IntrasisApp\bin\x64\Debug\net10.0-windows8.0\Intrasis.exe
WindowsLocalDebugger
+ C:\Intrasis\Database\U20043\U20043.ipf sys hemlig
+ NativeOnly
\ No newline at end of file
diff --git a/src/Ogr/OgrConverter.cpp b/src/Ogr/OgrConverter.cpp
index 150df2e1..478ec3dc 100644
--- a/src/Ogr/OgrConverter.cpp
+++ b/src/Ogr/OgrConverter.cpp
@@ -71,22 +71,35 @@ void AddPoints(CShape* shp, OGRLineString* geom, int startPointIndex, int endPoi
{
ShpfileType shpType;
shp->get_ShapeType(&shpType);
- bool isM = ShapeUtility::IsM(shpType);
+ bool haveZ = ShapeUtility::IsZ(shpType);
+ bool haveM = ShapeUtility::HaveM(shpType);
VARIANT_BOOL vb;
- double x, y, z;
+ double x, y, z, m;
for( int i = startPointIndex; i < endPointIndex; i++ )
{
- if (isM)
+ if ( haveZ )
{
- shp->get_XY(i, &x, &y, &vb);
- shp->get_M(i, &z);
+ shp->get_XYZ(i, &x, &y, &z);
+ if( haveM )
+ {
+ shp->get_M(i, &m);
+ geom->addPoint(x, y, z, m);
+ }
+ else
+ geom->addPoint(x, y, z);
}
- else
+ else // No Z
{
- shp->get_XYZ(i, &x, &y, &z);
+ shp->get_XY(i, &x, &y, &vb);
+ if( haveM )
+ {
+ shp->get_M(i, &m);
+ geom->addPointM(x, y, m);
+ }
+ else
+ geom->addPoint(x, y);
}
- geom->addPoint(x, y, z);
}
}
@@ -106,12 +119,15 @@ OGRGeometry* OgrConverter::ShapeToGeometry(IShape* shape, OGRwkbGeometryType for
long numPoints, numParts;
long beg_part, end_part;
ShpfileType shptype;
- double x,y,z;
-
+ double x,y,z,m;
+
shp->get_ShapeType(&shptype);
shp->get_NumParts(&numParts);
shp->get_NumPoints(&numPoints);
+ bool haveZ = ShapeUtility::IsZ(shptype);
+ bool haveM = ShapeUtility::HaveM(shptype);
+
VARIANT_BOOL vb;
if (shptype == SHP_POINT || shptype == SHP_POINTM || shptype == SHP_POINTZ)
@@ -120,18 +136,27 @@ OGRGeometry* OgrConverter::ShapeToGeometry(IShape* shape, OGRwkbGeometryType for
OGRPoint *oPnt = (OGRPoint*)OGRGeometryFactory::createGeometry(wkbPoint);
if (numPoints > 0)
{
- if (shptype == SHP_POINTM)
+ if ( haveZ )
{
- shp->get_XY(0, &x, &y, &vb);
- shp->get_M(0, &z);
+ shp->get_XYZ(0, &x, &y, &z);
+ if( haveM )
+ {
+ shp->get_M(0, &m);
+ oPnt->setM(m);
+ }
+ oPnt->setZ(z);
}
- else
+ else // No Z
{
- shp->get_XYZ(0, &x, &y, &z);
+ shp->get_XY(0, &x, &y, &vb);
+ if( haveM )
+ {
+ shp->get_M(0, &m);
+ oPnt->setM(m);
+ }
}
oPnt->setX(x);
oPnt->setY(y);
- oPnt->setZ(z);
}
oGeom = oPnt;
}
@@ -144,19 +169,28 @@ OGRGeometry* OgrConverter::ShapeToGeometry(IShape* shape, OGRwkbGeometryType for
{
for( int i = 0; i < numPoints; i++ )
{
- if (shptype == SHP_MULTIPOINTM)
+ OGRPoint *oPnt = (OGRPoint*)OGRGeometryFactory::createGeometry(wkbPoint);
+ if ( haveZ )
{
- shp->get_XY(i, &x, &y, &vb);
- shp->get_M(i, &z);
+ shp->get_XYZ(0, &x, &y, &z);
+ oPnt->setZ(z);
+ if( haveM )
+ {
+ shp->get_M(0, &m);
+ oPnt->setM(m);
+ }
}
- else
+ else // No Z
{
- shp->get_XYZ(i, &x, &y, &z);
+ shp->get_XY(0, &x, &y, &vb);
+ if( haveM )
+ {
+ shp->get_M(0, &m);
+ oPnt->setM(m);
+ }
}
- OGRPoint *oPnt = (OGRPoint*)OGRGeometryFactory::createGeometry(wkbPoint);
oPnt->setX(x);
oPnt->setY(y);
- oPnt->setZ(z);
oMPnt->addGeometryDirectly(oPnt); // no memory release is needed when "direct" methods are used
}
}
@@ -412,11 +446,11 @@ IShape * OgrConverter::GeometryToShape(OGRGeometry* oGeom, bool isM,
if (oForceType != wkbNone)
oType = oForceType;
- if (oType == wkbPoint || oType == wkbPoint25D || oType == wkbPointZM)
+ if (oType == wkbPoint || oType == wkbPoint25D || oType == wkbPointM || oType == wkbPointZM)
{
if (oType == wkbPoint)
shptype = SHP_POINT;
- else if (oType == wkbPoint25D || oType == wkbPointZM)
+ else if (oType == wkbPoint25D || oType == wkbPointM || oType == wkbPointZM)
shptype = isM ? SHP_POINTM : SHP_POINTZ;
OGRPoint* oPnt = (OGRPoint *) oGeom;
@@ -424,20 +458,23 @@ IShape * OgrConverter::GeometryToShape(OGRGeometry* oGeom, bool isM,
ComHelper::CreateShape(&shp);
shp->put_ShapeType(shptype);
+ bool haveZ = shptype == SHP_POINTZ;
+ bool haveM = shptype == SHP_POINTZ || shptype == SHP_POINTM;
+
ComHelper::CreatePoint(&pnt);
pnt->put_X(oPnt->getX());
pnt->put_Y(oPnt->getY());
- if (isM) pnt->put_M(oPnt->getZ());
- else pnt->put_Z(oPnt->getZ());
+ if(haveZ) pnt->put_Z(oPnt->getZ());
+ if(haveM) pnt->put_M(oPnt->getM());
shp->InsertPoint(pnt,&pointIndex,&retval);
pnt->Release();
}
- else if (oType == wkbMultiPoint || oType == wkbMultiPoint25D || oType == wkbMultiPointZM)
+ else if (oType == wkbMultiPoint || oType == wkbMultiPoint25D || oType == wkbMultiPointM || oType == wkbMultiPointZM)
{
if (oType == wkbMultiPoint)
shptype = SHP_MULTIPOINT;
- else if (oType == wkbMultiPoint25D || oType == wkbMultiPointZM)
+ else if (oType == wkbMultiPoint25D || oType == wkbMultiPointM || oType == wkbMultiPointZM)
shptype = isM ? SHP_MULTIPOINTM : SHP_MULTIPOINTZ;
OGRMultiPoint* oMPnt = (OGRMultiPoint* ) oGeom;
@@ -447,6 +484,9 @@ IShape * OgrConverter::GeometryToShape(OGRGeometry* oGeom, bool isM,
ComHelper::CreateShape(&shp);
shp->put_ShapeType(shptype);
+ bool haveZ = shptype == SHP_MULTIPOINTZ;
+ bool haveM = shptype == SHP_MULTIPOINTZ || shptype == SHP_MULTIPOINTM;
+
for(long i = 0; i < oMPnt->getNumGeometries(); i++ )
{
OGRPoint* oPnt = (OGRPoint *) oMPnt->getGeometryRef(i);
@@ -457,8 +497,8 @@ IShape * OgrConverter::GeometryToShape(OGRGeometry* oGeom, bool isM,
ComHelper::CreatePoint(&pnt);
pnt->put_X(oPnt->getX());
pnt->put_Y(oPnt->getY());
- if (isM) pnt->put_M(oPnt->getZ());
- else pnt->put_Z(oPnt->getZ());
+ if(haveZ) pnt->put_Z(oPnt->getZ());
+ if(haveM) pnt->put_M(oPnt->getM());
shp->InsertPoint(pnt,&i,&retval);
pnt->Release();
}
@@ -466,11 +506,11 @@ IShape * OgrConverter::GeometryToShape(OGRGeometry* oGeom, bool isM,
}
}
- else if (oType == wkbLineString || oType == wkbLineString25D || oType == wkbLineStringZM)
+ else if (oType == wkbLineString || oType == wkbLineString25D || oType == wkbLineStringM || oType == wkbLineStringZM)
{
if (oType == wkbLineString)
shptype = SHP_POLYLINE;
- else if (oType == wkbLineString25D || oType == wkbLineStringZM)
+ else if (oType == wkbLineString25D || oType == wkbLineStringM || oType == wkbLineStringZM)
shptype = isM ? SHP_POLYLINEM : SHP_POLYLINEZ;
OGRLineString* oLine = (OGRLineString *) oGeom;
@@ -480,24 +520,27 @@ IShape * OgrConverter::GeometryToShape(OGRGeometry* oGeom, bool isM,
ComHelper::CreateShape(&shp);
shp->put_ShapeType(shptype);
shp->InsertPart(0,&partIndex,&retval);
-
+
+ bool haveZ = shptype == SHP_POLYLINEZ;
+ bool haveM = shptype == SHP_POLYLINEZ || shptype == SHP_POLYLINEM;
+
for(long i = 0; i < oLine->getNumPoints(); i++ )
{
ComHelper::CreatePoint(&pnt);
pnt->put_X(oLine->getX(i));
pnt->put_Y(oLine->getY(i));
- if (isM) pnt->put_M(oLine->getZ(i));
- else pnt->put_Z(oLine->getZ(i));
+ if(haveZ) pnt->put_Z(oLine->getZ(i));
+ if(haveM) pnt->put_M(oLine->getM(i));
shp->InsertPoint(pnt,&i,&retval);
pnt->Release();
}
}
- else if (oType == wkbMultiLineString || oType == wkbMultiLineString25D || oType == wkbMultiLineStringZM)
+ else if (oType == wkbMultiLineString || oType == wkbMultiLineString25D || oType == wkbMultiLineStringM || oType == wkbMultiLineStringZM)
{
if (oType == wkbMultiLineString)
shptype = SHP_POLYLINE;
- else if (oType == wkbMultiLineString25D || oType == wkbMultiLineStringZM)
+ else if (oType == wkbMultiLineString25D || oType == wkbMultiLineStringM || oType == wkbMultiLineStringZM)
shptype = isM ? SHP_POLYLINEM : SHP_POLYLINEZ;
OGRMultiLineString * oMLine = (OGRMultiLineString *) oGeom;
@@ -506,7 +549,10 @@ IShape * OgrConverter::GeometryToShape(OGRGeometry* oGeom, bool isM,
ComHelper::CreateShape(&shp);
shp->put_ShapeType(shptype);
-
+
+ bool haveZ = shptype == SHP_POLYLINEZ;
+ bool haveM = shptype == SHP_POLYLINEZ || shptype == SHP_POLYLINEM;
+
long count = 0;
for (long j=0; j < oMLine->getNumGeometries(); j++)
{
@@ -524,8 +570,8 @@ IShape * OgrConverter::GeometryToShape(OGRGeometry* oGeom, bool isM,
ComHelper::CreatePoint(&pnt);
pnt->put_X(oLine->getX(i));
pnt->put_Y(oLine->getY(i));
- if (isM) pnt->put_M(oLine->getZ(i));
- else pnt->put_Z(oLine->getZ(i));
+ if(haveZ) pnt->put_Z(oLine->getZ(i));
+ if(haveM) pnt->put_M(oLine->getM(i));
shp->InsertPoint(pnt,&count,&retval);
pnt->Release();
if (retval) count++;
@@ -536,7 +582,7 @@ IShape * OgrConverter::GeometryToShape(OGRGeometry* oGeom, bool isM,
}
// (meant to be part of poly; but we'll treat it alone also)
- else if (oType == wkbLinearRing)
+ else if (oType == wkbLinearRing)
{
OGRLinearRing* oRing;
@@ -552,31 +598,34 @@ IShape * OgrConverter::GeometryToShape(OGRGeometry* oGeom, bool isM,
shp->put_ShapeType(shptype);
shp->InsertPart(0,&partIndex,&retval);
+ bool haveZ = shptype == SHP_POLYGONZ;
+ bool haveM = shptype == SHP_POLYGONZ || shptype == SHP_POLYGONM;
+
for(long i=0; i< oRing->getNumPoints(); i++)
{
ComHelper::CreatePoint(&pnt);
pnt->put_X(oRing->getX(i));
pnt->put_Y(oRing->getY(i));
- if (isM) pnt->put_M(oRing->getZ(i));
- else pnt->put_Z(oRing->getZ(i));
+ if(haveZ) pnt->put_Z(oRing->getZ(i));
+ if(haveM) pnt->put_M(oRing->getM(i));
shp->InsertPoint(pnt,&i,&retval);
pnt->Release();
}
}
- else if (oType == wkbPolygon || oType == wkbPolygon25D || oType == wkbPolygonZM ||
+ else if (oType == wkbPolygon || oType == wkbPolygon25D || oType == wkbPolygonM || oType == wkbPolygonZM ||
oType == wkbMultiPolygon || oType == wkbMultiPolygon25D || oType == wkbMultiPolygonZM)
{
OGRPolygon* oPoly;
OGRLinearRing** papoRings=NULL;
int nRings = 0;
- if ((oType == wkbPolygon25D || oType == wkbPolygonZM || oType == wkbMultiPolygon25D || oType == wkbMultiPolygonZM) || force25D)
+ if ((oType == wkbPolygon25D || oType == wkbPolygonM || oType == wkbPolygonZM || oType == wkbMultiPolygon25D || oType == wkbMultiLineStringM || oType == wkbMultiPolygonZM) || force25D)
shptype = isM ? SHP_POLYGONM : SHP_POLYGONZ;
else if (oType == wkbPolygon || oType == wkbMultiPolygon)
shptype = SHP_POLYGON;
- if (oType == wkbPolygon || oType == wkbPolygon25D || oType == wkbPolygonZM)
+ if (oType == wkbPolygon || oType == wkbPolygon25D || oType == wkbPolygonM || oType == wkbPolygonZM)
{
oPoly = (OGRPolygon *) oGeom;
@@ -597,7 +646,7 @@ IShape * OgrConverter::GeometryToShape(OGRGeometry* oGeom, bool isM,
}
}
- else if (oType == wkbMultiPolygon || oType == wkbMultiPolygon25D || oType == wkbMultiPolygonZM)
+ else if (oType == wkbMultiPolygon || oType == wkbMultiPolygon25D || oType == wkbMultiPolygonM || oType == wkbMultiPolygonZM)
{
OGRMultiPolygon* oMPoly = (OGRMultiPolygon *) oGeom;
@@ -605,7 +654,7 @@ IShape * OgrConverter::GeometryToShape(OGRGeometry* oGeom, bool isM,
{
oPoly = (OGRPolygon *) oMPoly->getGeometryRef(iGeom);
- if (oPoly->getGeometryType() == wkbPolygon || oPoly->getGeometryType() == wkbPolygon25D || oPoly->getGeometryType() == wkbPolygonZM)
+ if (oPoly->getGeometryType() == wkbPolygon || oPoly->getGeometryType() == wkbPolygon25D || oPoly->getGeometryType() == wkbPolygonM || oPoly->getGeometryType() == wkbPolygonZM)
{
if( oPoly->getExteriorRing() == NULL) continue;
if (oPoly->getExteriorRing()->IsEmpty()) continue;
@@ -631,7 +680,10 @@ IShape * OgrConverter::GeometryToShape(OGRGeometry* oGeom, bool isM,
ComHelper::CreateShape(&shp);
shp->put_ShapeType(shptype);
-
+
+ bool haveZ = shptype == SHP_POLYGONZ;
+ bool haveM = shptype == SHP_POLYGONZ || shptype == SHP_POLYGONM;
+
OGRLinearRing *oRing;
long count = 0;
@@ -645,8 +697,8 @@ IShape * OgrConverter::GeometryToShape(OGRGeometry* oGeom, bool isM,
ComHelper::CreatePoint(&pnt);
pnt->put_X(oRing->getX(i));
pnt->put_Y(oRing->getY(i));
- if (isM) pnt->put_M(oRing->getZ(i));
- else pnt->put_Z(oRing->getZ(i));
+ if(haveZ) pnt->put_Z(oRing->getZ(i));
+ if(haveM) pnt->put_M(oRing->getM(i));
shp->InsertPoint(pnt,&count,&retval);
pnt->Release();
pnt = NULL;
diff --git a/src/Processing/GeometryHelper.cpp b/src/Processing/GeometryHelper.cpp
index 2230ce92..cffec066 100644
--- a/src/Processing/GeometryHelper.cpp
+++ b/src/Processing/GeometryHelper.cpp
@@ -236,6 +236,21 @@ tkExtentsRelation GeometryHelper::RelateExtents(CRect& r1, CRect& r2)
return tkExtentsRelation::erIntersection;
}
+//**************************************************************************
+// PointInSegment()
+//**************************************************************************
+bool GeometryHelper::PointInExtent(double xMin, double yMin, double xMax, double yMax, double ptX, double ptY)
+{
+ //xMin, yMin, xMax, yMax
+
+ if ((ptX < xMin && ptX < xMax) || (ptX > xMin && ptX > xMax) ||
+ (ptY < yMin && ptY < yMax) || (ptY > yMin && ptY > yMax))
+ {
+ return false;
+ }
+ return (xMin <= ptX && xMax >= ptX && xMax >= ptX && yMax >= ptY);
+}
+
//**************************************************************************
// PointOnSegment()
//**************************************************************************
diff --git a/src/Processing/GeometryHelper.h b/src/Processing/GeometryHelper.h
index be691b36..5606a1f0 100644
--- a/src/Processing/GeometryHelper.h
+++ b/src/Processing/GeometryHelper.h
@@ -13,6 +13,7 @@ class GeometryHelper
static tkExtentsRelation RelateExtents(IExtents* ext1, IExtents* ext2);
static tkExtentsRelation RelateExtents(CRect& r1, CRect& r2);
static double GetPointAngle(double &x, double &y);
+ static bool PointInExtent(double xMin, double yMin, double xMax, double yMax, double ptX, double ptY);
static bool PointOnSegment(double x1, double y1, double x2, double y2, double pntX, double pntY);
static double GetPointAngleDeg(double x, double y);
};
diff --git a/src/Resource.h b/src/Resource.h
index d22708b4..eeb142d8 100644
--- a/src/Resource.h
+++ b/src/Resource.h
@@ -85,6 +85,7 @@
#define IDC_SELECT2_CURSOR 220
#define IDC_IDENTIFY_CURSOR 221
#define IDC_PAN_ALTERNATE 222
+#define IDR_PLACEDLABELS 223
// Next default values for new objects
//
diff --git a/src/Shapefile/ShapeUtility.cpp b/src/Shapefile/ShapeUtility.cpp
index 0ef538e0..ce230760 100644
--- a/src/Shapefile/ShapeUtility.cpp
+++ b/src/Shapefile/ShapeUtility.cpp
@@ -28,6 +28,17 @@ bool ShapeUtility::IsZ(const ShpfileType shpType)
|| shpType == SHP_POLYGONZ;
}
+// **************************************************************
+// HaveM()
+// **************************************************************
+bool ShapeUtility::HaveM(const ShpfileType shpType)
+{
+ return shpType == SHP_POINTM || shpType == SHP_POINTZ
+ || shpType == SHP_MULTIPOINTM || shpType == SHP_MULTIPOINTZ
+ || shpType == SHP_POLYLINEM || shpType == SHP_POLYLINEZ
+ || shpType == SHP_POLYGONM || shpType == SHP_POLYGONZ;
+}
+
// **************************************************************
// Convert2D()
// **************************************************************
diff --git a/src/Shapefile/ShapeUtility.h b/src/Shapefile/ShapeUtility.h
index d58b3433..37852081 100644
--- a/src/Shapefile/ShapeUtility.h
+++ b/src/Shapefile/ShapeUtility.h
@@ -8,6 +8,7 @@ class ShapeUtility
static void SwapEndian(char* a, int size);
static bool IsM(ShpfileType shpType);
static bool IsZ(ShpfileType shpType);
+ static bool HaveM(const ShpfileType shpType);
static ShpfileType Convert2D(ShpfileType shpType);
static ShpfileType Get25DShapeType(ShpfileType shpTypeBase, bool isZ, bool isM);
static IShapeWrapper* CreateWrapper(char* data, int recordLength, bool forceCom);
diff --git a/src/Shapefile/ShapeWrapper.cpp b/src/Shapefile/ShapeWrapper.cpp
index b61a4c5c..29139726 100644
--- a/src/Shapefile/ShapeWrapper.cpp
+++ b/src/Shapefile/ShapeWrapper.cpp
@@ -304,7 +304,7 @@ int CShapeWrapper::get_PartEndPoint(const int partIndex)
}
if (partIndex == gsl::narrow_cast(_parts.size()) - 1)
{
- return gsl::narrow_cast(_parts.size()) - 1;
+ return gsl::narrow_cast(_points.size()) - 1;
}
return _parts[partIndex + 1] - 1;
}
diff --git a/src/Shapefile/ShapeWrapperCOM.cpp b/src/Shapefile/ShapeWrapperCOM.cpp
index addd14dd..82613a3c 100644
--- a/src/Shapefile/ShapeWrapperCOM.cpp
+++ b/src/Shapefile/ShapeWrapperCOM.cpp
@@ -471,21 +471,49 @@ bool CShapeWrapperCOM::InsertPointXYZM(const int pointIndex, const double x, con
return false;
}
+bool PointIsXYEqual(IPoint* p1, IPoint* p2)
+{
+ double x1, x2, y1, y2;
+ p1->get_X(&x1);
+ p2->get_X(&x2);
+ p1->get_Y(&y1);
+ p2->get_Y(&y2);
+ return abs(x1 - x2) < 0.00001 && abs(y1 - y2) < 0.00001;
+}
+
// ********************************************************
// DeletePoint()
// ********************************************************
bool CShapeWrapperCOM::DeletePoint(const int pointIndex)
{
- if (pointIndex < 0 || pointIndex >= gsl::narrow_cast(_points.size()))
+ auto count = gsl::narrow_cast(_points.size());
+ if (pointIndex < 0 || pointIndex >= count)
{
_lastErrorCode = tkINDEX_OUT_OF_BOUNDS;
return false;
}
+ const auto needToReClose = pointIndex == 0 && PointIsXYEqual(_points[count - 1], _points[0]);
_points[pointIndex]->Release();
_points.erase(_points.begin() + pointIndex);
+ if (needToReClose)
+ { // First point is the last point (to close)
+ count = gsl::narrow_cast(_points.size());
+ IPoint* pt;
+ auto hr = _points[0]->Clone(&pt);
+ if (FAILED(hr)) {
+ _lastErrorCode = tkINVALID_SHAPE;
+ return false;
+ }
+ auto replaceIndex = count - 1;
+ _points[replaceIndex]->Release();
+ _points.erase(_points.begin() + replaceIndex);
+ pt->AddRef();
+ _points.insert(_points.begin() + replaceIndex, pt);
+ }
_boundsChanged = true;
return true;
}
+
#pragma endregion
#pragma region Parts
diff --git a/src/Shapefile/dbf.cpp b/src/Shapefile/dbf.cpp
index 53123d23..6764eccb 100644
--- a/src/Shapefile/dbf.cpp
+++ b/src/Shapefile/dbf.cpp
@@ -12,7 +12,7 @@
DBFHandle SHPAPI_CALL DBFOpen_MW( CStringW pszFilename, const char * pszAccess )
{
- CStringA nameA = Utility::ConvertToUtf8(pszFilename);
+ CStringA nameA = Utility::ConvertToAnsi1252(pszFilename);
m_globalSettings.SetGdalUtf8(true);
DBFHandle handle = DBFOpen(nameA, pszAccess);
m_globalSettings.SetGdalUtf8(false);
@@ -21,7 +21,7 @@ DBFHandle SHPAPI_CALL DBFOpen_MW( CStringW pszFilename, const char * pszAccess )
DBFHandle SHPAPI_CALL DBFCreate_MW( CStringW nameW )
{
- CStringA nameA = Utility::ConvertToUtf8(nameW);
+ CStringA nameA = Utility::ConvertToAnsi1252(nameW);
m_globalSettings.SetGdalUtf8(true);
DBFHandle handle = DBFCreate(nameA);
m_globalSettings.SetGdalUtf8(false);
diff --git a/src/Structures/Extent.h b/src/Structures/Extent.h
index e33fb8ec..33a74a61 100644
--- a/src/Structures/Extent.h
+++ b/src/Structures/Extent.h
@@ -131,7 +131,7 @@ class Extent
top = yCent + dy;
}
- Point2D GetCenter ()
+ Point2D GetCenter ()
{
return Point2D((left + right) / 2.0, (top + bottom) / 2.0);
}
@@ -143,7 +143,9 @@ class Extent
CString ToString()
{
- return Debug::Format("x: %f; y: %f; w: %f; h: %f", left, top, Width(), Height());
+ auto width = Width();
+ auto height = Height();
+ return Debug::Format("x: %f; y: %f; w: %f; h: %f", left, top, width, height);
}
};
diff --git a/src/Structures/Structures.h b/src/Structures/Structures.h
index 36429d61..c47a9ffe 100644
--- a/src/Structures/Structures.h
+++ b/src/Structures/Structures.h
@@ -57,12 +57,22 @@ struct MeasurePoint
Point2D Proj;
double x; // in decimal degrees
double y;
+ double z;
+ double m;
void CopyTo(MeasurePoint& pnt2) {
pnt2.x = x;
pnt2.y = y;
+ pnt2.z = z;
+ pnt2.m = m;
pnt2.Proj = Proj;
}
- MeasurePoint() : Part(PartNone) {}
+ MeasurePoint() : Part(PartNone)
+ {
+ x = 0.0;
+ y = 0.0;
+ z = 0.0;
+ m = 0.0;
+ }
};
struct OgrUpdateError
diff --git a/src/Tiles/Caching/DiskCache.cpp b/src/Tiles/Caching/DiskCache.cpp
index 76ccf278..fa51cb83 100644
--- a/src/Tiles/Caching/DiskCache.cpp
+++ b/src/Tiles/Caching/DiskCache.cpp
@@ -100,7 +100,12 @@ void DiskCache::AddTile(TileCore* tile)
}
// TODO: better to get it from provider (as tile size is not necessarily 256 by 256 pixels)
+#if BIG_TILE_SIZE
+ auto tileImageSize = static_cast(tile->get_TileSize());
+ Gdiplus::Bitmap* bmp = new Gdiplus::Bitmap(tileImageSize, tileImageSize);
+#else
Gdiplus::Bitmap* bmp = new Gdiplus::Bitmap(256, 256);
+#endif
Gdiplus::Graphics* g = Gdiplus::Graphics::FromImage(bmp);
for (size_t i = 0; i < tile->Overlays.size(); i++)
diff --git a/src/Tiles/Caching/SQLiteCache.cpp b/src/Tiles/Caching/SQLiteCache.cpp
index 616821d4..c3fe9193 100644
--- a/src/Tiles/Caching/SQLiteCache.cpp
+++ b/src/Tiles/Caching/SQLiteCache.cpp
@@ -212,7 +212,13 @@ void SQLiteCache::AddTile(TileCore* tile)
if (val != SQLITE_OK)
{
- CallbackHelper::ErrorMsg("SQLiteCache::DoCaching: Failed to prepare statement.");
+ auto sqlite3_error = sqlite3_errmsg(_conn);
+ auto errorCode = sqlite3_extended_errcode(_conn);
+ //std:string errorMessage("SQLiteCache::DoCaching: Failed to prepare statement: ");
+ //errorMessage += sqlite3_error ? sqlite3_error : "Unknown error";
+ //CallbackHelper::ErrorMsg(errorMessage.c_str());
+ CallbackHelper::ErrorMsg(Debug::Format("SQLiteCache::DoCaching: Failed to prepare statement errorNo: %d Message: %s", errorCode, sqlite3_error));
+ //CallbackHelper::ErrorMsg("SQLiteCache::DoCaching: Failed to prepare statement.");
}
else
{
diff --git a/src/Tiles/Loaders/ITileLoader.cpp b/src/Tiles/Loaders/ITileLoader.cpp
index 8611df78..259e364a 100644
--- a/src/Tiles/Loaders/ITileLoader.cpp
+++ b/src/Tiles/Loaders/ITileLoader.cpp
@@ -20,6 +20,7 @@
// Paul Meems August 2018: Modernized the code as suggested by CLang and ReSharper
#include "StdAfx.h"
+#include
#include "ITileLoader.h"
#include "ILoadingTask.h"
diff --git a/src/Tiles/Projections/BaseProjection.cpp b/src/Tiles/Projections/BaseProjection.cpp
index c901ede5..83683b5b 100644
--- a/src/Tiles/Projections/BaseProjection.cpp
+++ b/src/Tiles/Projections/BaseProjection.cpp
@@ -84,10 +84,15 @@ void BaseProjection::GetTileSizeLatLon(CPoint point, int zoom, SizeLatLng &ret)
PointLatLng pnt2;
this->FromXYToLatLng(newPoint, zoom, pnt2);
-
+
// size
ret.WidthLng = fabs( pnt2.Lng - pnt1.Lng);
ret.HeightLat = fabs(pnt2.Lat - pnt1.Lat);
+
+ if (ret.WidthLng < ret.HeightLat)
+ ret.WidthLng = ret.HeightLat;
+ else if (ret.HeightLat < ret.WidthLng)
+ ret.HeightLat = ret.WidthLng;
}
// *******************************************************
@@ -137,6 +142,7 @@ void BaseProjection::getTileRectXY(Extent extentsWgs84, int zoom, CRect &rect)
{
CPoint p1, p2;
+ ::OutputDebugStringA(Debug::Format("tile extentsWgs84: %s\r\n", extentsWgs84.ToString()));
FromLatLngToXY(PointLatLng(extentsWgs84.top, extentsWgs84.left), zoom, p1);
FromLatLngToXY(PointLatLng(extentsWgs84.bottom, extentsWgs84.right), zoom, p2);
diff --git a/src/Tiles/Projections/BaseProjection.h b/src/Tiles/Projections/BaseProjection.h
index a26ee162..cdbbc596 100644
--- a/src/Tiles/Projections/BaseProjection.h
+++ b/src/Tiles/Projections/BaseProjection.h
@@ -30,7 +30,11 @@ class BaseProjection
: _minLat(0), _maxLat(0), _minLng(0), _maxLng(0), _yMin(0.0), _yMax(0.0), _xMin(0.0), _xMax(0.0),
_mapBounds(0.0, 0.0, 0.0, 0.0)
{
+#if BIG_TILE_SIZE
+ _tileSize = CSize(512, 512);
+#else
_tileSize = CSize(256, 256);
+#endif
_yInverse = false;
_earthRadius = 6378137.0;
_worldWide = true;
@@ -68,6 +72,7 @@ class BaseProjection
public:
virtual void FromLatLngToXY(PointLatLng pnt, int zoom, CPoint& ret) = 0;
+
virtual void FromXYToLatLng(CPoint pnt, int zoom, PointLatLng& ret) = 0;
virtual void FromXYToProj(CPoint pnt, int zoom, PointLatLng& ret) = 0;
virtual double GetWidth() = 0;
diff --git a/src/Tiles/Projections/CustomProjection.cpp b/src/Tiles/Projections/CustomProjection.cpp
index 047b27e9..a73c8763 100644
--- a/src/Tiles/Projections/CustomProjection.cpp
+++ b/src/Tiles/Projections/CustomProjection.cpp
@@ -19,6 +19,7 @@
* (Open source contributors should list themselves and their modifications here). */
#include "stdafx.h"
+#include
#include "CustomProjection.h"
// *******************************************************
@@ -29,7 +30,14 @@ void CustomProjection::FromLatLngToXY(PointLatLng pnt, int zoom, CPoint &ret)
{
double lat = pnt.Lat;
double lng = pnt.Lng;
-
+
+#if DEBUG
+ CComBSTR bstr;
+ CString proj;
+ _projWGS84->ExportToWktEx(&bstr);
+ proj = bstr;
+#endif
+
VARIANT_BOOL vb;
_projWGS84->Transform(&lng, &lat, &vb);
@@ -45,9 +53,17 @@ void CustomProjection::FromProjToXY(double lat, double lng, int zoom, CPoint &re
lat = Clip(lat, _yMin, _yMax);
lng = Clip(lng, _xMin, _xMax);
+ auto width = _xMax - _xMin;
+ auto height = _yMax - _yMin;
+ auto maxSize = max(width, height);
+#if SQUARE_TILES
+ double y = (lat - _yMin) / maxSize;
+ double x = (lng - _xMin) / maxSize;
+#else
double y = (lat - _yMin)/(_yMax - _yMin);
double x = (lng - _xMin)/(_xMax - _xMin);
-
+#endif
+
CSize s;
GetTileMatrixSizeXY(zoom, s);
int mapSizeX = s.cx;
@@ -88,8 +104,16 @@ void CustomProjection::FromXYToProj(CPoint pnt, int zoom, PointLatLng &ret)
double x = Clip(pnt.x, 0, mapSizeX) / mapSizeX;
double y = Clip(pnt.y, 0, mapSizeY) / mapSizeY;
+#if SQUARE_TILES
+ auto width = _xMax - _xMin;
+ auto height = _yMax - _yMin;
+ auto maxSize = max(width, height);
+ x = _xMin + x * (maxSize);
+ y = _yMin + y * (maxSize);
+#else
x = _xMin + x * (_xMax - _xMin);
y = _yMin + y * (_yMax - _yMin);
+#endif
ret.Lat = y;
ret.Lng = x;
@@ -102,8 +126,15 @@ void CustomProjection::GetTileSizeProj(int zoom, SizeLatLng &size)
{
CSize sizeInt;
GetTileMatrixSizeXY(zoom, sizeInt);
- size.WidthLng = (_xMax - _xMin) / (double)sizeInt.cx;
- size.HeightLat = (_yMax - _yMin) / (double)sizeInt.cy;
+ size.WidthLng = (_xMax - _xMin) / static_cast(sizeInt.cx);
+ size.HeightLat = (_yMax - _yMin) / static_cast(sizeInt.cy);
+
+#if SQUARE_TILES
+ if (size.WidthLng < size.HeightLat)
+ size.WidthLng = size.HeightLat; // make square tiles
+ else if (size.WidthLng > size.HeightLat)
+ size.HeightLat = size.WidthLng;
+#endif
}
// ******************************************************
diff --git a/src/Tiles/Providers/BaseProvider.cpp b/src/Tiles/Providers/BaseProvider.cpp
index a367dc56..9b723a02 100644
--- a/src/Tiles/Providers/BaseProvider.cpp
+++ b/src/Tiles/Providers/BaseProvider.cpp
@@ -26,6 +26,7 @@
#include
#include "SecureHttpClient.h"
+#include "WmsCustomProvider.h"
CString BaseProvider::_proxyUsername = "";
CString BaseProvider::_proxyPassword = "";
@@ -39,6 +40,18 @@ const CString filePrefix = "file:///";
TileCore* BaseProvider::GetTileImage(CPoint& pos, const int zoom)
{
auto* tile = new TileCore(this->Id, zoom, pos, this->_projection); // TODO: Fix compile warning
+ auto* customProvider = dynamic_cast(this);
+
+ if (tile->tileX() == 234 && tile->tileY() == 28)
+ ::OutputDebugStringA("\r\n");
+
+ if (customProvider != nullptr)
+ {
+ auto bbOrder = customProvider->get_BoundingBoxOrder();
+ tile->set_BoundingBoxOrder(bbOrder);
+ auto tileSize = customProvider->get_TileSize();
+ tile->set_TileSize(tileSize);
+ }
for (size_t i = 0; i < _subProviders.size(); i++)
{
@@ -172,6 +185,10 @@ CMemoryBitmap* BaseProvider::ProcessHttpRequest(void* secureHttpClient, const CS
case TileHttpContentType::httpXml:
if (IsWms())
{
+ auto status = client->GetStatus();
+ CString sOutput;
+ sOutput.AppendFormat("WMS server response status: %d", status);
+ ::OutputDebugStringA(sOutput.GetBuffer());
const CString s(body);
ParseServerException(s);
}
diff --git a/src/Tiles/Providers/WmsCustomProvider.cpp b/src/Tiles/Providers/WmsCustomProvider.cpp
index cf648e98..59d55191 100644
--- a/src/Tiles/Providers/WmsCustomProvider.cpp
+++ b/src/Tiles/Providers/WmsCustomProvider.cpp
@@ -28,20 +28,36 @@ CString WmsCustomProvider::MakeTileImageUrl(CPoint &pos, int zoom)
{
CString s = _urlFormat;
+ auto crsKey = "srs";
+ if(_version >= wv13)
+ crsKey = "crs";
+
s += "?request=GetMap&service=WMS";
s += "&layers=" + _layers;
CString temp;
- temp.Format("&crs=EPSG:%d", get_CustomProjection()->get_Epsg());
+ temp.Format("&%s=EPSG:%d", crsKey, get_CustomProjection()->get_Epsg());
s += temp;
s += "&bbox=" + GetBoundingBox(pos, zoom, _version, _bbo);
s += "&format=" + _format;
+#if BIG_TILE_SIZE
+ auto tileImageSize = get_TileSize();
+ CString tmp;
+ tmp.Format("&width=%d", tileImageSize);
+ s += tmp;
+ tmp.Format("&height=%d", tileImageSize);
+ s += tmp;
+ //s += "&width=512";
+ //s += "&height=512";
+#else
s += "&width=256";
s += "&height=256";
+#endif
s += get_VersionString();
s += "&styles=" + get_Styles();
+ ::OutputDebugStringA(s.GetBuffer());
return s;
}
@@ -50,14 +66,17 @@ CString WmsCustomProvider::MakeTileImageUrl(CPoint &pos, int zoom)
// ******************************************************
CString WmsCustomProvider::get_VersionString()
{
- switch (_version)
+ auto version = _version;
+ if ( version == wvAuto )
+ version = wv13; // Auto fall back to version 1.3
+
+ switch (version)
{
case wvEmpty:
return "";
case wv100:
return "&version=1.0.0";
case wv110:
- case wvAuto:
return "&version=1.1.1";
case wv111:
return "&version=1.1.1";
diff --git a/src/Tiles/Providers/WmsCustomProvider.h b/src/Tiles/Providers/WmsCustomProvider.h
index b16b0573..ba7adf17 100644
--- a/src/Tiles/Providers/WmsCustomProvider.h
+++ b/src/Tiles/Providers/WmsCustomProvider.h
@@ -32,6 +32,7 @@ class WmsCustomProvider : public WmsProviderBase
{
_version = wvAuto;
_bbo = bboAuto;
+ _tileSize = 512;
_projection = new CustomProjection();
_subProviders.push_back(this);
}
@@ -44,6 +45,7 @@ class WmsCustomProvider : public WmsProviderBase
CString _styles;
tkWmsVersion _version;
tkWmsBoundingBoxOrder _bbo;
+ int _tileSize;
public:
// properties
@@ -55,8 +57,10 @@ class WmsCustomProvider : public WmsProviderBase
void set_Format(CString value) { _format = value; }
tkWmsVersion get_Version() { return _version; }
void set_Version(tkWmsVersion value) { _version = value; }
- tkWmsBoundingBoxOrder get_BoundingBoxOrder() { return _bbo; }
+ tkWmsBoundingBoxOrder get_BoundingBoxOrder() const { return _bbo; }
void set_BoundingBoxOrder(tkWmsBoundingBoxOrder bbo) { _bbo = bbo; }
+ int get_TileSize() const { return _tileSize; }
+ void set_TileSize(int tileSize) { _tileSize = tileSize; }
CString get_Styles() { return _styles; }
void set_Styles(CString value) { _styles = value; }
diff --git a/src/Tiles/Providers/WmsProviderBase.cpp b/src/Tiles/Providers/WmsProviderBase.cpp
index 462e8bd2..b82e7fd8 100644
--- a/src/Tiles/Providers/WmsProviderBase.cpp
+++ b/src/Tiles/Providers/WmsProviderBase.cpp
@@ -33,6 +33,8 @@ CString WmsProviderBase::GetBoundingBox(CPoint &pos, int zoom, tkWmsVersion vers
pos.x++;
pos.y++;
_projection->FromXYToProj(pos, zoom, pnt2);
+ pos.x--;
+ pos.y--;
CString s;
@@ -50,7 +52,6 @@ CString WmsProviderBase::GetBoundingBox(CPoint &pos, int zoom, tkWmsVersion vers
case wv111:
default:
bbo = tkWmsBoundingBoxOrder::bboLongLat;
-
}
}
diff --git a/src/Tiles/TileCore.h b/src/Tiles/TileCore.h
index 5d3417d0..befdf160 100644
--- a/src/Tiles/TileCore.h
+++ b/src/Tiles/TileCore.h
@@ -88,6 +88,7 @@ class TileCore
_toDelete = false;
_inBuffer = false;
_geogBounds = projection->CalculateGeogBounds(pnt, zoom);
+ _bbo = bboAuto;
}
virtual ~TileCore()
@@ -115,6 +116,8 @@ class TileCore
bool _inBuffer;
// it's currently displayed or scheduled to be displayed; it must not be destroyed while cleaning the cache
int _providerId;
+ tkWmsBoundingBoxOrder _bbo;
+ int _tileSize;
public:
// a tile may be comprised of several semi-transparent bitmaps (e.g. satellite image and labels above it)
@@ -144,6 +147,10 @@ class TileCore
void isDrawn(bool value) { _drawn = value; }
bool toDelete() { return _toDelete; }
void toDelete(bool value) { _toDelete = value; }
+ tkWmsBoundingBoxOrder get_BoundingBoxOrder() const { return _bbo; }
+ void set_BoundingBoxOrder(tkWmsBoundingBoxOrder bbo) { _bbo = bbo; }
+ int get_TileSize() const { return _tileSize; }
+ void set_TileSize(int tileSize) { _tileSize = tileSize; }
public:
//methods
diff --git a/src/Tiles/TileHelper.cpp b/src/Tiles/TileHelper.cpp
index 36131b9f..7812765c 100644
--- a/src/Tiles/TileHelper.cpp
+++ b/src/Tiles/TileHelper.cpp
@@ -68,7 +68,7 @@ bool TileHelper::Transform(TileCore* tile, IGeoProjection* mapProjection, bool i
{
// projection for tiles matches map projection (most often it's Google Mercator; EPSG:3857)
PointLatLng pnt;
- CustomProjection* customProj = dynamic_cast(tile->get_Projection());
+ auto customProj = dynamic_cast(tile->get_Projection());
if (customProj)
{
diff --git a/src/Tiles/TileManager.cpp b/src/Tiles/TileManager.cpp
index d8a4201e..133572bc 100644
--- a/src/Tiles/TileManager.cpp
+++ b/src/Tiles/TileManager.cpp
@@ -22,6 +22,7 @@
#include "StdAfx.h"
#include "TileManager.h"
#include "TileCacheManager.h"
+#include "WmsCustomProvider.h"
// ************************************************************
// set_MapCallback()
@@ -150,6 +151,8 @@ bool TileManager::GetTileIndices(BaseProvider* provider, CRect& indices, int& zo
return false;
}
+ //VerifyLayers();
+
if (!_map->_GetTilesForMap(provider, _scalingRatio, indices, zoom))
{
Clear();
@@ -349,9 +352,20 @@ void TileManager::ClearBuffer()
// *********************************************************
bool TileManager::IsNewRequest(Extent& mapExtents, CRect indices, int providerId, int zoom)
{
+ auto layersSelectionChanged = false;
+ auto customProvider = reinterpret_cast(_provider);
+ if (customProvider != nullptr) {
+ auto layers = customProvider->get_Layers();
+ layersSelectionChanged = _lastLayers != layers;
+ if (layersSelectionChanged)
+ _tiles.clear();
+ _lastLayers = layers;
+ }
+
if (indices == _lastTileExtents &&
_lastProvider == providerId &&
- _lastZoom == zoom)
+ _lastZoom == zoom &&
+ !layersSelectionChanged)
{
// map extents has changed but the list of tiles to be displayed is the same
tilesLogger.WriteLine("The same list of tiles can be used.");
@@ -542,7 +556,8 @@ void TileManager::UpdateScreenBuffer()
{
if (_isBackground)
{
- _map->_MarkTileBufferChanged();
+ if( _map != nullptr )
+ _map->_MarkTileBufferChanged();
}
else
{
diff --git a/src/Tiles/TileManager.h b/src/Tiles/TileManager.h
index 3b15b32e..25be21aa 100644
--- a/src/Tiles/TileManager.h
+++ b/src/Tiles/TileManager.h
@@ -61,6 +61,7 @@ class TileManager
// can be wrapped in a separate class
CCriticalSection _tilesBufferLock;
vector _tiles;
+ CString _lastLayers;
Extent _projExtents; // extents of the world under current projection; in WGS84 it'll be (-180, 180, -90, 90)
bool _projExtentsNeedUpdate; // do we need to update bounds in m_projExtents on the next request?
diff --git a/src/Utilities/ColoringGraph.h b/src/Utilities/ColoringGraph.h
index 6e96c7f0..8e47f00e 100644
--- a/src/Utilities/ColoringGraph.h
+++ b/src/Utilities/ColoringGraph.h
@@ -1,4 +1,5 @@
#pragma once
+#include
#include
namespace Coloring
diff --git a/src/Utilities/ComHelper.cpp b/src/Utilities/ComHelper.cpp
index 678767a4..7c9739b7 100644
--- a/src/Utilities/ComHelper.cpp
+++ b/src/Utilities/ComHelper.cpp
@@ -242,6 +242,9 @@ HRESULT ComHelper::CreateInstance(tkInterface interfaceId, IDispatch** retVal)
case tkInterface::idGdalUtils:
result = CoCreateInstance(CLSID_GdalUtils, NULL, CLSCTX_INPROC_SERVER, IID_IGdalUtils, (void**)&val);
break;
+ case tkInterface::idPlacedLabels:
+ result = CoCreateInstance(CLSID_PlacedLabels, NULL, CLSCTX_INPROC_SERVER, IID_IPlacedLabels, (void**)&val);
+ break;
}
*retVal = val ? (IDispatch*)val : NULL;
return result;
diff --git a/src/Utilities/ComHelper.h b/src/Utilities/ComHelper.h
index 7a0733e8..0e4c8daf 100644
--- a/src/Utilities/ComHelper.h
+++ b/src/Utilities/ComHelper.h
@@ -8,5 +8,17 @@ class ComHelper
static void CreatePoint(IPoint** point);
static void CreateShape(IShape** shp);
static void CreateExtents(IExtents** box);
+
+#if DEBUG_ALLOCATED_OBJECTS
+ static bool GetBreak()
+ {
+ return _break;
+ }
+
+ static void SetBreak(bool breakValue)
+ {
+ _break = breakValue;
+ }
+#endif
};
diff --git a/src/Utilities/Debugging/ReferenceCounter.cpp b/src/Utilities/Debugging/ReferenceCounter.cpp
index a759d414..47b3c1fb 100644
--- a/src/Utilities/Debugging/ReferenceCounter.cpp
+++ b/src/Utilities/Debugging/ReferenceCounter.cpp
@@ -1,5 +1,10 @@
#include "stdafx.h"
#include "ReferenceCounter.h"
+#if DEBUG_ALLOCATED_OBJECTS
+#include "Shape.h"
+#include "ShapeDrawingOptions.h"
+#include "Shapefile.h"
+#endif
// ********************************************************
// WriteReport()
@@ -37,9 +42,92 @@ CString ReferenceCounter::GetReport(bool unreleasedOnly)
}
}
}
+
+#if DEBUG_ALLOCATED_OBJECTS
+ if (unreleasedOnly) {
+ if (referencePtrs.size() > 0) {
+ temp.Format("referencePtrs.count: %d\r\n", static_cast(referencePtrs.size()));
+ s += temp;
+ for (auto it = referencePtrs.begin(); it != referencePtrs.end();) {
+ const auto ptr = *it;
+
+ //temp.Format("0x%016llx\r\n", ptr);
+ //s += temp;
+
+ /*auto shp = static_cast(ptr);
+ CComBSTR tmp;
+ shp->Serialize2(VARIANT_FALSE, VARIANT_TRUE, &tmp);
+ temp = CString(tmp);
+ s += temp; */
+
+ /*auto sdOptions = static_cast(ptr);
+ CComBSTR tmp;
+ sdOptions->Serialize(&tmp);
+ temp = CString(tmp);
+ s += temp;*/
+
+ /*auto shape = static_cast(ptr);
+ CComBSTR key;
+ shape->get_Key(&key);
+ if (key != "") {
+ s += key;
+ } */
+
+ ++it;
+ }
+ }
+ }
+ else
+ referencePtrs.clear();
+#endif
+
if (temp.GetLength() == 0) {
s += "";
}
return s;
-}
\ No newline at end of file
+}
+
+#if DEBUG_ALLOCATED_OBJECTS
+CString ReferenceCounter::GetReferenceReport()
+{
+ CString s, temp;
+
+ if (!referencePtrs.empty()) {
+ temp.Format("referencePtrs.count: %d\r\n", static_cast(referencePtrs.size()));
+ s += temp;
+ for (auto it = referencePtrs.begin(); it != referencePtrs.end();) {
+ const auto ptr = *it;
+
+ //temp.Format("0x%016llx\r\n", ptr);
+ //s += temp;
+
+ /*auto shp = static_cast(ptr);
+ CComBSTR tmp;
+ shp->Serialize2(VARIANT_FALSE, VARIANT_TRUE, &tmp);
+ temp = CString(tmp);
+ s += temp; */
+
+ /*auto sdOptions = static_cast(ptr);
+ CComBSTR tmp;
+ sdOptions->Serialize(&tmp);
+ temp = CString(tmp);
+ s += temp;*/
+
+ /*auto shape = static_cast(ptr);
+ CComBSTR key;
+ shape->get_Key(&key);
+ if (key != "") {
+ s += CString(key) + " ";
+ }
+ CComBSTR bstr;
+ shape->ExportToWKT(&bstr);
+ s += "WKT: " + CString(bstr) + "\r\n"; */
+
+ ++it;
+ }
+ }
+
+ return s;
+}
+#endif
\ No newline at end of file
diff --git a/src/Utilities/Debugging/ReferenceCounter.h b/src/Utilities/Debugging/ReferenceCounter.h
index 23763993..348707cb 100644
--- a/src/Utilities/Debugging/ReferenceCounter.h
+++ b/src/Utilities/Debugging/ReferenceCounter.h
@@ -1,10 +1,16 @@
#pragma once
+#if DEBUG_ALLOCATED_OBJECTS
+#include
+#endif
class ReferenceCounter
{
static const int INTERFACES_COUNT = 100;
int referenceCounts[INTERFACES_COUNT];
int totalCounts[INTERFACES_COUNT];
+#if DEBUG_ALLOCATED_OBJECTS
+ unordered_set referencePtrs;
+#endif
public:
ReferenceCounter(void)
{
@@ -27,6 +33,26 @@ class ReferenceCounter
int* val = &referenceCounts[(int)type];
(*val)--;
}
+
void WriteReport(bool unreleasedOnly);
CString GetReport(bool unreleasedOnly);
+
+#if DEBUG_ALLOCATED_OBJECTS
+ void AddRef(void* pThis)
+ {
+ referencePtrs.insert(pThis);
+ }
+
+ void Release(void* pThis)
+ {
+ referencePtrs.erase(pThis);
+ }
+
+ long GetReferenceCount() const
+ {
+ return referencePtrs.size();
+ }
+
+ CString GetReferenceReport();
+#endif
};
diff --git a/src/Utilities/GdalHelper.cpp b/src/Utilities/GdalHelper.cpp
index 2ffd5cdb..cec38a99 100644
--- a/src/Utilities/GdalHelper.cpp
+++ b/src/Utilities/GdalHelper.cpp
@@ -113,7 +113,7 @@ int GdalHelper::CloseSharedOgrDataset(GDALDataset* ds)
const int count = ds->Dereference();
if (count == 0)
{
- //Debug::WriteLine("Shared datasource is closed.");
+ Debug::WriteLine("Shared datasource(%s) is closed.", ds->GetDescription());
RemoveCachedOgrDataset(ds);
GDALClose(ds);
}
@@ -139,6 +139,7 @@ void GdalHelper::RemoveCachedOgrDataset(GDALDataset* ds)
{
if (it->second == ds)
{
+ Debug::WriteLine("RemoveCachedOgrDataset(ds: %s)", it->first.GetString());
m_ogrDatasets.erase(it->first);
break;
}
@@ -740,7 +741,7 @@ CStringW GdalHelper::GetDefaultConfigPath(const GdalPath option)
path += L"\\gdalplugins\\";
break;
case PathProjLib:
- path += L"\\proj7\\share\\";
+ path += L"\\proj9\\share\\";
break;
}
return path;
diff --git a/src/Utilities/Logger.cpp b/src/Utilities/Logger.cpp
index 351ed331..bfd72d72 100644
--- a/src/Utilities/Logger.cpp
+++ b/src/Utilities/Logger.cpp
@@ -31,7 +31,7 @@ namespace Debug
{
if (IsOpened() || Debug::IsDebugMode())
{
- TCHAR buffer[1024];
+ TCHAR buffer[4096];
va_list args;
va_start( args, format);
vsprintf( buffer, format, args );
diff --git a/src/Utilities/UtilityFunctions.cpp b/src/Utilities/UtilityFunctions.cpp
index a8d70a24..906345b3 100644
--- a/src/Utilities/UtilityFunctions.cpp
+++ b/src/Utilities/UtilityFunctions.cpp
@@ -1,4 +1,4 @@
-#include "StdAfx.h"
+#include "StdAfx.h"
#include
#include
#include "macros.h"
@@ -39,6 +39,15 @@ namespace Utility
return utf8;
}
+ // ********************************************************
+ // ConvertToAnsi1252()
+ // ********************************************************
+ CStringA ConvertToAnsi1252(CStringW unicode) {
+ USES_CONVERSION;
+ CStringA acp = CW2A(unicode, CP_ACP);
+ return acp;
+ }
+
// ********************************************************
// ConvertFromUtf8()
// ********************************************************
@@ -705,6 +714,9 @@ namespace Utility
}
break;
}
+ case admMetricMeters:
+ localizedUnits = lsSquareMeters;
+ break;
case admHectars:
{
area /= 10000.0;
diff --git a/src/Utilities/UtilityFunctions.h b/src/Utilities/UtilityFunctions.h
index aefc94d9..d0d6905f 100644
--- a/src/Utilities/UtilityFunctions.h
+++ b/src/Utilities/UtilityFunctions.h
@@ -18,7 +18,8 @@ namespace Utility
CString UrlEncode(CString s);
CStringW XmlFilenameToUnicode(CStringA s, bool utf8);
- CStringA ConvertToUtf8(CStringW unicode);
+ CStringA ConvertToUtf8(CStringW unicode);
+ CStringA ConvertToAnsi1252(CStringW unicode);
CStringW ConvertFromUtf8(CStringA utf8);
CString GetSocketErrorMessage(DWORD socketError);
diff --git a/src/changingVersionNumbers.txt b/src/changingVersionNumbers.txt
index e628a111..703af3a6 100644
--- a/src/changingVersionNumbers.txt
+++ b/src/changingVersionNumbers.txt
@@ -1,5 +1,5 @@
When releasing a new version version numbers need to be updated on several locations:
-MapWinGIS.rc lines: 115, 116, 134, 140 [5.4.0.0]
+MapWinGIS.rc lines: 115, 116, 134, 140 [5.4.0.4]
MapWinGIS.cpp lines: 33, 34 [5.4]
MapWinGIS.idl line: 6742 (helpfile("MapWinGIS.chm")) [5.4]
, 6764 (helpstring("Dispatch interface for Map Control")) [5.4]
diff --git a/support/GDAL_SDK/v143/include/win32/!!!VC2019 win32 headers should be here!!!.txt b/support/GDAL_SDK/v143/include/win32/!!!VC2019 win32 headers should be here!!!.txt
new file mode 100644
index 00000000..0519ecba
--- /dev/null
+++ b/support/GDAL_SDK/v143/include/win32/!!!VC2019 win32 headers should be here!!!.txt
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/support/GDAL_SDK/v143/lib/win32/!!!VC2019 win32 libs should be here!!!.txt b/support/GDAL_SDK/v143/lib/win32/!!!VC2019 win32 libs should be here!!!.txt
new file mode 100644
index 00000000..0519ecba
--- /dev/null
+++ b/support/GDAL_SDK/v143/lib/win32/!!!VC2019 win32 libs should be here!!!.txt
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/support/GDAL_SDK/v143/removeOldGdalFiles.ps1 b/support/GDAL_SDK/v143/removeOldGdalFiles.ps1
new file mode 100644
index 00000000..0336ee24
--- /dev/null
+++ b/support/GDAL_SDK/v143/removeOldGdalFiles.ps1
@@ -0,0 +1,3 @@
+Get-ChildItem bin\* -Force -Exclude !!!*.txt | Remove-Item -force -recurse
+Get-ChildItem include\* -Force -Exclude !!!*.txt | Remove-Item -force -recurse
+Get-ChildItem lib\* -Force -Exclude !!!*.txt | Remove-Item -force -recurse
\ No newline at end of file
diff --git a/support/ShapeLib/ShapeLib-toolset142.vcxproj b/support/ShapeLib/ShapeLib-toolset142.vcxproj
new file mode 100644
index 00000000..d62ee7ba
--- /dev/null
+++ b/support/ShapeLib/ShapeLib-toolset142.vcxproj
@@ -0,0 +1,204 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {A0B00502-605B-4382-B313-5983F6BC8E71}
+ Win32Proj
+ ShapeLib
+ 10.0
+
+
+
+ StaticLibrary
+ true
+ v143
+ Unicode
+
+
+ StaticLibrary
+ true
+ v143
+ Unicode
+
+
+ StaticLibrary
+ false
+ v143
+ true
+ Unicode
+
+
+ StaticLibrary
+ false
+ v143
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(SolutionDir)lib\$(PlatformToolset)\$(Platform)\$(Configuration)\
+ $(ProjectDir)$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)lib\$(PlatformToolset)\$(Platform)\$(Configuration)\
+ $(ProjectDir)$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)lib\$(PlatformToolset)\$(Platform)\$(Configuration)\
+ $(ProjectDir)$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)lib\$(PlatformToolset)\$(Platform)\$(Configuration)\
+ $(ProjectDir)$(Platform)\$(Configuration)\
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_CRT_SECURE_NO_WARNINGS;SHAPELIB_DLLEXPORT;_DEBUG;_LIB;%(PreprocessorDefinitions)
+ %(AdditionalIncludeDirectories)
+ OldStyle
+ false
+ MultiThreadedDLL
+ Default
+
+
+ Windows
+ true
+
+
+ $(OutDir)$(TargetName)$(TargetExt)
+
+
+ %(AdditionalLibraryDirectories)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_CRT_SECURE_NO_WARNINGS;SHAPELIB_DLLEXPORT;_DEBUG;_LIB;%(PreprocessorDefinitions)
+ %(AdditionalIncludeDirectories)
+ OldStyle
+ false
+ MultiThreadedDLL
+ Default
+
+
+ Windows
+ true
+
+
+ $(OutDir)$(TargetName)$(TargetExt)
+
+
+ %(AdditionalLibraryDirectories)
+
+
+
+
+ Level3
+
+
+ Full
+
+
+ false
+ WIN32;_CRT_SECURE_NO_WARNINGS;SHAPELIB_DLLEXPORT;NDEBUG;_LIB;%(PreprocessorDefinitions)
+ %(AdditionalIncludeDirectories)
+ None
+ false
+ true
+
+
+ Windows
+ true
+ true
+ true
+
+
+ $(OutDir)$(TargetName)$(TargetExt)
+
+
+ %(AdditionalLibraryDirectories)
+
+
+
+
+ Level3
+
+
+ Full
+
+
+ true
+ WIN32;_CRT_SECURE_NO_WARNINGS;SHAPELIB_DLLEXPORT;NDEBUG;_LIB;%(PreprocessorDefinitions)
+ %(AdditionalIncludeDirectories)
+ None
+ false
+ true
+
+
+ Windows
+ true
+ true
+ true
+
+
+ $(OutDir)$(TargetName)$(TargetExt)
+
+
+ %(AdditionalLibraryDirectories)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/support/ShapeLib/ShapeLib-toolset143.vcxproj b/support/ShapeLib/ShapeLib-toolset143.vcxproj
new file mode 100644
index 00000000..f4f82cd5
--- /dev/null
+++ b/support/ShapeLib/ShapeLib-toolset143.vcxproj
@@ -0,0 +1,208 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {D6A9A8D7-5556-47C9-A002-FAA9B9BD1CEA}
+ Win32Proj
+ ShapeLib
+ 10.0
+
+
+
+ StaticLibrary
+ true
+ v143
+ Unicode
+
+
+ StaticLibrary
+ true
+ v143
+ Unicode
+
+
+ StaticLibrary
+ false
+ v143
+ true
+ Unicode
+
+
+ StaticLibrary
+ false
+ v143
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(SolutionDir)lib\$(PlatformToolset)\$(Platform)\$(Configuration)\
+ $(ProjectDir)$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)lib\$(PlatformToolset)\$(Platform)\$(Configuration)\
+ $(ProjectDir)$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)lib\$(PlatformToolset)\$(Platform)\$(Configuration)\
+ $(ProjectDir)$(Platform)\$(Configuration)\
+ $(RootNamespace)
+
+
+ $(SolutionDir)lib\$(PlatformToolset)\$(Platform)\$(Configuration)\
+ $(ProjectDir)$(Platform)\$(Configuration)\
+ $(RootNamespace)
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_CRT_SECURE_NO_WARNINGS;SHAPELIB_DLLEXPORT;_DEBUG;_LIB;%(PreprocessorDefinitions)
+ %(AdditionalIncludeDirectories)
+ OldStyle
+ false
+ MultiThreadedDLL
+ Default
+
+
+ Windows
+ true
+
+
+ $(OutDir)$(TargetName)$(TargetExt)
+
+
+ %(AdditionalLibraryDirectories)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_CRT_SECURE_NO_WARNINGS;SHAPELIB_DLLEXPORT;_DEBUG;_LIB;%(PreprocessorDefinitions)
+ %(AdditionalIncludeDirectories)
+ OldStyle
+ false
+ MultiThreadedDLL
+ Default
+ stdcpp17
+
+
+ Windows
+ true
+
+
+ $(OutDir)$(RootNamespace)$(TargetExt)
+
+
+ %(AdditionalLibraryDirectories)
+
+
+
+
+ Level3
+
+
+ Full
+
+
+ false
+ WIN32;_CRT_SECURE_NO_WARNINGS;SHAPELIB_DLLEXPORT;NDEBUG;_LIB;%(PreprocessorDefinitions)
+ %(AdditionalIncludeDirectories)
+ None
+ false
+ true
+
+
+ Windows
+ true
+ true
+ true
+
+
+ $(OutDir)$(TargetName)$(TargetExt)
+
+
+ %(AdditionalLibraryDirectories)
+
+
+
+
+ Level3
+
+
+ Full
+
+
+ true
+ WIN32;_CRT_SECURE_NO_WARNINGS;SHAPELIB_DLLEXPORT;NDEBUG;_LIB;%(PreprocessorDefinitions)
+ %(AdditionalIncludeDirectories)
+ None
+ false
+ true
+ stdcpp17
+
+
+ Windows
+ true
+ true
+ true
+
+
+ $(OutDir)$(RootNamespace)$(TargetExt)
+
+
+ %(AdditionalLibraryDirectories)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/support/SupportLibs-toolset142.sln b/support/SupportLibs-toolset142.sln
new file mode 100644
index 00000000..aca31bc5
--- /dev/null
+++ b/support/SupportLibs-toolset142.sln
@@ -0,0 +1,52 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.33130.400
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spatialindex-mw", "spatialindex\spatialindex-vc\spatialindex-toolset142.vcxproj", "{38FBBD59-8344-4D8E-B728-3D51763B6A70}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cqlib-toolset142", "cqlib\cqlib-toolset142.vcxproj", "{E81699D6-81BA-41BF-A3A9-DD4CEF0B4E95}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShapeLib-toolset142", "ShapeLib\ShapeLib-toolset142.vcxproj", "{A0B00502-605B-4382-B313-5983F6BC8E71}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Debug|Win32.ActiveCfg = Debug|Win32
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Debug|Win32.Build.0 = Debug|Win32
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Debug|Win32.Deploy.0 = Debug|Win32
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Debug|x64.ActiveCfg = Debug|x64
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Debug|x64.Build.0 = Debug|x64
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Release|Win32.ActiveCfg = Release|Win32
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Release|Win32.Build.0 = Release|Win32
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Release|x64.ActiveCfg = Release|x64
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Release|x64.Build.0 = Release|x64
+ {E81699D6-81BA-41BF-A3A9-DD4CEF0B4E95}.Debug|Win32.ActiveCfg = Debug|Win32
+ {E81699D6-81BA-41BF-A3A9-DD4CEF0B4E95}.Debug|Win32.Build.0 = Debug|Win32
+ {E81699D6-81BA-41BF-A3A9-DD4CEF0B4E95}.Debug|x64.ActiveCfg = Debug|x64
+ {E81699D6-81BA-41BF-A3A9-DD4CEF0B4E95}.Debug|x64.Build.0 = Debug|x64
+ {E81699D6-81BA-41BF-A3A9-DD4CEF0B4E95}.Release|Win32.ActiveCfg = Release|Win32
+ {E81699D6-81BA-41BF-A3A9-DD4CEF0B4E95}.Release|Win32.Build.0 = Release|Win32
+ {E81699D6-81BA-41BF-A3A9-DD4CEF0B4E95}.Release|x64.ActiveCfg = Release|x64
+ {E81699D6-81BA-41BF-A3A9-DD4CEF0B4E95}.Release|x64.Build.0 = Release|x64
+ {A0B00502-605B-4382-B313-5983F6BC8E71}.Debug|Win32.ActiveCfg = Debug|Win32
+ {A0B00502-605B-4382-B313-5983F6BC8E71}.Debug|Win32.Build.0 = Debug|Win32
+ {A0B00502-605B-4382-B313-5983F6BC8E71}.Debug|x64.ActiveCfg = Debug|x64
+ {A0B00502-605B-4382-B313-5983F6BC8E71}.Debug|x64.Build.0 = Debug|x64
+ {A0B00502-605B-4382-B313-5983F6BC8E71}.Release|Win32.ActiveCfg = Release|Win32
+ {A0B00502-605B-4382-B313-5983F6BC8E71}.Release|Win32.Build.0 = Release|Win32
+ {A0B00502-605B-4382-B313-5983F6BC8E71}.Release|x64.ActiveCfg = Release|x64
+ {A0B00502-605B-4382-B313-5983F6BC8E71}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {78295CF0-1F26-4776-978E-2AAFFC25227B}
+ EndGlobalSection
+EndGlobal
diff --git a/support/SupportLibs-toolset143.sln b/support/SupportLibs-toolset143.sln
new file mode 100644
index 00000000..a97bf9bf
--- /dev/null
+++ b/support/SupportLibs-toolset143.sln
@@ -0,0 +1,52 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.13.35931.197
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spatialindex-mw", "spatialindex\spatialindex-vc\spatialindex-toolset142.vcxproj", "{38FBBD59-8344-4D8E-B728-3D51763B6A70}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShapeLib-toolset143", "ShapeLib\ShapeLib-toolset143.vcxproj", "{D6A9A8D7-5556-47C9-A002-FAA9B9BD1CEA}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cqlib-toolset143", "cqlib\cqlib-toolset143.vcxproj", "{19A1259D-0DCC-4FE5-9B0F-CF46B6F9DA81}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Debug|Win32.ActiveCfg = Debug|Win32
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Debug|Win32.Build.0 = Debug|Win32
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Debug|Win32.Deploy.0 = Debug|Win32
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Debug|x64.ActiveCfg = Debug|x64
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Debug|x64.Build.0 = Debug|x64
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Release|Win32.ActiveCfg = Release|Win32
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Release|Win32.Build.0 = Release|Win32
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Release|x64.ActiveCfg = Release|x64
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}.Release|x64.Build.0 = Release|x64
+ {D6A9A8D7-5556-47C9-A002-FAA9B9BD1CEA}.Debug|Win32.ActiveCfg = Debug|Win32
+ {D6A9A8D7-5556-47C9-A002-FAA9B9BD1CEA}.Debug|Win32.Build.0 = Debug|Win32
+ {D6A9A8D7-5556-47C9-A002-FAA9B9BD1CEA}.Debug|x64.ActiveCfg = Debug|x64
+ {D6A9A8D7-5556-47C9-A002-FAA9B9BD1CEA}.Debug|x64.Build.0 = Debug|x64
+ {D6A9A8D7-5556-47C9-A002-FAA9B9BD1CEA}.Release|Win32.ActiveCfg = Release|Win32
+ {D6A9A8D7-5556-47C9-A002-FAA9B9BD1CEA}.Release|Win32.Build.0 = Release|Win32
+ {D6A9A8D7-5556-47C9-A002-FAA9B9BD1CEA}.Release|x64.ActiveCfg = Release|x64
+ {D6A9A8D7-5556-47C9-A002-FAA9B9BD1CEA}.Release|x64.Build.0 = Release|x64
+ {19A1259D-0DCC-4FE5-9B0F-CF46B6F9DA81}.Debug|Win32.ActiveCfg = Debug|Win32
+ {19A1259D-0DCC-4FE5-9B0F-CF46B6F9DA81}.Debug|Win32.Build.0 = Debug|Win32
+ {19A1259D-0DCC-4FE5-9B0F-CF46B6F9DA81}.Debug|x64.ActiveCfg = Debug|x64
+ {19A1259D-0DCC-4FE5-9B0F-CF46B6F9DA81}.Debug|x64.Build.0 = Debug|x64
+ {19A1259D-0DCC-4FE5-9B0F-CF46B6F9DA81}.Release|Win32.ActiveCfg = Release|Win32
+ {19A1259D-0DCC-4FE5-9B0F-CF46B6F9DA81}.Release|Win32.Build.0 = Release|Win32
+ {19A1259D-0DCC-4FE5-9B0F-CF46B6F9DA81}.Release|x64.ActiveCfg = Release|x64
+ {19A1259D-0DCC-4FE5-9B0F-CF46B6F9DA81}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {78295CF0-1F26-4776-978E-2AAFFC25227B}
+ EndGlobalSection
+EndGlobal
diff --git a/support/cqlib/cqlib-toolset142.vcxproj b/support/cqlib/cqlib-toolset142.vcxproj
new file mode 100644
index 00000000..8c089ae9
--- /dev/null
+++ b/support/cqlib/cqlib-toolset142.vcxproj
@@ -0,0 +1,226 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {E81699D6-81BA-41BF-A3A9-DD4CEF0B4E95}
+ cqlib
+ 10.0
+
+
+
+ StaticLibrary
+ v143
+ false
+ MultiByte
+
+
+ StaticLibrary
+ v143
+ false
+ MultiByte
+
+
+ StaticLibrary
+ v143
+ false
+ MultiByte
+
+
+ StaticLibrary
+ v143
+ false
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>12.0.21005.1
+
+
+ $(SolutionDir)lib\$(PlatformToolset)\$(Platform)\$(Configuration)\
+ $(ProjectDir)$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)lib\$(PlatformToolset)\$(Platform)\$(Configuration)\
+ $(ProjectDir)$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)lib\$(PlatformToolset)\$(Platform)\$(Configuration)\
+ $(ProjectDir)$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)lib\$(PlatformToolset)\$(Platform)\$(Configuration)\
+ $(ProjectDir)$(Platform)\$(Configuration)\
+
+
+
+ Disabled
+ WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)
+ Default
+ MultiThreadedDLL
+
+ .\Debug/cqlib.pch
+ .\Debug/
+ .\Debug/
+ .\Debug/
+ Level3
+ true
+ EditAndContinue
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+ 0x0409
+
+
+ $(OutDir)cqlib.lib
+ true
+
+
+
+
+ X64
+
+
+ Disabled
+ WIN32;WIN64;_DEBUG;_LIB;%(PreprocessorDefinitions)
+ Default
+ MultiThreadedDLL
+
+ .\Debug/cqlib.pch
+ .\Debug/
+ .\Debug/
+ .\Debug/
+ Level3
+ true
+ ProgramDatabase
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+ 0x0409
+
+
+ $(OutDir)$(TargetName)$(TargetExt)
+ true
+
+
+
+
+ Full
+ Default
+ WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
+ true
+ MultiThreadedDLL
+
+
+
+ $(IntDir)cqlib.pch
+ $(IntDir)
+ $(IntDir)
+ $(IntDir)
+ Level3
+ true
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ 0x0409
+
+
+ $(OutDir)cqlib.lib
+ true
+
+
+ $(OutDir)$(ProjectName).bsc
+
+
+
+
+
+
+
+ X64
+
+
+ Full
+ Default
+ WIN32;WIN64;NDEBUG;_LIB;%(PreprocessorDefinitions)
+ true
+ MultiThreadedDLL
+
+
+
+ $(IntDir)cqlib.pch
+ $(IntDir)
+ $(IntDir)
+ $(IntDir)
+ Level3
+ true
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ 0x0409
+
+
+ $(OutDir)cqlib.lib
+ true
+ true
+
+
+ $(OutDir)$(ProjectName).bsc
+
+
+ Copy lib to general lib folder
+ rem copy "$(TargetPath)" "$(ProjectDir)..\lib\v142\$(Platform)"
+
+
+
+
+ Disabled
+ EnableFastChecks
+ Disabled
+ EnableFastChecks
+ MaxSpeed
+ MaxSpeed
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/support/cqlib/cqlib-toolset143.vcxproj b/support/cqlib/cqlib-toolset143.vcxproj
new file mode 100644
index 00000000..e4d8f278
--- /dev/null
+++ b/support/cqlib/cqlib-toolset143.vcxproj
@@ -0,0 +1,228 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {19A1259D-0DCC-4FE5-9B0F-CF46B6F9DA81}
+ cqlib
+ 10.0
+
+
+
+ StaticLibrary
+ v143
+ false
+ MultiByte
+
+
+ StaticLibrary
+ v143
+ false
+ MultiByte
+
+
+ StaticLibrary
+ v143
+ false
+ MultiByte
+
+
+ StaticLibrary
+ v143
+ false
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>12.0.21005.1
+
+
+ $(SolutionDir)lib\$(PlatformToolset)\$(Platform)\$(Configuration)\
+ $(ProjectDir)$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)lib\$(PlatformToolset)\$(Platform)\$(Configuration)\
+ $(ProjectDir)$(Platform)\$(Configuration)\
+ $(RootNamespace)
+
+
+ $(SolutionDir)lib\$(PlatformToolset)\$(Platform)\$(Configuration)\
+ $(ProjectDir)$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)lib\$(PlatformToolset)\$(Platform)\$(Configuration)\
+ $(ProjectDir)$(Platform)\$(Configuration)\
+ $(RootNamespace)
+
+
+
+ Disabled
+ WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)
+ Default
+ MultiThreadedDLL
+
+ .\Debug/cqlib.pch
+ .\Debug/
+ .\Debug/
+ .\Debug/
+ Level3
+ true
+ EditAndContinue
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+ 0x0409
+
+
+ $(OutDir)cqlib.lib
+ true
+
+
+
+
+ X64
+
+
+ Disabled
+ WIN32;WIN64;_DEBUG;_LIB;%(PreprocessorDefinitions)
+ Default
+ MultiThreadedDLL
+
+ .\Debug/cqlib.pch
+ .\Debug/
+ .\Debug/
+ .\Debug/
+ Level3
+ true
+ ProgramDatabase
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+ 0x0409
+
+
+ $(OutDir)$(TargetName)$(TargetExt)
+ true
+
+
+
+
+ Full
+ Default
+ WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
+ true
+ MultiThreadedDLL
+
+
+
+ $(IntDir)cqlib.pch
+ $(IntDir)
+ $(IntDir)
+ $(IntDir)
+ Level3
+ true
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ 0x0409
+
+
+ $(OutDir)cqlib.lib
+ true
+
+
+ $(OutDir)$(ProjectName).bsc
+
+
+
+
+
+
+
+ X64
+
+
+ Full
+ Default
+ WIN32;WIN64;NDEBUG;_LIB;%(PreprocessorDefinitions)
+ true
+ MultiThreadedDLL
+
+
+
+ $(IntDir)cqlib.pch
+ $(IntDir)
+ $(IntDir)
+ $(IntDir)
+ Level3
+ true
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+ 0x0409
+
+
+ $(OutDir)cqlib.lib
+ true
+ true
+
+
+ $(OutDir)$(ProjectName).bsc
+
+
+ Copy lib to general lib folder
+ rem copy "$(TargetPath)" "$(ProjectDir)..\lib\v142\$(Platform)"
+
+
+
+
+ Disabled
+ EnableFastChecks
+ Disabled
+ EnableFastChecks
+ MaxSpeed
+ MaxSpeed
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/support/spatialindex/spatialindex-vc/spatialindex-toolset141.vcxproj b/support/spatialindex/spatialindex-vc/spatialindex-toolset141.vcxproj
index 37b60a5a..30eb2514 100644
--- a/support/spatialindex/spatialindex-vc/spatialindex-toolset141.vcxproj
+++ b/support/spatialindex/spatialindex-vc/spatialindex-toolset141.vcxproj
@@ -23,32 +23,32 @@
{38FBBD59-8344-4D8E-B728-3D51763B6A70}
spatialindex
ManagedCProj
- 10.0.17763.0
+ 10.0
StaticLibrary
- v141
+ v142
Unicode
false
true
StaticLibrary
- v141
+ v142
Unicode
false
StaticLibrary
- v141
+ v142
Unicode
false
true
StaticLibrary
- v141
+ v142
Unicode
false
@@ -93,7 +93,7 @@
Disabled
- $(SolutionDir)include;%(AdditionalIncludeDirectories)
+ $(SolutionDir)include;C:\SWDEV\Projects\Lib\MapWinGIS\src\vcpkg\packages\libspatialindex_x64-windows\include;%(AdditionalIncludeDirectories)
WIN32;_DEBUG;SPATIALINDEX_CREATE_DLL;%(PreprocessorDefinitions)
MultiThreadedDLL
@@ -108,12 +108,13 @@
Disabled
- $(SolutionDir)include;%(AdditionalIncludeDirectories)
+ $(SolutionDir)include;C:\SWDEV\Projects\Lib\MapWinGIS\src\vcpkg\packages\libspatialindex_x64-windows\include;%(AdditionalIncludeDirectories)
WIN64;_DEBUG;SPATIALINDEX_CREATE_DLL;%(PreprocessorDefinitions)
MultiThreadedDLL
Level3
ProgramDatabase
+ stdcpp17
diff --git a/support/spatialindex/spatialindex-vc/spatialindex-toolset142.vcxproj b/support/spatialindex/spatialindex-vc/spatialindex-toolset142.vcxproj
new file mode 100644
index 00000000..51e521e7
--- /dev/null
+++ b/support/spatialindex/spatialindex-vc/spatialindex-toolset142.vcxproj
@@ -0,0 +1,315 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ spatialindex-mw
+ {38FBBD59-8344-4D8E-B728-3D51763B6A70}
+ spatialindex
+ ManagedCProj
+ 10.0
+
+
+
+ StaticLibrary
+ v143
+ Unicode
+ false
+ true
+
+
+ StaticLibrary
+ v143
+ Unicode
+ false
+
+
+ StaticLibrary
+ v143
+ Unicode
+ false
+ true
+
+
+ StaticLibrary
+ v143
+ Unicode
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>12.0.21005.1
+
+
+ $(SolutionDir)lib\$(PlatformToolset)\$(Platform)\$(Configuration)\
+ $(ProjectDir)$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)lib\$(PlatformToolset)\$(Platform)\$(Configuration)\
+ $(ProjectDir)$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)lib\$(PlatformToolset)\$(Platform)\$(Configuration)\
+ $(ProjectDir)$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)lib\$(PlatformToolset)\$(Platform)\$(Configuration)\
+ $(ProjectDir)$(Platform)\$(Configuration)\
+
+
+
+ X64
+
+
+ Disabled
+ $(SolutionDir)include;C:\SWDEV\Projects\Lib\MapWinGIS\src\vcpkg\packages\libspatialindex_x64-windows\include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;SPATIALINDEX_CREATE_DLL;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+
+ Level3
+ OldStyle
+ Default
+
+
+
+
+ X64
+
+
+ Disabled
+ $(SolutionDir)include;C:\SWDEV\Projects\Lib\MapWinGIS\src\vcpkg\packages\libspatialindex_x64-windows\include;%(AdditionalIncludeDirectories)
+ WIN64;_WIN64;_DEBUG;SPATIALINDEX_CREATE_DLL;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+
+ Level3
+ ProgramDatabase
+ stdcpp20
+
+
+
+
+ X64
+
+
+ Full
+ $(SolutionDir)include;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+
+ Level3
+
+ false
+ true
+
+
+
+
+ X64
+
+
+ Full
+ $(SolutionDir)include;%(AdditionalIncludeDirectories)
+ WIN64;NDEBUG;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+
+ Level3
+
+ false
+ true
+
+
+
+
+ true
+ true
+
+
+ true
+ true
+
+
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+ $(IntDir)%(Filename)1.obj
+ $(IntDir)%(Filename)1.xdc
+ $(IntDir)%(Filename)1.obj
+ $(IntDir)%(Filename)1.xdc
+ $(IntDir)%(Filename)1.obj
+ $(IntDir)%(Filename)1.xdc
+ $(IntDir)%(Filename)1.obj
+ $(IntDir)%(Filename)1.xdc
+
+
+ $(IntDir)%(Filename)1.obj
+ $(IntDir)%(Filename)1.xdc
+ $(IntDir)%(Filename)1.obj
+ $(IntDir)%(Filename)1.xdc
+ $(IntDir)%(Filename)1.obj
+ $(IntDir)%(Filename)1.xdc
+ $(IntDir)%(Filename)1.obj
+ $(IntDir)%(Filename)1.xdc
+
+
+ $(IntDir)%(Filename)1.obj
+ $(IntDir)%(Filename)1.xdc
+ $(IntDir)%(Filename)1.obj
+ $(IntDir)%(Filename)1.xdc
+ $(IntDir)%(Filename)1.obj
+ $(IntDir)%(Filename)1.xdc
+ $(IntDir)%(Filename)1.obj
+ $(IntDir)%(Filename)1.xdc
+
+
+
+ $(IntDir)%(Filename)1.obj
+ $(IntDir)%(Filename)1.xdc
+ $(IntDir)%(Filename)1.obj
+ $(IntDir)%(Filename)1.xdc
+ $(IntDir)%(Filename)1.obj
+ $(IntDir)%(Filename)1.xdc
+ $(IntDir)%(Filename)1.obj
+ $(IntDir)%(Filename)1.xdc
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(IntDir)%(Filename)2.obj
+ $(IntDir)%(Filename)2.xdc
+ $(IntDir)%(Filename)2.obj
+ $(IntDir)%(Filename)2.xdc
+ $(IntDir)%(Filename)2.obj
+ $(IntDir)%(Filename)2.xdc
+ $(IntDir)%(Filename)2.obj
+ $(IntDir)%(Filename)2.xdc
+
+
+ $(IntDir)%(Filename)2.obj
+ $(IntDir)%(Filename)2.xdc
+ $(IntDir)%(Filename)2.obj
+ $(IntDir)%(Filename)2.xdc
+ $(IntDir)%(Filename)2.obj
+ $(IntDir)%(Filename)2.xdc
+ $(IntDir)%(Filename)2.obj
+ $(IntDir)%(Filename)2.xdc
+
+
+ $(IntDir)%(Filename)2.obj
+ $(IntDir)%(Filename)2.xdc
+ $(IntDir)%(Filename)2.obj
+ $(IntDir)%(Filename)2.xdc
+ $(IntDir)%(Filename)2.obj
+ $(IntDir)%(Filename)2.xdc
+ $(IntDir)%(Filename)2.obj
+ $(IntDir)%(Filename)2.xdc
+
+
+ $(IntDir)%(Filename)2.obj
+ $(IntDir)%(Filename)2.xdc
+ $(IntDir)%(Filename)2.obj
+ $(IntDir)%(Filename)2.xdc
+ $(IntDir)%(Filename)2.obj
+ $(IntDir)%(Filename)2.xdc
+ $(IntDir)%(Filename)2.obj
+ $(IntDir)%(Filename)2.xdc
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test/TestApplication.sln b/test/TestApplication.sln
index 0906b468..dcee9933 100644
--- a/test/TestApplication.sln
+++ b/test/TestApplication.sln
@@ -1,24 +1,30 @@

Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2013
-VisualStudioVersion = 12.0.21005.1
+# Visual Studio Version 17
+VisualStudioVersion = 17.13.35931.197 d17.13
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApplication", "TestApplication\TestApplication.csproj", "{E813DA57-E5F5-48A6-A6B2-3545ECAAD7CB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E813DA57-E5F5-48A6-A6B2-3545ECAAD7CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E813DA57-E5F5-48A6-A6B2-3545ECAAD7CB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E813DA57-E5F5-48A6-A6B2-3545ECAAD7CB}.Debug|x64.ActiveCfg = Debug|x64
+ {E813DA57-E5F5-48A6-A6B2-3545ECAAD7CB}.Debug|x64.Build.0 = Debug|x64
{E813DA57-E5F5-48A6-A6B2-3545ECAAD7CB}.Debug|x86.ActiveCfg = Debug|x86
{E813DA57-E5F5-48A6-A6B2-3545ECAAD7CB}.Debug|x86.Build.0 = Debug|x86
{E813DA57-E5F5-48A6-A6B2-3545ECAAD7CB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E813DA57-E5F5-48A6-A6B2-3545ECAAD7CB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E813DA57-E5F5-48A6-A6B2-3545ECAAD7CB}.Release|x64.ActiveCfg = Release|x64
+ {E813DA57-E5F5-48A6-A6B2-3545ECAAD7CB}.Release|x64.Build.0 = Release|x64
{E813DA57-E5F5-48A6-A6B2-3545ECAAD7CB}.Release|x86.ActiveCfg = Release|x86
{E813DA57-E5F5-48A6-A6B2-3545ECAAD7CB}.Release|x86.Build.0 = Release|x86
EndGlobalSection
diff --git a/test/TestApplication/Properties/Resources.Designer.cs b/test/TestApplication/Properties/Resources.Designer.cs
index 4394a5e5..655def32 100644
--- a/test/TestApplication/Properties/Resources.Designer.cs
+++ b/test/TestApplication/Properties/Resources.Designer.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:4.0.30319.34014
+// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -19,7 +19,7 @@ namespace TestApplication.Properties {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
diff --git a/test/TestApplication/Properties/Settings.Designer.cs b/test/TestApplication/Properties/Settings.Designer.cs
index 24009990..ddc38812 100644
--- a/test/TestApplication/Properties/Settings.Designer.cs
+++ b/test/TestApplication/Properties/Settings.Designer.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:4.0.30319.34014
+// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -12,7 +12,7 @@ namespace TestApplication.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.13.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
diff --git a/test/TestApplication/TestApplication.csproj b/test/TestApplication/TestApplication.csproj
index 8fa054cf..cf875459 100644
--- a/test/TestApplication/TestApplication.csproj
+++ b/test/TestApplication/TestApplication.csproj
@@ -10,7 +10,7 @@
Properties
TestApplication
TestApplication
- v4.5.1
+ v4.8
512
false
@@ -43,6 +43,7 @@
prompt
4
false
+ x64
pdbonly
@@ -73,6 +74,24 @@
prompt
false
+
+ true
+ C:\Projects\Lib\MapWinGIS_org\src\bin\Debug\x64\
+ TRACE;DEBUG;CODE_ANALYSIS
+ full
+ x64
+ 7.3
+ prompt
+ false
+
+
+ C:\Projects\Lib\MapWinGIS_org\src\bin\Debug\x64\
+ TRACE
+ true
+ x64
+ 7.3
+ prompt
+
diff --git a/test/TestApplication/app.config b/test/TestApplication/app.config
index faedb805..95b45144 100644
--- a/test/TestApplication/app.config
+++ b/test/TestApplication/app.config
@@ -9,145 +9,145 @@
-
+
-
+
-
+
0, 0
-
+
-
+
-
+
-
+
-
+
-
+
-
+
0
-
+
0
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -156,4 +156,4 @@
-
+