I hope you have a nice day, so here is my problem: I'm trying to find the middle point of most populated positions (X/Y) on a map but i'm stuck and i can't find a good and effective way to do it.
To find this position i've access to an collection of entities (and these entities have a Position property (which is a Vector2D) and map size
public readonly struct Vector2D
{
private static readonly double Sqrt = Math.Sqrt(2);
private static readonly Random Random = new Random();
public static Vector2D Zero { get; } = new Vector2D();
public int X { get; }
public int Y { get; }
public Vector2D(int x, int y)
{
X = x;
Y = y;
}
public Vector2D GetDistanceTo(Vector2D vector2D) => new Vector2D(Math.Abs(vector2D.X - X), Math.Abs(vector2D.Y - Y));
public int GetDistance(Vector2D destination)
{
int x = Math.Abs(X - destination.X);
int y = Math.Abs(Y - destination.Y);
int min = Math.Min(x, y);
int max = Math.Max(x, y);
return (int)(min * Sqrt + max - min);
}
public bool IsInRange(Vector2D position, int range)
{
int dx = Math.Abs(X - position.X);
int dy = Math.Abs(Y - position.Y);
return dx <= range && dy <= range && dx + dy <= range + range / 2;
}
public override string ToString() => $"{X}/{Y}";
}
That's the only thing i've tried
public Vector2D FindMostPopulatedPosition()
{
IEnumerable<Vector2D> positions = Entities.Select(x => x.Position);
return new Vector2D((int)positions.Average(x => x.X), (int)positions.Average(x => x.Y));
}
Here is some example images
Red dot: All entities
Blue dot: The position i'm looking for
Thanks for reading (and for your help)
Related
This question already has answers here:
Changing the value of an element in a list of structs
(7 answers)
Closed 10 months ago.
In the following program, I am unable to modify individual list items:
public class Program
{
static void Main(string[] args)
{
List<Point2d> list = new List<Point2d>();
list.Add(new Point2d(0, 0));
list.Add(new Point2d(0, 1));
foreach (Point2d item in list)
{
item.Print();
}
Point2d p = list[0];
p.Set(-1, -1);
foreach (Point2d item in list)
{
item.Print();
}
Console.ReadKey();
}
}
Output:
(0,0) (0,1) (0,0) (0,1)
My expected output was:
(0,0) (0,1) (-1,-1) (0,1)
What am I doing incorrectly?
Relevant source code:
public struct Point2d : IEquatable<Point2d>
{
public double X { get; set; }
public double Y { get; set; }
#region constructor
public Point2d(double x, double y)
{
X = x;
Y = y;
}
#endregion
public void Print()
{
Console.Write("(");
Console.Write(X);
Console.Write(",");
Console.Write(Y);
Console.Write(") ");
}
public void Set(double x, double y)
{
X = x;
Y = y;
}
public double GetDistance(Point2d otherPoint)
{
return Math.Sqrt(GetSquaredDistance(otherPoint));
}
public double GetSquaredDistance(Point2d otherPoint)
{
return ((otherPoint.X - X) * (otherPoint.X - X))
+ ((otherPoint.Y - Y) * (otherPoint.Y - Y));
}
public Point2d GetTranslated(Point2d center)
{
return new Point2d(X + center.X, Y + center.Y);
}
#region override string ToString()
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append("(" + X + " , " + Y + ")");
return sb.ToString();
}
#endregion
#region equality comparison implementations
public override bool Equals(object other)
{
if (!(other is Point2d)) return false;
return Equals((Point2d)other);
}
public bool Equals(Point2d other)
{
return X == other.X && Y == other.Y;
}
public override int GetHashCode()
{
return (int)Math.Round(Y * 31.0 + X, 0); // 31 = some prime number
}
public static bool operator ==(Point2d a1, Point2d a2)
{
return a1.Equals(a2);
}
public static bool operator !=(Point2d a1, Point2d a2)
{
return !a1.Equals(a2);
}
#endregion
}
Point2d is a struct so when you did Point2d p = list[0]; you made a totally separate copy of the object. Your set only changed the copy not the original, you either need to make Point2d a class or add a list[0] = p; after the set.
Bugs like this is why it is recommended to make structs immutable and have no Set methods.
I have a simple class point
public class point
{
private double X;
private double Y;
public double x
{
get { return X; }
set { X = value; }
}
public double y
{
get { return Y; }
set { Y = value; }
}
public point() { }
public point(double _x , double _y)
{
x = _x;
y = _y;
}
}
and I'm trying to use this loop to get unique values
for (int i = 0; i < dim.Count; i++)
{
if (dimO[i].x == dim[i].x && dimO[i].y == dim[i].y)
{
continue;
}
else
{
dimO.Add(dim[i]);
}
}
but I got an " out of index" exception .. what's wrong here?
You should override Equals and GetHashCode if you want to compare a point by its x and y.
public override bool Equals(object obj)
{
var point2 = obj as Point;
return point2 != null && point2.x == x && point2.y == y;
}
public override int GetHashCode()
{
unchecked // Overflow is fine, just wrap
{
int hash = 17;
// Suitable nullity checks etc, of course :)
hash = hash * 23 + X.GetHashCode();
hash = hash * 23 + Y.GetHashCode();
return hash;
}
}
I take the hash code function here.
Now you could have a list of unique points by using
var dim0 = (new HashSet(dim)).ToList();
// linq
var dim0 = dim.Distinct().ToList();
Or if you want to use for loop
var dim0 = new List<Point>();
foreach(var p in dim){
if(!dim0.Contains(p)){
dim0.Add(p);
}
}
Your solution is not working because dim0 does not initially have any point.
Error is
"A readonly field cannot be assigned to(...)"
I must return vector, which equal sum of two another vectors (vector and vector1)
ReadOnlyVector has readonly fields X and Y. How can I initialize them and return new ReadOnlyVector?
public class ReadOnlyVector
{
public readonly double X;
public readonly double Y;
public ReadOnlyVector(int x, int y)
{
X = x;
Y = y;
}
public ReadOnlyVector Add (ReadOnlyVector vector, ReadOnlyVector vector1)
{
return new ReadOnlyVector {X = vector.X + vector1.X, Y = vector.Y + vector1.Y}
}
}
Use the constructor. You're currently using object initializer syntax.
public ReadOnlyVector Add (ReadOnlyVector vector, ReadOnlyVector vector1)
{
return new ReadOnlyVector(vector.X + vector1.X, vector.Y + vector1.Y);
}
Hi this is my problem I have an array of points P(x,y) and I need to sort these points from the furthest to the closest, respect to the barycenter of a Polygon, this what I have done (I know this is a bad solution ) how can I do a better and aboveall faster solution?
List<C2DPoint> OrderedGripperPoints = new List<C2DPoint> { };
while(myGripperPoints.Count!=0)
{
double dist=-1;
int index=-1;
for(int k=0;k<myGripperPoints.Count;k++)
{
if(myGripperPoints[k].Distance(WorkScrap.GetCentroid())>=dist)
{
index = k;
dist = myGripperPoints[k].Distance(WorkScrap.GetCentroid());
}
}
OrderedGripperPoints.Add(myGripperPoints[index]);
myGripperPoints.RemoveAt(index);
}
Thanks for your answers...
Use Linq to order points.
using System.Linq;
var sortedList = myGripperPoints.OrderBy(p => p.Distance(WorkScrap.GetCentroid())).ToList();
Consider the following code:
Point Class (assumed class definition)
class Point
{
public int X { get; set;}
public int Y { get; set;}
}
Point EqualityComparer
class PointEqualityComparer : IEqualityComparer<Point>
{
public bool Equals(Point p1, Point p2) { return p1.X == p2.X && p1.Y == p2.Y; }
public int GetHashCode(Point p) { return p.X.GetHashCode() *31 + p.Y.GetHashCode()*23; }
}
Create a Dictionary with Point as Key and Distance as value (assuming integer):
Dictionary<Point,int> pointDictionary =
new Dictionary<Point, int>(new PointEqualityComparer());
Add Points as follows:
Point p = new Point {X = <value>, Y = <value>};
pointDictionary.Add(p,p.Distance(WorkScrap.GetCentroid()));
Order by Distance as follows:
pointDictionary.OrderByDescending(x => x.Value).ToList();
Ordering is done by Distance in Descending order as expected
Result would be List<KeyValuePair<Point,int>>, where elements are in Descending order
I have a linear array which I need to reshape as of a stack of 2D data. In this particular case, the stack only contains one element so the output should be an array with dimensions (height, width, 1).
This is related to a previous question, where I was asking about the same operation in the other direction (3D to 1D).
What is the fastest way to map this data to a 3D array?
I was planning to take the following approach:
public static byte[, ,] ToBuffer3D<TDepth>(this byte[] buffer, int w, int h)
{
byte[, ,] buff3D = new byte[h, w, 1];
for (int i = 0; i < buffer.Length; i++)
{
buff3D[(int)Math.Floor(i / (double)w), i % w, 0] = buffer[i];
}
return buff3D;
}
But it seems like it might be possible to take advantage of how the data is already stored in memory to copy more than one element at a time. Is there some other mapping approach that could be employed in C#?
This is likely to be somewhat faster:
public static byte[,,] ToBuffer3Da(this byte[] buffer, int w, int h)
{
byte[,,] buff3D = new byte[h, w, 1];
Buffer.BlockCopy(buffer, 0, buff3D, 0, h*w);
return buff3D;
}
if you use the base class and implementation defined below, you have a class that supports both linear and dimensional indexing at the same time. No conversion or copying is necessary.
Use it like this,
var matrix = new DecomposedMatrix<byte>(10, 10, 10)
foreach(var b int matrix)
{
...
}
for (var i = 0; i < matrix.Count; i++)
{
...
var item = matrix[i];
...
}
for (var x = 0; x < matrix.H; x++)
for (var y = 0; y < matrix.W; y++)
for (var z = 0; z < matrix.D; z++)
{
...
var item = matrix[x, y, z];
...
}
classes follow ...
public abstract class DecomposedMatrix
{
private readonly int h;
private readonly int w;
private readonly int d;
protected DecomposedMatrix(int h, int w, int d)
{
this.h = h;
this.w = w;
this.d = d;
}
public int W
{
get
{
return this.w;
}
}
public int D
{
get
{
return this.d;
}
}
public int H
{
get
{
return this.h;
}
}
protected int DereferenceCoordinates(int x, int y, int z)
{
if (x >= this.H || y >= this.W || z >= this.D)
{
throw new IndexOutOfRangeException();
}
if (x < 0 || y < 0 || z < 0)
{
throw new IndexOutOfRangeException();
}
return z + (y * this.D) + (x * this.W * this.D);
}
}
and the implementation
public class DecomposedMatrix<T> : DecomposedMatrix, IReadOnlyList<T>
{
private readonly IList<T> data;
public DecomposedMatrix(int h, int w, int d)
: base(h, w, d)
{
this.data = new T[h * w * d];
}
public T this[int index]
{
get
{
return this.data[index];
}
set
{
this.data[index] = value;
}
}
public T this[int x, int y, int z]
{
get
{
return this.data[this.DereferenceCoordinates(x, y, z)];
}
set
{
this.data[this.DereferenceCoordinates(x, y, z)] = value;
}
}
public int Count
{
get
{
return this.data.Count;
}
}
public IEnumerator<T> GetEnumerator()
{
return this.data.GetEnumerator();
}
public IEnumerator IEnumerable.GetEnumerator()
{
return this.data.GetEnumerator();
}
}