コード例 #1
0
 public void FindAnyPerpendicular_GivenNullVector_ReturnsUndefinedVector()
 {
     var v = new Vector3D(0, 0, 0);
     var p = v.FindAnyPerpendicular();
     Assert.IsTrue(p.IsUndefined());
     Assert.AreEqual(new Vector3D(0, 0, 0), v); // check that the input vector is unchanged
 }
コード例 #2
0
 public void FindAnyPerpendicular_GivenLargeVector_ReturnsUnitZ()
 {
     var v = new Vector3D(1e-100, 1e100, 0);
     var p = v.FindAnyPerpendicular();
     Assert.AreEqual(new Vector3D(0, 0, 1), p);
     Assert.AreEqual(new Vector3D(1e-100, 1e100, 0), v); // check that the input vector is unchanged
 }
コード例 #3
0
ファイル: Plant.cs プロジェクト: XiBeichuan/hydronumerics
        private void AddBranch(MeshBuilder mesh, Point3D p0, Vector3D direction, int p)
        {
            double angle = GetAngleBetween(direction, UpVector);
            bool isStem = angle < 10;


            double h = isStem ? 2.5 : 2;
            double r = (Level+1-p)*0.1;

            mesh.AddCone(p0, direction, r, r * 0.8, h, false, false, 12);
            var p1 = p0 + direction*h;

            if (p == Level)
                return;

            if (isStem)
            {
                var rightVector=direction.FindAnyPerpendicular();
                var t0 = new RotateTransform3D(new AxisAngleRotation3D(rightVector, GetRandom(3)));
                AddBranch(mesh, p1, t0.Transform(direction), p + 1);
                
                var t1 = new RotateTransform3D(new AxisAngleRotation3D(rightVector, 95 + GetRandom(5)));
                var d1 = t1.Transform(direction);
                int nBranches = 5+GetRandom(2);
                for (int i = 0; i < nBranches; i++)
                {
                    double a = 360.0 * i / nBranches + GetRandom(25);
                    var t2 = new RotateTransform3D(new AxisAngleRotation3D(UpVector, a));
                    AddBranch(mesh, p1, t2.Transform(d1), p + 1);
                }
            } else
            {
                var rightVector=Vector3D.CrossProduct(direction, UpVector);
                var t1 = new RotateTransform3D(new AxisAngleRotation3D(rightVector, -5 + GetRandom(5)));
                var t2 = new RotateTransform3D(new AxisAngleRotation3D(UpVector, 45+GetRandom(10)));
                var t3 = new RotateTransform3D(new AxisAngleRotation3D(UpVector, -45 + GetRandom(10)));
                var d1 = t1.Transform(direction);
                AddBranch(mesh, p1, d1, p + 1);
                AddBranch(mesh, p1, t2.Transform(d1), p + 1);
                AddBranch(mesh, p1, t3.Transform(d1), p + 1);                
            }
        }
コード例 #4
0
        private static Transform3D CreateBodyTransform(Point3D p, Vector3D z)
        {
            double length = z.Length;
            z.Normalize();
            var x = z.FindAnyPerpendicular();
            x.Normalize();
            var y = Vector3D.CrossProduct(z, x);

            var mat = new Matrix3D(x.X, x.Y, x.Z, 0, y.X, y.Y, y.Z, 0, z.X*length, z.Y*length, z.Z*length, 0, p.X, p.Y, p.Z, 1);
            return new MatrixTransform3D(mat);
        }
コード例 #5
0
        private static Transform3D CreateHeadTransform(Point3D p, Vector3D z)
        {
            z.Normalize();
            var x = z.FindAnyPerpendicular();
            x.Normalize();
            var y = Vector3D.CrossProduct(z, x);

            var mat = new Matrix3D(
                x.X, x.Y, x.Z, 0,
                y.X, y.Y, y.Z, 0,
                z.X, z.Y, z.Z, 0, p.X, p.Y, p.Z, 1);

            return new MatrixTransform3D(mat);
        }
