private static Tuple <SamplePoint[], Neuron_SensorPosition[][]> CreateNeurons(ShipPartDNA dna, ItemOptions itemOptions) { #region count // Figure out how many sample points to create //NOTE: radius assumes a sphere, but this camera is a cone. Not perfect, but good enough double radius = (dna.Scale.X + dna.Scale.Y + dna.Scale.Z) / (3d * 2d); // xyz should all be the same anyway double volume = Math.Pow(radius, itemOptions.Sensor_NeuronGrowthExponent); int numSamples = Convert.ToInt32(Math.Ceiling(itemOptions.CameraHardCoded_NeuronDensity * volume)); if (numSamples == 0) { numSamples = 1; } #endregion //TODO: Calculate this based on the densitiy of sets inside the cone portion of the unit sphere double setSize = .1; #region positions // Get points in a cone //NOTE: Going with a narrower angle, because the neurons will go to the edges, but the neurons will be the center of a vision sphere -- so the actual vision will be larger than this cone Vector3D[] pointsModel = Math3D.GetRandomVectors_Cone_EvenDist(numSamples, CameraColorRGBDesign.CameraDirection, 60, .2, 1); // Turn into sensor neurons Neuron_SensorPosition[][] neurons = pointsModel. Select(o => GetNeuronSet(o.ToPoint(), setSize)). ToArray(); double worldMax = itemOptions.CameraHardCoded_WorldMax; //NOTE: The term world is a bit misleading. It's world distances, but still technically model coords. It's just not neural's unit circle coords Point3D[] pointsWorld = pointsModel. Select(o => { double distanceFromOrigin = o.Length; return(o.ToUnit() * (worldMax * Math.Pow(distanceFromOrigin, 3))); }). Select(o => o.ToPoint()). ToArray(); #endregion #region vision radius // Delaunay //TODO: Throw out thin triangles Tetrahedron[] tetras = Math3D.GetDelaunay(pointsWorld, 10); double approximateRadius = worldMax * .667; double[] cellRadii = null; if (tetras == null) { cellRadii = Enumerable.Range(0, pointsWorld.Length). Select(o => approximateRadius). ToArray(); } else { Tuple <int, int>[] uniqueLines = Tetrahedron.GetUniqueLines(tetras); cellRadii = Enumerable.Range(0, pointsWorld.Length). Select(o => GetCellRadius(o, pointsWorld, uniqueLines, approximateRadius)). ToArray(); } #endregion // Turn into sample points SamplePoint[] samplePoints = Enumerable.Range(0, numSamples). Select(o => new SamplePoint(pointsModel[o].ToPoint(), pointsWorld[o].ToVector(), cellRadii[o], neurons[o])). ToArray(); return(Tuple.Create(samplePoints, neurons)); }