private static Neuron_SensorPosition[] GetNeuronSet(Point3D centerPoint, double size) { double half = size / 2; Vector3D posDir = new Vector3D(half, half, half); Vector3D halfPosDir = posDir / 2; // posDir's length is half of the cube's diagonal, so halfPosDir length is a quarter of the diagonal Vector3D orth = Vector3D.CrossProduct(posDir, new Vector3D(-1, 1, -1)); orth = Vector3D.CrossProduct(posDir, orth); orth = orth.ToUnit() * halfPosDir.Length; Point3D posMid = centerPoint + halfPosDir + orth; Point3D negMid = centerPoint - halfPosDir - (orth * .5); // using a different distance so it's not symetric Neuron_SensorPosition[] retVal = new Neuron_SensorPosition[5]; retVal[0] = new Neuron_SensorPosition(centerPoint - posDir, true); retVal[1] = new Neuron_SensorPosition(negMid, true); retVal[2] = new Neuron_SensorPosition(centerPoint, true); retVal[3] = new Neuron_SensorPosition(posMid, true); retVal[4] = new Neuron_SensorPosition(centerPoint + posDir, true); return(retVal); }
public FuelTank(EditorOptions options, ItemOptions itemOptions, ShipPartDNA dna) : base(options, dna, itemOptions.FuelTank_Damage.HitpointMin, itemOptions.FuelTank_Damage.HitpointSlope, itemOptions.FuelTank_Damage.Damage) { _itemOptions = itemOptions; this.Design = new FuelTankDesign(options, true); this.Design.SetDNA(dna); double surfaceArea, radius; _container = GetContainer(out surfaceArea, out _scaleActual, out radius, itemOptions, dna); _dryMass = surfaceArea * itemOptions.FuelTank_WallDensity; this.Radius = radius; _neuron = new Neuron_SensorPosition(new Point3D(0, 0, 0), false); this.Destroyed += FuelTank_Destroyed; }
public PlasmaTank(EditorOptions options, ItemOptions itemOptions, ShipPartDNA dna) : base(options, dna, itemOptions.PlasmaTank_Damage.HitpointMin, itemOptions.PlasmaTank_Damage.HitpointSlope, itemOptions.PlasmaTank_Damage.Damage) { _itemOptions = itemOptions; this.Design = new PlasmaTankDesign(options, true); this.Design.SetDNA(dna); double surfaceArea, radius; _container = FuelTank.GetContainer(out surfaceArea, out _scaleActual, out radius, itemOptions, dna); _mass = _container.QuantityMax * itemOptions.PlasmaTank_Density; // max quantity is the volume this.Radius = radius; _neuron = new Neuron_SensorPosition(new Point3D(0, 0, 0), false); this.Destroyed += PlasmaTank_Destroyed; }
private static (Neuron_SensorPosition rot_dirspeed, Neuron_SensorPosition rot_radius, Neuron_SensorPosition[] linear) CreateNeurons(ShipPartDNA dna, ItemOptionsArco itemOptions) { #region ring - linear // Figure out how many to make //NOTE: This radius isn't taking SCALE into account. The other neural parts do this as well, so the neural density properties can be more consistent double radius = (dna.Scale.X + dna.Scale.Y) / (2d * 2d); // XY should always be the same anyway (not looking at Z for this. Z is just to keep the sensors from getting too close to each other) double area = Math.Pow(radius, itemOptions.MotionController2_NeuronGrowthExponent); int neuronCount = (area * itemOptions.MotionController2_NeuronDensity).ToInt_Ceiling(); neuronCount += 2; // manually add two for the rotation neruons if (neuronCount < 7) { neuronCount = 7; } var neuronPositions = SplitNeuronPositions(dna.Neurons); // Place them evenly around the perimiter of a circle. Vector3D[] linearPositions = NeuralUtility.GetNeuronPositions_CircularShell_Even(neuronPositions?.linear, neuronCount, radius); Neuron_SensorPosition[] linearNeurons = linearPositions. Select(o => new Neuron_SensorPosition(o.ToPoint(), true, false)). ToArray(); #endregion #region interior - rotation Neuron_SensorPosition rotateDirSpeed = new Neuron_SensorPosition(new Point3D(-.25, 0, 0), false, false); Neuron_SensorPosition rotateRadius = new Neuron_SensorPosition(new Point3D(.25, 0, 0), true, false); #endregion return ( rotateDirSpeed, rotateRadius, linearNeurons ); }
public MotionController2(EditorOptions options, ItemOptionsArco itemOptions, ShipPartDNA dna, AIMousePlate mousePlate) : base(options, dna, itemOptions.MotionController_Damage.HitpointMin, itemOptions.MotionController_Damage.HitpointSlope, itemOptions.MotionController_Damage.Damage) { _itemOptions = itemOptions; _mousePlate = mousePlate; this.Design = new MotionController2Design(options, true); this.Design.SetDNA(dna); GetMass(out _mass, out double volume, out double radius, out _scaleActual, dna, itemOptions); this.Radius = radius; var neurons = CreateNeurons(dna, itemOptions); _neuron_rotate_direction_speed = neurons.rot_dirspeed; _neuron_rotate_radius = neurons.rot_radius; _neurons_linear = neurons.linear; _neurons_all = UtilityCore.Iterate <Neuron_SensorPosition>(_neuron_rotate_direction_speed, _neuron_rotate_radius, _neurons_linear).ToArray(); }
public EnergyTank(EditorOptions options, ItemOptions itemOptions, ShipPartDNA dna) : base(options, dna, itemOptions.EnergyTank_Damage.HitpointMin, itemOptions.EnergyTank_Damage.HitpointSlope, itemOptions.EnergyTank_Damage.Damage) { _itemOptions = itemOptions; this.Design = new EnergyTankDesign(options, true); this.Design.SetDNA(dna); double radius; _container = GetContainer(out _scaleActual, out radius, itemOptions, dna); this.Radius = radius; _mass = _container.QuantityMax * itemOptions.EnergyTank_Density; _neuron = new Neuron_SensorPosition(new Point3D(0, 0, 0), false); this.Destroyed += EnergyTank_Destroyed; }
private static Neuron_SensorPosition[] GetNeuronSet_STRAIGHTLINE(Point3D centerPoint, double size) { //TODO: If the count gets much over 4, put them in a more compact pattern, some kind of spiral, or the verticies of a polyhedron //Math3D.GetRandomVectors_SphericalShell_EvenDist Neuron_SensorPosition[] retVal = new Neuron_SensorPosition[5]; double stepSize = size / retVal.Length; double half = size / 2; for (int cntr = 0; cntr < retVal.Length; cntr++) { double offset = -half + (cntr * stepSize); Point3D position = new Point3D(centerPoint.X + offset, centerPoint.Y + offset, centerPoint.Z + offset); // doing the offset on each axis so the total length is sqrt(2) instead of 1 retVal[cntr] = new Neuron_SensorPosition(position, true); } return(retVal); }
public CargoBay(EditorOptions options, ItemOptions itemOptions, ShipPartDNA dna) : base(options, dna, itemOptions.CargoBay_Damage.HitpointMin, itemOptions.CargoBay_Damage.HitpointSlope, itemOptions.CargoBay_Damage.Damage) { _itemOptions = itemOptions; this.Design = new CargoBayDesign(options, true); this.Design.SetDNA(dna); double volume, radius; GetMass(out _dryMass, out volume, out radius, _itemOptions, dna); _scaleActual = new Vector3D(dna.Scale.X, dna.Scale.Y, dna.Scale.Z); this.MaxVolume = volume; this.Radius = radius; _neuron = new Neuron_SensorPosition(new Point3D(0, 0, 0), false); this.Destroyed += CargoBay_Destroyed; }
internal static void CreateNeurons(out Neuron_SensorPosition[] neuronsR, out Neuron_SensorPosition[] neuronsG, out Neuron_SensorPosition[] neuronsB, out OverlayResult[][] overlayR, out OverlayResult[][] overlayG, out OverlayResult[][] overlayB, out int pixelWidthHeight, ShipPartDNA dna, ItemOptions itemOptions, double neuronDensity) { const int MINPIXELWIDTH = 16; #region Calculate counts // Figure out how many neurons to make //NOTE: This radius isn't taking SCALE into account. The other neural parts do this as well, so the neural density properties can be more consistent double radius = (dna.Scale.X + dna.Scale.Y + dna.Scale.Z) / (3d * 2d); // xyz should all be the same anyway double area = Math.Pow(radius, itemOptions.Sensor_NeuronGrowthExponent); int neuronCount = Convert.ToInt32(Math.Ceiling(neuronDensity * area)); if (neuronCount == 0) { neuronCount = 1; } // Figure out how many pixels to make pixelWidthHeight = neuronCount / 9; // dividing by 3 to get the number of neurons in a single plate. divide that by 3, because that's a good ratio of neuron cells to pixels if (pixelWidthHeight < MINPIXELWIDTH) { pixelWidthHeight = MINPIXELWIDTH; } #endregion #region Neurons // Place them evenly in a sphere //NOTE: An interesting side effect of calling this for each generation is that the parent may not have been perfectly evenly spaced, but calling this //again will slightly refine the positions Vector3D[][] positions = GetNeuronPositions(dna.Neurons, neuronCount, 3, radius); // Create neurons neuronsR = positions[0].Select(o => new Neuron_SensorPosition(o.ToPoint(), true)).ToArray(); neuronsG = positions[1].Select(o => new Neuron_SensorPosition(o.ToPoint(), true)).ToArray(); neuronsB = positions[2].Select(o => new Neuron_SensorPosition(o.ToPoint(), true)).ToArray(); #endregion #region Polygons around neurons // Figure out which pixels each neuron intersects with VoronoiResult2D[] voronoi = new VoronoiResult2D[3]; voronoi[0] = Math2D.CapVoronoiCircle(Math2D.GetVoronoi(positions[0].Select(o => new Point(o.X, o.Y)).ToArray(), true)); voronoi[1] = Math2D.CapVoronoiCircle(Math2D.GetVoronoi(positions[1].Select(o => new Point(o.X, o.Y)).ToArray(), true)); voronoi[2] = Math2D.CapVoronoiCircle(Math2D.GetVoronoi(positions[2].Select(o => new Point(o.X, o.Y)).ToArray(), true)); #region Figure out the extremes Point[] allEdgePoints = voronoi.SelectMany(o => o.EdgePoints).ToArray(); Point min = new Point(allEdgePoints.Min(o => o.X), allEdgePoints.Min(o => o.Y)); Point max = new Point(allEdgePoints.Max(o => o.X), allEdgePoints.Max(o => o.Y)); double width = max.X - min.X; double height = max.Y - min.Y; // Enlarge a bit min.X -= width * .05d; min.Y -= height * .05d; max.X += width * .05d; max.Y += height * .05d; width = max.X - min.X; height = max.Y - min.Y; Vector offset = new Vector(-min.X, -min.Y); #endregion // Figure out which pixels each polygon overlaps overlayR = GetIntersections(new Size(width, height), pixelWidthHeight, pixelWidthHeight, GetPolygons(voronoi[0], offset)); overlayG = GetIntersections(new Size(width, height), pixelWidthHeight, pixelWidthHeight, GetPolygons(voronoi[1], offset)); overlayB = GetIntersections(new Size(width, height), pixelWidthHeight, pixelWidthHeight, GetPolygons(voronoi[2], offset)); #endregion }
/// <summary> /// This sets all the neurons from 0 to magnitude. Magnitude needs to be from 0 to 1, and is based on the currently felt gravity compared /// to what the sensor has seen as the max felt /// </summary> internal static void UpdateNeurons(Neuron_SensorPosition[] neurons, double neuronMaxRadius, Vector3D vector, double magnitude) { const double MINDOT = 1.25d; if (Math3D.IsNearZero(vector)) { // There is no gravity to report for (int cntr = 0; cntr < neurons.Length; cntr++) { neurons[cntr].Value = 0d; } return; } Vector3D gravityUnit = vector.ToUnit(); for (int cntr = 0; cntr < neurons.Length; cntr++) { if (neurons[cntr].PositionUnit == null) { // This neuron is sitting at 0,0,0 neurons[cntr].Value = magnitude; } else { // Figure out how aligned this neuron is with the gravity vector double dot = Vector3D.DotProduct(gravityUnit, neurons[cntr].PositionUnit.Value); dot += 1d; // get this to scale from 0 to 2 instead of -1 to 1 // Scale minDot double radiusPercent = neurons[cntr].PositionLength / neuronMaxRadius; double revisedMinDot = UtilityCore.GetScaledValue_Capped(0d, MINDOT, 0d, 1d, radiusPercent); // Rig it so that the lower radius neurons will fire stronger double minReturn = 1d - radiusPercent; if (minReturn < 0d) { minReturn = 0d; } // Figure out what percentage of magnitude to use double percent; if (dot < revisedMinDot) { percent = UtilityCore.GetScaledValue_Capped(0d, minReturn, 0d, revisedMinDot, dot); } else { percent = UtilityCore.GetScaledValue_Capped(minReturn, 1d, revisedMinDot, 2d, dot); } // Set the neuron neurons[cntr].Value = percent * magnitude; } } }