[mapguide-users] Markup perpendicular
Jackie Ng
jumpinjackie at gmail.com
Tue Jan 5 17:40:53 EST 2010
This ClosestVertex of the ClosestFeature with the smallest distance should
the your point in question.
Also I'm a bit fuzzy with my spatial operators: WITHIN, TOUCHES, CONTAINS,
CROSSES (and possibly others) all seem to be legitimate operators for this
scenario.
- Jackie
Jamo wrote:
>
> Thanks for your help Jackie,
>
> I've gone through your quick freehand code :) very well done
>
> Perhaps a problem that the FDO provider "SDF" doesn't support Spatial
> operator TOUCHES or WITHIN
> after removing Touches I now get an error when adding entries to the
> matches list.
> If i expand the iterations it could be finding a result but not writting
> it to the collection?
>
>
> I can find the nearest road easy enough by doing a distance measurement
> form the point digitized to the nearest road.
>
> Create a feature reader use current view extents as spatial filter select
> all road features within screen then iterate through each one and use the
> smallest distance to find the closest road.
>
> but what I need to do is for the distance measured to return the point it
> has found as being the closest point? it only returns the distance....
> would have thought it would know the point of intersection with the road
> as well if it has found the distance to the nearest geometry?
>
> using System;
> using System.Collections.Generic;
> using System.Linq;
> using System.Web;
> using System.Web.UI;
> using System.Web.UI.WebControls;
> using OSGeo.MapGuide;
> using System.Text;
> using System.Collections.Specialized;
>
> public partial class markup_distancebetween_Default : System.Web.UI.Page
> {
> static String sessionID;
> static String mapName;
> static double x;
> static double y;
>
> class ClosestFeature
> {
> public double Distance { get; set; }
> public MgProperty FeatureId { get; set; }
> public MgCoordinate ClosestVertex { get; set; }
> }
>
> protected void Page_Load(object sender, EventArgs e)
> {
> Response.Charset = "utf-8";
> if (Page.IsPostBack == false)
> GetRequestParameters();
>
>
> MapGuideApi.MgInitializeWebTier(Request.ServerVariables["APPL_PHYSICAL_PATH"]
> + "../webconfig.ini");
> MgUserInformation cred = new MgUserInformation(sessionID);
>
> //connect to the site and get a feature service and a resource
> service instances
> MgSiteConnection site = new MgSiteConnection();
> site.Open(cred);
> MgResourceService resourceSrvc =
> site.CreateService(MgServiceType.ResourceService) as MgResourceService;
> MgFeatureService featureSrvc =
> site.CreateService(MgServiceType.FeatureService) as MgFeatureService;
>
> //Create a temporary map runtime object, locate the layer
> MgMap map = new MgMap(site);
> map.Open(mapName);
>
> Response.Write(GetClosestFeature(map, 10, 50,
> "plnCLRoads").FeatureId);
>
>
> }
>
>
> MgGeometry CreateTestCircle(double joinDist)
> {
> MgGeometryFactory GF = new MgGeometryFactory();
> MgCoordinate arcPt1 = GF.CreateCoordinateXY(x + joinDist, y);
>
> MgCoordinate arcPt2 = GF.CreateCoordinateXY(x - joinDist, y);
> MgCoordinate arcPt3 = GF.CreateCoordinateXY(x, y + joinDist);
> MgCoordinate arcPt4 = GF.CreateCoordinateXY(x, y - joinDist);
> MgArcSegment newGeom = GF.CreateArcSegment(arcPt1,arcPt2,arcPt3);
> MgArcSegment newGeom1 = GF.CreateArcSegment(arcPt2, arcPt1, arcPt4);
>
> MgCurveSegmentCollection myCurve = new MgCurveSegmentCollection();
> myCurve.Add(newGeom);
> myCurve.Add(newGeom1);
>
> MgCurvePolygon myPoly =
> GF.CreateCurvePolygon(GF.CreateCurveRing(myCurve), null);
>
> return myPoly;
> }
>
> //
> // Gets the outermost coordinates of a given geometry
> //
> List<MgCoordinate> GetOuterCoordinates(MgGeometry geom)
> {
> List<MgCoordinate> coords = new List<MgCoordinate>();
> switch(geom.GeometryType)
> {
> case MgGeometryType.Point:
> {
> coords.Add(((MgPoint)geom).Coordinate);
> }
> break;
> case MgGeometryType.Polygon:
> {
> MgCoordinateIterator iter =
> ((MgPolygon)geom).ExteriorRing.Coordinates;
> while(iter.MoveNext())
> {
> coords.Add(iter.GetCurrent());
> }
> }
> break;
> case MgGeometryType.CurvePolygon:
> {
> MgCoordinateIterator iter =
> ((MgCurvePolygon)geom).ExteriorRing.Coordinates;
> while(iter.MoveNext())
> {
> coords.Add(iter.GetCurrent());
> }
> }
> break;
> case MgGeometryType.LineString:
> {
> MgLineString lstr = (MgLineString)geom;
> coords.Add(lstr.StartCoordinate);
> coords.Add(lstr.EndCoordinate);
> }
> break;
> case MgGeometryType.CurveString:
> {
> MgLineString lstr = (MgLineString)geom;
> coords.Add(lstr.StartCoordinate);
> coords.Add(lstr.EndCoordinate);
> }
> break;
> default: //MgMulti* geometry types
> {
> //I'm not bothering to code this :-P
> //But you'd basically go through each sub-geometry and aggregate its
> coordinates
> //If sub-geometry is polygon, aggregate its exterior ring coordinates.
> }
> break;
> }
> return coords;
> }
>
> // Gets the closest road feature from the map at the given point.
> //
> // A test circle is constructed to test for touching road features. If no
> features are found, the
> // circle is "inflated" by the specified distance. This is repeated until
> there are results, or
> // the max number of iterations has been reached.
> //
> // Returns the closes matching feature (ID, and its distance) or null if
> no result is found after
> // the specified number of iterations.
> //
> ClosestFeature GetClosestFeature(MgMap map, int maxIterations, double
> incrementDist, String layerName)
> {
> MgLayer roadLayer = map.GetLayers().GetItem(layerName) as MgLayer;
> MgCoordinateSystem mapCs = new
> MgCoordinateSystemFactory().Create(map.GetMapSRS().ToString());
> SortedList<double, ClosestFeature> matches = new SortedList<double,
> ClosestFeature>();
> double distance = 1.0;
> int iterations = 0;
> MgWktReaderWriter wktIO = new MgWktReaderWriter();
> MgAgfReaderWriter agfIO = new MgAgfReaderWriter();
> MgGeometryFactory geomFact = new MgGeometryFactory();
>
> do
> {
> MgFeatureQueryOptions options = new MgFeatureQueryOptions();
>
> //Create our test circle.
> MgGeometry testCircle = CreateTestCircle(distance);
> string testWkt = wktIO.Write(testCircle);
> options.SetFilter("Geometry WITHIN GeomFromText('" + testWkt +
> "')");
>
> //Run Query, see if there are any matches.
> MgFeatureReader reader = roadLayer.SelectFeatures(options);
> while (reader.ReadNext())
> {
> //We have a match.
> int featureId = reader.GetInt32("FeatId"); //Assuming
> FeatureId is the identity property
> MgByteReader agf = reader.GetGeometry("Geometry");
> MgGeometry matchGeom = agfIO.Read(agf);
>
> //Get its outermost coordinates
> List<MgCoordinate> outerCoords =
> GetOuterCoordinates(matchGeom);
> if (outerCoords.Count > 0)
> {
> foreach (MgCoordinate coord in outerCoords)
> {
> MgPoint testPoint = geomFact.CreatePoint(coord);
>
> //If touches or within our test circle, record this result
> if (testCircle.Touches(testPoint) ||
> testCircle.Contains(testPoint))
> {
>
> double dist =
> mapCs.MeasureEuclideanDistance(coord, geomFact.CreateCoordinateXY(x, y));
>
> ClosestFeature result = new ClosestFeature();
> result.Distance = dist;
> result.ClosestVertex = coord;
> result.FeatureId = new MgInt32Property("FeatId",
> featureId);
>
> matches.Add(distance, result);
> }
> }
> }
> }
>
> //We have at least one result, we can stop iterating.
> if (matches.Count > 0)
> break;
>
> //Otherwise, inflate our test circle.
> iterations++;
> distance += incrementDist;
> }
> while (matches.Count == 0 && iterations < maxIterations);
>
> //If there are results, return the first one.
> if (matches.Count > 0)
> {
> return matches.Values[0]; //First entry is the closest since
> entries are sorted by distance.
> }
>
> return null; //Couldn't find a result after maxIteration attempts,
> return null.
> }
>
> //MgInsertFeatures addThis(String geomCol, MgGeometry geom)
> //{
> // MgAgfReaderWriter agfReaderWriter = new MgAgfReaderWriter();
> // MgPropertyCollection PropertyCollection = new
> MgPropertyCollection();
> // //add geometry
> // //Response.Write(road.GeometryType);
> // MgByteReader geometryByteReader = agfReaderWriter.Write(geom);
> // MgGeometryProperty geometryProperty = new
> MgGeometryProperty(geomCol, geometryByteReader);
> // PropertyCollection.Add(geometryProperty);
>
> // MgInsertFeatures insertFeatures = new MgInsertFeatures("test",
> PropertyCollection);
> // return insertFeatures;
> //}
>
> //MgGeometry shortGeometry(MgPoint click, MgGeometry closest, double
> joinDist)
> //{
> // MgGeometryFactory GF = new MgGeometryFactory();
> // joinDist = joinDist + 0.001;
> // MgCoordinate arcPt1 = GF.CreateCoordinateXY(click.Coordinate.X +
> joinDist, click.Coordinate.Y);
>
> // MgCoordinate arcPt2 = GF.CreateCoordinateXY(click.Coordinate.X -
> joinDist, click.Coordinate.Y);
> // MgCoordinate arcPt3 = GF.CreateCoordinateXY(click.Coordinate.X,
> click.Coordinate.Y + joinDist);
> // MgCoordinate arcPt4 = GF.CreateCoordinateXY(click.Coordinate.X,
> click.Coordinate.Y - joinDist);
> // MgArcSegment newGeom =
> GF.CreateArcSegment(arcPt1,arcPt2,arcPt3);
> // MgArcSegment newGeom1 = GF.CreateArcSegment(arcPt2, arcPt1,
> arcPt4);
>
> // MgCurveSegmentCollection myCurve = new
> MgCurveSegmentCollection();
> // myCurve.Add(newGeom);
> // myCurve.Add(newGeom1);
>
> // MgCurvePolygon myPoly =
> GF.CreateCurvePolygon(GF.CreateCurveRing(myCurve), null);
>
> // Response.Write(closest.Intersects(myPoly));
>
> // return myPoly;
> //
> //Response.Write(myPoly.Intersection(closest).Centroid.Coordinate.X + " "
> + myPoly.Intersection(closest).Centroid.Coordinate.Y);
> //}
>
> void GetRequestParameters()
> {
> if (Request.HttpMethod == "POST")
> GetParameters(Request.Form);
> else
> GetParameters(Request.QueryString);
> }
>
> void GetParameters(NameValueCollection parameters)
> {
> mapName = GetParameter(parameters, "MAPNAME");
> sessionID = GetParameter(parameters, "SESSION");
> x = GetDouble(parameters, "x0");
> y = GetDouble(parameters, "y0");
> }
> String GetParameter(NameValueCollection parameters, String name)
> {
> String strval = parameters[name];
> if (null == strval)
> return "";
>
> return strval.Trim();
> }
>
> double GetDouble(NameValueCollection parameters, String name)
> {
> double strval = Convert.ToDouble(parameters[name]);
> if (null == strval)
> return 0;
>
> return strval;
> }
>
> }
>
>
--
View this message in context: http://n2.nabble.com/Markup-perpendicular-tp4253574p4257913.html
Sent from the MapGuide Users mailing list archive at Nabble.com.
More information about the mapguide-users
mailing list