May be way off base Here... If I understand correctly Mapguide Utilizes GEOS 3.0...Anyone? http://download.osgeo.org/geos/doxygen/namespaces.html
If so couldn't You create one big geometry out of all roads on screen then use the Distance DistanceOp function to find the nearest object? http://download.osgeo.org/geos/doxygen/classgeos_1_1operation_1_1distance_1_ 1DistanceOp.html I'm probably way out in the middle of nowhere on this answer, but who knows maybe It's a good idea? -----Original Message----- From: [email protected] [mailto:[email protected]] On Behalf Of Jamo Sent: Tuesday, January 05, 2010 4:08 PM To: [email protected] Subject: Re: [mapguide-users] Markup perpendicular 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-tp4253574p4257729.html Sent from the MapGuide Users mailing list archive at Nabble.com. _______________________________________________ mapguide-users mailing list [email protected] http://lists.osgeo.org/mailman/listinfo/mapguide-users _______________________________________________ mapguide-users mailing list [email protected] http://lists.osgeo.org/mailman/listinfo/mapguide-users
