I need an algorithm that can fit n rectangles of any size in a larger one minimizing its area - optimization

I need an algorithm that would take n rectangles of any sizes, and calculate a rectangle big enough to fit them all, minimizing its area so the wasted area is minimum, and also returning the position of all the smaller rectangles within.
The specific task I need this to implement on is in a sprite sheet compiler that would take individual PNG files and make a large PNG with all the images in it, so individual frames can be blitted from this surface at run time.
A nice to have feature would be that it aims to a specific given width/height ratio, but it's not mandatory.
I'd prefer simple, generic code I can port to another language.

This is what I put together for my own needs. The T parameter is whatever object you want associated with the results (think of it like the Tag property). It takes a list of sizes and returns a list of Rects that are arranged
static class LayoutHelper
{
/// <summary>
/// Determines the best fit of a List of Sizes, into the desired rectangle shape
/// </summary>
/// <typeparam name="T">Holder for an associated object (e.g., window, UserControl, etc.)</typeparam>
/// <param name="desiredWidthToHeightRatio">the target rectangle shape</param>
/// <param name="rectsToArrange">List of sizes that have to fit in the rectangle</param>
/// <param name="lossiness">1 = non-lossy (slow). Greater numbers improve speed, but miss some best fits</param>
/// <returns>list of arranged rects</returns>
static public List<Tuple<T, Rect>> BestFitRects<T>(double desiredWidthToHeightRatio,
List<Tuple<Size, T>> rectsToArrange, int lossiness = 10)
{
// helper anonymous function that tests for rectangle intersections or boundary violations
var CheckIfRectsIntersect = new Func<Rect, List<Rect>, double, bool>((one, list, containerHeight) =>
{
if (one.Y + one.Height > containerHeight) return true;
return list.Any(two =>
{
if ((one.Top > two.Bottom) ||
(one.Bottom < two.Top) ||
(one.Left > two.Right) ||
(one.Right < two.Left)) return false; // no intersection
return true; // intersection found
});
});
// helper anonymous function for adding drop points
var AddNewPotentialDropPoints = new Action<SortedDictionary<Point, object>, Rect>(
(potentialDropPoints, newRect) =>
{
// Only two locations make sense for placing a new rectangle, underneath the
// bottom left corner or to the right of a top right corner
potentialDropPoints[new Point(newRect.X + newRect.Width + 1,
newRect.Y)] = null;
potentialDropPoints[new Point(newRect.X,
newRect.Y + newRect.Height + 1)] = null;
});
var sync = new object();
// the outer boundary that limits how high the rectangles can stack vertically
var containingRectHeight = Convert.ToInt32(rectsToArrange.Max(a => a.Item1.Height));
// always try packing using the tallest rectangle first, working down in height
var largestToSmallest = rectsToArrange.OrderByDescending(a => a.Item1.Height).ToList();
// find the maximum possible container height needed
var totalHeight = Convert.ToInt32(rectsToArrange.Sum(a => a.Item1.Height));
List<Tuple<T, Rect>> bestResults = null;
// used to find the best packing arrangement that approximates the target container dimensions ratio
var bestResultsProximityToDesiredRatio = double.MaxValue;
// try all arrangements for all suitable container sizes
Parallel.For(0, ((totalHeight + 1) - containingRectHeight) / lossiness,
//new ParallelOptions() { MaxDegreeOfParallelism = 1},
currentHeight =>
{
var potentialDropPoints = new SortedDictionary<Point, object>(Comparer<Point>.Create((p1, p2) =>
{
// choose the leftmost, then highest point as earlier in the sort order
if (p1.X != p2.X) return p1.X.CompareTo(p2.X);
return p1.Y.CompareTo(p2.Y);
}));
var localResults = new List<Tuple<T, Rect>>();
// iterate through the rectangles from largest to smallest
largestToSmallest.ForEach(currentSize =>
{
// check to see if the next rectangle fits in with the currently arranged rectangles
if (!potentialDropPoints.Any(dropPoint =>
{
var workingPoint = dropPoint.Key;
Rect? lastFittingRect = null;
var lowY = workingPoint.Y;
var highY = workingPoint.Y - 1;
var boundaryFound = false;
// check if it fits in the current arrangement of rects
do
{
// create a positioned rectangle out of the size dimensions
var workingRect = new Rect(workingPoint,
new Point(workingPoint.X + currentSize.Item1.Width,
workingPoint.Y + currentSize.Item1.Height));
// keep moving it up in binary search fashion until it bumps the higher rect
if (!CheckIfRectsIntersect(workingRect, localResults.Select(a => a.Item2).ToList(),
containingRectHeight + (currentHeight * lossiness)))
{
lastFittingRect = workingRect;
if (!boundaryFound)
{
highY = Math.Max(lowY - ((lowY - highY) * 2), 0);
if (highY == 0) boundaryFound = true;
}
else
{
lowY = workingPoint.Y;
}
}
else
{
boundaryFound = true;
highY = workingPoint.Y;
}
workingPoint = new Point(workingPoint.X, lowY - (lowY - highY) / 2);
} while (lowY - highY > 1);
if (lastFittingRect.HasValue) // found the sweet spot for this rect
{
var newRect = lastFittingRect.Value;
potentialDropPoints.Remove(dropPoint.Key);
// successfully found the best location for the new rectangle, so add it to the pending results
localResults.Add(Tuple.Create(currentSize.Item2, newRect));
AddNewPotentialDropPoints(potentialDropPoints, newRect);
return true;
}
return false;
}))
{
// this only occurs on the first square
var newRect = new Rect(0, 0, currentSize.Item1.Width, currentSize.Item1.Height);
localResults.Add(Tuple.Create(currentSize.Item2, newRect));
AddNewPotentialDropPoints(potentialDropPoints, newRect);
}
});
// layout is complete, now see if this layout is the best one found so far
var layoutHeight = localResults.Max(a => a.Item2.Y + a.Item2.Height);
var layoutWidth = localResults.Max(a => a.Item2.X + a.Item2.Width);
var widthMatchingDesiredRatio = desiredWidthToHeightRatio * layoutHeight;
double ratioProximity;
if (layoutWidth < widthMatchingDesiredRatio)
ratioProximity = widthMatchingDesiredRatio / layoutWidth;
else
ratioProximity = layoutWidth / widthMatchingDesiredRatio;
lock (sync)
{
if (ratioProximity < bestResultsProximityToDesiredRatio)
{
// this layout is the best approximation of the desired container dimensions, so far
bestResults = localResults;
bestResultsProximityToDesiredRatio = ratioProximity;
}
}
});
return bestResults ?? new List<Tuple<T, Rect>>() {Tuple.Create(rectsToArrange[0].Item2,
new Rect(new Point(0, 0), new Point(rectsToArrange[0].Item1.Width, rectsToArrange[0].Item1.Height))) };
}
}

