I have posted up a bit of code i'm working on to produce some suggested road safety signage diagrams on the GIS, given a point of work length and type. Still working on the dialog just figuring out how best to accomplish the geometry side of things.
Was wondering if anyone has had much luck with the topology.net libraries and if they could share some knowledge on how best to implement? I found this http://code.google.com/p/tf-net/issues/detail?id=2 MgGeometry issue I can get the centreline of works using code below .... however I'm coming unstuck when it gets to corners and curves.... should be able to fix it with a bit of maths, but if this topology.net works it'd be great. Given a MgGeomery collection and a point I would like to return a geometry from point in all direction along roads unitl length is greater than a given distance? and return a MgGeometry that I can use to buffer. Wall of text below :-) 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; using System.IO; 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 String RoadName { get; set; } public MgCoordinate UserInput { get; set; } public MgGeometry Road { 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); MgGeometryFactory GF = new MgGeometryFactory(); MgPoint userClick = GF.CreatePoint(GF.CreateCoordinateXY(x, y)); ClosestFeature result = new ClosestFeature(); result.UserInput = userClick.Coordinate; MgFeatureReader feats = map.GetLayers().GetItem("plnCLRoads").SelectFeatures(new MgFeatureQueryOptions()); MgAgfReaderWriter agf = new MgAgfReaderWriter(); result.Distance = -1; while (feats.ReadNext()) { MgGeometry myGeom = agf.Read(feats.GetGeometry("Geometry")); if (myGeom.Distance(userClick, null) < result.Distance || result.Distance == -1) { result.Road = myGeom; result.Distance = myGeom.Distance(userClick, null); if (feats.IsNull("Name") == false) { result.RoadName = feats.GetString("Name") + " " + feats.GetString("Type"); } } } Response.Write("<BR/><BR/>Therefore the closest Road is <BR/>" + result.RoadName + " and is " + result.Distance + " m away<BR/>"); {//test insert geometries into a Featuresource so I can check visually MgClassDefinition myClassDef = new MgClassDefinition(); myClassDef.SetName("test"); myClassDef.SetDescription("test" + " Feature Source"); myClassDef.SetDefaultGeometryPropertyName("testGeom"); MgDataPropertyDefinition prop = new MgDataPropertyDefinition("KEY"); prop.SetDataType(MgPropertyType.Int32); prop.SetAutoGeneration(true); prop.SetReadOnly(true); myClassDef.GetIdentityProperties().Add(prop); myClassDef.GetProperties().Add(prop); //Set geometry property MgGeometricPropertyDefinition geomProp = new MgGeometricPropertyDefinition("testGeom"); geomProp.SetGeometryTypes(MgFeatureGeometricType.Point | MgFeatureGeometricType.Curve | MgFeatureGeometricType.Surface); myClassDef.GetProperties().Add(geomProp); //Create the schema MgFeatureSchema schema = new MgFeatureSchema("test" + "Schema", "test" + "SchemaDesc"); schema.GetClasses().Add(myClassDef); MgCreateSdfParams sdfParams = new MgCreateSdfParams("MGA-56 (GDA94 / MGA zone 56)", map.GetMapSRS(), schema); featureSrvc.CreateFeatureSource(new MgResourceIdentifier("Library://test.FeatureSource"), sdfParams); MgFeatureCommandCollection commands = new MgFeatureCommandCollection(); //check if linestring has more than 2 vertexs. Response.Write(testEdge.IsClosed); MgCoordinateIterator lineCoords = ((MgLineString)result.Road).GetCoordinates(); //for (int curveCount = 0; curveCount < ((MgCurveString)result.Road).Count;curveCount++) //{ // Response.Write(((MgCurveString)result.Road).GetSegment(curveCount).Dimension + "<BR/>"); //} //MgWktReaderWriter wkt = new MgWktReaderWriter(); //Response.Write(wkt.Write(result.Road).ToString() + "<BR/>"); int vertCount = 0; while (lineCoords.MoveNext()) { vertCount = vertCount + 1; } // if more than 2 vertexs then check to see which segment is the closest. if (vertCount != 2) { lineCoords.Reset(); MgGeometryCollection lineSegments = new MgGeometryCollection(); MgCoordinate lastCoord = null; while (lineCoords.MoveNext()) { MgCoordinate thisCoord = lineCoords.GetCurrent(); if (lastCoord != null) { MgCoordinateCollection newLineCoords = new MgCoordinateCollection(); newLineCoords.Add(lastCoord); newLineCoords.Add(thisCoord); lineSegments.Add(GF.CreateLineString(newLineCoords)); } lastCoord = thisCoord; } lineCoords.Reset(); lineCoords.MoveNext(); MgCoordinateCollection lastSegment = new MgCoordinateCollection(); lastSegment.Add(lastCoord); lastSegment.Add(lineCoords.GetCurrent()); lineSegments.Add(GF.CreateLineString(lastSegment)); foreach (MgGeometry geom in lineSegments) { if (geom.Distance(userClick, null) == result.Distance) { Response.Write("ooooooh found the closest segment"); result.Road = geom; } } } double y2, y1, x2, x1, px, py,ux, uy, lx, ly; MgLineString LS = result.Road as MgLineString; x1 = LS.GetStartCoordinate().X; y1 = LS.GetStartCoordinate().Y; x2 = LS.GetEndCoordinate().X; y2 = LS.GetEndCoordinate().Y; double a = Math.Atan(-(y2 - y1) / (x2 - x1)); a = a + Math.PI; //create point for line of intersection px = result.UserInput.X + (result.Distance + 0.01) * Math.Sin(a); py = result.UserInput.Y + (result.Distance + 1) * Math.Cos(a); MgCoordinateCollection perpCol = new MgCoordinateCollection(); perpCol.Add(GF.CreateCoordinateXY(px, py)); perpCol.Add(result.UserInput); if (GF.CreateLineString(perpCol).Crosses(result.Road) == false) { a = a + Math.PI; px = result.UserInput.X + (result.Distance + 0.01) * Math.Sin(a); py = result.UserInput.Y + (result.Distance + 0.01) * Math.Cos(a); perpCol.Clear(); perpCol.Add(GF.CreateCoordinateXY(px, py)); perpCol.Add(result.UserInput); } //now I have the perp point of intersection just offset two points either side. MgCoordinate intCoord = GF.CreateLineString(perpCol).Intersection(result.Road).Centroid.Coordinate; a = a + (Math.PI / 2); ux = intCoord.X + 10 * Math.Sin(a); uy = intCoord.Y + 10 * Math.Cos(a); lx = intCoord.X - 10 * Math.Sin(a); ly = intCoord.Y - 10 * Math.Cos(a); MgCoordinateCollection workSiteCol = new MgCoordinateCollection(); workSiteCol.Add(GF.CreateCoordinateXY(ux, uy)); workSiteCol.Add(GF.CreateCoordinateXY(lx, ly)); commands.Add(addThis("testGeom",GF.CreateLineString(workSiteCol).Buffer(3,null), myClassDef.Name)); MgPropertyCollection insertResults; insertResults = featureSrvc.UpdateFeatures(new MgResourceIdentifier("Library://test.FeatureSource"), commands, false); MgResourceIdentifier dataSourceId = new MgResourceIdentifier("Library://test.FeatureSource"); String myLayerName = "test"; if (DoesLayerExist(myLayerName, map) == false) { String layerDef = "Library://test.LayerDefinition"; MgResourceIdentifier layerDefId = new MgResourceIdentifier(layerDef); MgByteReader layerDefContent = BuildLayerDefinitionContent("Library://test.FeatureSource", myLayerName); resourceSrvc.SetResource(layerDefId, layerDefContent, null); MgLayer myLayer = new MgLayer(layerDefId, resourceSrvc); myLayer.SetName(myLayerName); myLayer.SetLegendLabel(myLayerName); myLayer.SetDisplayInLegend(true); myLayer.SetSelectable(true); MgLayerGroup myLayerGroup; if (DoesLayerGroupExist("Redline", map) == false) { myLayerGroup = new MgLayerGroup("Redline"); myLayerGroup.SetLegendLabel("Redline / Markup"); myLayerGroup.SetDisplayInLegend(true); myLayerGroup.SetVisible(true); myLayerGroup.SetDisplayInLegend(true); map.GetLayerGroups().Insert(0, myLayerGroup); } else { myLayerGroup = map.GetLayerGroups().GetItem("Redline"); } myLayer.SetGroup(myLayerGroup); map.GetLayers().Insert(0, myLayer); myLayer.ForceRefresh(); map.Save(resourceSrvc); } RegisterStartupScript("1", "<script>parent.parent.parent.mapFrame.Refresh();</script>"); } } bool DoesLayerGroupExist(String LayerGroupName, MgMap Map) { MgLayerGroupCollection layerGroups = Map.GetLayerGroups(); return (layerGroups.Contains(LayerGroupName)); } MgByteReader BuildLayerDefinitionContent(String ResourceId, String FeatureName) { String layerTempl = LoadTemplate(Request, "markup/requests/reqLayerDef1.templ"); String[] vals = { ResourceId, FeatureName + "Schema:" + FeatureName, "testGeom" }; layerTempl = Substitute(layerTempl, vals); byte[] bytes = Encoding.UTF8.GetBytes(layerTempl); MgByteSource src = new MgByteSource(bytes, bytes.Length); return src.GetReader(); } bool DoesLayerExist(String LayerName, MgMap Map) { MgLayerCollection layers = Map.GetLayers(); return (layers.Contains(LayerName)); } String LoadTemplate(HttpRequest request, String filePath) { StreamReader sr = File.OpenText(request.ServerVariables["APPL_PHYSICAL_PATH"] + filePath); String template = sr.ReadToEnd(); return template; } String Substitute(String templ, String[] vals) { StringBuilder res = new StringBuilder(); int index = 0, val = 0; bool found; do { found = false; int i = templ.IndexOf('%', index); if (i != -1) { found = true; res.Append(templ.Substring(index, i - index)); if (i < templ.Length - 1) { if (templ[i + 1] == '%') res.Append('%'); else if (templ[i + 1] == 's') res.Append(vals[val++]); else res.Append('@'); //add a character illegal in jscript so we know the template was incorrect index = i + 2; } } } while (found); res.Append(templ.Substring(index)); return res.ToString(); } MgInsertFeatures addThis(String geomCol, MgGeometry geom, String className) { MgAgfReaderWriter agfReaderWriter = new MgAgfReaderWriter(); MgPropertyCollection PropertyCollection = new MgPropertyCollection(); MgByteReader geometryByteReader = agfReaderWriter.Write(geom); MgGeometryProperty geometryProperty = new MgGeometryProperty(geomCol, geometryByteReader); PropertyCollection.Add(geometryProperty); MgInsertFeatures insertFeatures = new MgInsertFeatures(className, PropertyCollection); return insertFeatures; } MgGeometry shortGeometry(MgCoordinate click, MgGeometry closest, double joinDist) { MgGeometryFactory GF = new MgGeometryFactory(); joinDist = joinDist + 0.5; Response.Write(joinDist + "mts "); MgCoordinate arcPt1 = GF.CreateCoordinateXY(click.X + joinDist, click.Y); MgCoordinate arcPt2 = GF.CreateCoordinateXY(click.X - joinDist, click.Y); MgCoordinate arcPt3 = GF.CreateCoordinateXY(click.X, click.Y + joinDist); MgCoordinate arcPt4 = GF.CreateCoordinateXY(click.X, click.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); //write out spatial operations //Response.Write("<BR/>Contains: " + closest.Contains(myPoly)); //Response.Write("<BR/>Crosses: " + closest.Crosses(myPoly)); //Response.Write("<BR/>Disjoint: " + closest.Disjoint(myPoly)); //Response.Write("<BR/>Intersects: " + closest.Intersects(myPoly)); //Response.Write("<BR/>Overlaps: " + closest.Overlaps(myPoly)); //Response.Write("<BR/>Touches: " + closest.Touches(myPoly)); //Response.Write("<BR/>Within: " + closest.Within(myPoly)); //if(closest.Intersects(myPoly)) // Response.Write("<BR/>" + closest.Intersection(myPoly).Length); return myPoly; } 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/Topology-net-and-mapguide-tp4289752p4289752.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