コード例 #6
0
        /// <summary>
        /// Adds a surface of revolution.
        /// </summary>
        /// <param name="origin">The origin.</param>
        /// <param name="axis">The axis.</param>
        /// <param name="section">The points defining the curve to revolve.</param>
        /// <param name="sectionIndices">The indices of the line segments of the section.</param>
        /// <param name="thetaDiv">The number of divisions.</param>
        /// <param name="textureValues">The texture values.</param>
        public void AddSurfaceOfRevolution(
            Point3D origin,
            Vector3D axis,
            IList<Point> section,
            IList<int> sectionIndices,
            int thetaDiv = 37,
            IList<double> textureValues = null)
        {
            if (this.textureCoordinates != null && textureValues == null)
            {
                throw new ArgumentNullException("textureValues");
            }

            if (textureValues != null && textureValues.Count != section.Count)
            {
                throw new InvalidOperationException(WrongNumberOfTextureCoordinates);
            }

            axis.Normalize();

            // Find two unit vectors orthogonal to the specified direction
            var u = axis.FindAnyPerpendicular();
            var v = Vector3D.CrossProduct(axis, u);
            var circle = GetCircle(thetaDiv);
            int n = section.Count;
            int index0 = this.positions.Count;
            for (int i = 0; i < thetaDiv; i++)
            {
                var w = (v * circle[i].X) + (u * circle[i].Y);
                for (int j = 0; j < n; j++)
                {
                    var q1 = origin + (axis * section[j].Y) + (w * section[j].X);
                    this.positions.Add(q1);
                    if (this.normals != null)
                    {
                        double tx = section[j + 1].X - section[j].X;
                        double ty = section[j + 1].Y - section[j].Y;
                        var normal = (-axis * ty) + (w * tx);
                        normal.Normalize();
                        this.normals.Add(normal);
                    }

                    if (this.textureCoordinates != null)
                    {
                        this.textureCoordinates.Add(new Point((double)i / (thetaDiv - 1), textureValues == null ? (double)j / (n - 1) : textureValues[j]));
                    }
                }
            }

            for (int i = 0; i < thetaDiv; i++)
            {
                var ii = (i + 1) % thetaDiv;
                for (int j = 0; j + 1 < sectionIndices.Count; j += 2)
                {
                    var j0 = sectionIndices[j];
                    var j1 = sectionIndices[j + 1];

                    int i0 = index0 + (i * n) + j0;
                    int i1 = index0 + (ii * n) + j0;
                    int i2 = index0 + (i * n) + j1;
                    int i3 = index0 + (ii * n) + j1;

                    this.triangleIndices.Add(i0);
                    this.triangleIndices.Add(i1);
                    this.triangleIndices.Add(i3);

                    this.triangleIndices.Add(i3);
                    this.triangleIndices.Add(i2);
                    this.triangleIndices.Add(i0);
                }
            }
        }
コード例 #7
0
        /// <summary>
        /// Adds a surface of revolution.
        /// </summary>
        /// <param name="points">The points (x coordinates are distance from the origin along the axis of revolution, y coordinates are radius, )</param>
        /// <param name="textureValues">The v texture coordinates, one for each point in the <paramref name="points" /> list.</param>
        /// <param name="origin">The origin of the revolution axis.</param>
        /// <param name="direction">The direction of the revolution axis.</param>
        /// <param name="thetaDiv">The number of divisions around the mesh.</param>
        /// <remarks>
        /// See http://en.wikipedia.org/wiki/Surface_of_revolution.
        /// </remarks>
        public void AddRevolvedGeometry(IList<Point> points, IList<double> textureValues, Point3D origin, Vector3D direction, int thetaDiv)
        {
            direction.Normalize();

            // Find two unit vectors orthogonal to the specified direction
            var u = direction.FindAnyPerpendicular();
            var v = Vector3D.CrossProduct(direction, u);

            u.Normalize();
            v.Normalize();

            var circle = GetCircle(thetaDiv);

            int index0 = this.positions.Count;
            int n = points.Count;

            int totalNodes = (points.Count - 1) * 2 * thetaDiv;
            int rowNodes = (points.Count - 1) * 2;

            for (int i = 0; i < thetaDiv; i++)
            {
                var w = (v * circle[i].X) + (u * circle[i].Y);

                for (int j = 0; j + 1 < n; j++)
                {
                    // Add segment
                    var q1 = origin + (direction * points[j].X) + (w * points[j].Y);
                    var q2 = origin + (direction * points[j + 1].X) + (w * points[j + 1].Y);

                    // TODO: should not add segment if q1==q2 (corner point)
                    // const double eps = 1e-6;
                    // if (Point3D.Subtract(q1, q2).LengthSquared < eps)
                    // continue;
                    this.positions.Add(q1);
                    this.positions.Add(q2);

                    if (this.normals != null)
                    {
                        double tx = points[j + 1].X - points[j].X;
                        double ty = points[j + 1].Y - points[j].Y;
                        var normal = (-direction * ty) + (w * tx);
                        normal.Normalize();

                        this.normals.Add(normal);
                        this.normals.Add(normal);
                    }

                    if (this.textureCoordinates != null)
                    {
                        this.textureCoordinates.Add(new Point((double)i / (thetaDiv - 1), textureValues == null ? (double)j / (n - 1) : textureValues[j]));
                        this.textureCoordinates.Add(new Point((double)i / (thetaDiv - 1), textureValues == null ? (double)(j + 1) / (n - 1) : textureValues[j + 1]));
                    }

                    int i0 = index0 + (i * rowNodes) + (j * 2);
                    int i1 = i0 + 1;
                    int i2 = index0 + ((((i + 1) * rowNodes) + (j * 2)) % totalNodes);
                    int i3 = i2 + 1;

                    this.triangleIndices.Add(i1);
                    this.triangleIndices.Add(i0);
                    this.triangleIndices.Add(i2);

                    this.triangleIndices.Add(i1);
                    this.triangleIndices.Add(i2);
                    this.triangleIndices.Add(i3);
                }
            }
        }
