[fdo-users] MPolygon <-> FDO

Jonio, Dennis (Aviation) DJonio at miami-airport.com
Mon Mar 10 07:01:51 EDT 2008


Gavin,
Sunday night? ... you the man!!!

Obviously then, since my users and I are in no mood to move away from
Map3d, the issue: "MPolygon allows rings to be slightly open, while FDO
does not.", creates some real-world dissonance.

BTW, Saturday I coded up the same method using OSGeo.MapGuide, not one
of my thirteen(13) test cases produced a closed 
MgCurveString(all produced valid mgcurvestrings). OSGeo.Geometry
produces nine(9) out of thirteen(13) rings!!! :-) Good thing I didn't
start with the MapGuide API's! It would seem the lesson I must learn
here is that MG's definition of "closed" is different from the other
two(2) and I have 3 definitions of "closedness".

Gee ... do ya think I've got a problem here?

Ok ... back to the real issue. Would you be kind enough to show me what
more I must do to make FDO curves work? I sincerely do not know what
else to do to make the start and end match to reach the FDO definition
of closedness.

I know it is redundant but I include the MapGuide code in case you are
interested. (and maybe I am doing it wrong)

public static MgGeometry MGGeometryInterfaceFromMPolygon(MPolygon mpoly)
{
	Document doc =
Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActi
veDocument;
	Editor ed = doc.Editor;
	MgGeometry rtn_geometry = null;
	MgGeometryFactory mggf = new MgGeometryFactory();
	MgCurveRing mgExternalRing = null;
	MgCurveString mgcs_TestCase = null;
	MgArcSegment mgArcSeg;
	MgLinearSegment mgLinearSeg;
	MgCoordinateCollection mgCoorColl = new
MgCoordinateCollection();
	MgCurveSegmentCollection mgCurveSegColl = new
MgCurveSegmentCollection();
	MgCurveRingCollection mgCurveRingColl = new
MgCurveRingCollection();
	if (IsItACurvePolygon(mpoly) == true)
	{
		int loops = mpoly.NumMPolygonLoops;
		for (int i = 0; i < loops; i++)
		{
			MPolygonLoop mPolygonLoop =
mpoly.GetMPolygonLoopAt(i);
			Point2d[] pts = new Point2d[mPolygonLoop.Count];
			double[] blgs = new double[mPolygonLoop.Count];
			int z = 0;
			for (; z < mPolygonLoop.Count; z++)
			{
				Point2d tmp_pt;
				if (z == mPolygonLoop.Count - 1)
				{
					pts[z] = pts[0];
				}
				else
				{
					double X =
Math.Round(mPolygonLoop[z].Vertex.X, 10, MidpointRounding.AwayFromZero);
					double Y =
Math.Round(mPolygonLoop[z].Vertex.Y, 10, MidpointRounding.AwayFromZero);
					tmp_pt = new Point2d(X, Y);
					pts[z] = tmp_pt;
				}
				blgs[z] = mPolygonLoop[z].Bulge;
			}

			for (int j = 0; j < mPolygonLoop.Count - 1; j++)
			{
				mgArcSeg = null;
				mgLinearSeg = null;
				double theBulge = blgs[j];
				if (theBulge != 0.0)
				{
					CircularArc2d ca2d = new
CircularArc2d(pts[j], pts[j + 1], theBulge, false);
					MgCoordinate dpi_start =
mggf.CreateCoordinateXY(ca2d.StartPoint.X, ca2d.StartPoint.Y);
					MgCoordinate dpi_end =
mggf.CreateCoordinateXY(ca2d.EndPoint.X, ca2d.EndPoint.Y);
					Point2d midpoint =
ca2d.EvaluatePoint(0.5);
					double mp_X =
Math.Round(midpoint.X, 10, MidpointRounding.AwayFromZero);
					double mp_Y =
Math.Round(midpoint.Y, 10, MidpointRounding.AwayFromZero);
					midpoint = new Point2d(mp_X,
mp_Y);
					MgCoordinate dpi_center =
mggf.CreateCoordinateXY(midpoint.X, midpoint.Y);
					mgArcSeg =
mggf.CreateArcSegment(dpi_start, dpi_end, dpi_center);
				}
				else
				{
					mgCoorColl.Clear();
					MgCoordinate seg_s =
mggf.CreateCoordinateXY(pts[j].X, pts[j].Y);
					MgCoordinate seg_e =
mggf.CreateCoordinateXY(pts[j + 1].X, pts[j + 1].Y);
					mgCoorColl.Add(seg_s);
					mgCoorColl.Add(seg_e);
					mgLinearSeg =
mggf.CreateLinearSegment(mgCoorColl);
				}
				if (mgLinearSeg != null)
					mgCurveSegColl.Add(mgLinearSeg);
				else
					mgCurveSegColl.Add(mgArcSeg);
			} // for vertex count

			mgcs_TestCase =
mggf.CreateCurveString(mgCurveSegColl);
			MgCurveRing ring = null;
			if (mgcs_TestCase.IsClosed() == false)
			{
				ed.WriteMessage("\nNotClosed - Valid:{0}
Start:{1},{2} End:{3},{4}",
					mgcs_TestCase.IsValid(),
					mgcs_TestCase.StartCoordinate.X,
					mgcs_TestCase.StartCoordinate.Y,
					mgcs_TestCase.EndCoordinate.X,
					mgcs_TestCase.EndCoordinate.Y
					);
				ring =
mggf.CreateCurveRing(mgCurveSegColl);
			}
			else
			{
				ring =
mggf.CreateCurveRing(mgCurveSegColl);
			}
			if (i == 0)
			{
				if (ring != null)
					mgExternalRing = ring;
			}
			else
			{
				if (ring != null)
					mgCurveRingColl.Add(ring);
			}
		}// for each loop in the mpolygon
		if (mgcs_TestCase.IsClosed() == true)
			rtn_geometry =
mggf.CreateCurvePolygon(mgExternalRing, mgCurveRingColl);
	}
	else
	{
		MgLinearRing mgExternalLinearRing = null;
		MgLinearRing mgLinearRingInner = null;
		
		MgLinearRingCollection mgLinearRingColl = new
MgLinearRingCollection();
		int loops = mpoly.NumMPolygonLoops;
		for (int i = 0; i < loops; i++)
		{
			MPolygonLoop mPolygonLoop =
mpoly.GetMPolygonLoopAt(i);
			mgCoorColl.Clear();
			foreach (BulgeVertex bv in mPolygonLoop)
			{
				MgCoordinate coor_start =
mggf.CreateCoordinateXY(bv.Vertex.X, bv.Vertex.Y);
				mgCoorColl.Add(coor_start);
			}
			if (i == 0)
			{
				mgExternalLinearRing =
mggf.CreateLinearRing(mgCoorColl);
			}
			else
			{
				mgLinearRingInner =
mggf.CreateLinearRing(mgCoorColl);
				mgLinearRingColl.Add(mgLinearRingInner);
			}
		}
		rtn_geometry = mggf.CreatePolygon(mgExternalLinearRing,
mgLinearRingColl);
	}
	return rtn_geometry;
}


