first of all thanks for reading.
I have a web application that heavily uses Google Earth Plugin to show some sensor data and other stuff.
I'm trying to give the user the capability to define areas and volumes drawing them in the plugin.
I was able to add area features (such as creation, visualization, editing and deletion).
Now i'm working on volumes but i really do not know what is the best way to handle them. An inportant thing to note is that i'm only interested in volumes with parallel upper and lower surface (no pyramid, no complex figures, only prisms)
The first idea that came in my mind is to create a custom object made of 2 polygon and an array of edges to connect every polygon vertex of the upper surface to the respective one in the lower surface.
Something like:
//Create the upper surface (polygon)
var aPolygonUpperPlacemark = ge.createPlacemark("");
var aPolygonUpper = ge.createPolygon("");
aPolygonUpper.setAltitudeMode(ge.ALTITUDE_RELATIVE_TO_GROUND);
aPolygonUpperPlacemark.setGeometry(aPolygonUpper);
var aOuterUpper = ge.createLinearRing("");
aPolygonUpper.setOuterBoundary(aOuterUpper);
ge.getFeatures().appendChild(aPolygonUpperPlacemark);
//Create the lower surface (polygon)
var aPolygonLowerPlacemark = ge.createPlacemark("");
var aPolygonLower = ge.createPolygon("");
aPolygonLower.setAltitudeMode(ge.ALTITUDE_RELATIVE_TO_GROUND);
aPolygonLowerPlacemark.setGeometry(aPolygonLower);
var aOuterLower = ge.createLinearRing("");
aPolygonLower.setOuterBoundary(aOuterLower);
ge.getFeatures().appendChild(aPolygonLowerPlacemark);
var myPrism = {
upperSurface: aPolygonUpperPlacemark,
lowerSurface: aPolygonLowerPlacemark,
edges: new Array()
};
The proble here is that the lateral surfaces will not get displayed as real surfaces but only as lines. On the other hand i could probably create another polygon for each lateral surface but this would make the management of such a 3d shape more complex than what i'd like it to be.
So my question is, is there any better way to handle 3d shapes or maybe a built-in geometry?
Nota that i cannot rely in 3d models (so external Kmz cannot be loaded) as at the end the 3d shape creation will be a user's feature.
Just create the upper polygon (e.g. ensure the coordinates include altitude), and then ensure is set to 1. You can do this in the API using setExtrude(true).
See https://developers.google.com/kml/documentation/kml_tut#polygons for details
I'd also recommend you check out the utility library - it makes things like this much more concise. See for example this extruded polygon example: http://earth-api-utility-library.googlecode.com/svn/trunk/extensions/examples/poly-draw-extruded.html
Related
I am having 2D design in microstation and I wanted to represent this design in web using any tool(javascript/Unity 3D or any other) where the web tool will not have all the functionality but basic functionality like reshaping or adding a new shape should be available.
As of now, my approach is once I created a design in microstation then I am capturing properties of shapes like the cordinates of a line and now using these coordinates I wanted to represent in the browser since this is a 2D design so it will be plotted in some location (x,y) for example I have created a line in microstation from (2,2) to (10,10) so it will be a straight line and I have all the coordinates I tried redrawing it in Unity which am able to do but I am facing issue to change the length from (2,2) to (20,20) by mouse click. And my goal is to do it in runtime, not in Unity editor tool.
This is an example of a straight line I wanted to do it for all geometric shape,any guidance would be appreciated.
As of now am trying Unity to do so but struggling in the edit part is there a way to achieve this in unity?
I also looked at various javascript libraries like konvaJS, makerJS, ThreeJS, etc. but except konvajs none of the other library provide facilities like reshaping, in Konva also creating shape using a mouse not found any solution for this.
Can we achieve this by any of the two approaches, of course, am not looking for all functionality only a few custom functionality, if yes which approach will be the best, and which tool should I proceed with?
Any guidance will be helpful.
To draw a line-segment, you can use LineRenderer.
//two points of the line-segment are known (or got from the Transform of GameObject)
Vector3 start;
Vector3 end;
GameObject myLine = new GameObject();
myLine.transform.position = start;
myLine.AddComponent<LineRenderer>();
LineRenderer lr = myLine.GetComponent<LineRenderer>();
lr.material = new Material(Shader.Find("Particles/Alpha Blended Premultiply"));
lr.SetColors(color, color);
lr.SetWidth(0.1f, 0.1f);
lr.SetPosition(0, start);
lr.SetPosition(1, end);
//to change the points of this line
myLine.transform.position = another_start;
lr.SetPosition(0, another_start);
lr.SetPosition(1, another_end);
There are also other solutions:
Use scaled cube or capsule primitive.
3rd-party plugins: vectrosity
To get mouse clicked position, use Camera.main.ScreenToWorldPoint(Input.mousePosition).
To determine when your mouse is clicked, use Input.GetMouseButtonUp.
I'm using easeljs and attempting to generate a simple water simulation based on this physics liquid demo. The issue I'm struggling with is the final step where the author states they "get hard edges". It is this step that merges the particles into an amorphous blob that gives the effect of cohesion and flow.
In case the link is no longer available, in summary, I've followed the simulation "steps" and created a prototype for particle liquid with the following :
Created a particle physics simulation
Added a blur filter
Apply a threshold to get "hard edges"
So I wrote some code that is using a threshold check to color red (0xFF0000) any shapes/particles that meet the criteria. In this case the criteria is any that have a color greater than RGB (0,0,200). If not, they are colored blue (0x0000FF).
var blurFilter = new createjs.BlurFilter(emitter.size, emitter.size*3, 1);
var thresholdFilter = new createjs.ThresholdFilter(0, 0, 200, 0xFF0000, 0x0000FF);
Note that only blue and red appear because of the previously mentioned threshold filter. For reference, the colors generated are RGB (0,0,0-255). The method r() simply generates a random number up to the passed in value.
graphics.beginFill(createjs.Graphics.getRGB(0,0,r(255)));
I'm using this idea of applying a threshold criteria so that I can later set some boundaries around the particle adhesion. My thought is that larger shapes would have greater "gravity".
You can see from the fountain of particles running below in the attached animated gif that I've completed Steps #1-2 above, but it is this Step #3 that I'm not certain how to apply. I haven't been able to identify a single filter that I could apply from easeljs that would transform the shapes or merge them in any way.
I was considering that I might be able to do a getBounds() and draw a new shape but they wouldn't truly be merged at that time. Nor would they exhibit the properties of liquid despite being larger and appearing to be combined.
bounds = blurFilter.getBounds(); // emitter.size+bounds.x, etc.
The issue really becomes how to define the shapes that are blurred in the image. Apart from squinting my eyes and using my imagination I haven't been able to come to a solution.
I also looked around for a solution to apply gravity between shapes so they could, perhaps, draw together and combine but maybe it's simply that easeljs is not the right tool for this.
Thanks for any thoughts on how I might approach this.
I have a student who is using MapBox.js (v1.6.0) to display some tiles that they made in TileMill. These tiles use the Tooltip functionality provided by TileMill (documentation) to add some interactivity. My student is also using a MapBox Streets layer to give some detailed views of roadways, etc. The problem is, when I use both of these layers together in the map, the interactivity from the tiles doesn't work.
Here is the code that doesn't work:
var map = L.mapbox.map("map");
var tilesOSM = L.mapbox.tileLayer("username.id1");
var tilesTileMill = L.mapbox.tileLayer("username.id2");
map
.addLayer(tilesOSM)
.addLayer(tilesTileMill)
.setView(L.latLng(61, -160.5), 4)
.setMaxBounds(L.latLngBounds(L.latLng(50,-180), L.latLng(72,-129)));
We have tried several iterations of this code, but the only way we can get it to work is by using the L.mapbox.map(3) method and then using the _ insertAtTheBottom_ parameter of the L.map.addLayer() function.
var map = L.mapbox.map("map", "username.id2", {});
map
.addLayer(L.mapbox.tileLayer("username.id1"), true)
.setView(L.latLng(61, -160.5), 4)
.setMaxBounds(L.latLngBounds(L.latLng(50,-180), L.latLng(72,-129)));
My question is three fold.
What is the difference between these two implementations?
Why is the tileLayer created using L.mapbox.tileLayer() different than the one created and automatically added using L.mapbox.map(3)?
Are there plans to address this discontinuity in future changes to the API or will support for interactive tiles be dropped in TileMill 2?
What is the difference between these two implementations?
If you check out what L.mapbox.map does internally, it adds a gridLayer and gridControl for the layer you specify. Basically the map constructor makes all of the safe assumptions it could make and does them automatically as a convenience.
Why is the tileLayer created using L.mapbox.tileLayer() different than the one created and automatically added using L.mapbox.map(3)?
It's the same - there's a gridLayer and gridControl in the mix when you use L.mapbox.map(3), and those are what make things interactive.
Are there plans to address this discontinuity in future changes to the API
It's not as much a discontinuity than an API design: we decided to keep tileLayers decoupled from gridLayers and gridControls so you can mix & match them - if you want to switch which layer interactive features come from, or disable interactivity without disabling the tile layer, you can.
will support for interactive tiles be dropped in TileMill 2?
No, you can use TileMill 2 and see how it supports interactivity. We aren't going to remove or phase this out, though vector tiles will have new methods of interaction.
For your second example, you would want something like:
var map = L.mapbox.map("map", "username.id2", {});
var gridLayer = L.mapbox.gridLayer("username.id1").addTo(map);
var gridControl = L.mapbox.gridControl(gridLayer).addTo(map);
map
.addLayer(L.mapbox.tileLayer("username.id1"), true)
.setView(L.latLng(61, -160.5), 4)
.setMaxBounds(L.latLngBounds(L.latLng(50,-180), L.latLng(72,-129)));
I am trying to learn how to use the Javascript library leaflet along with d3 to create various map visualisations.
I have been following this tutorial which creates a choropleth map of the United States with some interactivity. This provides some of what I need, but the main functionality I want is to have a list of lat/long coordinates classified according to which region they belong to.
This would mean, in the tutorial map for example, if I had a lat long value (55, -3) which fell within the state of Arizona's polygon, the program could classify this point as belonging to Arizona.
Is there a function in the leaflet (or d3) library which will allow me to enter a lat long coordinate as a parameter and return the name of the feature it belongs to? The tutorial above allows you to attach a function to every feature via the onEveryFeature property and can fire mouseover events when each feature is hovered over. Surely there is a way to extend this functionality to numerically entered data instead of mouse points?
Leaflet would need some tweaking if you wish to do this. It leaves the handling of mouseclicks to the browser and therefore does not need logic for determining if a point lies inside a polygon.
I am not very knowledgeable about d3 but it's not glaringly obvious to me how it'd do this out of the box. Looking at the polygon code, I do find a clipping algorithm and intersection of infinite lines.
If you add a third library, however, this should be rather simple.
The OpenLayers Geometry library can determine if a point lies inside a polygon.
EDIT: I got this to work, see also http://jsfiddle.net/VaY3E/4/
var parser = new OpenLayers.Format.GeoJSON();
var vectors = parser.read(statesData);
var lat = 36;
var lon = -96;
var point = new OpenLayers.Geometry.Point(lon, lat);
for( var i = 0; i< vectors.length; i++ ){
if(vectors[i].geometry.intersects(point)){
alert(vectors[i].attributes['name']);
}
}
Or you could use https://github.com/maxogden/geojson-js-utils , a bit more specific library. It looks like it knows how to read GeoJSON and it has a method gju.pointInPolygon. I've not tested it though.
I need to plot thousands of points, perhaps close to 50,000 with the dojo charting library. It works, but it's definitely very slow and lags the browser. Is there any way I can get better performance?
EDIT:
I solved by applying a render filter to the data. Essentially, I have a new item parameter called "render" which is set to false by my json source if the point is expected to overlap others. My DataSeries then queries for all points where render:true. This way all of the data is there still for non-visual sources that want all of the points, while my charts now run smoothly.
Psuedocode:
def is_overlapped(x, y, x_round, y_round)
rounded_x = round(x, x_round)
rounded_y = round(y, y_round)
hash = hash_xy(rounded_x, rounded_y)
if(#overlap_filter[hash].nil?)
#overlap_filter[hash] = true
return false
end
return true
end
x_round and y_round can be determined by the x and y ranges, say for example range / 100
I know this isn't probably exactly the answer you're looking for, but have you considered simply reducing the number of points you are plotting? I don't know the specific function of the graph(s), but I'd imagine most graphs with that many points are unnecessary; and no observer is going to be able to take that level of detail in.
Your solution could lie with graphing techniques rather than JavaScript. E.g. you could most likely vastly reduce the number of points and use a line graph instead of a scatter plot while still communicating similar levels of information to your intended target.