How to check Google map overlay type - google-maps

Is that possible to check the type of a google map overlay.
var polygon = new G.Polygon();
var rectangle = new G.Rectangle();
var circle = new G.Circle();
var shape;
Now, my code will dynamically assign these overlay to shape variable.
But how can I detect or check the type of an overlay named shape? I can't find the solution using Google.

You can use instanceof, but I'd advise against it. It's not part of the API and could break any time in the future.
It would be better to assign an attribute upon initialization.
var polygon = new G.Polygon();
polygon.type = 'polygon';
var rectangle = new G.Rectangle();
polygon.type = 'rectangle';
var circle = new G.Circle();
polygon.type = 'circle';
console.log(shape.type);

You can check the class via the Javascript instanceof operator:
var polygon = new G.Polygon();
var rectangle = new G.Rectangle();
var circle = new G.Circle();
var shape = selectShape(polygon, rectangle, circle); // your dynamic selection funktion
if (shape instanceof G.Polygon) {
alert("found Polygon");
}

I wrote a function that returns the type of shape it was given. It supports circle and polygon but I'm sure someone can figure out how to add rectangle. It simply checks for unique properties of each.
function typeOfShape(shape){
if(typeof shape.getPath === "function"){
return "polygon";
}else if(typeof shape.getRadius === "function"){
return "circle";
}else{
return "unknown";
}
}

Related

addCircle to existing movieclip, using name of clip from an array

