Exemplo n.º 1
0
        public void Update_AnyThread(double elapsedTime)
        {
            //TODO: Draw from energy (maybe only if non null)
            //if (_energyTanks.RemoveQuantity(elapsedTime * _volume * _itemOptions.VisionSensorAmountToDraw * ItemOptions.ENERGYDRAWMULT, true) > 0d)
            //{
            //    // The energy tank didn't have enough
            //    //NOTE: To be clean, I should set the neuron outputs to zero, but anything pulling from them should be checking this
            //    //anyway.  So save the processor (also, because of threading, setting them to zero isn't as atomic as this property)
            //    _isOn = false;
            //    return;
            //}

            //_isOn = true;

            Point linear = Math3D.GetCenter(_neurons_linear.Select(o => Tuple.Create(o.Position, o.Value)).ToArray()).ToPoint2D();


            //TODO: Look at the desired rotation
            //
            // Need to store the point that is being rotated around
            //
            // Basically a unit vector that holds the current location within a circle, then use radius to calculate the center of rotation for this tick



            _mousePlate.CurrentPoint2D = linear;
        }
Exemplo n.º 2
0
        private const double MOVEPERSTEPPERCENT = 1d;           // this seems to be stable with 100%, if nessassary, drop it down a bit so that parts don't move as far each step

        #endregion

        //TODO: Make a better version, probably a combination of pulling in and separating
        public static void PullInCrude(out bool changed, PartSeparator_Part[] parts)
        {
            // Figure out the max radius
            double[] sizes           = parts.Select(o => (o.Size.X + o.Size.Y + o.Size.Z) / 3d).ToArray();
            double   largestPart     = sizes.Max();
            double   maxRadius       = largestPart * 8d;
            double   maxRadiusSquare = maxRadius * maxRadius;

            Point3D center = Math3D.GetCenter(parts.Select(o => Tuple.Create(o.Position, o.Mass)).ToArray());

            changed = false;

            for (int cntr = 0; cntr < parts.Length; cntr++)
            {
                Vector3D offset = parts[cntr].Position - center;                //NOTE: This is just going to the center of the part, it's not considering the extents of the part (this method IS called crude)
                if (offset.LengthSquared < maxRadiusSquare)
                {
                    continue;
                }

                // Pull it straight in
                double difference = offset.Length - maxRadius;
                offset.Normalize();
                offset *= difference * -1d;

                parts[cntr].Position += offset;         //NOTE: I'm not going to change the center of mass

                changed = true;
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// This finds the best point by converting neuron positions/values into a hilly terrain, and taking a contour plot.
        /// The middle of the biggest polygon is the chosen point.
        /// </summary>
        private void Update_Contour()
        {
            const double CONTOURHEIGHT = .6667d;

            #region Set heights

            double maxHeight = 0;

            for (int cntr = 0; cntr < _neurons.Length; cntr++)
            {
                _terrainPoints[cntr].Z = _neurons[cntr].Value * 100;
                if (_terrainPoints[cntr].Z > maxHeight)
                {
                    maxHeight = _terrainPoints[cntr].Z;
                }
            }

            for (int cntr = 0; cntr < _terrainTriangles.Length; cntr++)
            {
                _terrainTriangles[cntr].PointsChanged();
            }

            double height = maxHeight * CONTOURHEIGHT;

            #endregion

            Triangle plane = new Triangle(new Point3D(-1, 0, height), new Point3D(1, 0, height), new Point3D(0, 1, height));      // normal needs to point up

            // Get the contour polygons
            var polys = Math3D.GetIntersection_Mesh_Plane(_terrainTriangles, plane);
            if (polys == null || polys.Length == 0)
            {
                // Nothing, don't move
                _mousePlate.CurrentPoint2D = new Point(0, 0);
                return;
            }
            else if (polys.Length == 1)
            {
                // Just one polygon, no need to take the expense of calculating volume
                _mousePlate.CurrentPoint2D = Math3D.GetCenter(polys[0].Polygon3D).ToPoint2D();
                return;
            }

            // Find the polygon with the highest volume
            var topPoly = polys.
                          Select(o => new { Poly = o, Volume = o.GetVolumeAbove() }).
                          OrderByDescending(o => o.Volume).
                          First();

            // Go to the center of this polygon
            _mousePlate.CurrentPoint2D = Math3D.GetCenter(topPoly.Poly.Polygon3D).ToPoint2D();
        }
Exemplo n.º 4
0
        /// <summary>
        /// This is a helper method to turn som node positions into points to pass to AddStaticItems()
        /// </summary>
        public static IEnumerable <Tuple <ISOMInput, Point3D> > GetSOMNodeStaticPositions(SOMNode node, SOMNode[] allNodes, double innerRadius)
        {
            // Convert to Point3D
            var initial = allNodes.
                          Select(o =>
            {
                Vector3D position = new Vector3D();
                if (o.Position.Size >= 1)
                {
                    position.X = o.Position[0];
                }
                if (o.Position.Size >= 2)
                {
                    position.Y = o.Position[1];
                }
                if (o.Position.Size >= 3)
                {
                    position.Z = o.Position[2];
                }

                return(Tuple.Create(o, position, position.Length));
            }).
                          OrderBy(o => o.Item3).
                          ToArray();

            // Find the closest one (that isn't the one passed in)
            var firstNonZero = initial.
                               Where(o => o.Item1.Token != node.Token).
                               FirstOrDefault(o => !o.Item3.IsNearZero());

            double scale = 1d;

            if (firstNonZero != null)
            {
                scale = (innerRadius * 1.25) / firstNonZero.Item3;
            }

            // Make sure they are spaced properly
            var scaled = initial.
                         Select(o => Tuple.Create(o.Item1, (o.Item2 * scale).ToPoint())).
                         ToArray();

            // These need to be centered over the origin, because the points will try to drift to the center
            Point3D  center = Math3D.GetCenter(scaled.Select(o => o.Item2));
            Vector3D offset = new Vector3D(-center.X, -center.Y, -center.Z);

            return(scaled.
                   Select(o => Tuple.Create((ISOMInput)o.Item1, o.Item2 + offset)).
                   ToArray());
        }
Exemplo n.º 5
0
        private static Vector3D[] GetForces(SketchDots sketches, bool useOutput, double mult)
        {
            // Give them a very slight pull toward the origin so that the cloud doesn't drift away
            Point3D center     = Math3D.GetCenter(sketches.Sketches.Select(o => o.Position));
            double  centerMult = mult * -5;

            Vector3D centerPullForce = center.ToVector() * centerMult;

            Vector3D[] retVal = Enumerable.Range(0, sketches.Sketches.Length).
                                Select(o => centerPullForce).
                                ToArray();

            // Figure out which set of distances to use
            var distances = useOutput ? sketches.Distances_Output : sketches.Distances_Input;

            foreach (var link in distances)
            {
                // Spring from 1 to 2
                Vector3D spring       = sketches.Sketches[link.Item2].Position - sketches.Sketches[link.Item1].Position;
                double   springLength = spring.Length;

                double difference = link.Item3 - springLength;
                difference *= mult;

                if (Math3D.IsNearZero(springLength))
                {
                    spring = Math3D.GetRandomVector_Spherical_Shell(Math.Abs(difference));
                }
                else
                {
                    spring = spring.ToUnit() * Math.Abs(difference);
                }

                if (difference > 0)
                {
                    // Gap needs to be bigger, push them away
                    retVal[link.Item1] -= spring;
                    retVal[link.Item2] += spring;
                }
                else if (difference < 0)
                {
                    // Close the gap
                    retVal[link.Item1] += spring;
                    retVal[link.Item2] -= spring;
                }
            }

            return(retVal);
        }
Exemplo n.º 6
0
        private static Tuple <HullVoronoiExploder_Response, bool> SplitHull(ITriangleIndexed[] convexHull, Tuple <Point3D, Vector3D, double>[] shots, HullVoronoiExploder_Options options, double aabbLen)
        {
            #region intersect with the hull

            var hits = shots.
                       Select(o => new HullVoronoiExploder_ShotHit()
            {
                Shot = o,
                Hit  = GetHit(convexHull, o.Item1, o.Item2, o.Item3),
            }).
                       Where(o => o.Hit != null).
                       ToArray();

            if (hits.Length == 0)
            {
                return(null);
            }

            #endregion

            #region voronoi

            Point3D[] controlPoints = GetVoronoiCtrlPoints(hits, convexHull, options.MinCount, options.MaxCount, aabbLen);

            VoronoiResult3D voronoi = Math3D.GetVoronoi(controlPoints, true);
            if (voronoi == null)
            {
                return(null);
            }

            #endregion

            // There is enough to start populating the response
            HullVoronoiExploder_Response retVal = new HullVoronoiExploder_Response()
            {
                Hits          = hits,
                ControlPoints = controlPoints,
                Voronoi       = voronoi,
            };

            #region intersect voronoi and hull

            // Intersect
            Tuple <int, ITriangleIndexed[]>[] shards = null;
            try
            {
                shards = Math3D.GetIntersection_Hull_Voronoi_full(convexHull, voronoi);
            }
            catch (Exception)
            {
                return(Tuple.Create(retVal, false));
            }

            if (shards == null)
            {
                return(Tuple.Create(retVal, false));
            }

            // Smooth
            if (options.ShouldSmoothShards)
            {
                shards = shards.
                         Select(o => Tuple.Create(o.Item1, Asteroid.SmoothTriangles(o.Item2))).
                         ToArray();
            }

            // Validate
            shards = shards.
                     Where(o => o.Item2 != null && o.Item2.Length >= 3).
                     Where(o =>
            {
                Vector3D firstNormal = o.Item2[0].NormalUnit;
                return(o.Item2.Skip(1).Any(p => !Math.Abs(Vector3D.DotProduct(firstNormal, p.NormalUnit)).IsNearValue(1)));
            }).
                     ToArray();

            if (shards.Length == 0)
            {
                return(Tuple.Create(retVal, false));
            }

            #endregion

            #region populate shards

            retVal.Shards = shards.
                            Select(o =>
            {
                var aabb = Math3D.GetAABB(o.Item2);

                double radius = Math.Sqrt((aabb.Item2 - aabb.Item1).Length / 2);

                Point3D center      = Math3D.GetCenter(TriangleIndexed.GetUsedPoints(o.Item2));
                Vector3D centerVect = center.ToVector();

                Point3D[] allPoints = o.Item2[0].AllPoints.
                                      Select(p => p - centerVect).
                                      ToArray();

                TriangleIndexed[] shiftedTriangles = o.Item2.
                                                     Select(p => new TriangleIndexed(p.Index0, p.Index1, p.Index2, allPoints)).
                                                     ToArray();

                return(new HullVoronoiExploder_Shard()
                {
                    VoronoiControlPointIndex = o.Item1,
                    Hull_ParentCoords = o.Item2,
                    Hull_Centered = shiftedTriangles,
                    Radius = radius,
                    Center_ParentCoords = center,
                });
            }).
                            Where(o => o != null).
                            ToArray();

            #endregion

            return(Tuple.Create(retVal, true));
        }
Exemplo n.º 7
0
 /// <summary>
 /// This is the average of the 4 points
 /// </summary>
 public Point3D GetCenterPoint()
 {
     return(Math3D.GetCenter(new[] { this.AllPoints[this.Index0], this.AllPoints[this.Index1], this.AllPoints[this.Index2], this.AllPoints[this.Index3] }));
 }
Exemplo n.º 8
0
        private static Model3DGroup GetModel_Klinth(WeaponSpikeBallDNA dna, WeaponSpikeBallDNA finalDNA, WeaponMaterialCache materials)
        {
            Model3DGroup retVal = new Model3DGroup();

            var from = dna.KeyValues;
            var to   = finalDNA.KeyValues;

            double spikeLength = WeaponDNA.GetKeyValue("spikeLength", from, to, StaticRandom.NextPercent(dna.Radius * 1.1d, .05));
            double ballRadius  = dna.Radius;

            double spikeRadius = WeaponDNA.GetKeyValue("spikeRadius", from, to, StaticRandom.NextPercent(dna.Radius * .2, .1));

            var color = WeaponMaterialCache.GetKlinth(dna.MaterialsForCustomizable);

            finalDNA.MaterialsForCustomizable = color.Item3;

            GeometryModel3D geometry;

            #region Ball

            geometry = new GeometryModel3D();

            geometry.Material     = color.Item1;
            geometry.BackMaterial = color.Item1;

            Icosidodecahedron ball = UtilityWPF.GetIcosidodecahedron(ballRadius);

            geometry.Geometry = UtilityWPF.GetMeshFromTriangles_IndependentFaces(ball.AllTriangles);

            retVal.Children.Add(geometry);

            #endregion

            #region Spikes

            // Put a spike through the center of each pentagon
            foreach (Vector3D spikeLocation in ball.PentagonPolys.Select(o => Math3D.GetCenter(o.Select(p => ball.AllPoints[p]))))
            {
                geometry = new GeometryModel3D();

                geometry.Material     = color.Item2;
                geometry.BackMaterial = color.Item2;

                RotateTransform3D transform = new RotateTransform3D(new QuaternionRotation3D(Math3D.GetRotation(new Vector3D(0, 0, 1), spikeLocation)));       // the tube builds along z

                List <TubeRingBase> rings = new List <TubeRingBase>();

                double spikeLengthMid = spikeLength * .8d;

                rings.Add(new TubeRingRegularPolygon(0, false, spikeRadius, spikeRadius, false));
                rings.Add(new TubeRingRegularPolygon(spikeLengthMid, false, spikeRadius, spikeRadius, false));
                rings.Add(new TubeRingDome(spikeLength - spikeLengthMid, false, 3));

                geometry.Geometry = UtilityWPF.GetMultiRingedTube(9, rings, false, false, transform);

                retVal.Children.Add(geometry);
            }

            #endregion

            return(retVal);
        }
Exemplo n.º 9
0
        private static Model3DGroup GetModel_Composite(WeaponSpikeBallDNA dna, WeaponSpikeBallDNA finalDNA, WeaponMaterialCache materials)
        {
            Model3DGroup retVal = new Model3DGroup();

            Random rand = StaticRandom.GetRandomForThread();

            var from = dna.KeyValues;
            var to   = finalDNA.KeyValues;

            double spikeOrthLength = WeaponDNA.GetKeyValue("spikeOrthLength", from, to, rand.NextPercent(dna.Radius * 1.4d, .1));
            double spikeDiagLength = WeaponDNA.GetKeyValue("spikeDiagLength", from, to, rand.NextPercent(dna.Radius * 1.15d, .05));
            double ballRadius      = dna.Radius;

            double spikeOrthRadius = WeaponDNA.GetKeyValue("spikeOrthRadius", from, to, rand.NextPercent(dna.Radius * .5, .1));
            double spikeDiagRadius = WeaponDNA.GetKeyValue("spikeDiagRadius", from, to, rand.NextPercent(dna.Radius * .5, .1));

            double ballRadiusDepth = ballRadius * .1;       //this is how far the triangle parts of the ball sink in

            var color = WeaponMaterialCache.GetComposite(dna.MaterialsForCustomizable);

            finalDNA.MaterialsForCustomizable = color.Item4;

            GeometryModel3D geometry;

            #region Ball - outer

            geometry = new GeometryModel3D();

            geometry.Material     = color.Item1;
            geometry.BackMaterial = color.Item1;

            Rhombicuboctahedron ball = UtilityWPF.GetRhombicuboctahedron(ballRadius * 2, ballRadius * 2, ballRadius * 2);

            TriangleIndexed[] usedTriangles = UtilityCore.Iterate(
                ball.Squares_Orth.SelectMany(o => o),
                ball.Squares_Diag.SelectMany(o => o),
                GetModel_Composite_SquareSides(ball, ballRadiusDepth * 1.1)       // this builds plates that go toward the center of the ball, because the triangles are indented
                ).ToArray();

            geometry.Geometry = UtilityWPF.GetMeshFromTriangles_IndependentFaces(usedTriangles);

            retVal.Children.Add(geometry);

            #endregion
            #region Ball - inner

            geometry = new GeometryModel3D();

            geometry.Material     = color.Item2;
            geometry.BackMaterial = color.Item2;

            // Use the triangles, but suck them in a bit
            geometry.Geometry = UtilityWPF.GetMeshFromTriangles_IndependentFaces(GetModel_Composite_IndentedTriangles(ball, ballRadiusDepth));

            retVal.Children.Add(geometry);

            #endregion

            #region Spikes

            var spikeLocations = UtilityCore.Iterate(ball.SquarePolys_Orth.Select(o => Tuple.Create(true, o)), ball.SquarePolys_Diag.Select(o => Tuple.Create(false, o))).
                                 Select(o => new { IsOrth = o.Item1, Center = Math3D.GetCenter(o.Item2.Select(p => ball.AllPoints[p])).ToVector() });

            // Put a spike through the center of each square
            foreach (var spikeLocation in spikeLocations)
            {
                geometry = new GeometryModel3D();

                geometry.Material     = color.Item3;
                geometry.BackMaterial = color.Item3;

                RotateTransform3D transform = new RotateTransform3D(new QuaternionRotation3D(Math3D.GetRotation(new Vector3D(0, 0, 1), spikeLocation.Center)));       // the tube builds along z

                List <TubeRingBase> rings = new List <TubeRingBase>();

                double spikeLengthActual = spikeLocation.IsOrth ? spikeOrthLength : spikeDiagLength;
                double spikeRadiusActual = spikeLocation.IsOrth ? spikeOrthRadius : spikeDiagRadius;

                rings.Add(new TubeRingRegularPolygon(0, false, spikeRadiusActual, spikeRadiusActual, false));
                rings.Add(new TubeRingPoint(spikeLengthActual, false));

                geometry.Geometry = UtilityWPF.GetMultiRingedTube(9, rings, true, false, transform);

                retVal.Children.Add(geometry);
            }

            #endregion

            return(retVal);
        }
Exemplo n.º 10
0
        private static Tuple <Dot, Vector3D>[] GetForces(DotVisuals dots, bool useOutput, double mult)
        {
            // Figure out which set of distances to use
            var distances = useOutput ? dots.Distances_Output : dots.Distances_Input;

            #region Calculate forces

            Tuple <Dot, Vector3D>[] forces = distances.
                                             //AsParallel().     //TODO: if distances.Length > threshold, do this in parallel
                                             SelectMany(o =>
            {
                // Spring from 1 to 2
                Vector3D spring     = o.Item2.Position - o.Item1.Position;
                double springLength = spring.Length;

                double difference = o.Item3 - springLength;
                difference       *= mult;

                if (Math1D.IsNearZero(springLength))
                {
                    spring = Math3D.GetRandomVector_Spherical_Shell(Math.Abs(difference));
                }
                else
                {
                    spring = spring.ToUnit() * Math.Abs(difference);
                }

                if (difference > 0)
                {
                    // Gap needs to be bigger, push them away (default is closing the gap)
                    spring = -spring;
                }

                return(new[]
                {
                    Tuple.Create(o.Item1, spring),
                    Tuple.Create(o.Item2, -spring)
                });
            }).
                                             ToArray();

            #endregion

            // Give them a very slight pull toward the origin so that the cloud doesn't drift away
            Point3D center     = Math3D.GetCenter(dots.Dots.Select(o => o.Position));
            double  centerMult = mult * -5;

            Vector3D centerPullForce = center.ToVector() * centerMult;

            // Group by dot
            var grouped = forces.
                          GroupBy(o => o.Item1.Token);

            return(grouped.
                   Select(o =>
            {
                Vector3D sum = centerPullForce;
                Dot dot = null;

                foreach (var force in o)
                {
                    dot = force.Item1;
                    sum += force.Item2;
                }

                return Tuple.Create(dot, sum);
            }).
                   ToArray());
        }