dennis

-----Original Message-----
From: fdo-users-bounces at lists.osgeo.org
[mailto:fdo-users-bounces at lists.osgeo.org] On Behalf Of Gavin Cramer
Sent: Sunday, March 09, 2008 10:02 PM
To: FDO Users Mail List
Subject: RE: [fdo-users] MPolygon <-> FDO

Hi, Dennis.  MPolygon allows rings to be slightly open, while FDO does
not.  Your data contains rings whose starting and ending positions have
not been latched.  Closing any of these slightly open rings will be
required during conversion.  That is all that there needs to be to this
issue.

Your examples were useable to create CurveString instances.  However,
creating Ring values will require that the X and Y ordinates of the
start/end positions match.  There are lots of cases where datatype
conversion requires adaptations in conversion code.  In fact, your own
code, which computes the mid positions for arcs, is already such a case.

If you want to make a case for more flexibility should be allowed for
the reading of existing real-world data, you can propose it.  The
requirement for any Z ordinates to match at ring ends was removed in a
previous release.  While the FGF data format does redundantly store
starting and ending positions of rings, changing the matching
requirement could introduce defects in code that assumed the closedness
of rings, however.  Plus, some database formats may still require
correctly closed rings, even if FDO does not catch it.

Gavin



More information about the fdo-users mailing list