I am currently building a project where I have a map with a number of ship and aircraft. What I am trying to achieve is to check the Line of Sight distance between them.
I have set up a LOS Calculator which checks the height of one platform and the height of a second platform then gives a response. That works fine.
I then wanted to addCircle based on the result from this calculator. So if the result was 10 it would draw a circle 10cm in radius. If the result was 100 then it would draw it at 100, you get the picture. This works.
My problem now is that I need to be able to click on one platform either before or after I have made the calculation and the .addCircle be added to that movieClip. I have set up an array to store the movieclips instance names and traced that. I have added a field on stage so that you can click on a platform and it will recognise the platform clicked. I am just lost as to how to get the circle into the movieClip that has been clicked.
I am very new to AS3 so this is starting todo my head in. Any help would be greatly appreciated.
The code I have is attached below. I hope I have inserted this properly. Thanks again
import flash.events.MouseEvent;
import flash.display.MovieClip;
stage.focus=ht1;
// creation of array containing movieclips and code that adds the clicked movieclip to Array-platformClicked
var platformArray:Array = [arunta_mc, f15_mc];
var platformClicked = [];
var selectedPlatform:MovieClip = new MovieClip();
for(var i:int = 0; i < platformArray.length; i++) {
platformArray[i].buttonMode = true;
platformArray[i].addEventListener(MouseEvent.CLICK, item_onClick);
}
function item_onClick(event:MouseEvent):void {
var selectedPlatformArray:Array = platformArray.filter(checkName);
selectedPlatform = selectedPlatformArray[0];
myText.text = event.currentTarget.name + " was clicked";
var platformClicked = String(event.currentTarget.name);
trace(platformClicked);
}
function checkName(item:MovieClip, index:int, array:Array):Boolean
{
return(item.name == platformClicked);
}
//setup of LOS Calculator code
var counter:Number=1;
operator_txt.text = "+";
ht1.restrict="-0123456789.";
ht2.restrict="-0123456789.";
var myresult:Number;
var test = [];
//start of code when equal button is pressed
equal_btn.addEventListener(MouseEvent.CLICK, equalhandler);
var newCircle:Shape = new Shape();//defines circle to be drawn
function equalhandler(event:MouseEvent):void{
newCircle.graphics.lineStyle(1, 0x000000);
newCircle.graphics.beginFill(0x435632);
newCircle.alpha = .1;
//start of result code
result_txt.text = String(int((1.23*(Math.sqrt(Number(parseFloat(ht1.text)+parseFloat(ht2.text)+""))))));
var test = String(int((1.23*(Math.sqrt(Number(parseFloat(ht1.text)+parseFloat(ht2.text)+""))))));
trace(test);
//end of result code
newCircle.graphics.drawCircle(0,0,test);//add circle based on LOS calculation
newCircle.graphics.endFill();
//var selectedPlatform:MovieClip = selectedPlatformArray[0];
selectedPlatform.addChild(newCircle);//this is where I need to add newCircle to the movieClip that is clicked
trace(selectedPlatform);
//trace(platformClicked);
}
//start of code for the clear button
clear_btn.addEventListener(MouseEvent.CLICK, clearhandler);
function clearhandler(event:MouseEvent):void{
ht1.text=ht2.text=result_txt.text="";
removeChild(newCircle);
var test = [];
}
You can use the filter() method to check each item's name, like so:
var selectedPlatformArray:Array = platformArray.filter(checkName);
and somewhere in your code, define the checkName function
function checkName(item:MovieClip, index:int, array:Array):Boolean
{
return (item.name == platformClicked);
}
selectedPlatformArray will now contain all elements that return true for the checkName function, and as long as you don't have multiple MovieClips with the same name the array should only contain one element, which you can retrieve simply by accessing the first element of the array:
var selectedPlatform:MovieClip = selectedPlatformArray[0];
Alternatively, you can also use the getChildByName() function, like so:
var selectedPlatform:MovieClip = stage.getChildByName(platformClicked);
However this depends on where the objects are added to, and if they're not all in the same container (or not added at all), then this isn't the best option. It's a quick and simple solution for small projects though.
Anyway, whatever method you use you can then easily add the circle to it in your equalHandler function as usual:
selectedPlatform.addChild(newCircle);
I'd recommend checking out the documentation for both filter() and getChildByName(), to get a better understanding of how they work, since my examples only showed how you'd use them in this specific situation.
Complete code that you should have:
import flash.events.MouseEvent;
import flash.display.MovieClip;
stage.focus=ht1;
// creation of array containing movieclips and code that adds the clicked movieclip to Array-platformClicked
var platformArray:Array = [arunta_mc, f15_mc];
var platformClicked:String = "";
var selectedPlatform:MovieClip = new MovieClip();
for(var i:int = 0; i < platformArray.length; i++) {
platformArray[i].buttonMode = true;
platformArray[i].addEventListener(MouseEvent.CLICK, item_onClick);
}
function item_onClick(event:MouseEvent):void {
var selectedPlatformArray:Array = platformArray.filter(checkName);
selectedPlatform = selectedPlatformArray[0];
myText.text = event.currentTarget.name + " was clicked";
platformClicked = String(event.currentTarget.name);
trace(platformClicked);
}
function checkName(item:MovieClip, index:int, array:Array):Boolean
{
return(item.name == platformClicked);
}
//setup of LOS Calculator code
var counter:Number=1;
operator_txt.text = "+";
ht1.restrict="-0123456789.";
ht2.restrict="-0123456789.";
var myresult:Number;
var test:String = "";
//start of code when equal button is pressed
equal_btn.addEventListener(MouseEvent.CLICK, equalhandler);
var newCircle:Shape = new Shape();//defines circle to be drawn
function equalhandler(event:MouseEvent):void{
newCircle.graphics.lineStyle(1, 0x000000);
newCircle.graphics.beginFill(0x435632);
newCircle.alpha = .1;
//start of result code
result_txt.text = String(int((1.23*(Math.sqrt(Number(parseFloat(ht1.text)+parseFloat(ht2.text)+""))))));
test = String(int((1.23*(Math.sqrt(Number(parseFloat(ht1.text)+parseFloat(ht2.text)+""))))));
trace(test);
//end of result code
newCircle.graphics.drawCircle(0,0,test);//add circle based on LOS calculation
newCircle.graphics.endFill();
//var selectedPlatform:MovieClip = selectedPlatformArray[0];
selectedPlatform.addChild(newCircle);//this is where I need to add newCircle to the movieClip that is clicked
trace(selectedPlatform);
//trace(platformClicked);
}
//start of code for the clear button
clear_btn.addEventListener(MouseEvent.CLICK, clearhandler);
function clearhandler(event:MouseEvent):void{
ht1.text=ht2.text=result_txt.text="";
selectedPlatform.removeChild(newCircle);
test = "";
}

use 1 object multiple times in as3?

