Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed last month.
Improve this question
Suppose I have a finite set of points distributed in a unit square. I can't access the point coordinates; instead, I can only specify a (point, radius) pair and see how many points fall inside that circle. I want to find a set of circles such that each point is in at least one circle, and no circle contains more than 1000 points. What's an efficient way to do this? E.g. a way that minimizes the expected number of (point, radius) searches?
I tried a recursive approach. E.g. f(point, radius) takes a circle and returns a set of smaller circles that cover it. Then recurse until each circle contains fewer than 1000 points. But there's not a straightforward (to me) way to choose the smaller circles in the recursive step.
Edit: Circles are allowed to overlap with each other / with the outside of the square.
Not having a strict partition ("strict" - where the circles in the solution may not overlap and points must appear in exactly 1 circle) simplifies the problem.
The straight-forward way to subdivide a circle under those circumstances is to form a set of child circles that circumscribe the four quadrants of the parent...
Here's a (cursorily tested) demo using that approach
class Circle {
constructor(x,y,radius) {
Object.assign(this, { x, y, radius })
this.rSquared = radius*radius
}
contains(point) {
let dx = point.x - this.x
let dy = point.y - this.y
return dx*dx + dy*dy < this.rSquared
}
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
ctx.stroke();
}
subdivide() {
const halfR = this.radius / 2.0
const smallR = this.radius * Math.SQRT2 / 2.0
return [
new Circle(this.x-halfR, this.y-halfR, smallR),
new Circle(this.x-halfR, this.y+halfR, smallR),
new Circle(this.x+halfR, this.y-halfR, smallR),
new Circle(this.x+halfR, this.y+halfR, smallR),
]
}
}
// this class keeps a set of random points and answers countInCircle()
// solutions may only call countInCircle()
class Puzzler {
constructor(count) {
this.points = []
for (let i=0; i<count; i++) {
let point = { x: Math.random()*width, y: Math.random()*height}
this.points.push(point)
}
}
// answer how many points fall inside circle
countInCircle(circle) {
return this.points.reduce((total, p) => total += circle.contains(p) ? 1 : 0, 0);
}
drawSolution(circles) {
// draw the random points
this.points.map(p => ctx.fillRect(p.x,p.y,2,2))
// draw the circles in the solution
ctx.strokeStyle = 'lightgray'
circles.forEach(circle => circle.draw())
// log some stats - commented a few of these out for snippet brevity
const counts = circles.map(circle => this.countInCircle(circle));
console.log('circles:', circles.length)
// console.log('counts:', counts.join(', '))
// console.log('counts above 100:', counts.filter(c => c > 100).length)
const averageCount = counts.reduce((a, b) => a + b) / counts.length
console.log('average count:', averageCount.toFixed(2))
const uncovered = this.points.reduce((total, point) => {
return total + (circles.some(circle => circle.contains(point)) ? 0 : 1)
}, 0)
console.log('uncovered points:', uncovered)
}
}
// setup canvas
const canvas = document.getElementById('canvas')
const { width, height } = canvas
const ctx = canvas.getContext('2d')
// setup puzzle
const count = 1000
const maxCountPer = 100
const puzzler = new Puzzler(count, maxCountPer)
// begin with an encompasing circle, subdivide and solve recursively
// until all subdivided circles meet the count criterion
let r = width*Math.SQRT2/2
let c = new Circle(width/2.0, width/2.0, r)
let solution = solve(c);
function solve(circle) {
let result = []
let count = puzzler.countInCircle(circle)
if (count > 0 && count <= maxCountPer) {
result.push(circle);
} else if (count > maxCountPer) {
circle.subdivide().forEach(c => {
result.push(...solve(c))
})
}
return result
}
requestAnimationFrame(() => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
puzzler.drawSolution(solution)
});
<h1>Circles Puzzle</h1>
<canvas style="border: 1px solid gray;" id="canvas" height="800" width="800"></canvas>
Assumption: When you pick a point and a radius, you get back a list of points that are in the containing circle. I.e., you know which points are covered by which circles.
If that's correct,then you can map out the approximate relative location of all points, after which answers to this similar question should carry you over the finish line.
To map out the relative location of all points:
Note that you can find the distance between any pair of points by centering your circle on one and using binary search on your radius to find the distance to the other within whatever precision you want to use.
Next choose three arbitrary points that aren't too close together. Pick an arbitrary point. Grow the radius, say to 1/4. Pick an arbitrary point close to that radius (by incrementing radius a bit to get another point, or using binary search on radius). Say the distance between these first two points is d. Pick a third point at distance >= d from the first two points but ideally close to d, again by incrementing the two radii or binary search on the same.
Now you have a roughly equilateral triangle. It isn't important that it's equilateral, but it is important that the points aren't very close, and aren't co-linear.
Next, give these three points coordinates. Say the first point is at (0,0), the second point is at (0, dist to first point). The third point will have two possible locations based on its distance from the first two. Choose the one in the first quadrant (arbitrarily).
All other points can now be positioned relative to this triangle by finding their distance two the points of the triangle.
For purposes of your problem, it doesn't matter that the cloud of points is rotated relative to the input, or that we don't know where the unit square is relative to the points. You have a cloud of points with (approximately) known coordinates, and can proceed accordingly.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 3 years ago.
Improve this question
I'm looking at an example from Nature of Code.
The particular example has a ball accelerate towards the cursor. However, it does not stop when it reaches it, actually it has maximum momentum, and starts to decelerate once it passes it, accelerate towards the cursor, and overshoot it again.
My question is, how to have the ball accelerate, then start decelerating BEFORE it touches the cursor using a transition such as ease out, so it stops before it touches the cursor?
The ProcessingJS code:
// The Nature of Code
// Daniel Shiffman
// http://natureofcode.com
// A Mover object
Mover mover;
void setup() {
size(640,360);
mover = new Mover();
}
void draw() {
background(255);
// Update the position
mover.update();
// Display the Mover
mover.display();
}
// The Nature of Code
// Daniel Shiffman
// http://natureofcode.com
class Mover {
// The Mover tracks position, velocity, and acceleration
PVector position;
PVector velocity;
PVector acceleration;
// The Mover's maximum speed
float topspeed;
Mover() {
// Start in the center
position = new PVector(width/2,height/2);
velocity = new PVector(0,0);
topspeed = 5;
}
void update() {
// Compute a vector that points from position to mouse
PVector mouse = new PVector(mouseX,mouseY);
PVector acceleration = PVector.sub(mouse,position);
// Set magnitude of acceleration
acceleration.setMag(0.2);
// Velocity changes according to acceleration
velocity.add(acceleration);
// Limit the velocity by topspeed
velocity.limit(topspeed);
// position changes by velocity
position.add(velocity);
}
void display() {
stroke(0);
strokeWeight(2);
fill(127);
ellipse(position.x,position.y,48,48);
}
}
The Nature of Code is an awesome book and I'm often coming back to read it, especially when it comes to autonomous agents.
About your specific question, Shiffman deals with this exact problem just a little bit further in the same chapter. Take a look at example 6.2 on this page and you'll get the approximative comportment you just described. It's a little bit too long to post the whole thing, but here's an excerpt just in case the site goes down in the future and someone reads this question:
void arrive(PVector target) {
PVector desired = PVector.sub(target,location);
// The distance is the magnitude of
// the vector pointing from
// location to target.
float d = desired.mag();
desired.normalize();
// If we are closer than 100 pixels...
if (d < 100) {
//[full] ...set the magnitude
// according to how close we are.
float m = map(d,0,100,0,maxspeed);
desired.mult(m);
//[end]
} else {
// Otherwise, proceed at maximum speed.
desired.mult(maxspeed);
}
// The usual steering = desired - velocity
PVector steer = PVector.sub(desired,velocity);
steer.limit(maxforce);
applyForce(steer);
}
I can take no credit for the code, as it's Shiffman's writing. I'm just the messenger. Have fun and thanks for the glory points!
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
i'm trying to make a card game called sets (Here a link to how it works). I need to create 27 cards (array) and then check each time take 12 cards out of it and get the pairs. Does anyone know the best way to search for pairs. Like to check which cards:
They all have the same number or have three different numbers.
They all have the same symbol or have three different symbols.
They all have the same color or have three different colors.
How can i use the wright datatype in the array and later check which is the good one in a function
I tried using a array with strings which contains the color, shape and amount. Like green triangle 3x times is: gt3. But i cant find out how to compare them for the good pairs
The short answer, that you can implement right away is using a 2D-array.
You learned that an array can hold values. An array can also hold other arrays. So you can use an array per card to hold the properties, and store all those arrays in a 'cardset' array. You can now access the individual card properties by using 2 indexes. The code below can help you understand:
String[] card_a = {"G", "T","3"};
String[] card_b = {"R", "S","2"};
String[] card_c = {"G", "S","1"};
String[][] cardset = {card_a, card_b, card_c};
void setup(){
//Print the number on card_a
print(cardset[0][2]);
//Compare the number on card_a with the number on card_b
if(cardset[0][2] == cardset[1][2]){
print("Equal!");
}
else{
print("Unequal!");
}
}
You can also instantiate a 2D-array directly like this:
String[][] cardset = { {"G", "T","3"},
{"R", "S","2"},
{"G", "S","1"}
};
The long answer is that you should learn about the power of objects.
I won't fully explain it, because that would be very lengthy and the internet is full of excellent explanations - better than mine would ever be.
I suggest you read this tutorial on the processing website. I can also advice this video series on the basics of both processing and programming, including objects.
The code below shows you what a basic implementation of an object can look like. This might not make a whole lot of sense to you yet. That's okay. Objects are a fundamental programming principle, but it takes some time - and a good explanation - to get your head around. Therefor I highly suggest you check out the tutorials I posted above. It will probably take some time before you fully master the concept, but when you do, you can harness its power.
class Card {
String shape;
int number;
color col;
Card(String s, int n, color c) {
shape = s;
number = n;
col = c;
}
}
void setup() {
color red = color(255, 0, 0);
color green = color(0, 255, 0);
color blue = color(0, 0, 255);
Card a = new Card("Circle", 1, red);
Card b = new Card("Square", 2, green);
Card c = new Card("Circle", 3, blue);
//Check for equal shapes
if (a.shape == b.shape && b.shape ==c.shape ) {
print("All shapes equal");
}
//Check for unequal shapes
if (a.shape != b.shape && a.shape != c.shape && b.shape !=c.shape ) {
print("All shapes unequal");
}
}
I'm working on a specific layout algorithm to display photos in a unit based grid. The desired behaviour is to have every photo placed in the next available space line by line.
Since there could easily be a thousand photos whose positions need to be calculated at once, efficiency is very important.
Has this problem maybe been solved with an existing algorithm already?
If not, how can I approach it to be as efficient as possible?
Edit
Regarding the positioning:
What I'm basically doing right now is iterating every line of the grid cell by cell until I find room to fit the element. That's why 4 is placed next to 2.
How about keeping a list of next available row by width? Initially the next-available-row list looks like:
(0,0,0,0,0)
When you've added the first photo, it looks like
(0,0,0,0,1)
Then
(0,0,0,2,2)
Then
(0,0,0,3,3)
Then
(1,1,1,4,4)
And the final photo doesn't change the list.
This could be efficient because you're only maintaining a small list, updating a little bit at each iteration (versus searching the entire space every time. It gets a little complicated - there could be a situation (with a tall photo) where the nominal next available row doesn't work, and then you could default to the existing approach. But overall I think this should save a fair amount of time, at the cost of a little added complexity.
Update
In response to #matteok's request for a coordinateForPhoto(width, height) method:
Let's say I called that array "nextAvailableRowByWidth".
public Coordinate coordinateForPhoto(width, height) {
int rowIndex = nextAvailableRowByWidth[width + 1]; // because arrays are zero-indexed
int[] row = space[rowIndex]
int column = findConsecutiveEmptySpace(width, row);
for (int i = 1; i < height; i++) {
if (!consecutiveEmptySpaceExists(width, space[i], column)) {
return null;
// return and fall back on the slow method, starting at rowIndex
}
}
// now either you broke out and are solving some other way,
// or your starting point is rowIndex, column. Done.
return new Coordinate(rowIndex, column);
}
Update #2
In response to #matteok's request for how to update the nextAvailableRowByWidth array:
OK, so you've just placed a new photo of height H and width W at row R. Any elements in the array which are less than R don't change (because this change didn't affect their row, so if there were 3 consecutive spaces available in the row before placing the photo, there are still 3 consecutive spaces available in it after). Every element which is in the range (R, R+H) needs to be checked, because it might have been affected. Let's postulate a method maxConsecutiveBlocksInRow() - because that's easy to write, right?
public void updateAvailableAfterPlacing(int W, int H, int R) {
for (int i = 0; i < nextAvailableRowByWidth.length; i++) {
if (nextAvailableRowByWidth[i] < R) {
continue;
}
int r = R;
while (maxConsecutiveBlocksInRow(r) < i + 1) {
r++;
}
nextAvailableRowByWidth[i] = r;
}
}
I think that should do it.
How about a matrix (your example would be 5x9) where each cell has a value representing the distance from the top left corner (for instance (row+1)*(column+1) [+1 is only necessary if your first row and value are 0]). In this matrix you look for the area which has the lowest value (when summing up the values of empty cells).
A 2nd matrix (or a 3rd dimension of the first matrix) stores the status of each cell.
edit:
int[][] grid = new int[9][5];
int[] filledRows = new int [9];
int photowidth = 2;
int photoheight = 1;
int emptyRowCounter = 0;
boolean photoFits = true;
for(int i = 0; i < grid.length; i++){
for(int m = 0; m < filledRows.length; m++){
if(filledRows[m]-(photoHeight-1) > i || filledRows[m]+(photoHeight-1) < i){
for(int j = 0; j < grid[i].length; j++){
if(grid[i][j] == 0){
for(int k = 0; k < photowidth; k++){
for(int l = 0; k < photoheight){
if(grid[i+l][j+k]!=0){
photoFits = false;
}
}
}
} else{
emptyRowCounter++;
}
}
if(photoFits){
//place Photo at i,j
}
if(emptyRowCounter == 5){
filledRows[i] = 1;
}
}
}
}
In the gif you have above, it turned out nicely that there was a photo (5) that could fit into the gap under (1) and to the left of (2). My intuition suggests we want to avoid creating gaps like that. Here is an idea that should avoid these gaps.
Maintain a list of "open regions", where an open region has a int leftBoundary, an int topBoundary, and an optional int bottomBoundary. The first open region is just the whole grid (leftBoundary:0, topBoundary: 0, bottom: null).
Sort the photos by height, breaking ties by width.
Until you have placed all photos:
Choose the tallest photo (in case of ties, choose the widest of the tallest photos). Find the first open region it can fit in (such that grid.Width - region.leftBoundary >= photo.Width). Place the photo at the top left of this region. When you place this photo, it may span the entire width or height of the region.
If it spans both the width and the height of the region, the region is filled! Remove this region from the list of open regions.
If it spans the width, but not the height, add the photo's height to the topBoundary of the region.
If it spans the height, but not the width, add the photo's width to the leftBoundary of the region.
If it does not span the height or width of the boundary, we are going to conceptually divide this region into two: one region will cover the space directly to the right of this photo (call it rightRegion), and the other region will cover the space below this region (call it belowRegion).
rightRegion = {
leftBoundary = parentRegion.leftBoundary + photo.width,
topBoundary = parentRegion.topBoundary,
bottomBoundary = parentRegion.topBoundary + photo.height
}
belowRegion = {
leftBoundary = 0,
topBoundary = parentRegion.topBoundary + photo.height,
bottomBoundary = parentRegion.bottomBoundary
}
Replace the current region in the list of open regions with rightRegion, and insert belowRegion directly after rightRegion.
You can visualize how this algorithm would work on your example: First, it would sort the photos: (2,3,4,1,5).
It considers 2, which fits into the first region (the whole grid). When it places 2 at the top left, it splits that region into the space directly to the right of 2, and the space below 2.
Then, it considers 3. It considers the open regions in turn. The first open region is to the right of 2. 3 fits there, so that's where it goes. It spans the width of the region, so the region's topBoundary gets adjusted downward.
Then, it considers 4. It again fits in the first open region, so it places 4 there. 4 spans the height of the region, so the region's leftBoundary gets adjusted rightward.
Then, 1 gets put in the 1x1 gap to the right of 4, filling its region. Finally, 5 gets put just below 2.
I have a list of points XY and I want to group them by a given distance, let's say all the points that are at x distance between them should be grouped in different list.
Basically if I have A=(0,0), B=(0,1), C=(0,2), I want to group all points that have a maxDistance of 1, in order to obtain :[[A,B],[C]] ;
I didn't really understand your question, so I'm not really sure how you want to do the grouping, but this might start you off in the right direction, at least.
(Written in VB, but near-identical in C# - You also didn't state your language preference):
Dim MyPoints As New List(Of Point)
MyPoints.Add(New Point(0, 0))
MyPoints.Add(New Point(0, 1))
MyPoints.Add(New Point(0, 2))
Dim query = From pt1 In MyPoints
From pt2 In MyPoints
Where Not (pt1.Equals(pt2))
Select New With {.pt1 = pt1, .pt2 = pt2, .dist = Math.Sqrt((pt1.X - pt2.X) ^ 2 + (pt1.Y - pt2.Y) ^ 2)}
What are you trying to do is named clustering, which means grouping a set of data (two dimensional points in your case) into a set of groups with some characteristics (a given distance between points). I strongly recommend to read link provided above to understand it better. You might be interested in two types of clustering:
hierarchical clustering, which creates groups based on distance connectivity,
centroids, which creates groups "surrounding" centers of groups
It all depends how much data you have. For small sets you can try to implement some simple algorithms by yourself. For bigger data, I would prefer to use third-party library like Numl which contains methods for both abovementioned types.
Here is an example code of clustering using Numl. Given class:
class Point
{
[Feature]
public double X { get; set; }
[Feature]
public double Y { get; set; }
public Point(double X, double Y)
{
this.X = X;
this.Y = Y;
}
public override string ToString()
{
return string.Format("({0}; {1})", X, Y);
}
}
you can write:
var model = new HClusterModel();
var desc = Descriptor.Create<Point>();
var linker = new CentroidLinker(new EuclidianDistance());
var data = new List<Point>() { new Point(0.0, 1.0),
new Point(0.0, 2.0),
new Point (10.0, 0.0) };
var result = model.Generate(desc, data, linker);
foreach (var cluster in result.Children)
{
Console.WriteLine("Cluster:");
Console.WriteLine(string.Join(", ", cluster.Members.OfType<Point>()));
}
which results in:
I had a stab at it, although this probably isn't a fantastically efficient way to do things; the link in Konrad's answer seems like a good place to explore.
I'm not entirely sure how you're defining "within range", so I assumed a simple distance calculation.
// Set up some points
List<Point> Points = new List<Point>();
Points.Add(new Point(0, 0));
Points.Add(new Point(0, 1));
Points.Add(new Point(0, 2));
// Distance
int maxDistance = 1;
// Replace as appropriate
Func<Point, Point, int, bool> myDistanceFunction = delegate(Point p1, Point p2, int range)
{
// Same coordinate.
if (p1 == p2)
return true;
int xDelta = p1.X - p2.X;
int yDelta = p1.Y - p2.Y;
double distance = Math.Sqrt(xDelta * xDelta + yDelta * yDelta);
return (distance <= range);
};
// Loop through all points and calculate distance to all other points.
var Results = Points.Select(firstPoint => new
{
TargetPoint = firstPoint,
PointsInRange = Points
.Where(secondPoint =>
(secondPoint != firstPoint) && // Will you allow same coordinates?
myDistanceFunction(secondPoint, firstPoint, maxDistance))
});
// Spit the results out.
foreach (var result in Results)
{
Console.WriteLine("Point {0} - Points within {1} unit(s):", result.TargetPoint, maxDistance);
foreach (var point in result.PointsInRange)
{
Console.WriteLine("\t{0}", point);
}
}
Output:
Point {X=0,Y=0} - Points within 1 unit(s):
{X=0,Y=1}
Point {X=0,Y=1} - Points within 1 unit(s):
{X=0,Y=0}
{X=0,Y=2}
Point {X=0,Y=2} - Points within 1 unit(s):
{X=0,Y=1}
There's room for improvement e.g. it doesn't feel smart to calculate distances for pairs of points twice, and I'm not if you'll allow duplicate coordinates, but there might be something of use in there.
You could also write the distance function as a lamba expression, although I'm not sure it's clearer.
Func<Point, Point, int, bool> myDistanceFunction =
(
(p1, p2, range) => Math.Sqrt(
((p1.X - p2.X) * (p1.X - p2.X)) +
((p1.Y - p2.Y) * (p1.Y - p2.Y))
) <= range
);
Sorry to all, i made a post not so clear, basically im using c# and i was excluding clustering for specific purpose, let's say i have some points and their ids and i need to "cluster them", keeping information about ids , then simply made a medium point on X axis, cos im interested only in grouping by that position attribute.
At the end, points are maximum 10, and keeping information about ids is very important to know who is where, so i thought to collect ids of points close enough and then use that list of list of coordinates to make out results, did it very raw, cos im in a rush, but fully opened to further implementation, just im not able to use linq :)
So i used something like this :
// class to hold information
public class userObject{
public string id;
public Vector3D position=Vector3D.Zero;
public userObject(string Id, Vector3D Position){
id=Id;
position=Position;
}
}
// list of grouped ids (nanocluster :)
public Dictionary<int, List<userObject>> slots ;
private void forceCheck(){
// create list of object from incoming coordinates (ids and point vector3d)
List<userObject> users=new List<userObject>();
for(int a=0;a<FId_In.SliceCount;a++){
userObject uo=new userObject(FId_In[a],FPositions_In[a]);
users.Add(uo);
}
// Clean result, this is different in another version im working on
slots =new Dictionary<int,List<userObject>>();
// check for close points ( a couple of lines should be changed to achieve a real clustring, but this way i can control all points will not create an horizontal cluster, told u raw mode on
for(int k=0;k<users.Count;k++){
List<userObject> matches=new List<userObject>();
// Check if ids is already registered in one slot
int isInSlot=checkIdInSlots(users[k].id);
if(isInSlot==-1){
matches.Add(users[k]);
for(int j=k+1;j<users.Count;j++){
// call a function to check x distance, but can use full vector3d when needed
if(checkClose(users[k].position,users[j].position,FXThreshold_In[0])){
matches.Add(users[j]);
}
}
// finally add entry with grouped ids....sure all this is a line of linq :D
addNewSlot(matches);
}
}
}
WOuld be nice to understand better how linq can be used to achive same result, sure can be more robust, thank you all :)