Context: I'm a just-hours-old newbie at OpenLayers, please be gentle.
Fundamentally, I have a map with some drawn objects on it. If I understand things correctly, I have a number of OpenLayer.Feature.Vector (layers?) with a number of OpenLayer.Geometry "things" (like LinearRing) on it.
At the moment, I seem to be able to get a nice representation of the geometry, using .toString(). Yes, I suspect I'm doing it wrong -- feel free to point me in the right direction.
This yields a very human readable, and database storable, strings such as:
POINT(-104.74560546875 44.2841796875)
POLYGON((-96.52783203125 44.6796875,-96.52783203125 45.734375,-92.22119140625 45.734375,-92.22119140625 44.6796875,-96.52783203125 44.6796875))
LINESTRING(-105.71240234375 44.6796875,-106.06396484375 42.658203125,-103.55908203125 42.7021484375,-103.47119140625 45.55859375,-104.65771484375 45.20703125)
Is there an inverse way of getting these back into the object format from whence they came?
I'd love to be using JSON, but can't seem to get GeoJSON to accept my OpenLayer.Feature.Vector object (which is what the CLASS_NAME property says it is when I peer inside).
Many thanks.
The Openlayers.Geometry objects’ toString method converts them nicely to WKT (Well-Known Text). If you use a GIS layer on top of your database (like PostGIS for PostGres, SQL Spatial for SQL Server, Spatialite for SQLite, etc.), they should offer functions that enable you to process WKT.
But if you want to convert that WKT to a new Openlayers.Geometry object (in the browser), you can use the fromWKT function:
var point = OpenLayers.Geometry.fromWKT('POINT(-104.74560546875 44.2841796875)');
alert(point.toString()); // POINT(-104.74560546875 44.2841796875)
Here, the variable point will now contain a new Openlayers.Geometry object, which has the same properties as the original one you used toString() on.
If you pass an array to the fromWKT function, it will return a GeometryCollection containing all the generated geometries.
var geometryTexts = [
'POINT(-104.74560546875 44.2841796875)'
, 'POLYGON((-96.52783203125 44.6796875,-96.52783203125 45.734375,-92.22119140625 45.734375,-92.22119140625 44.6796875,-96.52783203125 44.6796875))'
, 'LINESTRING(-105.71240234375 44.6796875,-106.06396484375 42.658203125,-103.55908203125 42.7021484375,-103.47119140625 45.55859375,-104.65771484375 45.20703125)'
],
collection = OpenLayers.Geometry.fromWKT(geometryTexts);
After this, collection.toString() should yield the following:
GEOMETRYCOLLECTION(POINT(-104.74560546875 44.2841796875),POLYGON((-96.52783203125 44.6796875,-96.52783203125 45.734375,-92.22119140625 45.734375,-92.22119140625 44.6796875,-96.52783203125 44.6796875)),LINESTRING(-105.71240234375 44.6796875,-106.06396484375 42.658203125,-103.55908203125 42.7021484375,-103.47119140625 45.55859375,-104.65771484375 45.20703125))
In my other answer, I went with WKT because you mentioned it. I now see that you seem to prefer GeoJSON.
To convert a vector layer or an Openlayers.Geometry object to a GeoJSON string, you should use the OpenLayers.Format.GeoJSON.write function:
var geoJSON = new OpenLayers.Format.GeoJSON(),
geoJSONText = geoJSON.write(geometryObject);
Note that you should be able to pass your object to this function, since (according to documentation) it accepts an OpenLayers.Feature.Vector as well as a OpenLayers.Geometry or an array of features.
Conversely, when you’ve got a GeoJSON string, you can convert that back to an object using the OpenLayers.Format.GeoJSON.read function:
var geometry = geoJSON.read(geoJSONText, 'Geometry');
The second parameter lets you indicate which type of object you’d like returned. Read the docs linked to for more information.
Also, take a look at this demo for a more extensive example. (View the source of the page to see how they’re doing it).
Related
I am trying to convert an iGraph object to a gexf object using the rgexf package so that I can write a file usable with Gephi, which I prefer for network visualization.
My iGraph object is created by reading in two CSVs: h.edges and h.nodes. There are both edge and node attributes. Once the files are read in, I create the iGraph object, calculate centrality measures and then attach the centrality measures as node attributes. The code looks like so:
iNet = graph_from_data_frame(d=h.edges, vertices = h.nodes, directed = F)
V(iNet)$degree = degree(iNet)
V(iNet)$eig = evcent(iNet)$vector
V(iNet)$betweenness = betweenness(iNet)
This appears to be working fine since I can do all the normal iGraph functions -- plot, calculate centralities, identify communities, etc. My problem comes when I try to convert this to a gexf object. I run the following code:
library(rgexf)
iNet.gexf igraph.to.gexf(iNet)
But get the below error message:
Error in `[.data.frame`(x, r, vars, drop = drop) :
undefined columns selected
Anyone know what's happening? Although I know the example here can all be done just by uploading the two CSVs straight to Gephi and running the calculations there, the end goal is to be able to attach iGraph's more robust calculations as attributes in ways that Gephi can't.
I see that the following syntax is used in examples:
GeomFromText('Polygon((1 1, 2 2, 3 3))');
The double parenthesis caused a bit of a trouble so I decided to look it up in the official documentation. At my non-small surprise the search mysql polygon did not give me the documentation of this function. A search to mysql geomfromtext also did not give the definition of the function GeomFromText.
So I'm still looking for the official documentation of these functions.
I see that the MySQL Reference Manual for GeomFromText() doesn't even give a typical function definition either, but it does describe how to use it. GeomFromText() converts from "well-known text" (abbreviated as WKT) to MySQL's internal format. WKT is simply a textual representation of a geometry object, which can be a polygon as your example, or any of the other geometry types. A key point to understand is that Polygon(...) is the WKT format for a polygon; it isn't a MySQL function call, even though it sort of looks like one.
Polygons can contain holes. When defining a polygon, you may optionally supply one or more interior boundaries to define such holes. The WKT for polygons use inner parentheses to distinguish these boundaries from one other. Even if you don't want to define holes, the inner parentheses are still required. Wikipedia provides some simple examples of polygon WKTs together with pictures of the resulting polygons.
Gone thru the livedocs but the examples are quite sparse.
Can anyone give me some good 'real world' examples of when and why you might use the
map and filter methods of the new Vector class in Actionscript?
The Vector filter and map methods work just the same as the methods in the Array class of the same name. Check the following two pages for filter examples for arrays (they work just the same for the Vector class):
http://troyworks.com/blog/2007/12/16/as3-arrayfilter-r0xr/
http://www.onebyonedesign.com/tutorials/array_methods/
I couldn't find any decent as3 map examples, but the jQuery equivalent explains how/why you would use it fairly well:
http://api.jquery.com/jQuery.map/
As for real world uses, filter is unbelievably useful. Suppose you have a Vector filled with Employee objects. You can use the filter method as a non-destructive way to get all the Employees whose name starts with "A", or whose salary is greater than $50,000. The map function is similar, but it creates a new Vector and allows you to alter the objects, so you could potentially cast each Employee as a new type, such as HighlyPaidEmployee.
I'm looking at the geometry data type in Sql Server 2008 and it looks interesting but the documentation does not seem that good. Would I be able to store cones, cylinders and spheres in the WKT format? These features traditionally have a radius and not hundreds of points.
To the best of my knowledge your are going to have to use an external application to render your shape as a large number of points. See this blog for a technique for rendering circles.
One possibility to consider is a CLR proc to render the shapes you need and a view with indexes. I don't know how well that will perform, but it just might work.
sorry for the late reply. You could always write your own User-Defined-Type called Circle, with two properties namely Centroid and Radius.
Inside the newly formed UDT, create a method that takes the properties Centroid (Point3D), and Radius (Double). After this, create a method that uses both SqlGeometry and SqlGeometryBuilder to build the newly formed object.
First, create a Point instance of Geometry. Inherit the Centroid values from the class object, then, create another Geometry Polygon that's derived from the Point object, and STBuffer(Radius) it.
Below is my example: (written in 30min)
public SqlGeometry ToSQLGeometry()
{
int srid = this.SRID; // i.e. 4326
SqlGeometry geom = new SqlGeometry();
SqlGeometryBuilder gb = new SqlGeometryBuilder();
OpenGisGeometryType pt = OpenGisGeometryType.Point;
gb.SetSrid(srid);
gb.BeginGeometry(pt);
gb.BeginFigure(this.Centroid.X, this.Centroid.Y, this.Centroid.Z, this.Centroid.M);
gb.EndFigure();
gb.EndGeometry();
geom = gb.ConstructedGeometry;
geom = geom.MakeValid(); // Optional for Point data
SqlGeometry geomCircle = new SqlGeometry();
geomCircle = geom.STBuffer(this.Radius);
return geomCircle;
}
When you've done this in VS2010 by using the CLR project type, you can deploy it to your database.
In SQL, you can call the object as such:: Parse(X Y Z M,R)
declare #c Circle
set #c = Circle::Parse('5 6 7 8,2')
select 'Circle', #c.ToString(), #c.ToSQLGeometry()
Had a quick look around and found this MSDN page on Spatial Samples. It covers all the Methods to enter data in WKT, WKB & XML(GML) as well as functions to view the in Human Readable form. It also covers MakeValid, STIsValid & STSrid.
There looks to be a fair few SQL examples that you may find useful
I'm working in Python here (which is actually pass-by-name, I think), but the idea is language-agnostic as long as method parameters behave similarly:
If I have a function like this:
def changefoo(source, destination):
destination["foo"] = source
return destination
and call it like so,
some_dict = {"foo": "bar"}
some_var = "a"
new_dict = changefoo(some_var, some_dict)
new_dict will be a modified version of some_dict, but some_dict will also be modified.
Assuming the mutable structure like the dict in my example will almost always be similarly small, and performance is not an issue (in application, I'm taking abstract objects and changing into SOAP requests for different services, where the SOAP request will take an order of magnitude longer than reformatting the data for each service), is this okay?
The destination in these functions (there are several, it's not just a utility function like in my example) will always be mutable, but I like to be explicit: the return value of a function represents the outcome of a deterministic computation on the parameters you passed in. I don't like using out parameters but there's not really a way around this in Python when passing mutable structures to a function. A couple options I've mulled over:
Copying the parameters that will be mutated, to preserve the original
I'd have to copy the parameters in every function where I mutate them, which seems cumbersome and like I'm just duplicating a lot. Plus I don't think I'll ever actually need the original, it just seems messy to return a reference to the mutated object I already had.
Just use it as an in/out parameter
I don't like this, it's not immediately obvious what the function is doing, and I think it's ugly.
Create a decorator which will automatically copy the parameters
Seems like overkill
So is what I'm doing okay? I feel like I'm hiding something, and a future programmer might think the original object is preserved based on the way I'm calling the functions (grabbing its result rather than relying on the fact that it mutates the original). But I also feel like any of the alternatives will be messy. Is there a more preferred way? Note that it's not really an option to add a mutator-style method to the class representing the abstract data due to the way the software works (I would have to add a method to translate that data structure into the corresponding SOAP structure for every service we send that data off too--currently the translation logic is in a separate package for each service)
If you have a lot of functions like this, I think your best bet is to write a little class that wraps the dict and modifies it in-place:
class DictMunger(object):
def __init__(self, original_dict):
self.original_dict = original_dict
def changefoo(source)
self.original_dict['foo'] = source
some_dict = {"foo": "bar"}
some_var = "a"
munger = DictMunger(some_dict)
munger.changefoo(some_var)
# ...
new_dict = munger.original_dict
Objects modifying themselves is generally expected and reads well.