コード例 #8
0
        /// <summary>
        /// Add a surface of revolution
        /// http://en.wikipedia.org/wiki/Surface_of_revolution
        /// </summary>
        /// <param name="points">The points.</param>
        /// <param name="origin">The origin.</param>
        /// <param name="direction">The direction.</param>
        /// <param name="thetaDiv">The theta div.</param>
        public void AddRevolvedGeometry(PointCollection points, Point3D origin, Vector3D direction, int thetaDiv)
        {
            direction.Normalize();

            // Find two unit vectors orthogonal to the specified direction
            var u = direction.FindAnyPerpendicular();
            var v = Vector3D.CrossProduct(direction, u);

            u.Normalize();
            v.Normalize();


            var circle = GetCircle(thetaDiv);

            int index0 = positions.Count;
            int nPoints = points.Count;

            int totalNodes = (points.Count - 1) * 2 * thetaDiv;
            int rowNodes = (points.Count - 1) * 2;

            for (int i = 0; i < thetaDiv; i++)
            {
                Vector3D w = v * circle[i].X + u * circle[i].Y;

                for (int j = 0; j + 1 < nPoints; j++)
                {
                    // Add segment
                    var q1 = origin + direction * points[j].X + w * points[j].Y;
                    var q2 = origin + direction * points[j + 1].X + w * points[j + 1].Y;


                    // todo:should not add segment if q1==q2 (corner point)
                    // const double eps = 1e-6;
                    // if (Point3D.Subtract(q1, q2).LengthSquared < eps)
                    //    continue;

                    double tx = points[j + 1].X - points[j].X;
                    double ty = points[j + 1].Y - points[j].Y;

                    var normal = -direction * ty + w * tx;
                    normal.Normalize();

                    positions.Add(q1);
                    positions.Add(q2);

                    if (normals != null)
                    {
                        normals.Add(normal);
                        normals.Add(normal);
                    }

                    if (textureCoordinates != null)
                    {
                        textureCoordinates.Add(new Point((double)i / (thetaDiv - 1), (double)j / (nPoints - 1)));
                        textureCoordinates.Add(new Point((double)i / (thetaDiv - 1), (double)(j + 1) / (nPoints - 1)));
                    }

                    int i0 = index0 + i * rowNodes + j * 2;
                    int i1 = i0 + 1;
                    int i2 = index0 + ((i + 1) * rowNodes + j * 2) % totalNodes;
                    int i3 = i2 + 1;

                    triangleIndices.Add(i1);
                    triangleIndices.Add(i2);
                    triangleIndices.Add(i0);

                    triangleIndices.Add(i1);
                    triangleIndices.Add(i3);
                    triangleIndices.Add(i2);
                }
            }
        }