I am having trouble integrating OpenSeaMap into GWT application. I have followed their example and example of GWT-OpenLayers TMS. Here is my code:
private void initMap(MapView map) {
TMSOptions seamarkOptions = new TMSOptions();
seamarkOptions.setType("png");
seamarkOptions.setGetURL(getMyUrl());
seamarkOptions.setNumZoomLevels(18);
seamarkOptions.setIsBaseLayer(false);
seamarkOptions.setDisplayOutsideMaxExtent(true);
map.addLayer(OSM.Mapnik("OpenStreetMap"));
map.addLayer(new TMS("Seamark", "http://t1.openseamap.org/seamark/", seamarkOptions));
}
private static native JSObject getMyUrl() /*-{
function get_my_url(bounds) {
var res = this.map.getResolution();
var x = Math.round((bounds.left - this.maxExtent.left) / (res * this.tileSize.w));
var y = Math.round((this.maxExtent.top - bounds.top) / (res * this.tileSize.h));
var z = this.map.getZoom();
var limit = Math.pow(2, z);
if (y < 0 || y >= limit) {
return null;
} else {
x = ((x % limit) + limit) % limit;
url = this.url;
path= z + "/" + x + "/" + y + "." + this.type;
if (url instanceof Array) {
url = this.selectUrl(path, url);
}
return url+path;
}
}
return get_my_url;
}-*/;
It don't work at all. Even more - for some reason the 'Seamark' overlay is disabled in Layers selector. Also I have tried using following JSNI function as getURL for TMS layer:
public static native JSObject getTileURL() /*-{
return $wnd.getTileURL;
}-*/;
That function comes from http://map.openseamap.org/javascript/map_utils.js But no luck too.
Any help appreciated.
The reason of this issue was null maxExtent property of Map object. It was initialised as follows:
mapWidget = new MapWidget("100%", "100%", new MapOptions());
I have updated to the following:
MapOptions defaultMapOptions = new MapOptions();
defaultMapOptions.setMaxExtent(new Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34));
mapWidget = new MapWidget("100%", "100%", defaultMapOptions);
Now it works.
Related
I need to view the segments and handles of the path that defines a SymbolItem. It is a related issue to this one but in reverse (I want the behavior displayed on that jsfiddle).
As per the following example, I can view the bounding box of the SymbolItem, but I cannot select the path itself in order to view its segments/handles. What am I missing?
function onMouseDown(event) {
project.activeLayer.selected = false;
// Check whether there is something on that position already. If there isn't:
// Add a circle centered around the position of the mouse:
if (event.item === null) {
var circle = new Path.Circle(new Point(0, 0), 10);
circle.fillColor = '#' + Math.floor(Math.random() * 16777215).toString(16);
var circleSymbol = new SymbolDefinition(circle);
multiply(circleSymbol, event.point);
}
// If there is an item at that position, select the item.
else {
event.item.selected = true;
}
}
function multiply(item, location) {
for (var i = 0; i < 10; i++) {
var next = item.place(location);
next.position.x = next.position.x + 20 * i;
}
}
Using SymbolDefinition/SymbolItem prevent you from changing properties of each symbol items.
The only thing you can do in this case is select all symbols which share a common definition.
To achieve what you want, you have to use Path directly.
Here is a sketch showing the solution.
function onMouseDown(event) {
project.activeLayer.selected = false;
if (event.item === null) {
var circle = new Path.Circle(new Point(0, 0), 10);
circle.fillColor = Color.random();
// just pass the circle instead of making a symbol definition
multiply(circle, event.point);
}
else {
event.item.selected = true;
}
}
function multiply(item, location) {
for (var i = 0; i < 10; i++) {
// use passed item for first iteration, then use a clone
var next = i === 0 ? item : item.clone();
next.position = location + [20 * i, 0];
}
}
I'm trying to figure out how to extrude an already loaded .obj object to make it "thicker". I think I'm looking for a way to scale my object not from its anchor point but scaling it by each polygon normal.
A classic example would be to take a "ring" object. If you scale it up with just the normal scale methods it just gets bigger from the center but I want the ring to become thicker/thinner. Its called a 'normal scale' in cinema 4d.
Here's some example code of what I currently have, and which isn't giving me the expected result.
var objLoader = new THREE.OBJLoader();
var material = new THREE.MeshLambertMaterial({color:'yellow', shading:THREE.FlatShading});
objLoader.load('objects/gun/M1911.obj', function (obj) {
obj.traverse(function (child) {
if (child instanceof THREE.Mesh) {
child.geometry.computeVertexNormals();
child.material = material;
}
});
obj.material = material;
obj.scale.set(7, 7, 7);
scene.add(obj);
});
scaleGeo: function (geo, ratio) {
for (var i = 0; i < geo.faces.length; i++) {
var faceI = geo.faces[i];
var vertexArr = [faceI.a, faceI.b, faceI.c];
for (var j = 0; j < vertexArr.length; j++) {
var vertexJ = geo.vertices[vertexArr[j]];
var normalJ = faceI.vertexNormals[j];
if (vertexJ.hasScale) continue;
vertexJ.x += normalJ.x * ratio;
vertexJ.y += normalJ.y * ratio;
vertexJ.z += normalJ.z * ratio;
vertexJ.hasScale = true;
}
}
return geo;
},
I am developing a script for Adobe Bridge CS6. For the moment, all I want to do is to access the size (width and height) of a thumbnail that the user has selected and show it, either on a popup or on the console. Here is my script:
function TestBridge() {
this.requiredContext = "\tAdobe Bridge must be running.\n\tExecute against Bridge as the Target.\n";
}
TestBridge.prototype.run = function() {
if(!this.canRun())
{
return false;
}
var selectedThumbnails = app.document.getSelection();
if (selectedThumbnails.length > 0) {
$.writeln("MEEEEEPT");
var thumb = selectedThumbnails[0];
var x = thumb.core.preview.preview.width;
var y = thumb.core.preview.preview.height;
//alert('MEEEEEPT: x = ' + x + ', y = ' + y);
$.writeln("MEEEEEPT: x = " + x + ", y = " + y);
return true;
}
$.writeln("MOOO");
return false;
}
TestBridge.prototype.canRun = function()
{
// Must be running in Bridge & have a selection
if( (BridgeTalk.appName == "bridge") && (app.document.selectionLength == 1)) {
return true;
}
// Fail if these preconditions are not met.
// Bridge must be running,
// There must be a selection.
$.writeln("ERROR:: Cannot run.");
$.writeln(this.requiredContext);
return false;
}
The only problem is that... well, it doesnt work. I open it on ExtendScript Toolkit, set the target to Bridge CS6, hit "Run"... and all that happens is that the console says "Result: canRun()".
Looking at other code samples from Adobe, I see that the structure of their scripts is pretty much the same as mine, so I don't really know what I'm doing wrong.
Edit: what I needed was to add in the end a line to call the function, like so:
new.TestBridge.run();
Silly, silly mistake.
I am a little stuck and need some advice/help.
I have a progress bar:
<mx:ProgressBar id="appProgress" mode="manual" width="300" label="{appProgressMsg}" minimum="0" maximum="100"/>
I have two listener functions, one sets the progress, and one sets the appProgressMsg:
public function incProgress(e:TEvent):void {
var p:uint = Math.floor(e.data.number / e.data.total * 100);
trace("Setting Perc." + p);
appProgress.setProgress(p, 100);
}
public function setApplicationProgressStep(e:TEvent):void {
trace("Setting step:" + e.data);
appProgressMsg = e.data;
}
I want to reuse this progress bar alot. And not necessarily for ProgressEvents, but when going through steps.
For instance, I loop over a bunch of database inserts, and want to undate the progress etc.
Here is a sample:
public function updateDatabase(result:Object):void {
var total:int = 0;
var i:int = 0;
var r:SQLResult;
trace("updateDatabase called.");
for each (var table:XML in this.queries.elements("table")) {
var key:String = table.attribute("name");
if (result[key]) {
send(TEvent.UpdateApplicationProgressStep, "Updating " + key);
i = 1;
total = result[key].length;
for each (var row:Object in result[key]) {
//now, we need to see if we already have this record.
send(TEvent.UpdateApplicationProgress, { number:i, total: total } );
r = this.query("select * from " + key + " where server_id = '" + row.id + "'");
if (r.data == null) {
//there is no entry with this id, make one.
this.query(table.insert, row);
} else {
//it exists, so let's update.
this.update(key, row);
}
i++;
}
}
}
}
Everything works fine.
That is, the listener functions are called and I get trace output like:
updateDatabase called.
Setting step:Updating project
Setting Perc 25
Setting Perc 50
Setting Perc 75
Setting Perc 100
The issue is, only the very last percent and step is shown. that is, when it's all done, the progress bar jumps to 100% and shows the last step label.
Does anyone know why this is?
Thanks in advance for any help,
Jason
The new code, which works awesomely I might add:
public function updateDatabase(result:Object, eindex:int = 0, sindex:int = 0 ):void {
var total:int = 0;
var i:int = 0;
var j:int;
var r:SQLResult;
var table:XML;
var key:String;
var elems:XMLList = this.queries.elements("table");
var startTime:int = getTimer();
var row:Object;
for (i = eindex; i < elems.length(); i++) {
table = elems[i];
key = table.attribute("name");
if (!result[key])
continue;
total = result[key].length;
send(TEvent.UpdateApplicationProgressStep, "Updating " + key);
for (j = sindex; j < result[key].length; j++) {
if (getTimer() - startTime > 100) {
setTimeout(updateDatabase, 100, result, i, j);
send(TEvent.UpdateApplicationProgress, { number:j, total: total } );
return;
}
row = result[key][j];
r = this.query("select * from " + key + " where server_id = '" + row.id + "'");
if (r.data == null) {
//there is no entry with this id, make one.
this.query(table.insert, row,false);
} else {
//it exists, so let's update.
this.update(key, row,false);
}
}
send(TEvent.UpdateApplicationProgress, { number:1, total: 1 } );
}
}
Flash is single threaded. The display will not update until your function returns. For this reason, you should never have any code that runs for longer than about 100ms (1/10th of a second), otherwise the UI (or even the entire browser) will appear to be locked up.
The general solution is to split up your work over multiple frames, here is some pseudo-code:
function doWork(arg1:Obj, arg2:Obj, start:int=0) {
var startTime = getTimer(); // store starting time
for(i=start; i<length; i++) {
if(getTimer() - startTime > 100) { // see if we've been working too long
trace("Current progress: "+(i/length * 100)+"%");
updateProgress( i / length );
setTimeout(doWork, 100, arg1, arg2, i); // schedule more work to be done
return; // stop current loop
}
trace("Working on item "+i);
// processing here
}
trace("All work done");
}
doWork(data1, data2); // start the work
Your pseudo-code works for updating the progress bar however in my case my "work" was copying of files from DVD to the appStorageDirectory which seem to reintroduce the same issue that your work around resolved - the progress bar now does not update
Here is my hack of your solution
function doWork(arg1:int, arg2:int, start:int=0) {
var startTime = getTimer(); // store starting time
for(var i:int=start; i<arg2; i++) {
if(getTimer() - startTime > 100 ) { // see if we've been working too long
trace("Current progress: "+(i/arg2 * 100)+"%");
setTimeout(doWork, 100, i, arg2, i); // schedule more work to be done
return; // stop current loop
}
trace("Working on item "+i);
dispatchEvent(new progressMadeEvent("incrementChange",i,arg2))
var dir:String = copyRes[i].nativePath.toString().split(OSSep).pop()
copyRes[i].copyTo(appStore.resolvePath(dir)) // copies dir from DVD to appStorageDir
}
trace("All work done");
}
I am trying to center an image in the middle of the stage and scale it proportionally to the correct aspect ratio based on its loader's size when the image is loading.
In my main app runner I do:
private var rec:Rectangle = new Rectangle();
private var img:BitmapDisplay = new BitmapDisplay();
stage.addEventListener(Event.RESIZE, setRect);
img.imageURL = "some/path/to/image.jpg";
addChild(img);
private function setRect():void
{
var horz:Number = stage.stageWidth / 16;
var vert:Number = stage.y + stage.stageHeight / 16;
rec.x = horz;
rec.y = 80;
rec.width = stage.stageWidth - horz;
rec.height = stage.stageHeight - (vert * 2) - rec.y;
img.boundary = rec;
}
Then in my image (BitmapDisplay) class I have:
// sets the boundary of the image and resizes it
public function set boundary(rect:Rectangle):void
{
_imageBoundary = rect;
resizeImage();
}
private function resizeImage():void
{
var aspect:Number = _ldr.content.width / _ldr.content.height;
var cAspect:Number = _imageBoundary.width / _imageBoundary.height;
if (aspect <= cAspect)
{
_ldr.height = _imageBoundary.height;
_ldr.width = aspect * _ldr.height;
}
else
{
_ldr.width = _imageBoundary.width;
_ldr.height = _ldr.width / aspect;
}
var _pad:int = 7;
_ldr.x = (_imageBoundary.width - _ldr.width) / 2 + _imageBoundary.x - _pad;
_ldr.y = (_imageBoundary.height - _ldr.height) / 2 + _imageBoundary.y - _pad;
}
}
Is there something obvious keeping this from working right?
I want a 16th of the stage to be the bounds for the image and for the image to scale/resize based on this rect.
Thanks...
It turns out that this had more to do with the loader not being ready to be resized. There was some error checking in my code that needed to be reformatted, so now when the resize function gets called, it doesn't do anything until the loader is ready and the boundary is set.