[mapguide-users] Markup perpendicular

Jamo adam.jamison at portbris.com.au
Tue Jan 5 17:07:46 EST 2010

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
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)
+ "../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();
        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);

        Response.Write(GetClosestFeature(map, 10, 50,


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();

	MgCurvePolygon myPoly = GF.CreateCurvePolygon(GF.CreateCurveRing(myCurve),

	return myPoly;

// Gets the outermost coordinates of a given geometry
List<MgCoordinate> GetOuterCoordinates(MgGeometry geom)
    List<MgCoordinate> coords = new List<MgCoordinate>();
		case MgGeometryType.Point:
		case MgGeometryType.Polygon:
				MgCoordinateIterator iter = ((MgPolygon)geom).ExteriorRing.Coordinates;
		case MgGeometryType.CurvePolygon:
				MgCoordinateIterator iter =
		case MgGeometryType.LineString:
				MgLineString lstr = (MgLineString)geom;
		case MgGeometryType.CurveString:
				MgLineString lstr = (MgLineString)geom;
		default: //MgMulti* geometry types
			    //I'm not bothering to code this :-P
				//But you'd basically go through each sub-geometry and aggregate its
				//If sub-geometry is polygon, aggregate its exterior ring coordinates.
	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
    SortedList<double, ClosestFeature> matches = new SortedList<double,
    double distance = 1.0;
    int iterations = 0;
    MgWktReaderWriter wktIO = new MgWktReaderWriter();
    MgAgfReaderWriter agfIO = new MgAgfReaderWriter();
    MgGeometryFactory geomFact = new MgGeometryFactory();
        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) ||

                        double dist = mapCs.MeasureEuclideanDistance(coord,
geomFact.CreateCoordinateXY(x, y));
                        ClosestFeature result = new ClosestFeature();
                        result.Distance = dist;
                        result.ClosestVertex = coord;
                        result.FeatureId = new MgInt32Property("FeatId",

                        matches.Add(distance, result);
		//We have at least one result, we can stop iterating.
		if (matches.Count > 0)
		//Otherwise, inflate our test circle.
        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
    //    //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",
    //    return insertFeatures;

    //MgGeometry shortGeometry(MgPoint click, MgGeometry closest, double
    //    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,

    //    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 + " " +

    void GetRequestParameters()
        if (Request.HttpMethod == "POST")

    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.

More information about the mapguide-users mailing list