Problems with double array? - c#

I am required to create a program which reads in data from a .cvs file, and use these (x, y and z) values for a series of calculations.
I read in the file as a string, and then split this into 3 smaller strings for x, y and z.
The x, y and z coordinates represents the x and y coordinates of the contours of a lake, and the depth (z).
One of the calculations which I have to do, is to calculate the surface area of the lake, using the formula (x[i]*y[i+1])-(x[i+1]*y[i]), where z(depth) = 0.
I can get my code to run perfectly, up until the x[i+1] and y[i+1], where it keeps giving me a value of 0.
Can someone please tell me how to fix this?
Here is my code;
{
string[] ss = File.ReadAllLines(#"C:File.csv");
for (int i = 1; i < ss.Length; i++)
{
string[] valuesAsString = ss[i].Split(new char[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries);
double[] X = new double[valuesAsString.Length];
double[] Y = new double[valuesAsString.Length];
double[] Z = new double[valuesAsString.Length];
for (int n = 0; n < 1; n++)
{
X[n] = double.Parse(valuesAsString[0]);
Y[n] = double.Parse(valuesAsString[1]);
}
do
{
double SurfaceArea = (X[n] * Y[n + 1]) - (X[n + 1] * Y[n]);
Console.WriteLine(SurfaceArea);
}
while (Z[n] == 0);
}
}

Ok, im not sure if i got it right, so you if you would take a look to what i did and tell me if its of any help.
After reviewng it a little i came up with the following:
A class for the values
public class ValueXyz
{
public double X { get; set; }
public double Y { get; set; }
public int Z { get; set; }
}
A class to manange the calculation:
public class SurfaceCalculator
{
private ValueXyz[] _valuesXyz;
private double _surface;
private readonly string _textWithValues;
public SurfaceCalculator(string textWithValues)
{
_textWithValues = textWithValues;
SetValuesToCalculate();
}
public double Surface
{
get { return _surface; }
}
public void CalculateSurface()
{
for (var i = 0; i < _valuesXyz.Length; i++)
{
if (_valuesXyz[i].Z == 0)
_surface = (_valuesXyz[i].X*_valuesXyz[i + 1].Y) - (_valuesXyz[i + 1].X*_valuesXyz[i].Y);
}
}
private void SetValuesToCalculate()
{
var valuesXyz = _textWithValues.Split(' ');
_valuesXyz = valuesXyz.Select(item => new ValueXyz
{
X = Convert.ToDouble(item.Split(',')[0]),
Y = Convert.ToDouble(item.Split(',')[1]),
Z = Convert.ToInt32(item.Split(',')[2])
}).ToArray();
}
}
So now your client code could do somethin like:
[TestMethod]
public void TestSurfaceCalculatorGetsAValue()
{
//var textWithValues = File.ReadAllText(#"C:File.csv");
var textWithValues = "424.26,424.26,0 589.43,231.46,0 720.81,14.22,1";
var calculator = new SurfaceCalculator(textWithValues);
calculator.CalculateSurface();
Assert.IsNotNull(calculator.Surface);
}
I'm not very sure i got the idea correct of how to implement the formula, but i just wanted to expose an alternative you can use, you can never have to many ways of doing one thing :).
Cheers.
By the way part of the intent i had, was not tying up your funcionality to the csv in case your source for the text in the future would change.

Step through your code in the debugger. Pay special attention to tbe behavior of the line
for (int n = 0; n < 1; n++)
This loop will execute how many times? What will the value of n be during each iteration through the loop?

Well, one thing i noticed is when you're setting your X, Y, Z vars, you're setting it to the Length of the array object instead of it's value - is that intentional?
Put a debug break on the line with:
double SurfaceArea = (X[n] * Y[n + 1]) - (X[n + 1] * Y[n]);
and check the datatype of "X", "Y" and "Z"
I've had problems in the past where it tries to calculate them as strings (because it took it out of the data source as strings). I ended up fixing it by adding CInt() to each of the variables (or Convert.ToInt32();).
Hope this helps.

As this looks like it might be a homework problem, I am trying not to give a direct solution in my answer, but I see a number of questionable parts of your code that you should examine.
Why are X, Y, Z arrays? You are creating a new array each time through the outer loop, setting the length of the array to the number of elements in the line, then only assigning a value to one element of X and Y, and never assigning Z to anything.
As phoog suggests in his answer, what is the purpose of: for (int n = 0; n < 1; n++)?
What are you trying to accomplish with the do-while loop? As it has been mentioned in the comments by Mr Skeet, X[n], Y[n], Z[n] don't exist because n does not exist outside of the loop it is declared for. Even if it did exist Z[n] will always be zero because you never assign anything to the Z array after it is initialized, so the do-while loop will run forever.

Related

Checking distance between items of list taking too much time. Is there a way to make it faster?

I'm following Sebastian Lague's Procedural Landmass Generation tutorial . He is generating landmass' color by height value. But I want to separate landmass to a array or list as areas by their color. Because the way Sebastian use generates too many water or mountain areas so I want to make them less. I tried to edit the code of him but the code I made tooks 2-3 minutes to separate. Does anyone have idea to make it faster?
The class I use to seperate regions and the areas in every region:
public class Positions
{
public int regionID;
public int areaID;
public int x;
public float y;
public int z;
}
List<Positions> positions = new List<Positions>();
The code I try to find and list them:
for (int y = 0; y<mapChunkSize; y++)
{
for (int x = 0; x<mapChunkSize; x++)
{
float currentHeight = noiseMap[x, y];
for (int i = 0; i<regions.Length; i++)
{
if (currentHeight <= regions[i].height)
{
int areaID = 0;
if(positions.Where(x => x.regionID == i).Count() != 0)
{
areaID = getNeighourIndex(i, x, y);
}
Positions p = new Positions { regionID = i, areaID = areaID, x = x, y = noiseMap[x, y], z = y };
positions.Add(p);
break;
}
}
}
}
int getNeighourIndex(int regionID, int x, int y)
{
List<Positions> pos = positions.Where(x => x.regionID == regionID).ToList();
if (pos.Where(q => Vector2Int.Distance(new Vector2Int(q.x, q.z), new Vector2Int(x, y)) <= 1).Count() > 0)
return pos.Find(q => Vector2Int.Distance(new Vector2Int(q.x, q.z), new Vector2Int(x, y)) <= 1).areaID;
return (pos.Select(q => q.areaID).OrderBy(x => x).LastOrDefault()) + 1;
}
As always when doing optimizing, the first step should be to measure, ideally with a profiler since this can hint at what it is that takes most time.
But I would guess that the majority of the time is spent in positions.Where(x => x.regionID == regionID). To solve this you could use a multi value dictionary, i.e. a dictionary where each key can map to multiple values. It is fairly easy to make your own wrapper around a Dictionary<TKey, List<TValue>>, or you could use one from Microsoft.Experimental.Collections.
You could also consider using a hierarchical search structure for the points, like a kd-tree, quad-tree or similar.
Also, if performance is of high importance, using LINQ is likely not the best option. LINQ is convenient, but the abstraction adds some overhead. In most cases this overhead is irrelevant, but in tight loops like this it may very well be a significant factor.

How to initialize an array by default in a single row C#?

I have this line of code and I want under certain conditions to initialize the whole array to true in one line,
How can I do that?
public bool[,] OptionalHours { get; set; } = new bool[6, 24];
Technically, this would do it:
for(int i = 0, x = _optionalHours.GetLength(0), y = _optionalHours.GetLength(1); i < x * y; _optionalHours[i/y, i%y] = true, i++);
It gets shorter if you're happy to fix the 6 and 24 and jiggle some ops around:
for(int i = 6*24; --i >= 0; _optionalHours[i/24, i%24] = true);
Would you use it though? Well; could you understand it immediately and are happy to explain it to anyone else who asks? If yes, then use it. If no then go for something more expected:
for(int x = _optionalHours.GetUpperBound(0); x >= 0; x--)
for(int y = _optionalHours.GetUpperBound(1); y >= 0; y--)
_optionalHours[x, y] = true;
There aren't any prizes at code review for the person who wrote the most WTF..
It's also quite a small array (hours in a week?) so you could also init it with this one-liner that's easier to figure:
var _optionalHours = new[,]{
{true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true},
{true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true},
{true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true},
{true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true},
{true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true},
{true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true}
};
As an idle curiosity, you could also do it "mathematically", wrap the array in a class that will invert the bools if some condition is set:
public class SixByTwentyFour
{
private bool[,] _optionalHours { get; set; } = new bool[6, 24];
public bool CertainCondition;
public bool this[int x, int y]{
get => _optionalHours[x,y] ^ CertainCondition;
set { _optionalHours[x,y] = value ^ CertainCondition; }
}
}
You can access an instance of this class as though it were a 2D array:
var sbtf = new SixByTwentyFour();
sbtf.CertainCondition = true;
Console.WriteLine(sbtf[1,1]); //prints true
This one doesn't give you a "Properties should not return arrays" warning if you have an analayzer enabled that looks for such :D

Wrapping C# primitives in struct performance implications

I am writing some code on geometry processing, delaunay triangulation to be more specific, and I need it to be fast, so I use simple arrays of primitive as data structure to represent my triangulation information, here is a sample of it
private readonly float2[] points;
private readonly int[] pointsHalfEdgeStartCount;
private readonly int[] pointsIncomingHalfEdgeIndexes;
So let's say I want to iterate fast through all the incoming half-edge of the point of index p, I just do this using the precomputed arrays:
int count = pointsHalfEdgeStartCount[p * 2 + 1];
for (int i = 0; i < count; i++)
{
var e = pointsIncomingHalfEdgeIndexes[pointsHalfEdgeStartCount[p * 2] + i]
}
// pointsHalfEdgeStartCount[p * 2] is the start index
And this is fast enought, but does not feel safe or very clear. So I had the idea of wrapping my index into struct to make it clearer while retaining the performance, somthing like that:
public readonly struct Point
{
public readonly int index;
public readonly DelaunayTriangulation delaunay
public Point(int index, DelaunayTriangulation delaunay)
{
this.index = index;
this.delaunay = delaunay;
}
public int GetIncomingHalfEdgeCount() => delaunay.pointsEdgeStartCount[index * 2 + 1];
public HalfEdge GetIncomingHalfEdge(int i)
{
return new HalfEdge(
delaunay,
delaunay.pointsIncomingHalfEdgeIndexes[delaunay.pointsEdgeStartCount[index * 2] + i]
);
}
//... other methods
}
Then I can just do so:
int count = p.GetIncomingHalfEdgeCount();
for (int i = 0; i < count; i++)
{
var e = p.GetIncomingHalfEdge(i);
}
However it was kind of killing my performance, being a lot slower (around 10 times) on a benchmark I did, iterating over all the points and iterating over all their incoming half-edge. I guess because storing a reference to the delaunay triangulaiton in each point struct was an obvious waste and slowed down all the operations involving points, having twice the amount of data to move.
I could make the DelaunayTriangulation a static class but it was not practical for other reasons, so I did that:
public readonly struct Point
{
public readonly int index;
public Point(int index) => this.index = index;
public int GetIncomingHalfEdgeCount(DelaunayTriangulation delaunay) => delaunay.pointsEdgeStartCount[index * 2 + 1];
public HalfEdge GetIncomingHalfEdge(DelaunayTriangulation delaunay, int i)
{
return new HalfEdge(
delaunay.pointsIncomingHalfEdgeIndexes[delaunay.pointsEdgeStartCount[index * 2] + i]
);
}
//... other methods
}
I can just do so:
int count = p.GetIncomingHalfEdgeCount(delaunay);
for (int i = 0; i < count; i++)
{
var e = p.GetIncomingHalfEdge(delaunay, i);
}
It was quite a lot faster, but still 2.5 times slower than the first method using simple int. I wondered if it could be because I was getting int in the first method while I got HalfEdge struct in the other methods (A struct similar to the Point struct, contains only an index as data and a couple of methods), and difference between plain int and the faster struct vanished when I used the e int to instantiate a new HalfEdge struct. Though I am not sure why is that so costly.Weirder still, I explored for clarity sake the option of wrinting the method inside the Delaunay class instead of the Point struct:
// In the DelaunayTriangulation class:
public int GetPointIncomingHalfEdgeCount(Point p) => pointsEdgeStartCount[p.index * 2 + 1];
public HalfEdge GetPointIncomingHalfEdge(Point p, int i)
{
return new HalfEdge(
pointsIncomingHalfEdgeIndexes[pointsEdgeStartCount[p.index * 2] + i]
);
}
And I used it like this:
int count = delaunay.GetPointIncomingHalfEdgeCount(p);
for (int i = 0; i < count; i++)
{
var e = delaunay.GetPointIncomingHalfEdge(p, i);
}
And it was 3 times slower than the previous method! I have no idea why.
I tried to use disassembly to see what machine code was generated but I failed to do so (I am working with Unity3D). Am I condemned to rely on plain int in arrays and sane variable naming and to renounce on trying to have some compile-time type checking (is this int really a point index ?)
I am not even bringing up other questions such as, why it is even slower when I try to use IEnumerable types with yields like so:
public IEnumerable<int> GetPointIncomingHalfEdges(Point p)
{
int start = pointsEdgeStartCount[p.index * 2]; // this should be a slight optimization right ?
int count = pointsEdgeStartCount[p.index * 2 + 1];
for (int i = 0; i < count; i++)
{
yield pointsIncomingHalfEdgeIndexes[start + i];
}
}
I have added a compiler directive for aggressive inlining and it seems to make up for the discrepencies in time! For some reason the compiler fails to inline correctly for:
var e = delaunay.GetPointIncomingHalfEdge(p, i);
While it managed to do so with
var e = p.GetIncomingHalfEdge(delaunay, i);
Why ? I do not know. However It would be far easier if I was able to see how the code is compiled and I could not find how to do that. I will search that, maybe open another question and if I find a better explaination I will come back!

Point Classification in a set of Bounding Boxes

I have a set of bounding boxes(rectangular) in a 3D space. The bounds of each box are computed and stored in a dictionary named "RegionBounds". Also, a set of points are populated in a List named "PointsToCategorize" Given a point(x,y,z) coordinates from the List populated and a bounding box to be checked in, i can check if the point is inside the box or not. The problem is, this is a big dataset. The number of points to be checked are like 1000 and the no of bounding boxes are like 250-300. So, if i loop through each bounding box for each given point; the total time it takes is like 5-6 minutes. Is there any efficient method that would do the process quicker ? If possible, a small code to do so would be great
public struct iBounds {
public double x1, x2;
public double y1, y2;
public double z1, z2;
}
public struct iPoint {
public double x,y,z
}
Dictionary<String, iBounds> RegionBounds = new Dictionary<String, iBounds>();
List<iPoint> PointsToCategorize = new List<iPoint>();
int no_of_bounding_boxes = 300;
int no_of_points_to_categorize = 1000;
for (int i = 1; i <= no_of_bounding_boxes; i++)
{
String boundingBoxName = "bound_" + i;
iBounds boundingBox = new iBounds
{
x1 = Computed By Some Other method and Formulas,
x2 = Computed By Some Other method and Formulas,
y1 = Computed By Some Other method and Formulas,
y2 = Computed By Some Other method and Formulas,
z1 = Computed By Some Other method and Formulas,
z2 = Computed By Some Other method and Formulas
};
RegionBounds.Add(boundingBoxName, boundingBox);
}
////////////Start of Output section /////////////////////////
for(int i= 1; i < = PointsToCategorize.Count; i++){
foreach(var pair in RegionBounds)
{
String myboxNmame = pair.Key;
iBounds myboxBounds = pair.Value;
Console.WriteLine(PointInside(PointsToCategorize[i],myboxBounds).ToString());
}
}
////////////// End of Output section //////////////////
private bool PointInside(iPoint mypoint, iBounds boxToBeCheckedIn)
{
if (mypoint.x > boxToBeCheckedIn.x1) && (mypoint.x < boxToBeCheckedIn.x2){
if (mypoint.y > boxToBeCheckedIn.y1) && (mypoint.y < boxToBeCheckedIn.y2){
if (mypoint.z > boxToBeCheckedIn.z1) && (mypoint.z < boxToBeCheckedIn.z2){
return true;
}
}
}else{
return false;
}
}
You may want to use a OcTree or a kD-tree data structure, which is way more efficient than iterating through all the boxes.
See also this article at the section 2-D orthogonal range searching, it has a very good resume of available techniques and algorithms, which are easily extendable to 3D

Algorithm: Checking for conditions in 3D array

This one is hard to explain! Sorry for that, but here goes...
I have a 3D array of some data [X][Y][Z], and I like to check for about 10 different combination conditions and keep only data when it's a match... Example:
X Y Z
//myData[1..1000000][1..10][1..10].foo // foo is an int
X[i].Y[ii].Z[iii].foo; // X is a container, Y= 1 to 10 levels. And Z= objects
//I want to apply a "filter" to the Z objects...
Lets say I want to find all combinations where the sum of "foo" is smaller and larger than two numbers, and only keep those Z objects
For next iteration i want to find lets say only where "foo" is a prime number, still keeping only Z objects
And so on for more conditions, resulting in smaller and smaller list.
It doesn't matter in wich order they are performed.
I sort of know how to do it, but I end up in some really nasty loops...
Any Ideas? Maybe adding to another list is faster than deleting from original list?
Thanks in advance!
When you want to chain together logic like this, I think you really want to use Linq. Unfortunately, it can be cumbersome to use Linq on multidimensional arrays. With some helper methods, though, we can convert the data array into something more usable. First, let's build a wrapper class for any object that has 3 dimensions associated with it:
public class ThreeDimensionalArrayExtension<T> {
public int X { get; set; }
public int Y { get; set; }
public int Z { get; set; }
public T Value { get; set; }
}
Next, let's write a helper method that converts 3-dimsensional arrays to IEnumerables of the new type:
public static class ThreeDimensionalArrayExtensionMethods {
public static IEnumerable<ThreeDimensionalArrayExtension<T>> ConvertArray<T>(this T[,,] foos) {
for(var x = 0; x < foos.GetLength(0); x++) {
for (var y = 0; y < foos.GetLength(1); y++) {
for (var z = 0; z < foos.GetLength(2); z++) {
yield return new ThreeDimensionalArrayExtension<T> { X = x, Y = y , Z = z, Value = foos[x, y, z] };
}
}
}
}
}
Note that since we are using an iterator block (the yield-return pattern), calling this method does not actually perform any computation.
Now we can use the power of Linq on your 3-dimensional array to filter it however we want!
myData.ConvertArray().Where(d => d.Value.Foo > 5)
.Where(d => IsPrime(d.Value.Foo))
.Where(...);
Edit:
I see that you're using 3 nested classes and not a multidimensional array which I assumed you were using. The goal should still be to convert that object to an IEnumerable upon which you can very easily chain Linq queries to filter or project the data. In your case, you can do:
public static class ThreeDimensionalArrayExtensionMethods {
public static IEnumerable<ThreeDimensionalArrayExtension<X>> ConvertArray(this X[] foos) {
for(var x = 0; x < foos.Count(); x++) {
for (var y = 0; y < foos[x].Count(); y++) {
for (var z = 0; z < foos[x][y].Count(); z++) {
yield return new ThreeDimensionalArrayExtension<T> { X = x, Y = y , Z = z, Value = foos[x][y][z] };
}
}
}
}
}
And then use the same call to ConvertArray followed by the filtering Where clauses described above.
If you don't care about the X/Y/Z indices, you can also just use SelectMany to project the multidimensional list onto a single dimensional list:
X.SelectMany(y => y.SelectMany(z => z)).Where(z => z.Foo > 5);

Categories

Resources