Given a collection of points, I'd like to find the center of a bounding box (fixed-length and width) that maximizes the number of points within said box. I'm at a loss for an efficient way to do this.
Algorithm with complexity O(N^2*logN) (I hope that better one exists):
Edit: article exploiting interval trees claims O(NlogN) complexity
Sort data array A by X coordinate.
Scan A with sweep line left to right.
For every point in A get LeftX = A[k].X - left coordinate of vertical band, find the rightmost coordinate of vertical band RightX = LeftX + Width.
Copy points inside the band to another array B.
Sort B by Y-coordinate.
Scan B width sweep line top to down.
For every point B[i] get TopY = B[i].Y - top coordinate of rectangle, calculate BottomY = TopY + Height.
Use binary search in B:
B[j] is the last bottom point in B with B[j].Y <= BottomY.
Find number of points in the current rectangle:
Number of points is N(k, i) = j - i + 1
Check whether N(k, i) is maximum among others
This seems like a difficult problem, here is my idea:
Hold a graph, each node holds a rectangle and a subset of points. the rectangle defines the area where placing the bounding box in would overlap all the points in the subset.
To build the graph:
Start with a root node holding the empty set and the rect [top:-inf, bottom:inf, left:-inf, right:inf]
For each point in the tree call this recursive function with the root node (pseudo code):
function addPoint(node, point)
// check that you didn't already try to add this point to this node
// node.tested can be a hash set
if(node.tested contains point)
return
node.tested.add(point)
newRect = node.rect.intersectWith(boundingBoxAround(point))
// if the bounding box around the point does not intersect the rectangle, return
if(newRect is invalid) // rect is invalid if right<left or bottom<top
return
node.addChild(new node(newRect, node.pointSet U {point})
for each child of node
addPoint(child, point)
Now you just pick the node with the largest subset, you can keep track of that when building the graph so you don't need to run through the graph again.
I hope my idea is clear, let me know if I can explain it better.
Related
How can I draw filled elliptical sector using Bresenham's algorithm and bitmap object with DrawPixel method?
I have written method for drawing ellipse, but this method uses symmetry and passes only first quadrant. This algorithm is not situable for sectors. Of course, I can write 8 cycles, but I think it's not the most elegant solution of the task.
On integer math the usual parametrization is by using limiting lines (in CW or CCW direction) instead of your angles. So if you can convert those angles to such (you need sin,cos for that but just once) then you can use integer math based rendering for this. As I mentioned in the comment bresenham is not a good approach for a sector of ellipse as you would need to compute the internal iterators and counters state for the start point of interpolation and also it will give you just the circumference points instead of filled shape.
There are many approaches out there for this here a simple one:
convert ellipse to circle
simply by rescaling the smaller radius axis
loop through bbox of such circle
simple 2 nested for loops covering the outscribed square to our circle
check if point inside circle
simply check if x^2 + y^2 <= r^2 while the circle is centered by (0,0)
check if point lies between edge lines
so it should be CW with one edge and CCW with the other. You can exploit the cross product for this (its z coordinate polarity will tell you if point is CW or CCW against the tested edge line)
but this will work only up to 180 deg slices so you need also add some checking for the quadrants to avoid false negatives. But those are just few ifs on top of this.
if all conditions are met conver the point back to ellipse and render
Here small C++ example of this:
void elliptic_arc(int x0,int y0,int rx,int ry,int a0,int a1,DWORD c)
{
// variables
int x, y, r,
xx,yy,rr,
xa,ya,xb,yb, // a0,a1 edge points with radius r
mx,my,cx,cy,sx,sy,i,a;
// my Pixel access (you can ignore it and use your style of gfx access)
int **Pixels=Main->pyx; // Pixels[y][x]
int xs=Main->xs; // resolution
int ys=Main->ys;
// init variables
r=rx; if (r<ry) r=ry; rr=r*r; // r=max(rx,ry)
mx=(rx<<10)/r; // scale from circle to ellipse (fixed point)
my=(ry<<10)/r;
xa=+double(r)*cos(double(a0)*M_PI/180.0);
ya=+double(r)*sin(double(a0)*M_PI/180.0);
xb=+double(r)*cos(double(a1)*M_PI/180.0);
yb=+double(r)*sin(double(a1)*M_PI/180.0);
// render
for (y=-r,yy=y*y,cy=(y*my)>>10,sy=y0+cy;y<=+r;y++,yy=y*y,cy=(y*my)>>10,sy=y0+cy) if ((sy>=0)&&(sy<ys))
for (x=-r,xx=x*x,cx=(x*mx)>>10,sx=x0+cx;x<=+r;x++,xx=x*x,cx=(x*mx)>>10,sx=x0+cx) if ((sx>=0)&&(sx<xs))
if (xx+yy<=rr) // inside circle
{
if ((cx>=0)&&(cy>=0)) a= 0;// actual quadrant
if ((cx< 0)&&(cy>=0)) a= 90;
if ((cx>=0)&&(cy< 0)) a=270;
if ((cx< 0)&&(cy< 0)) a=180;
if ((a >=a0)||((cx*ya)-(cy*xa)<=0)) // x,y is above a0 in clockwise direction
if ((a+90<=a1)||((cx*yb)-(cy*xb)>=0))
Pixels[sy][sx]=c;
}
}
beware both angles must be in <0,360> range. My screen has y pointing down so if a0<a1 it will be CW direction which matches the routione. If you use a1<a0 then the range will be skipped and the rest of ellipse will be rendered instead.
This approach uses a0,a1 as real angles !!!
To avoid divides inside loop I used 10 bit fixed point scales instead.
You can simply divide this to 4 quadrants to avoid 4 if inside loops to improve performance.
x,y is point in circular scale centered by (0,0)
cx,cy is point in elliptic scale centered by (0,0)
sx,sy is point in elliptic scale translated to ellipse center position
Beware my pixel access is Pixels[y][x] but most apis use Pixels[x][y] so do not forget to change it to your api to avoid access violations or 90deg rotation of the result ...
I need to check whether a point lies within a given rectangle on a map. I am using leaflet to create bounding boxes which requires me to provide the south-west and north-east points of the rectangle.
I have the following information:
1. middle point of the top edge of the rectangle
2. middle point of the bottom edge of the rectangle
3. length of edge (i.e. breadth) = 1000 m.
It is safe to assume that the two points above are very close.
Any ideas on how this can be achieved will be helpful.
First, to get the upper left and lower right points, you'll need to use some geometry. This page: https://gis.stackexchange.com/questions/2951/algorithm-for-offsetting-a-latitude-longitude-by-some-amount-of-meters is a great example of how to accurately convert from meters to decimal degrees.
For example, in order to get the upper-left point, you are starting with the middle point of the line, and you have the total length of the line, you'll want to divide the length of the line by 2, then convert that length from meters to decimel degrees, then add the X coordinate by that amount. That will give you the upper-right corner. Repeat this for the lower-left corner by subtracting that amount instead of substracting.
var upperMiddlePoint = [30,50];
var segmentLength = 5000;
var northEastPoint = upperMiddlePoint;
var northEastPoint.x = northEastPoint.x + ((segmentLength / 2) * DECIMAL_DEGREES_PER_METER)
There's a quick and easy answer here: Simple calculations for working with lat/lon + km distance? that describes how to get the DECIMAL_DEGREES_PER_METER value in the above snippet.
To create a LatLngBounds object to represent your rectangle bounds. API Here.
var bounds = new L.LatLngBounds(southWestPoint, northEastPoint);
Then, use the LatLngBounds.contains() function, as described here, to determine if your point falls within these bounds.
var contains = bounds.contains([50, 30]);
if (contains) {
doStuff();
}
The contains boolean will be true if the bounds contain the point, false if not.
I have a list of points in cartesian plane, and a test point. I want to find list indices of three points nearest to test point. What's the better way to find these indices? Thanks in advance for tour replies.
=== EDIT ===
I've found a solution in C++. At first I create a vector:
typedef struct
{
int iIndex;
double dSqrDistance;
} IndexedDistance;
std::vector<IndexedDistance> xDistanceVector;
and then a function to sort its elements
bool compareIndexedDistance(IndexedDistance xD1, IndexedDistance xD2)
{
return (xD1.dSqrDistance < xD2.dSqrDistance);
}
Then in a loop I calculate all distances, then I sort them and at the end I take first three elements:
IndexedDistance xDistanceElement;
for (int i = 0; i < xPointList.size(); i++)
{
dSqrDistance = xPointList.at(i).sqrDistance(xTestPoint);
xDistanceElement.iIndex = i;
xDistanceElement.dSqrDistance = dSqrDistance;
xDistanceVector.push_back(xDistanceElement);
}
std::sort(xDistanceVector.begin(), xDistanceVector.end(), compareIndexedDistance);
xDistanceVector.resize(3);
In this way, I found what I need. I don't know if it's the best way, but it seems to work.
Binary space partitioning may provide algorithms complexity of O(log n * log n).
Determine bounds of your point set. Infinum and supremum points will give you an axis-aligned square containing all the points in set.
Split the bounding square in two by any of axis. Make a separate list of contained points for each square. Link each of bounding squares to the parent square.
Repeat splitting bounding squares (step 2) until corresponding lists of containing points will be reasonably small to utilize exhaustive search.
Now you will be able to use tree search to localize space around your point of interest and therefore greatly reduce number of distance tests.
The tricky part is that you must scan all the neighbour bounding squares around the point of interest because the closest point may lie in any of them.
I am trying to write an application to draw schematic diagrams which contain rectangles, lines and circles. Now I want to add another functionality to drag a rectangle to different position. The problem I am facing is to detect whether I have clicked within a rectangle or not. I know there is a function like Rectangle.Contains(Point). To use such method I need to use a for loop to check against each rectangle. If I have a large number of rectangles present, then its not wise to use this method. Is there any other way to do this task.
You need a computer graphics textbook, this and similar problems are often discussed.
If memory serves me, make sure the point is below the top edge of the rectangle, above the bottom edge, left of the right edge and right of the left edge.
Regarding testing a bunch of rectangles in a loop. Consider having a circle that each rectangle fits in, a bounding circle. First test to see if the point is farther from the origin of the circle than the radius of the circle. If so there is no need to test the rectangle, its a miss. OK, that was a very theoretical answer. In reality calculating the distance from the point to the origin can be a very expensive calculation, it involves a square root, it may be faster to do the four comparisons of the point in rectangle check. Again if memory servers me, we don't really care what the distance from the origin is only if it is greater than the radius. So only partially perform the distance calculation, omitting the final square root, and compare against the square of the radius. Of course you still need to experiment and profile to make sure this bounding circle check is faster than just doing the regular point in rectangle check and you need to make sure you will have sufficient misses to offset the hits where you will end up doing both the bounding circle and rectangle checks.
You need to use a spatial index to find quickly in which rectangle the mouse is. I suggest a R-tree, here is the theorical part:
http://en.wikipedia.org/wiki/R-tree
And the c#,implementation:
http://sourceforge.net/projects/cspatialindexrt/
Create an rtee, add your rectangles then call the rtree.nearest method with the mouse coordinate to know the rectangles containing the mouse cursor. You can play with the distance parameter.
Hope it helps,
Anben Panglose.
I would go about dividing the display region into a quadrant.
Then place the rectangles into top-left, top-right, bottom-left, bottom-right grids.
Placing them means, creating a list for every quadrant and placing the rectangles in it.
Once the point is clicked, determine which quarter it belongs to and search in those rectangles only. This approach reduces your linear search by 4 times.
Remember that you need to also take care of overlapping where the point can belong to many rectangles. Here the z-order of your rectangles matter. So while the list is maintained for a quadrant, it should be sorted with it's z-order as a key.
Hope this helps.
May be something like this?
public bool isRectangelContainPoint(RectangleF rec, PointF pt)
{
if (pt.X >= rec.Left && pt.X <= rec.Right && pt.Y <= rec.Bottom && pt.Y >= rec.Top)
return true;
else
return false;
}
I was wondering if the following algorithm to check if a point is inside a rectangle is valid.
I've developed it using my own intuition (no strong trig/math basis to support it), so I'd love to hear from someone with more experience in the matter.
Context:
The rectangle is defined with 4 points. It could be rotated.
Coordinates are always positive.
By definition, the point is considered inside the rectangle if intersects it.
Hypothesis:
Use the distance between the point and the rectangle vertices (first diagram below).
The maximum possible total distance is when the point is in one vertex (second diagram).
If the point is just outside the rectangle, the distance will be greater (third diagram).
Diagram link: http://i45.tinypic.com/id6o35.png
Algorithm (Java):
static boolean pointInsideRectangle(Point[] rect, Point point) {
double maxDistance = distance(rect[0], rect[1]);
maxDistance += distance(rect[0], rect[2]);
maxDistance += distance(rect[0], rect[3]);
double distance = 0;
for (Point rectPoint : rect) {
distance += distance(rectPoint, point);
if (distance > maxDistance) return false;
}
return true;
}
Questions: is this correct?
Short answer: NO :P (don´t fell bad about it)
Long Answer: Intersecction the areas from the four circles that you mention (max distance between opposite vertex) does not produce a rectangle.
Since I´m a bit rusty in geometry I can´t give full mathematical explanation (time constrain for my part), but give you some pseudocode of the procedure with the constrains that you ask (no fancy formulae), valid for any rectangle the wikipeida or a geometry book can fill the gaps.
Find the N,E,S,W vertex (the uppermost, rightmost, lowest and leftmost vertex) this is trivially easy for any rectangle but the axis aligned who can produce oddly assignation of the vertex (see images with examples)
Find the NE, SE, SW and NW border, this is the line equation in wikipedia or another link, again should be easy, but the axis aligned border should be analized carefully because those generate another type of ecuation/restriction.
Check if your point is on the "right side" of the border see inequality as mathematical term, only a point inside your rectangle satisfy the four restrictions as you can see in the image attached.
my apologies if I have overlook some command of java.geom that can accomplish this task
I hope this help with your endevour
You can try this.Lets name the point we have as A.Draw a line between A and every point of the rectangle.After that you get 4 different triangles.Calculate the area the triangles are taking(using Heron's formula) and compare it to the area of the rectangle.If the areas are the same then your point is inside the rectangle.
Cheers