I'm trying to make something like bookmarks, I have 1 note on the stage and when the user clicks it, it starts to drag and the users drops it where they want. the problem is I want these notes to be dragged multiple times.. here is my code:
import flash.events.MouseEvent;
//notess is the instance name of the movie clip on the stage
notess.inputText.visible = false;
//delet is a delete button inside the movie clip,
notess.delet.visible = false;
//the class of the object i want to drag
var note:notes = new notes ;
notess.addEventListener(MouseEvent.CLICK , newNote);
function newNote(e:MouseEvent):void
{
for (var i:Number = 1; i<10; i++)
{
addChild(note);
//inpuText is a text field in notess movie clip
note.inputText.visible = false;
note.x = mouseX;
note.y = mouseY;
note.addEventListener( MouseEvent.MOUSE_DOWN , drag);
note.addEventListener( MouseEvent.MOUSE_UP , drop);
note.delet.addEventListener( MouseEvent.CLICK , delet);
}
}
function drag(e:MouseEvent):void
{
note.startDrag();
}
function drop(e:MouseEvent):void
{
e.currentTarget.stopDrag();
note.inputText.visible = true;
note.delet.visible = true;
}
function delet(e:MouseEvent):void
{
removeChild(note);
}
any help will be appreciated.
You need to create a new instance of your note class when you drop, copy the location and other variables from the note you were dragging, add your new note to the stage, and return the dragging note to its original position.
Something like:
function drop($e:MouseEvent):void
{
$e.currentTarget.stopDrag();
dropNote($e.currentTarget as Note);
}
var newNote:Note;
function dropNote($note:Note):void
{
newNote = new Note();
// Copy vars:
newNote.x = $note.x;
newNote.y = $note.y;
// etc.
// restore original note.
// You will need to store its original position before you begin dragging:
$note.x = $note.originalX;
$note.y = $note.orgiinalY;
// etc.
// Finally, add your new note to the stage:
addChild(newNote);
}
... this is pseudo-code really, since I don't know if you need to add the new note to a list, or link it to its original note. If you Google ActionScript Drag Drop Duplicate, you will find quite a few more examples.
I think you are not target the drag object in drag function and problem in object instantiation
for (var i:Number = 1; i<numberOfNodes; i++) {
note = new note();
addChild(note);
...
....
}
function drag(e:MouseEvent):void{
(e.target).startDrag();
}
If you are dragging around multiple types of objects (eg. Notes and Images), you could do something like this, rather than hard coding the type of object to be instantiated.
function drop(e:MouseEvent):void{
// Get a reference to the class of the dragged object
var className:String = flash.utils.getQualifiedClassName(e.currentTarget);
var TheClass:Class = flash.utils.getDefinitionByName(className) as Class;
var scope:DisplayObjectContainer = this; // The Drop Target
// Convert the position of the dragged clip to local coordinates
var position:Point = scope.globalToLocal( DisplayObject(e.currentTarget).localToGlobal() );
// Create a new instance of the dragged object
var instance:DisplayObject = new TheClass();
instance.x = position.x;
instance.y = position.y;
scope.addChild(instance);
}

Record Paper.js path object and redraw again later

I draw with a mouse Paper.js. I need to keep these strokes and replay them at the same rate as in the video replay. How can I accomplish this?
In paper.js, the onFrame() function is called up to 60 times per second, while the onMouseMove() function "is called when the mouse moves within the project view", and contains the position of the mouse. By using both functions you can store the mouse motions and replay them later with close to the same time between positions.
var mousePosition = null;
function onMouseMove(event) {
if (mousePosition != null) {
var path = new Path();
path.strokeColor = 'black';
path.moveTo(mousePosition);
path.lineTo(event.point);
}
mousePosition = event.point;
}
var recordedPositions = [];
var delayFrames = 60;
function onFrame(event) {
if (mousePosition != null) {
recordedPositions.push(mousePosition);
if (recordedPositions.length > delayFrames) {
var path = new Path();
path.strokeColor = 'red';
delayedPositionIndex = recordedPositions.length - delayFrames;
path.moveTo(recordedPositions[delayedPositionIndex - 1]);
path.lineTo(recordedPositions[delayedPositionIndex]);
}
}
}
I do not know the timing accuracy/resolution/dependability of onFrame(). Alternatively you could just use javascript timing events as in this answer: How can I use javascript timing to control on mouse stop and on mouse move events

Box/Rectangle Draw Selection in Google Maps