Related

Creating an action for moving layers on the x axis to the widest width of a selected layer?

I want to make a variable action that separates a series of layers based on the widest width of one of those selected layers. 4 sprites are 100, 100, 100, 200 pixels wide. It'd separate the layers all by 200 pixels on the x axis and make the image 800 pixels wide total.
I am able to do this easily if all layers are the same but cannot make it work with variability. Not sure if there are any photoshop wizards willing to lend me their time to make a script but it would be extremely helpful!
I'd do something like this. This presumes that there're no groups, no Background layer, layers are normal layers and all document layers are used. Before-after (largest was 150px):
If you don't need them to change Y position, change 0 - layersInfo[i].top to 0 on line 13.
function main()
{
var doc = activeDocument,
layers = doc.layers, //getting all top layers
layersInfo = getInfo().reverse(), //getting layers info and reversing the array because DOM indexes are different order than AM indexes
elWidth = getWidestElement(layersInfo); // getting widest element
doc.resizeCanvas(elWidth * layers.length, doc.height.as("px"), AnchorPosition.TOPLEFT); // resizing canvas size to new width: widest element * number of elements
for (var i = 0; i < layers.length; i++) // for every top layer...
{
doc.activeLayer = layers[i]; // selecting the layer
layers[i].translate(i * elWidth - layersInfo[i].left, 0 - layersInfo[i].top) // moving it to top left corner of each block
}
function getInfo()
{
var layers = 1,
lyrs = [];
while (true)
{
ref = new ActionReference();
ref.putIndex(charIDToTypeID('Lyr '), layers);
try
{
var desc = executeActionGet(ref);
}
catch (err)
{
break;
}
var lyr = {},
bounds = desc.getObjectValue(stringIDToTypeID("bounds"));;
lyr.top = bounds.getDouble(stringIDToTypeID("top"));
lyr.left = bounds.getDouble(stringIDToTypeID("left"));
lyr.width = bounds.getDouble(stringIDToTypeID("width"));
lyrs.push(lyr)
layers++;
}
return lyrs
}; // end of getInfo()
function getWidestElement(layers)
{
var curWidth = 0;
for (var i = 0; i < layers.length; i++)
{
if (layers[i].width > curWidth) curWidth = layers[i].width;
}
return curWidth
}; // end of getWidestElement()
}
var curUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
try
{
app.activeDocument.suspendHistory("temp", "main()");
}
catch (e)
{
alert(e + '\nLine: ' + e.line)
}
app.preferences.rulerUnits = curUnits;

