private static Vector3D[] GetNeuronPositionsInitial(out Vector3D[] staticPoints, out double[] staticRepulseMult, Point3D[] dnaPositions, Point3D[] existingStaticPositions, double staticMultValue, int count, double radius, Func<double, Vector3D> getNewPoint) { //TODO: When reducing/increasing, it is currently just being random. It may be more realistic to take proximity into account. Play // a variant of conway's game of life or something Vector3D[] retVal; if (dnaPositions == null) { #region Create new retVal = new Vector3D[count]; for (int cntr = 0; cntr < count; cntr++) { //retVal[cntr] = Math3D.GetRandomVectorSpherical(radius); retVal[cntr] = getNewPoint(radius); // using a delegate instead } #endregion } else if (dnaPositions.Length > count) { #region Reduce List<Vector3D> posList = dnaPositions.Select(o => o.ToVector()).ToList(); int reduceCount = dnaPositions.Length - count; for (int cntr = 0; cntr < reduceCount; cntr++) { posList.RemoveAt(StaticRandom.Next(posList.Count)); } retVal = posList.ToArray(); #endregion } else if (dnaPositions.Length < count) { #region Increase List<Vector3D> posList = dnaPositions.Select(o => o.ToVector()).ToList(); int increaseCount = count - dnaPositions.Length; for (int cntr = 0; cntr < increaseCount; cntr++) { //posList.Add(Math3D.GetRandomVectorSpherical2D(radius)); posList.Add(getNewPoint(radius)); // using a delegate instead } retVal = posList.ToArray(); #endregion } else { #region Copy as is retVal = dnaPositions.Select(o => o.ToVector()).ToArray(); #endregion } // Prep the static point arrays staticPoints = null; staticRepulseMult = null; if (existingStaticPositions != null) { staticPoints = existingStaticPositions.Select(o => o.ToVector()).ToArray(); // This will force more than normal distance between brain chemical neurons and standard neurons. The reason I'm doing this // is because the brain chemical neurons can have some powerful effects on the brain, and when an offspring is made, the links // in the dna only hold neuron position. By having a larger gap, there is less chance of accidental miswiring staticRepulseMult = Enumerable.Range(0, staticPoints.Length).Select(o => staticMultValue).ToArray(); } // Exit Function return retVal; }
private static int GetDelaunayResults_SegmentCount(Point3D[] brains, Point3D[] io) { LinkItem[] brainItems = brains. Select(o => new LinkItem(o, 1d)). ToArray(); LinkItem[] ioItems = io. Select(o => new LinkItem(o, 1d)). ToArray(); // Self SortedList<Tuple<int, int>, double> all; LinkSetPair[] final; ItemLinker.Link_Self(out all, out final, brainItems); // Brain-IO Tuple<int, int>[] oneTwo = ItemLinker.Link_1_2(brainItems, ioItems); return final.Length + oneTwo.Length; }
public static Tuple<Point3D, Vector3D>[] BuildStroke(Point3D[] points, double smallestSubstrokeSize) { return BuildStroke(points. Select(o => new Tuple<Point3D, Vector3D?>(o, null)).ToArray(), smallestSubstrokeSize); }
public static TruncatedIcosidodecahedron GetTruncatedIcosidodecahedron(double radius, Transform3D transform = null) { //TODO: Currently, the points are hardcoded. All the polygons are regular. Take in a ratio for the length of side of the decagons. // 0 would make the decagons disappar, and the squares and hexagons would be it // 1 would make the squares disappear and the hexagons would become triangles // //The squares are the cornerstones. When calculating points, figure out what the centers of the various polygons are. Then adjust the //sizes of the squares. From that, find the rest of the points using the decagons. No need to find points for the hexagons, they have //no unique points #region Points double t = (1d + Math.Sqrt(5d)) / 2d; // φ double tS = t * t; // φ^2 double tI1 = 1d / t; // 1/φ double tI2 = 2d / t; // 2/φ double t2 = 2d * t; // 2φ double tA = 1d + (2d * t); // 1+2φ double tB = 2d + t; // 2+φ double tC = 3d + t; // 3+φ double tN1 = -1d + (3d * t); // -1+3φ double tN2 = -1d + (2d * t); // -1+2φ Point3D[] points = new Point3D[] { //(±1/φ, ±1/φ, ±(3+φ)) new Point3D(tI1, tI1, tC), new Point3D(tI1, tI1, -tC), new Point3D(tI1, -tI1, tC), new Point3D(tI1, -tI1, -tC), new Point3D(-tI1, tI1, tC), new Point3D(-tI1, tI1, -tC), new Point3D(-tI1, -tI1, tC), new Point3D(-tI1, -tI1, -tC), //(±2/φ, ±φ, ±(1+2φ)) new Point3D(tI2, t, tA), new Point3D(tI2, t, -tA), new Point3D(tI2, -t, tA), new Point3D(tI2, -t, -tA), new Point3D(-tI2, t, tA), new Point3D(-tI2, t, -tA), new Point3D(-tI2, -t, tA), new Point3D(-tI2, -t, -tA), //(±1/φ, ±φ^2, ±(-1+3φ)) new Point3D(tI1, tS, tN1), new Point3D(tI1, tS, -tN1), new Point3D(tI1, -tS, tN1), new Point3D(tI1, -tS, -tN1), new Point3D(-tI1, tS, tN1), new Point3D(-tI1, tS, -tN1), new Point3D(-tI1, -tS, tN1), new Point3D(-tI1, -tS, -tN1), //(±(-1+2φ), ±2, ±(2+φ)) new Point3D(tN2, 2, tB), new Point3D(tN2, 2, -tB), new Point3D(tN2, -2, tB), new Point3D(tN2, -2, -tB), new Point3D(-tN2, 2, tB), new Point3D(-tN2, 2, -tB), new Point3D(-tN2, -2, tB), new Point3D(-tN2, -2, -tB), //(±φ, ±3, ±2φ), new Point3D(t, 3, t2), new Point3D(t, 3, -t2), new Point3D(t, -3, t2), new Point3D(t, -3, -t2), new Point3D(-t, 3, t2), new Point3D(-t, 3, -t2), new Point3D(-t, -3, t2), new Point3D(-t, -3, -t2), }; points = points.Select(o => new Point3D[] { o, // orig new Point3D(o.Y, o.Z, o.X), // shift left new Point3D(o.Z, o.X, o.Y) // shift left twice }). SelectMany(o => o). ToArray(); double maxLength = points[0].ToVector().Length; double ratio = radius / maxLength; points = points.Select(o => (o.ToVector() * ratio).ToPoint()).ToArray(); if (transform != null) { points = points.Select(o => transform.Transform(o)).ToArray(); } #endregion int[][] decagonPolys = new int[][] { new int [] { 0, 6, 30, 78, 110, 62, 50, 98, 72, 24 }, new int [] { 14, 38, 86, 100, 52, 64, 112, 92, 44, 20 }, new int [] { 3, 27, 75, 104, 56, 68, 116, 81, 33, 9 }, new int [] { 15, 21, 45, 93, 119, 71, 59, 107, 87, 39 }, new int [] { 2, 8, 32, 80, 109, 61, 49, 97, 74, 26 }, new int [] { 1, 7, 31, 79, 108, 60, 48, 96, 73, 25 }, new int [] { 12, 36, 84, 101, 53, 65, 113, 90, 42, 18 }, new int [] { 4, 28, 76, 102, 54, 66, 114, 82, 34, 10 }, new int [] { 16, 22, 46, 94, 117, 69, 57, 105, 88, 40 }, new int [] { 17, 23, 47, 95, 118, 70, 58, 106, 89, 41 }, new int [] { 5, 29, 77, 103, 55, 67, 115, 83, 35, 11 }, new int [] { 13, 37, 85, 99, 51, 63, 111, 91, 43, 19 }, }; int[][] hexagonPolys = new int[][] { new int [] { 6, 18, 42, 66, 54, 30 }, new int [] { 82, 114, 90, 113, 89, 106 }, new int [] { 5, 17, 41, 65, 53, 29 }, new int [] { 77, 101, 84, 108, 79, 103 }, new int [] { 7, 19, 43, 67, 55, 31 }, new int [] { 83, 115, 91, 111, 87, 107 }, new int [] { 3, 15, 39, 63, 51, 27 }, new int [] { 0, 24, 48, 60, 36, 12 }, new int [] { 72, 98, 74, 97, 73, 96 }, new int [] { 1, 25, 49, 61, 37, 13 }, new int [] { 75, 99, 85, 109, 80, 104 }, new int [] { 76, 100, 86, 110, 78, 102 }, new int [] { 2, 26, 50, 62, 38, 14 }, new int [] { 8, 20, 44, 68, 56, 32 }, new int [] { 81, 116, 92, 112, 88, 105 }, new int [] { 9, 33, 57, 69, 45, 21 }, new int [] { 11, 35, 59, 71, 47, 23 }, new int [] { 93, 117, 94, 118, 95, 119 }, new int [] { 10, 34, 58, 70, 46, 22 }, new int [] { 4, 16, 40, 64, 52, 28 }, }; int[][] squarePolys = new int[][] { new int [] { 0, 12, 18, 6 }, new int [] { 36, 60, 108, 84 }, new int [] { 31, 55, 103, 79 }, new int [] { 43, 91, 115, 67 }, new int [] { 39, 87, 111, 63 }, new int [] { 3, 9, 21, 15 }, new int [] { 24, 72, 96, 48 }, new int [] { 25, 73, 97, 49 }, new int [] { 1, 13, 19, 7 }, new int [] { 37, 61, 109, 85 }, new int [] { 27, 51, 99, 75 }, new int [] { 33, 81, 105, 57 }, new int [] { 42, 90, 114, 66 }, new int [] { 41, 89, 113, 65 }, new int [] { 5, 11, 23, 17 }, new int [] { 35, 83, 107, 59 }, new int [] { 45, 69, 117, 93 }, new int [] { 29, 53, 101, 77 }, new int [] { 30, 54, 102, 78 }, new int [] { 28, 52, 100, 76 }, new int [] { 38, 62, 110, 86 }, new int [] { 26, 74, 98, 50 }, new int [] { 2, 14, 20, 8 }, new int [] { 32, 56, 104, 80 }, new int [] { 34, 82, 106, 58 }, new int [] { 46, 70, 118, 94 }, new int [] { 47, 71, 119, 95 }, new int [] { 4, 10, 22, 16 }, new int [] { 40, 88, 112, 64 }, new int [] { 44, 92, 116, 68 }, }; return new TruncatedIcosidodecahedron(decagonPolys, hexagonPolys, squarePolys, points); }
/// <summary> /// This returns the index and distance of the nodes that are close to search /// </summary> private static List<Tuple<int, double>> GetNearNodes(Point3D search, Point3D[] points, double searchRadiusMultiplier) { // Get the distances to each point double[] distSquared = points.Select(o => (o - search).LengthSquared).ToArray(); // Find the smallest distance int smallestIndex = 0; for (int cntr = 1; cntr < distSquared.Length; cntr++) { if (distSquared[cntr] < distSquared[smallestIndex]) { smallestIndex = cntr; } } // Figure out how far out to allow double min = Math.Sqrt(distSquared[smallestIndex]); double maxSquared = Math.Pow(min * searchRadiusMultiplier, 2d); // Find all the points in range List<Tuple<int, double>> retVal = new List<Tuple<int, double>>(); // This one is obviously in range (adding it now to avoid an unnessary sqrt) retVal.Add(new Tuple<int, double>(smallestIndex, min)); for (int cntr = 0; cntr < distSquared.Length; cntr++) { if (cntr == smallestIndex) { continue; } if (distSquared[cntr] < maxSquared) { retVal.Add(new Tuple<int, double>(cntr, Math.Sqrt(distSquared[cntr]))); } } // Exit Function return retVal; }
public static Dodecahedron GetDodecahedron(double radius, Transform3D transform = null) { // This is 12 pentagons #region Points double t = (1d + Math.Sqrt(5d)) / 2d; double t1 = 1d / t; Point3D[] points = new Point3D[] { //(±1, ±1, ±1) new Point3D(1, 1, 1), // 0 new Point3D(1, 1, -1), // 1 new Point3D(1, -1, 1), // 2 new Point3D(1, -1, -1), // 3 new Point3D(-1, 1, 1), // 4 new Point3D(-1, 1, -1), // 5 new Point3D(-1, -1, 1), // 6 new Point3D(-1, -1, -1), // 7 //(0, ±1/φ, ±φ) new Point3D(0, t1, t), // 8 new Point3D(0, t1, -t), // 9 new Point3D(0, -t1, t), // 10 new Point3D(0, -t1, -t), // 11 //(±1/φ, ±φ, 0) new Point3D(t1, t, 0), // 12 new Point3D(t1, -t, 0), // 13 new Point3D(-t1, t, 0), // 14 new Point3D(-t1, -t, 0), // 15 //(±φ, 0, ±1/φ) new Point3D(t, 0, t1), // 16 new Point3D(t, 0, -t1), // 17 new Point3D(-t, 0, t1), // 18 new Point3D(-t, 0, -t1), // 19 }; double maxLength = points[8].ToVector().Length; // this represents the longest vector double ratio = radius / maxLength; points = points.Select(o => (o.ToVector() * ratio).ToPoint()).ToArray(); if (transform != null) { points = points.Select(o => transform.Transform(o)).ToArray(); } #endregion int[][] pentagonPolys = new int[][] { new int [] { 2, 10, 6, 15, 13 }, new int [] { 0, 8, 10, 2, 16 }, new int [] { 0, 12, 14, 4, 8 }, new int [] { 1, 9, 5, 14, 12 }, new int [] { 1, 17, 3, 11, 9 }, new int [] { 2, 13, 3, 17, 16 }, new int [] { 3, 13, 15, 7, 11 }, new int [] { 6, 18, 19, 7, 15 }, new int [] { 4, 18, 6, 10, 8 }, new int [] { 4, 14, 5, 19, 18 }, new int [] { 5, 9, 11, 7, 19 }, new int [] { 0, 16, 17, 1, 12 }, }; return new Dodecahedron(pentagonPolys, points); }
public static TruncatedIcosahedron GetTruncatedIcosahedron(double radius, Transform3D transform = null) { #region Points double t = (1d + Math.Sqrt(5d)) / 2d; double t2 = t * 2d; double t3 = t * 3d; double tA = 1d + (2d * t); double tB = 2d + t; // Length compare: // t3 4.8541019662496847 // tA 4.23606797749979 // tB 3.6180339887498949 // t2 3.23606797749979 // 2 2 // t 1.6180339887498949 // 1 1 // 0 0 Point3D[] points = new Point3D[] { //------------------------------------------------- X axis //(±3φ, 0, ±1) new Point3D(t3, 0, 1), // 0 new Point3D(-t3, 0, 1), new Point3D(t3, 0, -1), new Point3D(-t3, 0, -1), // 3 //(±(1+2φ), ±φ, ±2) new Point3D(tA, t, 2), // 4 new Point3D(tA, -t, 2), new Point3D(-tA, t, 2), new Point3D(-tA, -t, 2), new Point3D(tA, t, -2), new Point3D(tA, -t, -2), new Point3D(-tA, t, -2), new Point3D(-tA, -t, -2), // 11 //(±(2+φ), ±2φ, ±1) new Point3D(tB, t2, 1), // 12 new Point3D(tB, t2, -1), new Point3D(tB, -t2, 1), new Point3D(tB, -t2, -1), new Point3D(-tB, t2, 1), new Point3D(-tB, t2, -1), new Point3D(-tB, -t2, 1), new Point3D(-tB, -t2, -1), // 19 //------------------------------------------------- Y axis //(±1, ±3φ, 0) new Point3D(1, t3, 0), // 20 new Point3D(1, -t3, 0), new Point3D(-1, t3, 0), new Point3D(-1, -t3, 0), // 23 //(±2, ±(1+2φ), ±φ) new Point3D(2, tA, t), // 24 new Point3D(2, tA, -t), new Point3D(2, -tA, t), new Point3D(2, -tA, -t), new Point3D(-2, tA, t), new Point3D(-2, tA, -t), new Point3D(-2, -tA, t), new Point3D(-2, -tA, -t), // 31 //(±1, ±(2+φ), ±2φ) new Point3D(1, tB, t2), // 32 new Point3D(1, tB, -t2), new Point3D(1, -tB, t2), new Point3D(1, -tB, -t2), new Point3D(-1, tB, t2), new Point3D(-1, tB, -t2), new Point3D(-1, -tB, t2), new Point3D(-1, -tB, -t2), // 39 //------------------------------------------------- Z axis //(0, ±1, ±3φ) new Point3D(0, 1, t3), // 40 new Point3D(0, 1, -t3), new Point3D(0, -1, t3), new Point3D(0, -1, -t3), // 43 //(±φ, ±2, ±(1+2φ)) new Point3D(t, 2, tA), // 44 new Point3D(-t, 2, tA), new Point3D(t, 2, -tA), new Point3D(-t, 2, -tA), new Point3D(t, -2, tA), new Point3D(-t, -2, tA), new Point3D(t, -2, -tA), new Point3D(-t, -2, -tA), // 51 //(±2φ, ±1, ±(2+φ)) new Point3D(t2, 1, tB), // 52 new Point3D(t2, 1, -tB), new Point3D(t2, -1, tB), new Point3D(t2, -1, -tB), new Point3D(-t2, 1, tB), new Point3D(-t2, 1, -tB), new Point3D(-t2, -1, tB), new Point3D(-t2, -1, -tB), // 59 }; double maxLength = points[0].ToVector().Length; double ratio = radius / maxLength; points = points.Select(o => (o.ToVector() * ratio).ToPoint()).ToArray(); if (transform != null) { points = points.Select(o => transform.Transform(o)).ToArray(); } #endregion // Pentagons int[][] pentagonPolys = new int[][] { new int [] { 40, 44, 32, 36, 45 }, new int [] { 42, 49, 38, 34, 48 }, new int [] { 41, 47, 37, 33, 46 }, new int [] { 43, 50, 35, 39, 51 }, new int [] { 1, 7, 58, 56, 6 }, new int [] { 0, 4, 52, 54, 5 }, new int [] { 3, 10, 57, 59, 11 }, new int [] { 2, 9, 55, 53, 8 }, new int [] { 18, 19, 31, 23, 30 }, new int [] { 14, 26, 21, 27, 15 }, new int [] { 12, 13, 25, 20, 24 }, new int [] { 16, 28, 22, 29, 17 }, }; // Hexagons int[][] hexagonPolys = new int[][] { new int [] { 40, 45, 56, 58, 49, 42 }, new int [] { 40, 42, 48, 54, 52, 44 }, new int [] { 41, 43, 51, 59, 57, 47 }, new int [] { 41, 46, 53, 55, 50, 43 }, new int [] { 1, 6, 16, 17, 10, 3 }, new int [] { 1, 3, 11, 19, 18, 7 }, new int [] { 0, 2, 8, 13, 12, 4 }, new int [] { 0, 5, 14, 15, 9, 2 }, new int [] { 34, 26, 14, 5, 54, 48 }, new int [] { 32, 44, 52, 4, 12, 24 }, new int [] { 38, 49, 58, 7, 18, 30 }, new int [] { 33, 25, 13, 8, 53, 46 }, new int [] { 35, 50, 55, 9, 15, 27 }, new int [] { 36, 28, 16, 6, 56, 45 }, new int [] { 39, 31, 19, 11, 59, 51 }, new int [] { 37, 47, 57, 10, 17, 29 }, new int [] { 20, 25, 33, 37, 29, 22 }, new int [] { 20, 22, 28, 36, 32, 24 }, new int [] { 21, 26, 34, 38, 30, 23 }, new int [] { 21, 23, 31, 39, 35, 27 }, }; return new TruncatedIcosahedron(pentagonPolys, hexagonPolys, points); }
public static Rhombicuboctahedron GetRhombicuboctahedron(double sizeX, double sizeY, double sizeZ, Transform3D transform = null) { #region Points double hX = sizeX / 2d; double hY = sizeY / 2d; double hZ = sizeZ / 2d; double sqrt2_1 = Math.Sqrt(2) + 1d; double sX = (sizeX / sqrt2_1) / 2d; // sX is half the width of one of the faces (the faces form an octogon) double sY = (sizeY / sqrt2_1) / 2d; double sZ = (sizeZ / sqrt2_1) / 2d; // Points Point3D[] points = new Point3D[] { // Top 4 new Point3D(sX, sY, hZ), // 0 new Point3D(sX, -sY, hZ), // 1 new Point3D(-sX, -sY, hZ), // 2 new Point3D(-sX, sY, hZ), // 3 // Top 8 new Point3D(hX, sY, sZ), // 4 new Point3D(hX, -sY, sZ), // 5 new Point3D(sX, -hY, sZ), // 6 new Point3D(-sX, -hY, sZ), // 7 new Point3D(-hX, -sY, sZ), // 8 new Point3D(-hX, sY, sZ), // 9 new Point3D(-sX, hY, sZ), // 10 new Point3D(sX, hY, sZ), // 11 // Bottom 8 new Point3D(hX, sY, -sZ), // 12 new Point3D(hX, -sY, -sZ), // 13 new Point3D(sX, -hY, -sZ), // 14 new Point3D(-sX, -hY, -sZ), // 15 new Point3D(-hX, -sY, -sZ), // 16 new Point3D(-hX, sY, -sZ), // 17 new Point3D(-sX, hY, -sZ), // 18 new Point3D(sX, hY, -sZ), // 19 // Bottom 4 new Point3D(sX, sY, -hZ), // 20 new Point3D(sX, -sY, -hZ), // 21 new Point3D(-sX, -sY, -hZ), // 22 new Point3D(-sX, sY, -hZ), // 23 }; if (transform != null) { points = points.Select(o => transform.Transform(o)).ToArray(); } #endregion int[][] squarePolys_Orth = new int[][] { new int[] { 0, 3, 2, 1 }, // Top new int[] { 4, 5, 13, 12 }, // Right new int[] { 6, 7, 15, 14 }, // Front new int[] { 8, 9, 17, 16 }, // Left new int[] { 10, 11, 19, 18 }, // Back new int[] { 20, 21, 22, 23 }, // Bottom }; int[][] squarePolys_Diag = new int[][] { // Top 4 angled new int[] {0, 1, 5, 4 }, new int[] { 1, 2, 7, 6 }, new int[] { 2, 3, 9, 8 }, new int[] { 0, 11, 10, 3 }, // Middle 4 angled new int[] { 4, 12, 19, 11 }, new int[] { 5, 6, 14, 13 }, new int[] { 7, 8, 16, 15 }, new int[] { 9, 10, 18, 17 }, // Bottom 4 angled new int[] { 12, 13, 21, 20 }, new int[] { 14, 15, 22, 21 }, new int[] { 16, 17, 23, 22 }, new int[] { 18, 19, 20, 23 }, }; TriangleIndexed[] triangles = new TriangleIndexed[] { // Top 4 new TriangleIndexed(0, 4, 11, points), new TriangleIndexed(1, 6, 5, points), new TriangleIndexed(2, 8, 7, points), new TriangleIndexed(3, 10, 9, points), // Bottom 4 new TriangleIndexed(12, 20, 19, points), new TriangleIndexed(13, 14, 21, points), new TriangleIndexed(15, 16, 22, points), new TriangleIndexed(17, 18, 23, points), }; return new Rhombicuboctahedron(squarePolys_Orth, squarePolys_Diag, triangles, points); }
public static Icosidodecahedron GetIcosidodecahedron(double radius, Transform3D transform = null) { //NOTE: Don't confuse this with an icosahedron. That is the more common object (made of equilateral triangles). //This object is made of pentagons and triangles. I'm just making this because it looks cool #region Points double t = (1d + Math.Sqrt(5d)) / 2d; double t2 = t / 2d; double t3 = (1d + t) / 2d; Point3D[] points = new Point3D[] { //(0,0,±φ) new Point3D(0, 0, t), // 0 new Point3D(0, 0, -t), // 1 //(0,±φ,0) new Point3D(0, t, 0), // 2 new Point3D(0, -t, 0), // 3 //(±φ,0,0) new Point3D(t, 0, 0), // 4 new Point3D(-t, 0, 0), // 5 //(±1/2, ±φ/2, ±(1+φ)/2) new Point3D(.5, t2, t3), // 6 new Point3D(.5, t2, -t3), // 7 new Point3D(.5, -t2, t3), // 8 new Point3D(.5, -t2, -t3), // 9 new Point3D(-.5, t2, t3), // 10 new Point3D(-.5, t2, -t3), // 11 new Point3D(-.5, -t2, t3), // 12 new Point3D(-.5, -t2, -t3), // 13 //(±φ/2, ±(1+φ)/2, ±1/2) new Point3D(t2, t3, .5), // 14 new Point3D(t2, t3, -.5), // 15 new Point3D(t2, -t3, .5), // 16 new Point3D(t2, -t3, -.5), // 17 new Point3D(-t2, t3, .5), // 18 new Point3D(-t2, t3, -.5), // 19 new Point3D(-t2, -t3, .5), // 20 new Point3D(-t2, -t3, -.5), // 21 //(±(1+φ)/2, ±1/2, ±φ/2) new Point3D(t3, .5, t2), // 22 new Point3D(t3, .5, -t2), // 23 new Point3D(t3, -.5, t2), // 24 new Point3D(t3, -.5, -t2), // 25 new Point3D(-t3, .5, t2), // 26 new Point3D(-t3, .5, -t2), // 27 new Point3D(-t3, -.5, t2), // 28 new Point3D(-t3, -.5, -t2), // 29 }; double maxLength = points[6].ToVector().Length; // this represents the longest vector double ratio = radius / maxLength; points = points.Select(o => (o.ToVector() * ratio).ToPoint()).ToArray(); if (transform != null) { points = points.Select(o => transform.Transform(o)).ToArray(); } #endregion int[][] pentagonPolys = new int[][] { new int [] { 0, 10, 26, 28, 12 }, new int [] { 26, 18, 19, 27, 5 }, new int [] { 5, 29, 21, 20, 28 }, new int [] { 10, 6, 14, 2, 18 }, new int [] { 3, 16, 8, 12, 20 }, new int [] { 0, 8, 24, 22, 6 }, new int [] { 9, 17, 3, 21, 13 }, new int [] { 27, 11, 1, 13, 29 }, new int [] { 4, 24, 16, 17, 25 }, new int [] { 1, 7, 23, 25, 9 }, new int [] { 4, 23, 15, 14, 22 }, new int [] { 2, 15, 7, 11, 19 }, }; TriangleIndexed[] triangles = new TriangleIndexed[] { new TriangleIndexed(0, 12, 8, points), new TriangleIndexed(0, 6, 10, points), new TriangleIndexed(10, 18, 26, points), new TriangleIndexed(5, 28, 26, points), new TriangleIndexed(12, 28, 20, points), new TriangleIndexed(3, 20, 21, points), new TriangleIndexed(8, 16, 24, points), new TriangleIndexed(3, 17, 16, points), new TriangleIndexed(9, 25, 17, points), new TriangleIndexed(4, 25, 23, points), new TriangleIndexed(4, 22, 24, points), new TriangleIndexed(13, 21, 29, points), new TriangleIndexed(1, 9, 13, points), new TriangleIndexed(1, 11, 7, points), new TriangleIndexed(11, 27, 19, points), new TriangleIndexed(5, 27, 29, points), new TriangleIndexed(6, 22, 14, points), new TriangleIndexed(2, 14, 15, points), new TriangleIndexed(2, 19, 18, points), new TriangleIndexed(7, 15, 23, points), }; return new Icosidodecahedron(pentagonPolys, triangles, points); }
private static Vector3D[] DistributeForces_UNECESSARRILYCOMLEX(Point3D[] bodyCenters, Point3D hitStart, Vector3D hitDirection, double mainBodyRadius, bool useDistDot = true, double distDotPow = .4) { Vector3D hitDirectionUnit = hitDirection.ToUnit(); double hitForceBase = hitDirection.Length / mainBodyRadius; var vectors = bodyCenters. Select(o => { Vector3D toPoint = o - hitStart; Vector3D toPointUnit = toPoint.ToUnit(); double dot = Vector3D.DotProduct(hitDirectionUnit, toPointUnit); double linearDot = Math3D.GetLinearDotProduct(hitDirectionUnit, toPointUnit); Vector3D along = toPoint.GetProjectedVector(hitDirection).ToUnit(false); Vector3D orth = (o - Math3D.GetClosestPoint_Line_Point(hitStart, hitDirection, o)).ToUnit(false); along *= linearDot; orth *= (1 - linearDot); double distance = toPoint.Length; // Exaggerate the distance based on dot product. That way, points in line with the hit will get more of the impact double scale = (1 - Math.Abs(linearDot)); scale = Math.Pow(scale, distDotPow); double scaledDistance = scale * distance; return new { ForcePoint = o, Distance = distance, ScaledDistance = scaledDistance, Along = along, Orth = orth, }; }). ToArray(); double[] distances = useDistDot ? vectors.Select(o => o.ScaledDistance).ToArray() : vectors.Select(o => o.Distance).ToArray(); double[] percents = ExplosionForceWorker.GetPercentOfProjForce(distances); Vector3D[] retVal = new Vector3D[vectors.Length]; for (int cntr = 0; cntr < vectors.Length; cntr++) { Vector3D along = vectors[cntr].Along * (hitForceBase * percents[cntr]); Vector3D orth = vectors[cntr].Orth * (hitForceBase * percents[cntr]); retVal[cntr] = along + orth; } return retVal; }
/// <summary> /// This will figure how much velocity to apply to each bodyCenter /// TODO: Also calculate angular velocities /// </summary> /// <param name="bodyCenters">The bodies to apply velocity to</param> /// <param name="hitStart">The point of impact</param> /// <param name="hitDirection">The direction and force of the impact</param> /// <param name="mainBodyRadius">The avg radius of the body that is getting blown apart</param> private static Vector3D[] DistributeForces(Point3D[] bodyCenters, Point3D hitStart, Vector3D hitDirection, double mainBodyRadius, HullVoronoiExploder_Options options) { Vector3D hitDirectionUnit = hitDirection.ToUnit(); double hitForceBase = hitDirection.Length / mainBodyRadius; var vectors = bodyCenters. Select(o => { Vector3D direction = o - hitStart; Vector3D directionUnit = direction.ToUnit(); double distance = direction.Length; double scaledDistance = distance; if (options.DistanceDot_Power != null) { double linearDot = Math3D.GetLinearDotProduct(hitDirectionUnit, directionUnit); // making it linear so the power function is more predictable // Exaggerate the distance based on dot product. That way, points in line with the hit will get more of the impact double scale = (1 - Math.Abs(linearDot)); scale = Math.Pow(scale, options.DistanceDot_Power.Value); scaledDistance = scale * distance; } return new { ForcePoint = o, Distance = distance, ScaledDistance = scaledDistance, DirectionUnit = directionUnit, }; }). ToArray(); double[] percents = GetPercentOfProjForce(vectors.Select(o => o.ScaledDistance).ToArray()); Vector3D[] retVal = new Vector3D[vectors.Length]; for (int cntr = 0; cntr < vectors.Length; cntr++) { retVal[cntr] = vectors[cntr].DirectionUnit * (hitForceBase * percents[cntr]); } return retVal; }
private static Point3D[] GetPlacements(int count, double minDistanceSquared, Point3D[] existing, Func<Vector3D> getRandVector) { Vector3D[] existingCast = existing == null ? new Vector3D[0] : existing.Select(o => o.ToVector()).ToArray(); List<Vector3D> retVal = new List<Vector3D>(); for (int cntr = 0; cntr < count; cntr++) { while (true) { // Ask the delegate for a random vector Vector3D test = getRandVector(); // Make sure this isn't too close to the other items bool wasTooClose = false; foreach (Vector3D prev in UtilityCore.Iterate(existingCast, retVal)) { double distance = (test - prev).LengthSquared; if (distance < minDistanceSquared) { wasTooClose = true; break; } } if (!wasTooClose) { retVal.Add(test); break; } } } // Exit Function return retVal.Select(o => o.ToPoint()).ToArray(); }
private static Point3D[] GetSpherePlacement(int count, double radius, double factor, Point3D[] existing) { // Calculate min distance double fourThirds = 4d / 3d; double volume = fourThirds * Math.PI * radius * radius * radius; volume *= factor; // give some slack (factor needs to be less than 1, the smaller it is, the closer they're allowed to be together) volume /= count + (existing == null ? 0 : existing.Length); // the sum of the little volumes can't exceed the total volume double minDistance = Math.Pow(volume / (fourThirds * Math.PI), 1d / 3d); // run the volume equation backward to get the radius // Convert to a vector array Vector3D[] existingVectors = null; if (existing != null) { existingVectors = existing.Select(o => o.ToVector()).ToArray(); } // Use this method instead. It should be a bit more efficient return Math3D.GetRandomVectors_Spherical_ClusteredMinDist(count, radius, minDistance, .001d, 1000, null, existingVectors, null).Select(o => o.ToPoint()).ToArray(); }
private double GetPercentVisible(Point3D[] polygon, Point3D[][] clipPolygons) { var transforms = Math2D.GetTransformTo2D(polygon); Point[][] clip2D = clipPolygons.Select(o => o.Select(p => transforms.Item1.Transform(p).ToPoint2D()).ToArray()).ToArray(); // Merge the polygons Polygon2D[] unions = null; try { unions = GetPolyUnion(clip2D); } catch (Exception ex) { throw; } // Get the area of the outer polygon double outerArea = Math2D.GetAreaPolygon(polygon.Select(o => transforms.Item1.Transform(o)).ToArray()); // Get the area of the inner polygons double innerArea = 0d; foreach (Polygon2D inner in unions) { double innerPoly = Math2D.GetAreaPolygon(inner.Polygon); double innerHoles = inner.Holes.Sum(o => Math2D.GetAreaPolygon(o)); // Add to the total innerArea += innerPoly - innerHoles; } return (outerArea - innerArea) / outerArea; }
private static Visual3D GetVisual_PolygonHull(Point3D[] polygon, Color color, double thickness) { if (polygon.Length < 3) { throw new ApplicationException("Need at least 3 points for a polygon"); } Vector3D normal = Math2D.GetPolygonNormal(polygon, PolygonNormalLength.Unit) * (thickness * .5d); Point3D[] top = polygon.Select(o => o + normal).ToArray(); Point3D[] bottom = polygon.Select(o => o - normal).ToArray(); TriangleIndexed[] topTriangles = Math2D.GetTrianglesFromConvexPoly(top); TriangleIndexed[] bottomTriangles = Math2D.GetTrianglesFromConvexPoly(bottom); //TODO: make triangles out of the sides // Material MaterialGroup materials = new MaterialGroup(); materials.Children.Add(new DiffuseMaterial(new SolidColorBrush(color))); materials.Children.Add(new SpecularMaterial(new SolidColorBrush(UtilityWPF.AlphaBlend(Colors.White, color, .5d)), 30d)); Model3DGroup geometries = new Model3DGroup(); // Geometry Model GeometryModel3D geometry = new GeometryModel3D(); geometry.Material = materials; geometry.BackMaterial = materials; geometry.Geometry = UtilityWPF.GetMeshFromTriangles_IndependentFaces(topTriangles); geometries.Children.Add(geometry); geometry = new GeometryModel3D(); geometry.Material = materials; geometry.BackMaterial = materials; geometry.Geometry = UtilityWPF.GetMeshFromTriangles_IndependentFaces(bottomTriangles); geometries.Children.Add(geometry); // Visual ModelVisual3D retVal = new ModelVisual3D(); retVal.Content = geometries; return retVal; }
private static Item3D DrawBrainGroup(Viewport3D viewport, Point3D[] points, Point3D center, Color color) { var lines = points. Select(o => Tuple.Create(o, center)); Visual3D visual = AddLines(viewport, lines, color, .09); return new Item3D(visual, 0, center); }