Quantcast
Channel: Faster way to pick pairs of integer coordinates from a "region" - Mathematica Stack Exchange
Viewing all articles
Browse latest Browse all 6

Faster way to pick pairs of integer coordinates from a "region"

$
0
0

I am trying to find a faster way to do this than what I have put together or by looping through a bunch of points.

I want to select all pairs of integer points ((x1,y1),(x2,y2)) such that:

  1. Point (x1,y1) is at a specified distance r1 from center point (xc,yc).
  2. Point (x2,y2) is farther away from the center point than the point (x1,y1) is.
  3. Points (x1,y1) and (x2,y2) are separated by a specified distance r2.
  4. These points will be referring to 512X512 images, so each x and y value is limited to be between 1 and 512. Also because of this, I am having distances r1 and r2 only be integers, and I round any distances calculated between two points to the nearest integer.

Conceptually, for each point (x1, y1) that is a distance r1 from the center point, I am selecting all points that are a distance r2 from (x1, y1) and farther away from the center point. In the end, I want a list of pairs of points ((x1,y1),(x2,y2)). Here is my function:

points[r1_, r2_] := Select[{x1, y1, x2, y2} /.   FindInstance[    1 <= x1 <= 512 &&     1 <= y1 <= 512 &&     1 <= x2 <= 512 &&     1 <= y2 <= 512 &&     Round[Sqrt[(x1 - xc)^2 + (y1 - yc)^2]] == r1 &&     r1 <= Round[Sqrt[(x2 - xc)^2 + (y2 - yc)^2]] <= (r1 + r2),    {x1, y1, x2, y2}, Integers, 512^2],  Round[Sqrt[(#[[1]] - #[[3]])^2 + (#[[2]] - #[[4]])^2]] == r2 &]

I put condition 3 in the Select function rather than in the FindInstance function because the FindInstance function couldn't handle it. 512^2 maximum number of instances is a lot larger than I need, but it seems like having that number be too large doesn't hurt anything.

My code works, it is just very slow. The smallest r1 value I am using is 197, and r2 starts at 0 (r1 and r2 are limited to integers as well). My center point for now is at (229,256). I am sure there is an easier way to do this that is also faster. Any suggestions?


UPDATE:

Thanks to Michael E2 and Henrik Schumacher for helping with a faster solution. Although the below answers were not what I was looking for specifically, I was able to use them to obtain what I was looking for. Here is what I have put together:

pointFind[r_, c_] :=   ArrayPad[(SparseArray@DiskMatrix[r]*       SparseArray@(1 - DiskMatrix[r - 1, 2*r + 1])) // Transpose,     Transpose@{c - r - 1, 512 - c - r}]["NonzeroPositions"];points[r1_, r2_,    c_] := ({#,        pointFind[r2, #]} /. {x_?NumericQ, y_?NumericQ} /;         Round[Norm[{x, y} - c]] < r1 -> Nothing) & /@    pointFind[r1, c];

Here is an example of the result:

test = points[20, 10, {100, 100}];Show[ ListPlot[test[[;; , 1]],  PlotRange -> {{65, 125}, {65, 125}},  PlotStyle -> Black], ListPlot[test[[1, 2]],  PlotStyle -> Red], Graphics[{Red, Point[test[[1, 1]]]}], AspectRatio -> 1]

I have plotted all points a rounded distance r1 (20) from the center, and then I picked one such point and show all of the points a distance r2 (10) from the first point that are farther from the center.

enter image description here

This works much much faster than what I had before. Thanks for everything!


Viewing all articles
Browse latest Browse all 6

Latest Images

Trending Articles





Latest Images