Determine if point is inside shape SQL Server 2014 [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I'm developing a GPS project I allow user to draw (using google) a shape(rectangle, polygon, circle, line)
and save it in database
SQL Fiddle
Now my requirement is to determine if a given point within anyone in the table
and return the id else return 0.
the trick is I save multiple shapes (Type column determine the shape type 2 is a rectangle- 4 is polygon)
What I have tried
Example
Note: I will be using this from C# and pass point as parameter
First of all I would suggest you save the Polygons as Spatial Data Types
In JavaScript you can easily convert the drawn polygons to a List/Array of Lat/Lngs
for a circle you need the radius and the center lat/lng of the circle
something like this:
var circleCenter = null;
var circlePolygon = null;
// set draw options on google map
mapObject.setOptions({ draggableCursor: 'crosshair' });
var drawGeofenceEvent = google.maps.event.addListener(mapObject, 'click', event => {
var myLatLng = event.latLng;
// create a marker for center
circleCenter = new google.maps.Marker({
map: mapObject,
position: myLatLng,
draggable: true
});
// create a temp circle polygon to plot on map
circlePolygon = new google.maps.Circle({
radius: 150,
editable: true,
draggable: true
});
circlePolygon.setMap(mapObject);
circlePolygon.bindTo('center', circleCenter, 'position');
google.maps.event.removeListener(drawGeofenceEvent);
});
// after drawing the geofence you want to get the lat/longs along the circumference
var circleCoordinates = this.googleCircleToPolylineArray(this.circleCenter.position, this.circlePolygon.getRadius() * 0.000621371, 1);
// copied from Stackoverflow - will post the link when I find it
googleCircleToPolylineArray(point, radius, dir) {
var lat = point.lat();
var lng = point.lng();
var d2r = Math.PI / 180; // degrees to radians
var r2d = 180 / Math.PI; // radians to degrees
var earthsradius = 3963; // 3963 is the radius of the earth in miles
// ReSharper disable once AssignedValueIsNeverUsed
var points = 32;
//var radius = 1; // radius in miles
// find the raidus in lat/lon
var rlat = (radius / earthsradius) * r2d;
var rlng = rlat / Math.cos(lat * d2r);
var extp = new Array();
for (var i = 0; i < points + 1; i++) {
var theta = Math.PI * (i / (points / 2));
var ex = lng + (rlng * Math.cos(theta)); // center a + radius x * cos(theta)
var ey = lat + (rlat * Math.sin(theta)); // center b + radius y * sin(theta)
extp.push({ Latitude: ey, Longitude: ex }); // new google.maps.LatLng(ey, ex)
}
return extp;
};
// then you would POST the circleCoordinates to the Server to save as a spatial data type
Then on the server you would convert the co-ordinates to a Well-Known-Text (WKT) Wikipedia - for Polygon use the following, when I say Polygon I mean circle, rectangle, triangle, hexagon etc. Anything which has the same start and end point (is closed).
for a line you would use the LINESTRING WKT
public static DbGeography CreatePolygon(Coordinate[] latLongs)
{
//POLYGON ((73.232821 34.191819,73.233755 34.191942,73.233653 34.192358,73.232843 34.192246,73.23269 34.191969,73.232821 34.191819))
var polyString = "";
foreach (var point in latLongs)
{
polyString += point.Longitude + " " + point.Latitude + ",";
}
polyString = polyString.TrimEnd(',');
polyString = string.Format("POLYGON(({0}))", polyString);
var polygonFromText = DbGeography.PolygonFromText(polyString, DbGeography.DefaultCoordinateSystemId);
return polygonFromText;
}
Reverse From DbGeography to Coordinates
public static List<Coordinate> PolygonToGeoPoints(DbGeography sptGeofenceArea)
{
var points = new List<Coordinate>();
string polygonText = sptGeofenceArea.ProviderValue.ToString();
polygonText = polygonText.Replace("POLYGON", "");
polygonText = polygonText.Replace("(", "").Replace(")", "").Trim();
var polPoints = polygonText.Split(',');
foreach (var point in polPoints)
{
var latlong = point.Trim().Split(' ');
points.Add(new Coordinate { Latitude = double.Parse(latlong[1]), Longitude = double.Parse(latlong[0]) });
}
return points;
}
I use Entity Framework and DbGeography types, I save the polygon as a spatial data type in the database.
You can edit the above code to return the Well-Known-Text (WKT) instead of the DbGeography data type.
Then once the spatial data type is stored in the database all you have to do is convert the point you want to check to a spatial data type OR WKT
WKT - SQL VERSION
DECLARE #point GEOGRAPHY;
SET #point = geography::Point(47.653, -122.358, 4326)
Select
*
From Polygons
where POLYGON.STIntersects(#point) = 1
SPATIAL TYPE - ENTITY FRAMEWORK
DbGeography point;
dbCOntext.Polygons.Where(s => point.Intersects(s.Polygon)).ToList();
EDIT
There is a common problem when creating the Polygon types - the points have to be in a certain order otherwise you would have a Polygon covering the entire earth except the required Polygon - to overcome that you can use the following -
LINK
#region
//https://www.exceptionnotfound.net/fixing-sql-server-spatial-not-a-valid-instance-of-geography-errors-in-c-sharp/
private static DbGeography CreatePolygon(string wellKnownText)
{
//First, get the area defined by the well-known text using left-hand rule
var sqlGeography = SqlGeography.STGeomFromText(new SqlChars(wellKnownText), DbGeography.DefaultCoordinateSystemId);
if(!sqlGeography.STIsValid())
throw new Exception("Invalid polygon, please draw the polygon again.");
sqlGeography = sqlGeography.MakeValid();
//Now get the inversion of the above area
var invertedSqlGeography = sqlGeography.ReorientObject();
//Whichever of these is smaller is the enclosed polygon, so we use that one.
if (sqlGeography.STArea() > invertedSqlGeography.STArea())
{
sqlGeography = invertedSqlGeography;
}
return DbSpatialServices.Default.GeographyFromProviderValue(sqlGeography);
}
#endregion
public static DbGeography CreatePolygon(Coordinate[] latLongs)
{
//POLYGON ((73.232821 34.191819,73.233755 34.191942,73.233653 34.192358,73.232843 34.192246,73.23269 34.191969,73.232821 34.191819))
var polyString = "";
foreach (var point in latLongs)
{
polyString += point.Longitude + " " + point.Latitude + ",";
}
polyString = polyString.TrimEnd(',');
polyString = string.Format("POLYGON(({0}))", polyString);
var dbGeographyPolygon = CreatePolygon(polyString);
return dbGeographyPolygon;
//var polygonFromText = DbGeography.PolygonFromText(polyString, DbGeography.DefaultCoordinateSystemId);
//return polygonFromText;
}

XNA 4.0 Camera and object handling on screen

For developing a side-scrolling platform 2D game I want to implement a moving camera class, the reason of using the class instead of moving the whole map is that I'll have to use too many objects at once witch will cause a lag. I cannot let that happen.
There's a nice algorithm for handling the camera, when player is moving further than the width of the screen then camera moves on players direction until he is once again in the middle of the screen, I've been working several days for making this algorithm work however there's been no success.
// Main
public class Camera
{
protected float _zoom;
protected Matrix _transform;
protected Matrix _inverseTransform;
//The zoom scalar (1.0f = 100% zoom level)
public float Zoom
{
get { return _zoom; }
set { _zoom = value; }
}
// Camera View Matrix Property
public Matrix Transform
{
get { return _transform; }
set { _transform = value; }
}
// Inverse of the view matrix,
// can be used to get
// objects screen coordinates
// from its object coordinates
public Matrix InverseTransform
{
get { return _inverseTransform; }
}
public Vector2 Pos;
// Constructor
public Camera()
{
_zoom = 2.4f;
Pos = new Vector2(0, 0);
}
// Update
public void Update(GameTime gameTime)
{
//Clamp zoom value
_zoom = MathHelper.Clamp(_zoom, 0.0f, 10.0f);
//Create view matrix
_transform = Matrix.CreateScale(new Vector3(_zoom, _zoom, 1)) *
Matrix.CreateTranslation(Pos.X, Pos.Y, 0);
//Update inverse matrix
_inverseTransform = Matrix.Invert(_transform);
}
}
This is the camera class I made for handling the screen, it's main purpose is to resize the screen, more precisely to zoom in and out whenever I want to change my screen, (Title screen, Playing screen, Game over, and like that.)
Moving the camera is quite simple with keys, like this.
if (keyState.IsKeyDown(Keys.D))
Cam.Pos.X -= 20;
if (keyState.IsKeyDown(Keys.A))
Cam.Pos.X += 20;
if (keyState.IsKeyDown(Keys.S))
Cam.Pos.Y -= 20;
if (keyState.IsKeyDown(Keys.W))
Cam.Pos.Y += 20;
And ofc. the drawing method witch apply the camera.
spriteBatch.Begin(SpriteSortMode.Texture, BlendState.AlphaBlend, null, null, null, null, Cam.Transform);
Here comes the part when I stop, so what I want to do is make something like 2 2D rooms. By Room I mean the place where I usually place objects. like this "Vector2(74, 63)" So I want to create a place where I could draw items that would stick to the screen and wouldn't move, and make the screen bounds that would make my algorithm to work, witch will be always on screen and as an addition it will check if one of the borders of the screen "room" reaches the certain coordinates of the map "room".
I think that the reason for that would be obvious because I don't want player to move camera outside the map when he reaches the wall, otherwise the player would already see a part of the next map where he will be transformed.
The reason of drawing both maps next to each other is again to reduce the loading time so player wouldn't have to wait for playing the next map.
Alright, so I've run into more troubles than I expected so I'll add extra information and will start with the player class:
// Main
public class Player
{
public Texture2D AureliusTexture;
public Vector2 position;
public Vector2 velocity;
public Vector2 PosForTheCam; // Variable that holds value for moving the camera
protected Vector2 dimensions;
protected CollisionPath attachedPath;
const float GRAVITY = 18.0f;
const float WALK_VELOCITY = 120f;
const float JUMP_VELOCITY = -425.0f;
// Constructor
public Player()
{
dimensions = new Vector2(23, 46);
position = new Vector2(50, 770);
}
public void Update(float deltaSeconds, List<CollisionPath> collisionPaths)
{
#region Input handling
KeyboardState keyState = Keyboard.GetState();
if (keyState.IsKeyDown(Keys.Left))
{
velocity.X = -WALK_VELOCITY;
}
else if (keyState.IsKeyDown(Keys.Right))
{
velocity.X = WALK_VELOCITY;
}
else
{
velocity.X = 0;
}
if (attachedPath != null && keyState.IsKeyDown(Keys.Space))
{
velocity.Y = JUMP_VELOCITY;
attachedPath = null;
}
velocity.Y += GRAVITY;
#endregion
#region Region of handling the camera based on Player
PosForTheCam.X = velocity.X;
#endregion
#region Collision checking
if (velocity.Y >= 0)
{
if (attachedPath != null)
{
position.X += velocity.X * deltaSeconds;
position.Y = attachedPath.InterpolateY(position.X) - dimensions.Y / 2;
velocity.Y = 0;
if (position.X < attachedPath.MinimumX || position.X > attachedPath.MaximumX)
{
attachedPath = null;
}
}
else
{
Vector2 footPosition = position + new Vector2(0, dimensions.Y / 2);
Vector2 expectedFootPosition = footPosition + velocity * deltaSeconds;
CollisionPath landablePath = null;
float landablePosition = float.MaxValue;
foreach (CollisionPath path in collisionPaths)
{
if (expectedFootPosition.X >= path.MinimumX && expectedFootPosition.X <= path.MaximumX)
{
float pathOldY = path.InterpolateY(footPosition.X);
float pathNewY = path.InterpolateY(expectedFootPosition.X);
if (footPosition.Y <= pathOldY && expectedFootPosition.Y >= pathNewY && pathNewY < landablePosition)
{
landablePath = path;
landablePosition = pathNewY;
}
}
}
if (landablePath != null)
{
velocity.Y = 0;
footPosition.Y = landablePosition;
attachedPath = landablePath;
position.X += velocity.X * deltaSeconds;
position.Y = footPosition.Y - dimensions.Y / 2;
}
else
{
position = position + velocity * deltaSeconds;
}
}
}
else
{
position += velocity * deltaSeconds;
attachedPath = null;
}
#endregion
}
}
So I state it clear that I asked my friend to do most of it because I wanted to handle the gravity and the slopes so we made it work similar like in Unity. And he happened to know how to do that.
And so I'll add the Update method that handles the camera from the Main Class.
MM.Update(gameTime); // Map Managher update function for map handling
Cam.Update(gameTime); // Camera update
Cam.Zoom = 2.4f; // Sets the zoom level for the title screen
// Takes the start position for camera in map and then turns off the update
// so the camera position can be changed. Else it would just keep an infinite
// loop and we couldn't change the camera.
if (StartInNewRoom)
{
Cam.Pos = MM.CameraPosition; // Applys the camera position value from the map manager class
StartInNewRoom = false;
}
I am unsure how to handle the camera, like I used your method and the result often ended up that camera moves by itself or it doesn't move at all.
If you don't want objects to move with the camera like a HUD you need a second spriteBatch.Begin() without your camera matrix which you draw after your actual scene.
To make the camera not move out of the map you could use some kind of collision detection. Just calculate the right border of your camera. It depends where the origin of your camera is.
Is your camera matrix working like this? Because the position should be negative or it will move in the wrong direction.
This is how mine looks like.
return Matrix.CreateTranslation(new Vector3(-camera.position.X, -camera.position.Y, 0)) *
Matrix.CreateRotationZ(Rotation) * Matrix.CreateScale(Zoom) *
Matrix.CreateTranslation(new Vector3(Viewport.Width * 0.5f, Viewport.Height * 0.5f, 0));
Viewport.Width/Height * 0.5 centers you camera.
You can also apply this behind your Pos.X/Y
To Camera follows player
public void Update(Player player)
{
//Clamp zoom value
_zoom = MathHelper.Clamp(_zoom, 0.0f, 10.0f);
//Create view matrix
_transform = Matrix.CreateScale(new Vector3(_zoom, _zoom, 1)) *
Matrix.CreateTranslation(player.Pos.X, player.Pos.Y, 0);
//Update inverse matrix
_inverseTransform = Matrix.Invert(_transform);
}

How do I add a radius line from the center of the circle to a point on the circle

The following code adds a circle of given radius to the graphics layer on an ArcGIS map. How can I add a line that joins center of the circle to any point on the circle to the graphics layer.
Basically the question is how do I calculate a point on the circle, draw a line that joins the center to the point on the circle and add it to the graphics layer.
performSearchPoint : function(e) {
var self = this;
var radius = $('#radius-distance').val();
if(radius > 0 && radius < 100000){
$('#besideMouse').removeClass('hide');
$('#besideMouse').show();
var loadingBMint = setInterval(this.loadingBM, 0);
var searchPointClick = OURAPP.App.Map.on("click",function(evt) {
loadingBMint = clearInterval(loadingBMint);
$('#besideMouse').hide();
var radius = $('#radius-distance').val();
var units = $("input:radio[name='unitsGroup']:checked").val();
if (units == "miles"){
units = "9035"; // if we use GeometryService
} else {
units = "9003"; // if we use GeometryService
}
//clear only search graphics
for ( var gr in OURAPP.App.Map.graphics.graphics) {
if(OURAPP.App.Map.graphics.graphics[gr].infoTemplate != null){
var template = OURAPP.App.Map.graphics.graphics[gr].infoTemplate;
if(template != "undefined" || template != null){
if(template.title.trim() == "Search Graphic"){
OURAPP.App.Map.graphics.remove(OURAPP.App.Map.graphics.graphics[gr]);
}
}}}
/*do buffer geometry for draw circle and use the circle geometry to get the features*/
var geoService = new OURAPP.esri.GeometryService("http://XXXX:YYYY/arcgis/rest/services/Utilities/Geometry/GeometryServer");
var params = new OURAPP.esri.BufferParameters();
params.geometries = [ evt.mapPoint ];
params.distances = [ radius ];
params.unit = units;
params.bufferSpatialReference = OURAPP.App.Map.spatialReference;
params.outSpatialReference = new OURAPP.esri.SpatialReference(4326);
var bufferPolygon = new OURAPP.esri.Polygon;
bufferPolygon.spatialReference = new OURAPP.esri.SpatialReference(4326);
geoService.buffer(params,function(geometries) {
var symbol = new OURAPP.esri.SimpleFillSymbol()
.setColor(null).outline.setColor("red");
dojo.forEach(geometries,function(geometry) {
geometry.spatialReference = new OURAPP.esri.SpatialReference(4326);
var graphic = new OURAPP.esri.Graphic(geometry,symbol);
// add name to identify the search graphics
var template = new OURAPP.esri.InfoTemplate(graphic.geometry);
template.setTitle("Search Graphic");
template.setContent("Map Query circle with Radius: " + radius);
graphic.setInfoTemplate(template);
OURAPP.App.Map.graphics.add(graphic);
bufferPolygon = geometry;
OURAPP.App.Map.setExtent(graphic.geometry.getExtent().expand(2));
});
self.searchType="Distance Search from point";
self.nameofplace=radius + " "+$("input:radio[name='unitsGroup']:checked").val();
self.showCount(bufferPolygon);
});
searchPointClick.remove();
});
}
},
I was able to draw a line and add it to the graphics layer using the following. The [-XX.XXXXXXXXXXXX,YY.YYYYYYYYYYY] is a random point on the map, Now only thing left is to find a point on a circle. So now the question becomes how to find a point which is X miles from a known point(Center of the circle) along the same latitude.
var lineSymbol = new OURAPP.esri.CartographicLineSymbol(
OURAPP.esri.CartographicLineSymbol.STYLE_SOLID,
new OURAPP.esri.Color([255,0,0]), 2,
OURAPP.esri.CartographicLineSymbol.CAP_SQUARE,
OURAPP.esri.CartographicLineSymbol.JOIN_MITER, 5
);
var lineGeometry = new OURAPP.esri.Polyline;
lineGeometry.spatialReference = new OURAPP.esri.SpatialReference(4326);
lineGeometry.addPath([[evt.mapPoint.getLongitude(),evt.mapPoint.getLatitude()], [-XX.XXXXXXXXXXXX,YY.YYYYYYYYYYY]])
var lineGraphic = new OURAPP.esri.Graphic(lineGeometry, lineSymbol);
OURAPP.App.Map.graphics.add(lineGraphic);
This is the best possible one i came up with and its working.
var lineSymbol = new OURAPP.esri.CartographicLineSymbol(
OURAPP.esri.CartographicLineSymbol.STYLE_SOLID,
new OURAPP.esri.Color([255,0,0]), 2,
OURAPP.esri.CartographicLineSymbol.CAP_SQUARE,
OURAPP.esri.CartographicLineSymbol.JOIN_MITER, 5
);
var radiusInMeters;
if (selectedUnit == "miles"){
radiusInMeters = radius*1609.34; //have to convert it to meters.
} else {
radiusInMeters = radius*0.3048; //have to convert it to meters.
}
// Calculate the new map point on the circle.
var radians = Math.PI/180;
var ltLong = OURAPP.esri.webMercatorUtils.xyToLngLat(evt.mapPoint.x + radiusInMeters*Math.cos(radians), evt.mapPoint.y + radiusInMeters*Math.sin(radians));
// Calculate the new map point on the circle.
var lineGeometry = new OURAPP.esri.Polyline;
lineGeometry.spatialReference = new OURAPP.esri.SpatialReference(4326);
lineGeometry.addPath([[evt.mapPoint.getLongitude(),evt.mapPoint.getLatitude()], ltLong]);
var lineGraphic = new OURAPP.esri.Graphic(lineGeometry, lineSymbol);

Draw the closest Bone (Shoulder - Head) of 2 tracking skeletons Kinect SDK v1.6

I'm looking a solution to draw the bone of the closest skeleton. I wrote code to draw the first tracking skeleton's bone. If the second person will closer than first I want to draw bone of second skeleton. Maybe somebody have any idea how to do it?
void sensor_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
{
// check for frame drop.
if (skeletonFrame == null)
{
return;
}
// copy the frame data in to the collection
skeletonFrame.CopySkeletonDataTo(totalSkeleton);
// get the first Tracked skeleton
skeleton = (from trackskeleton in totalSkeleton
where trackskeleton.TrackingState == SkeletonTrackingState.Tracked
select trackskeleton).FirstOrDefault();
if (skeleton != null)
{
if (skeleton.Joints[JointType.ShoulderCenter].TrackingState == JointTrackingState.Tracked && skeleton.Joints[JointType.Head].TrackingState == JointTrackingState.Tracked)
{
myCanvas.Children.Clear();
this.DrawHead();
}
}
}
}
// Draws the head.
private void DrawHead()
{
if (skeleton != null)
{
drawBone(skeleton.Joints[JointType.ShoulderCenter], skeleton.Joints[JointType.Head]);
}
}
// Draws the bone.
void drawBone(Joint trackedJoint1, Joint trackedJoint2)
{
Line skeletonBone = new Line();
skeletonBone.Stroke = Brushes.Black;
skeletonBone.StrokeThickness = 3;
Point joint1 = this.ScalePosition(trackedJoint1.Position);
skeletonBone.X1 = joint1.X;
skeletonBone.Y1 = joint1.Y;
Point joint2 = this.ScalePosition(trackedJoint2.Position);
skeletonBone.X2 = joint2.X;
skeletonBone.Y2 = joint2.Y;
myCanvas.Children.Add(skeletonBone);
}
/// <summary>
/// Scales the position.
/// </summary>
/// <param name="skeletonPoint">The skeltonpoint.</param>
/// <returns></returns>
private Point ScalePosition(SkeletonPoint skeletonPoint)
{
// return the depth points from the skeleton point
DepthImagePoint depthPoint = this.sensor.CoordinateMapper.MapSkeletonPointToDepthPoint(skeletonPoint, DepthImageFormat.Resolution640x480Fps30);
return new Point(depthPoint.X, depthPoint.Y);
}
define a certain threshold and if the bone is behind that threshold draw the joins x,y coordinates on the canvas. You will have to add code to update the position of the sprite accordingly.