I am working on Google Maps and want to implement a feature where a user can draw a box/rectangle using his/her mouse to select a region on map (like selecting multiple files in windows). Upon selection, I want to get all the markers that fall in the region. I have been looking around both Google Maps api and search but I am unable to find a solution. I tried using jQuery Selectable for selection but all it returns is a bunch of divs from which I am unable to determine if any marker is selected or not.
I found a Library keydragzoom (http://google-maps-utility-library-v3.googlecode.com/svn/tags/keydragzoom/1.0/docs/reference.html) and used it to draw a rectangle on the page.
Later, I edit the library and stopped it from zooming the selected area and instead made it return the correct co-ordinates in 'dragend' event. Then I manually looped through all the marker on the map to find the markers that are within that particular region. The library was not giving me the proper co-ordinates to I made the following changes.
Changed the DragZoom function to
var prj = null;
function DragZoom(map, opt_zoomOpts) {
var ov = new google.maps.OverlayView();
var me = this;
ov.onAdd = function () {
me.init_(map, opt_zoomOpts);
};
ov.draw = function () {
};
ov.onRemove = function () {
};
ov.setMap(map);
this.prjov_ = ov;
google.maps.event.addListener(map, 'idle', function () {
prj = ov.getProjection();
});
}
and DragZoom.prototype.onMouseUp_ function to
DragZoom.prototype.onMouseUp_ = function (e) {
this.mouseDown_ = false;
if (this.dragging_) {
var left = Math.min(this.startPt_.x, this.endPt_.x);
var top = Math.min(this.startPt_.y, this.endPt_.y);
var width = Math.abs(this.startPt_.x - this.endPt_.x);
var height = Math.abs(this.startPt_.y - this.endPt_.y);
var points={
top: top,
left: left,
bottom: top + height,
right: left + width
};
var prj = this.prjov_.getProjection();
// 2009-05-29: since V3 does not have fromContainerPixel,
//needs find offset here
var containerPos = getElementPosition(this.map_.getDiv());
var mapPanePos = getElementPosition(this.prjov_.getPanes().mapPane);
left = left + (containerPos.left - mapPanePos.left);
top = top + (containerPos.top - mapPanePos.top);
var sw = prj.fromDivPixelToLatLng(new google.maps.Point(left, top + height));
var ne = prj.fromDivPixelToLatLng(new google.maps.Point(left + width, top));
var bnds = new google.maps.LatLngBounds(sw, ne);
//this.map_.fitBounds(bnds);
this.dragging_ = false;
this.boxDiv_.style.display = 'none';
/**
* This event is fired when the drag operation ends.
* Note that the event is not fired if the hot key is released before the drag operation ends.
* #name DragZoom#dragend
* #param {GLatLngBounds} newBounds
* #event
*/
google.maps.event.trigger(this, 'dragend', points);
}
};

Google Maps add 2 GEvent Listeners. 1 for each marker

I have the following code which lets the user plot two points on a Google MAP. I then want to be able to catch the event for each point(marker) being dragged to a new location. I am bad at Javascript and have spent hours trying to do this so I think it's time I get some help..
What I am trying to do is get the user to plot two points(markers) draggable on the map. I then want to be able to have my script write the positions(lat,long) to the document. I will then calculate the distance between these as part of a shipping app I am making.
I would like to have the contents of the document (lat,long) updated when a marker(point) is dragged to a new location.
Also, I fixed a schoolboy error where the point vars were being decalred inside the switch statement. My problem is fixed by moving the Add event listener statements inside the switch statement. Thanks Cannonade :)
The next thing now is to try and calculate the distance (crow flies) between the two points
Again, thanks for you help.. appreciated as always!!
Updated Code that works:
var map = null;
var geocoder = null;
var zoom = 15;
var first_point = false;
var boundary = new Array();
var cCount = 0;
var point1;
var point2;
function initialize() {
if (GBrowserIsCompatible()) {
first_point = false;
map = new GMap2(document.getElementById("map_canvas"));
var center = new GLatLng(37.4419, -122.1419);
map.setCenter(center, zoom);
GEvent.addListener(map, "click", function(overlay,point)
{
if (overlay != null)
{}
else
{
var n = boundary.length;
switch (cCount)
{
case 0:
point1 = new GMarker(point,{draggable: true});
map.addOverlay(point1);
cCount++;
GEvent.addListener(point1, "dragend", function()
{
alert('P1 Dragged');
});
break;
case 1:
point2 = new GMarker(point,{draggable: true});
map.addOverlay(point2);
cCount++;
GEvent.addListener(point2, "dragend", function()
{
alert('P2 Dragged');
});
break;
case 2:
map.clearOverlays();
cCount=0;
break;
}
}
});
map.addControl(new GSmallMapControl());
geocoder = new GClientGeocoder();
}
}
I have taken your code and made the following fixes:
Fixed the unbalanced brackets I mentioned in the comment.
Moved the two addListener calls into the switch statement so that the point1 and point2 variables are still in scope when you attach the events.
You can check out the example here (source).
Edit:
Here is some Javascript code to get the linear distance between two points (in meters):
/* Convert degress to radians */
function deg2rad(deg) {
return deg / (180 / Math.PI);
}
/* Calculate distance between two points */
function point_distance(a, b) {
var r = 6378700;
var lat1 = a.y;
var lat2 = b.y;
var lon1 = a.x;
var lon2 = b.x;
var dist = r * Math.acos(Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) +
Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
Math.cos(deg2rad(lon1 - lon2)));
return dist;
}
This is based on the approximate radius of the earth being 6378700m.