private static Model3D GetModel_Symetrical_Axe(BezierSegment3D[][] segmentSets, MaterialGroup materialMiddle, MaterialGroup materialEdge, AxeSymetricalProps arg)
        {
            Model3DGroup retVal = new Model3DGroup();

            int squareCount = 8;

            // 2 is z=0.  0,4 are z=max.  1,3 are intermediate z's

            AddBezierPlates(squareCount, segmentSets[0], segmentSets[1], retVal, materialMiddle);

            AddBezierPlates(squareCount, new[] { segmentSets[1][0], segmentSets[1][1] }, new[] { segmentSets[2][0], segmentSets[2][1] }, retVal, materialMiddle);
            AddBezierPlate(squareCount, segmentSets[1][2], segmentSets[2][2], retVal, materialEdge);

            AddBezierPlates(squareCount, new[] { segmentSets[2][0], segmentSets[2][1] }, new[] { segmentSets[3][0], segmentSets[3][1] }, retVal, materialMiddle);
            AddBezierPlate(squareCount, segmentSets[2][2], segmentSets[3][2], retVal, materialEdge);

            AddBezierPlates(squareCount, segmentSets[3], segmentSets[4], retVal, materialMiddle);

            // End cap plates
            if (arg.isCenterFilled)
            {
                for (int cntr = 0; cntr < 2; cntr++)
                {
                    int index = cntr == 0 ? 0 : 4;

                    AddBezierPlate(squareCount, segmentSets[index][0], segmentSets[index][1], retVal, materialMiddle);        // top - bottom

                    BezierSegment3D extraSeg = new BezierSegment3D(segmentSets[index][2].EndIndex0, segmentSets[index][2].EndIndex1, null, segmentSets[index][2].AllEndPoints);
                    AddBezierPlate(squareCount, extraSeg, segmentSets[index][2], retVal, materialMiddle);     // edge
                }
            }
            else
            {
                AddBezierPlates(squareCount, segmentSets[0], segmentSets[4], retVal, materialMiddle);
            }

            return retVal;
        }
        private static BezierSegment3D[] TestAxeSimple2_Segments(Curves_AxeSimple2 arg)
        {
            Point3D[] points = arg.GetAllPoints();

            // Top
            BezierSegment3D top = new BezierSegment3D(arg.IndexTL, arg.IndexTR, null, points);

            // Edge
            Point3D controlTR = BezierUtil.GetControlPoint_End(arg.EndTR, arg.EndBR, arg.EndBL_1, true, arg.EdgeAngleT, arg.EdgePercentT);
            Point3D controlBR = BezierUtil.GetControlPoint_End(arg.EndBR, arg.EndTR, arg.EndTL, true, arg.EdgeAngleB, arg.EdgePercentB);
            BezierSegment3D edge = new BezierSegment3D(arg.IndexTR, arg.IndexBR, new[] { controlTR, controlBR }, points);

            // Bottom (right portion)
            BezierSegment3D bottomRight = null;
            if (arg.EndBL_2 == null)
            {
                Point3D controlR = BezierUtil.GetControlPoint_End(arg.EndBR, arg.EndBL_1, arg.EndTR, false, arg.B1AngleR, arg.B1PercentR);
                Point3D controlL = BezierUtil.GetControlPoint_End(arg.EndBL_1, arg.EndBR, arg.EndTR, false, arg.B1AngleL, arg.B1PercentL);
                bottomRight = new BezierSegment3D(arg.IndexBR, arg.IndexBL_1, new[] { controlR, controlL }, points);
            }
            else
            {
                bottomRight = new BezierSegment3D(arg.IndexBR, arg.IndexBL_1, null, points);
            }

            // Bottom (left portion)
            BezierSegment3D bottomLeft = null;
            if (arg.EndBL_2 != null)
            {
                Point3D controlR = BezierUtil.GetControlPoint_End(arg.EndBL_1, arg.EndBL_2.Value, arg.EndTR, false, arg.B2AngleR, arg.B2PercentR);
                Point3D controlL = BezierUtil.GetControlPoint_End(arg.EndBL_2.Value, arg.EndBL_1, arg.EndTR, false, arg.B2AngleL, arg.B2PercentL);
                bottomLeft = new BezierSegment3D(arg.IndexBL_1, arg.IndexBL_2, new[] { controlR, controlL }, points);
            }

            return UtilityCore.Iterate<BezierSegment3D>(top, edge, bottomRight, bottomLeft).ToArray();
        }
Exemple #3
0
 /// <summary>
 /// Get a single point along the curve
 /// </summary>
 public static Point3D GetPoint(double percent, BezierSegment3D segment)
 {
     return GetPoint(percent, UtilityCore.Iterate<Point3D>(segment.EndPoint0, segment.ControlPoints, segment.EndPoint1).ToArray());
 }
Exemple #4
0
        //TODO: Put this in Math3D
        public static Point3D BicubicInterpolation(BezierSegment3D top, BezierSegment3D bottom, BezierSegment3D left, BezierSegment3D right, double percentX, double percentY)
        {
            Point3D valueTop = BezierUtil.GetPoint(percentX, top);
            Point3D valueBottom = BezierUtil.GetPoint(percentX, bottom);

            Point3D valueLeft = BezierUtil.GetPoint(percentY, left);
            Point3D valueRight = BezierUtil.GetPoint(percentY, right);

            var points = new[]
                {
                    Tuple.Create(valueTop, 1 - percentY),
                    Tuple.Create(valueBottom, percentY),
                    Tuple.Create(valueLeft, 1 - percentX),
                    Tuple.Create(valueRight, percentX),
                };

            return Math3D.GetCenter(points);
        }
Exemple #5
0
        /// <summary>
        /// This returns points across sets of segment definition.  Each set is run through the other path overload.  So the endpoints
        /// of each set are guaranteed to be included in the return points (deduped)
        /// </summary>
        /// <param name="countPerPath">This is how many points per set (the total number of points will be countPerPath * segmentSets.Length)</param>
        public static Point3D[] GetPath(int countPerPath, BezierSegment3D[][] segmentSets)
        {
            //TODO: Make an overload that takes in total count instead of per path

            // Get the points for each set of beziers
            List<Point3D[]> perPathPoints = new List<Point3D[]>();

            foreach (BezierSegment3D[] segments in segmentSets)
            {
                if (segments.Length == 1)
                {
                    perPathPoints.Add(GetPoints(countPerPath, segments[0]));
                }
                else
                {
                    perPathPoints.Add(GetPath(countPerPath, segments));
                }
            }

            // Dedupe them
            List<Point3D> retVal = new List<Point3D>();

            retVal.AddRange(perPathPoints[0]);

            for (int cntr = 1; cntr < perPathPoints.Count; cntr++)
            {
                if (Math3D.IsNearValue(retVal[retVal.Count - 1], perPathPoints[cntr][0]))
                {
                    // First point dupes with the last
                    retVal.AddRange(perPathPoints[cntr].Skip(1));
                }
                else
                {
                    retVal.AddRange(perPathPoints[cntr]);
                }
            }

            if (Math3D.IsNearValue(retVal[0], retVal[retVal.Count - 1]))
            {
                retVal.RemoveAt(retVal.Count - 1);
            }

            return retVal.ToArray();
        }
Exemple #6
0
        private static BezierSegment3D[] GetBezierSegments_Open(Point3D[] ends, double along = .25)
        {
            // Precalculate the control points
            Tuple<Point3D, Point3D>[] controls = new Tuple<Point3D, Point3D>[ends.Length - 2];

            for (int cntr = 1; cntr < ends.Length - 1; cntr++)
            {
                Tuple<double, double> adjustedAlong = GetAdjustedRatios(ends[cntr - 1], ends[cntr], ends[cntr + 1], along);

                controls[cntr - 1] = GetControlPoints_Middle(ends[cntr - 1], ends[cntr], ends[cntr + 1], adjustedAlong.Item1, adjustedAlong.Item2);
            }

            // Build the return segments
            BezierSegment3D[] retVal = new BezierSegment3D[ends.Length - 1];

            for (int cntr = 0; cntr < ends.Length - 1; cntr++)
            {
                Point3D? ctrl0 = cntr == 0 ? (Point3D?)null : controls[cntr - 1].Item2;
                Point3D? ctrl1 = cntr == ends.Length - 2 ? (Point3D?)null : controls[cntr].Item1;

                retVal[cntr] = new BezierSegment3D(cntr, cntr + 1, UtilityCore.Iterate<Point3D>(ctrl0, ctrl1).ToArray(), ends);
            }

            return retVal;
        }
        private void DrawBellFail()
        {
            double midX = trkBellFailPeak.Value;

            BezierSegment3D[] bezier = BezierUtil.GetBezierSegments(new[] { new Point3D(0, 0, 0), new Point3D(midX, 1, 0), new Point3D(1, 0, 0) }, trkBellFailPinch.Value);

            // Add a control point so the curve will be attracted to the x axis at the two end points
            double run;
            if (trkBellFailLeftZero.Value > 0)
            {
                run = (bezier[0].EndPoint1.X - bezier[0].EndPoint0.X) * trkBellFailLeftZero.Value;
                bezier[0] = new BezierSegment3D(bezier[0].EndIndex0, bezier[0].EndIndex1, new[] { new Point3D(run, 0, 0), bezier[0].ControlPoints[0] }, bezier[0].AllEndPoints);
            }

            if (trkBellFailRightZero.Value > 0)
            {
                run = (bezier[1].EndPoint1.X - bezier[1].EndPoint0.X) * trkBellFailRightZero.Value;
                bezier[1] = new BezierSegment3D(bezier[1].EndIndex0, bezier[1].EndIndex1, new[] { bezier[1].ControlPoints[0], new Point3D(bezier[1].EndPoint1.X - run, 0, 0), }, bezier[1].AllEndPoints);
            }

            Random rand = StaticRandom.GetRandomForThread();

            //TODO: There is still a bug with calculating percent, or something
            //It might be treating X as a percent.  Maybe need to get the length of the lines, and take the percent of those???? - should be the same though

            IEnumerable<double> samples = Enumerable.Range(0, 50000).
                Select(o =>
                    {
                        double percent = rand.NextDouble();

                        int index;
                        if (percent < midX)
                        {
                            index = 0;
                            percent = percent / midX;
                        }
                        else
                        {
                            index = 1;
                            percent = (percent - midX) / (1d - midX);
                        }

                        double retVal = BezierUtil.GetPoint(percent, bezier[index]).Y;

                        if (retVal < 0) retVal = 0;
                        else if (retVal > 1) retVal = 1;

                        return retVal;
                    });

            IEnumerable<Point> idealLine = BezierUtil.GetPath(100, bezier).
                Select(o => o.ToPoint2D());

            DrawGraph(samples, idealLine);
        }
        private void DrawBezierPlate(int count, BezierSegment3D seg1, BezierSegment3D seg2, Color color, bool isShiny, bool ensureNormalsPointTheSame = false)
        {
            Point3D[] rim1 = BezierUtil.GetPoints(count, seg1);
            Point3D[] rim2 = BezierUtil.GetPoints(count, seg2);

            Point3D[] allPoints = UtilityCore.Iterate(rim1, rim2).ToArray();

            List<TriangleIndexed> triangles = new List<TriangleIndexed>();

            for (int cntr = 0; cntr < count - 1; cntr++)
            {
                triangles.Add(new TriangleIndexed(count + cntr, count + cntr + 1, cntr, allPoints));        // bottom left
                triangles.Add(new TriangleIndexed(cntr + 1, cntr, count + cntr + 1, allPoints));        // top right
            }

            #region Ensure all normals point the same way

            //Doesn't work
            //if (ensureNormalsPointTheSame)
            //{
            //    Vector3D firstNormal = triangles[0].Normal;
            //    bool[] sameNormals = triangles.Select(o => Vector3D.DotProduct(firstNormal, o.Normal) > 0).ToArray();

            //    int sameCount = sameNormals.Where(o => o).Count();

            //    if (sameCount != triangles.Count)
            //    {
            //        // Some up, some down.  Majority rules
            //        bool fixDifferents = sameCount > triangles.Count / 2;

            //        for(int cntr = 0; cntr < triangles.Count; cntr++)
            //        {
            //            if(sameNormals[cntr] != fixDifferents)
            //            {
            //                triangles[cntr] = new TriangleIndexed(triangles[cntr].Index1, triangles[cntr].Index0, triangles[cntr].Index2, triangles[cntr].AllPoints);
            //            }
            //        }
            //    }
            //}

            #endregion

            // Material
            MaterialGroup materials = new MaterialGroup();
            materials.Children.Add(new DiffuseMaterial(new SolidColorBrush(color)));
            if (isShiny)
            {
                materials.Children.Add(new SpecularMaterial(new SolidColorBrush(UtilityWPF.AlphaBlend(color, Colors.White, .5d)), 5d));
            }
            else
            {
                Color derivedColor = UtilityWPF.AlphaBlend(color, Colors.White, .8d);
                materials.Children.Add(new SpecularMaterial(new SolidColorBrush(Color.FromArgb(128, derivedColor.R, derivedColor.G, derivedColor.B)), 2d));
            }

            // Geometry Model
            GeometryModel3D geometry = new GeometryModel3D();
            geometry.Material = materials;
            geometry.BackMaterial = materials;
            geometry.Geometry = UtilityWPF.GetMeshFromTriangles(triangles.ToArray());

            // Model Visual
            ModelVisual3D model = new ModelVisual3D();
            model.Content = geometry;

            // Temporarily add to the viewport
            _viewport.Children.Add(model);
            _visuals.Add(model);
        }
        private static void AddBezierPlate(int count, BezierSegment3D seg1, BezierSegment3D seg2, Model3DGroup group, Material material)
        {
            // Since the bezier curves will have the same number of points, create a bunch of squares linking them (it's up to the caller
            // to make sure the curves don't cross, or you would get a bow tie)
            Point3D[] rim1 = BezierUtil.GetPoints(count, seg1);
            Point3D[] rim2 = BezierUtil.GetPoints(count, seg2);

            Point3D[] allPoints = UtilityCore.Iterate(rim1, rim2).ToArray();

            List<TriangleIndexed> triangles = new List<TriangleIndexed>();

            for (int cntr = 0; cntr < count - 1; cntr++)
            {
                triangles.Add(new TriangleIndexed(count + cntr, count + cntr + 1, cntr, allPoints));        // bottom left
                triangles.Add(new TriangleIndexed(cntr + 1, cntr, count + cntr + 1, allPoints));        // top right
            }

            // Geometry Model
            GeometryModel3D geometry = new GeometryModel3D();
            geometry.Material = material;
            geometry.BackMaterial = material;
            geometry.Geometry = UtilityWPF.GetMeshFromTriangles(triangles.ToArray());

            group.Children.Add(geometry);
        }
        private void BellFailDebug_Click(object sender, RoutedEventArgs e)
        {
            const int COUNT = 25;


            // The problem that this method illustrates is that rand.nextdouble() is thought of as x, but it's really % along arc length of the curve
            // And because there are two curves, it's some hacked up hybrid
            //
            // The original intent was to get the y coord at some fixed x.  But there's no one single calculation that would get that.  Samples would
            // need to be taken to figure out which percent along curve to use to get the desired x, and corresponding y



            try
            {
                double midX = trkBellFailPeak.Value;

                BezierSegment3D[] bezier = BezierUtil.GetBezierSegments(new[] { new Point3D(0, 0, 0), new Point3D(midX, 1, 0), new Point3D(1, 0, 0) }, trkBellFailPinch.Value);

                // Add a control point so the curve will be attracted to the x axis at the two end points
                double run;
                if (trkBellFailLeftZero.Value > 0)
                {
                    run = (bezier[0].EndPoint1.X - bezier[0].EndPoint0.X) * trkBellFailLeftZero.Value;
                    bezier[0] = new BezierSegment3D(bezier[0].EndIndex0, bezier[0].EndIndex1, new[] { new Point3D(run, 0, 0), bezier[0].ControlPoints[0] }, bezier[0].AllEndPoints);
                }

                if (trkBellFailRightZero.Value > 0)
                {
                    run = (bezier[1].EndPoint1.X - bezier[1].EndPoint0.X) * trkBellFailRightZero.Value;
                    bezier[1] = new BezierSegment3D(bezier[1].EndIndex0, bezier[1].EndIndex1, new[] { bezier[1].ControlPoints[0], new Point3D(bezier[1].EndPoint1.X - run, 0, 0), }, bezier[1].AllEndPoints);
                }




                //bezier[0] = new BezierSegment3D(bezier[0].EndIndex0, bezier[0].EndIndex1, new Point3D[0], bezier[0].AllEndPoints);
                //bezier[1] = new BezierSegment3D(bezier[1].EndIndex0, bezier[1].EndIndex1, new Point3D[0], bezier[1].AllEndPoints);




                var samples = Enumerable.Range(0, COUNT).
                    Select(o =>
                    {
                        double percentOrig = o.ToDouble() / COUNT.ToDouble();

                        int index;
                        double percent;
                        if (percentOrig < midX)
                        {
                            index = 0;
                            percent = percentOrig / midX;
                        }
                        else
                        {
                            index = 1;
                            percent = (percentOrig - midX) / (1d - midX);
                        }

                        Point3D point = BezierUtil.GetPoint(percent, bezier[index]);

                        //if (retVal < 0) retVal = 0;
                        //else if (retVal > 1) retVal = 1;

                        return new
                        {
                            PercentOrig = percentOrig,
                            PercentSub = percent,
                            Index = index,
                            Point = point,
                        };
                    }).
                    ToArray();



                Clear();

                Rect bounds = GetBounds();

                // Grid
                AddLine(bounds.BottomLeft, bounds.TopRight, _brushVeryLight);      // diagonal

                AddLine(bounds.TopLeft, bounds.TopRight, _brushVeryLight);      // 1
                double y = bounds.Bottom - (bounds.Height * .75);
                AddLine(new Point(bounds.Left, y), new Point(bounds.Right, y), _brushVeryLight);      // .75
                y = bounds.Bottom - (bounds.Height * .5);
                AddLine(new Point(bounds.Left, y), new Point(bounds.Right, y), _brushVeryLight);      // .5
                y = bounds.Bottom - (bounds.Height * .25);
                AddLine(new Point(bounds.Left, y), new Point(bounds.Right, y), _brushVeryLight);      // .25

                AddLine(new[] { bounds.TopLeft, bounds.BottomLeft, bounds.BottomRight }, _brushDark);     // axiis

                // Samples
                foreach (var sample in samples)
                {
                    AddLine(new Point(bounds.Left + (sample.PercentOrig * bounds.Width), bounds.Bottom), new Point(bounds.Left + (sample.Point.X * bounds.Width), bounds.Bottom - (sample.Point.Y * bounds.Height)), Brushes.Black);
                }


            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
Exemple #11
0
 // WPF models
 private static void AddBezierPlates(int count, BezierSegment3D[] seg1, BezierSegment3D[] seg2, Model3DGroup group, Material material)
 {
     for (int cntr = 0; cntr < seg1.Length; cntr++)
     {
         AddBezierPlate(count, seg1[cntr], seg2[cntr], group, material);
     }
 }
Exemple #12
0
        private static Model3D GetModel_Second_Axe(BezierSegment3D[][] segmentSets, MaterialGroup materialMiddle, MaterialGroup materialEdge)
        {
            Model3DGroup retVal = new Model3DGroup();

            int numSegments = segmentSets[0].Length;

            int squareCount = 8;

            // 2 is z=0.  0,4 are z=max.  1,3 are intermediate z's

            // Z to Z
            AddBezierPlates(squareCount, segmentSets[0], segmentSets[1], retVal, materialMiddle);

            if (numSegments == 3)
            {
                AddBezierPlates(squareCount, new[] { segmentSets[1][0], segmentSets[1][2] }, new[] { segmentSets[2][0], segmentSets[2][2] }, retVal, materialMiddle);
                AddBezierPlate(squareCount, segmentSets[1][1], segmentSets[2][1], retVal, materialEdge);

                AddBezierPlates(squareCount, new[] { segmentSets[2][0], segmentSets[2][2] }, new[] { segmentSets[3][0], segmentSets[3][2] }, retVal, materialMiddle);
                AddBezierPlate(squareCount, segmentSets[2][1], segmentSets[3][1], retVal, materialEdge);
            }
            else
            {
                AddBezierPlates(squareCount, new[] { segmentSets[1][0], segmentSets[1][3] }, new[] { segmentSets[2][0], segmentSets[2][3] }, retVal, materialMiddle);
                AddBezierPlates(squareCount, new[] { segmentSets[1][1], segmentSets[1][2] }, new[] { segmentSets[2][1], segmentSets[2][2] }, retVal, materialEdge);

                AddBezierPlates(squareCount, new[] { segmentSets[2][0], segmentSets[2][3] }, new[] { segmentSets[3][0], segmentSets[3][3] }, retVal, materialMiddle);
                AddBezierPlates(squareCount, new[] { segmentSets[2][1], segmentSets[2][2] }, new[] { segmentSets[3][1], segmentSets[3][2] }, retVal, materialEdge);
            }

            AddBezierPlates(squareCount, segmentSets[3], segmentSets[4], retVal, materialMiddle);

            // End cap plates
            for (int cntr = 0; cntr < 2; cntr++)
            {
                int index = cntr == 0 ? 0 : 4;

                // Turn the end cap into a polygon, then triangulate it
                Point3D[] endCapPoly = BezierUtil.GetPath(squareCount, segmentSets[index].Select(o => new[] { o }).ToArray());       // Call the jagged array overload so that the individual bezier end points don't get smoothed out

                TriangleIndexed[] endCapTriangles = Math2D.GetTrianglesFromConcavePoly3D(endCapPoly);
                if (cntr == 0)
                {
                    endCapTriangles = endCapTriangles.Select(o => new TriangleIndexed(o.Index0, o.Index2, o.Index1, o.AllPoints)).ToArray();        // need to do this so the normals point in the proper direction
                }

                AddPolyPlate(endCapTriangles, retVal, materialMiddle);
            }

            return retVal;
        }
Exemple #13
0
        private static BezierSegment3D[][] GetModel_Second_Curves(AxeSecondProps arg)
        {
            BezierSegment3D[][] retVal = new BezierSegment3D[5][];

            AxeSecondProps[] argLevels = new AxeSecondProps[5];

            argLevels[2] = arg;     // Edge
            #region Middle

            argLevels[1] = UtilityCore.Clone_Shallow(arg);

            // Right
            argLevels[1].EndTR = new Point3D(argLevels[1].EndTR.X * .8, argLevels[1].EndTR.Y * .9, .15);

            Vector3D offsetTR = new Point3D(argLevels[1].EndTR.X, argLevels[1].EndTR.Y, 0) - arg.EndTR;
            Quaternion angleTR = Math3D.GetRotation((arg.EndTL - arg.EndTR), offsetTR);

            Vector3D rotated = (arg.EndBL_1 - arg.EndBR).ToUnit() * offsetTR.Length;
            rotated = rotated.GetRotatedVector(angleTR.Axis, angleTR.Angle * -1.3);

            argLevels[1].EndBR = new Point3D(argLevels[1].EndBR.X + rotated.X, argLevels[1].EndBR.Y + rotated.Y, .15);      // can't just use percents of coordinates.  Instead use the same offset angle,distance that top left had

            // Left
            argLevels[1].EndTL = new Point3D(argLevels[1].EndTL.X, argLevels[1].EndTL.Y * .95, .3);

            if (argLevels[1].EndBL_2 == null)
            {
                argLevels[1].EndBL_1 = new Point3D(argLevels[1].EndBL_1.X, argLevels[1].EndBL_1.Y * .9, .3);
            }
            else
            {
                Vector3D offsetBL1 = arg.EndBR - arg.EndBL_1;
                double lengthBL1 = (new Point3D(argLevels[1].EndBR.X, argLevels[1].EndBR.Y, 0) - arg.EndBR).Length;
                offsetBL1 = offsetBL1.ToUnit() * (offsetBL1.Length - lengthBL1);

                argLevels[1].EndBL_1 = argLevels[1].EndBR - offsetBL1;
                argLevels[1].EndBL_1 = new Point3D(argLevels[1].EndBL_1.X, argLevels[1].EndBL_1.Y, .18);

                argLevels[1].EndBL_2 = new Point3D(argLevels[1].EndBL_2.Value.X, argLevels[1].EndBL_2.Value.Y * .9, .3);
            }

            argLevels[3] = argLevels[1].CloneNegateZ();

            #endregion
            #region Far

            argLevels[0] = UtilityCore.Clone_Shallow(arg);

            argLevels[0].EndTL = new Point3D(argLevels[0].EndTL.X, argLevels[0].EndTL.Y * .7, .4);

            argLevels[0].EndTR = new Point3D(argLevels[0].EndTR.X * .5, argLevels[0].EndTR.Y * .6, .25);

            if (argLevels[0].EndBL_2 == null)
            {
                argLevels[0].EndBR = new Point3D(argLevels[0].EndBR.X * .5, argLevels[0].EndBR.Y * .6, .25);
                argLevels[0].EndBL_1 = new Point3D(argLevels[0].EndBL_1.X, argLevels[0].EndBL_1.Y * .6, .4);
            }
            else
            {
                // Bottom Right
                Vector3D offset = (argLevels[1].EndBR - argLevels[1].EndBL_1) * .5;
                Point3D startPoint = argLevels[1].EndBL_1 + offset;     // midway along bottom edge

                offset = argLevels[1].EndTR - startPoint;

                argLevels[0].EndBR = startPoint + (offset * .15);       // from midway point toward upper right point
                argLevels[0].EndBR = new Point3D(argLevels[0].EndBR.X, argLevels[0].EndBR.Y, .25);      // fix z

                // Left of bottom right (where the circle cutout ends)
                offset = argLevels[1].EndBR - argLevels[1].EndBL_1;
                argLevels[0].EndBL_1 = Math3D.GetClosestPoint_Line_Point(argLevels[0].EndBR, offset, argLevels[0].EndBL_1);

                offset *= .05;
                Point3D minBL1 = argLevels[0].EndBR - offset;
                Vector3D testOffset = argLevels[0].EndBL_1 - argLevels[0].EndBR;
                if (Vector3D.DotProduct(testOffset, offset) < 0 || testOffset.LengthSquared < offset.LengthSquared)
                {
                    argLevels[0].EndBL_1 = minBL1;
                }

                // Bottom Left
                argLevels[0].EndBL_2 = new Point3D(argLevels[0].EndBL_2.Value.X, argLevels[0].EndBL_2.Value.Y * .6, .4);

                // Reduce the curve a bit
                argLevels[0].B2AngleL = argLevels[0].B2AngleL * .9;
                argLevels[0].B2PercentL = argLevels[0].B2PercentL * .95;

                argLevels[0].B2AngleR = argLevels[0].B2AngleR * .85;
                argLevels[0].B2PercentR = argLevels[0].B2PercentR * .95;
            }

            argLevels[4] = argLevels[0].CloneNegateZ();

            #endregion

            for (int cntr = 0; cntr < 5; cntr++)
            {
                BezierSegment3D[] segments = GetModel_Second_Segments(argLevels[cntr]);
                retVal[cntr] = segments;
            }

            return retVal;
        }
        private void DrawBezierLines(BezierSegment3D[] beziers, bool showLines, bool showControls, bool showEnds)
        {
            // Main Line
            if (showLines)
            {
                foreach (BezierSegment3D bezier in beziers)
                {
                    AddLines(BezierUtil.GetPoints(100, bezier), _mainLineC, 2);
                }
            }

            // Control Lines
            if (showControls)
            {
                foreach (BezierSegment3D bezier in beziers)
                {
                    if (bezier.ControlPoints == null)
                    {
                        continue;
                    }

                    AddLines(bezier.Combined, _controlLineC);

                    for (int cntr = 0; cntr < bezier.ControlPoints.Length; cntr++)
                    {
                        AddDot(bezier.ControlPoints[cntr], _controlPointC);
                    }
                }
            }

            // End Points
            if (showEnds)
            {
                foreach (Point3D points in beziers[0].AllEndPoints)
                {
                    AddDot(points, _endPointC);
                }
            }
        }
        private void DrawBell2()
        {
            Point[] points = GetBellPoints(txtBell2.Text);
            if (points == null)
            {
                txtBell2.Effect = _errorEffect;
                return;
            }

            txtBell2.Effect = null;

            BezierSegment3D[] bezier = BezierUtil.GetBezierSegments(points.Select(o => o.ToPoint3D()).ToArray(), trkBell2.Value);



            for (int cntr = 0; cntr < bezier.Length; cntr++)
            {
                bezier[cntr] = new BezierSegment3D(bezier[cntr].EndIndex0, bezier[cntr].EndIndex1, new Point3D[0], bezier[cntr].AllEndPoints);
            }



            Random rand = StaticRandom.GetRandomForThread();

            IEnumerable<double> samples = Enumerable.Range(0, 50000).
                Select(o => BezierUtil.GetPoint(rand.NextDouble(), bezier).Y);

            IEnumerable<Point> idealLine = BezierUtil.GetPath(100, bezier).
                Select(o => o.ToPoint2D());

            DrawGraph(samples, idealLine);



            var samples2 = Enumerable.Range(0, 1000).
                Select(o =>
                    {
                        double randPercent = rand.NextDouble();
                        Point3D point = BezierUtil.GetPoint(randPercent, bezier);
                        return Tuple.Create(randPercent, point.X, point.Y, point.Z);
                    }).
                OrderBy(o => o.Item1).
                ToArray();


            if (!samples2.All(o => o.Item4.IsNearZero()))
            {
                int three = 2;
            }

            if (!samples2.All(o => o.Item2.IsNearValue(o.Item3)))
            {
                int four = 7;
            }


            var samples2a = samples2.
                Select(o => Tuple.Create(o.Item1, o.Item2, o.Item1 - o.Item2)).
                ToArray();



            //IEnumerable<Point> testLine = Enumerable.Range(0, 150).
            //    Select(o => BezierUtil.GetPoint(o / 150d, bezier).ToPoint2D());

            //Rect bounds = GetBounds();

            //IEnumerable<Point> testLineFinal = idealLine
            //    .Select(o => new Point(bounds.Left + (o.X * bounds.Width), bounds.Bottom - (o.Y * bounds.Height)));

            //AddLine(testLineFinal, new SolidColorBrush(UtilityWPF.ColorFromHex("FF0000")), 1, "test line");
        }
 private void DrawBezierPlates(int count, BezierSegment3D[] seg1, BezierSegment3D[] seg2, Color color, bool isShiny, bool ensureNormalsPointTheSame = false)
 {
     for (int cntr = 0; cntr < seg1.Length; cntr++)
     {
         DrawBezierPlate(count, seg1[cntr], seg2[cntr], color, isShiny, ensureNormalsPointTheSame);
     }
 }
        private void DrawBell3()
        {
            Point[] points = GetBellPoints(txtBell3.Text);
            if (points == null)
            {
                txtBell3.Effect = _errorEffect;
                return;
            }

            txtBell3.Effect = null;

            BezierSegment3D bezier = new BezierSegment3D(0, 1, points.Select(o => o.ToPoint3D()).ToArray(), new[] { new Point3D(0, 0, 0), new Point3D(1, 1, 0) });

            Random rand = StaticRandom.GetRandomForThread();

            IEnumerable<double> samples = Enumerable.Range(0, 100000).
                Select(o => BezierUtil.GetPoint(rand.NextDouble(), bezier).Y);

            IEnumerable<Point> idealLine = BezierUtil.GetPoints(100, bezier).
                Select(o => o.ToPoint2D());

            DrawGraph(samples, idealLine);

            Rect bounds = GetBounds();

            for (int cntr = 0; cntr < bezier.ControlPoints.Length - 1; cntr++)
            {
                Point from = GetScaledPoint(bezier.ControlPoints[cntr], bounds);
                Point to = GetScaledPoint(bezier.ControlPoints[cntr + 1], bounds);
                AddLine(from, to, _brushLightBlue);
            }

            if (bezier.ControlPoints.Length > 0)
            {
                Point from = GetScaledPoint(bezier.EndPoint0, bounds);
                Point to = GetScaledPoint(bezier.ControlPoints[0], bounds);
                AddLine(from, to, _brushLightBlue);

                from = GetScaledPoint(bezier.EndPoint1, bounds);
                to = GetScaledPoint(bezier.ControlPoints[bezier.ControlPoints.Length - 1], bounds);
                AddLine(from, to, _brushLightBlue);
            }
        }
Exemple #18
0
        /// <summary>
        /// This returns points across several segment definitions.  count is the total number of sample points to return
        /// </summary>
        /// <remarks>
        /// This assumes that the segments are linked together into a single path
        /// 
        /// If the first and last point of segments are the same, then this will only return that shared point once (but the point count
        /// will still be how many were requested
        /// </remarks>
        public static Point3D[] GetPath(int count, BezierSegment3D[] segments)
        {
            // Get the total length of the curve
            double totalLength = 0;
            double[] cumulativeLengths = new double[segments.Length + 1];
            for (int cntr = 1; cntr < segments.Length + 1; cntr++)
            {
                totalLength += segments[cntr - 1].Length_quick;
                cumulativeLengths[cntr] = cumulativeLengths[cntr - 1] + segments[cntr - 1].Length_quick;
            }

            double countD = count - 1;

            Point3D[] retVal = new Point3D[count];

            retVal[0] = segments[0].EndPoint0;
            retVal[count - 1] = segments[segments.Length - 1].EndPoint1;        //NOTE: If the segment is a closed curve, this is the same point as retVal[0].  May want a boolean that tells whether the last point should be replicated

            int index = 0;

            for (int cntr = 1; cntr < count - 1; cntr++)
            {
                // Get the location along the entire path
                double totalPercent = cntr / countD;
                double portionTotalLength = totalLength * totalPercent;

                // Advance to the appropriate segment
                while (cumulativeLengths[index + 1] < portionTotalLength)
                {
                    index++;
                }

                // Get the percent of the current segment
                double localLength = portionTotalLength - cumulativeLengths[index];
                double localPercent = localLength / segments[index].Length_quick;

                // Calculate the bezier point
                retVal[cntr] = GetPoint(localPercent, segments[index].Combined);
            }

            return retVal;
        }
        private void Test2Segments2D(Point end1, Point end2, Point end3)
        {
            // Control points for 2
            var controlPoints = BezierUtil.GetControlPoints_Middle(end1, end2, end3, trkSingleLine2Segments2DPercent.Value, trkSingleLine2Segments2DPercent.Value);

            Point3D[] allEndPoints = new[] { end1, end2, end3 }.Select(o => o.ToPoint3D()).ToArray();

            var segment12 = new BezierSegment3D(0, 1, new[] { end1.ToPoint3D(), controlPoints.Item1.ToPoint3D() }, allEndPoints);
            var segment23 = new BezierSegment3D(1, 2, new[] { controlPoints.Item2.ToPoint3D(), end3.ToPoint3D() }, allEndPoints);

            // Calculate the beziers
            Point3D[] bezierPoints12 = BezierUtil.GetPoints(100, segment12);
            Point3D[] bezierPoints23 = BezierUtil.GetPoints(100, segment23);

            #region Draw

            PrepFor2D();

            foreach (var bezier in new[] { Tuple.Create(segment12, bezierPoints12), Tuple.Create(segment23, bezierPoints23) })
            {
                // Main Line
                for (int cntr = 0; cntr < bezier.Item2.Length - 1; cntr++)
                {
                    AddLine(bezier.Item2[cntr].ToPoint2D(), bezier.Item2[cntr + 1].ToPoint2D(), _mainLineB, 3);
                }

                if (chkShowDots.IsChecked.Value)
                {
                    foreach (Point3D point in bezier.Item2)
                    {
                        AddDot(point.ToPoint2D(), _mainLineB, 8);
                    }

                    // Control Lines
                    Point[] allPoints = UtilityCore.Iterate<Point3D>(bezier.Item1.EndPoint0, bezier.Item1.ControlPoints, bezier.Item1.EndPoint1).Select(o => o.ToPoint2D()).ToArray();

                    for (int cntr = 0; cntr < allPoints.Length - 1; cntr++)
                    {
                        AddLine(allPoints[cntr], allPoints[cntr + 1], _controlLineB, 1);
                    }

                    for (int cntr = 0; cntr < bezier.Item1.ControlPoints.Length; cntr++)
                    {
                        AddDot(bezier.Item1.ControlPoints[cntr].ToPoint2D(), _controlPointB);
                    }
                }
            }

            // End Points
            if (chkShowDots.IsChecked.Value)
            {
                AddDot(end1, _endPointB);
                AddDot(end2, _endPointB);
                AddDot(end3, _endPointB);
            }

            #endregion
        }
Exemple #20
0
        private static BezierSegment3D[] GetBezierSegments_Closed(Point3D[] ends, double along = .25)
        {
            //NOTE: The difference between closed and open is closed has one more segment that loops back to zero (and a control point for point zero)

            // Precalculate the control points
            Tuple<Point3D, Point3D>[] controls = new Tuple<Point3D, Point3D>[ends.Length - 1];

            for (int cntr = 1; cntr < ends.Length; cntr++)
            {
                int lastIndex = cntr == ends.Length - 1 ? 0 : cntr + 1;

                Tuple<double, double> adjustedAlong = GetAdjustedRatios(ends[cntr - 1], ends[cntr], ends[lastIndex], along);

                controls[cntr - 1] = GetControlPoints_Middle(ends[cntr - 1], ends[cntr], ends[lastIndex], adjustedAlong.Item1, adjustedAlong.Item2);
            }

            Tuple<double, double> adjustedAlong2 = GetAdjustedRatios(ends[ends.Length - 1], ends[0], ends[1], along);
            var extraControl = GetControlPoints_Middle(ends[ends.Length - 1], ends[0], ends[1], adjustedAlong2.Item1, adjustedAlong2.Item2);      // loop back

            // Build the return segments
            BezierSegment3D[] retVal = new BezierSegment3D[ends.Length];

            for (int cntr = 0; cntr < ends.Length; cntr++)
            {
                Point3D? ctrl0 = cntr == 0 ? extraControl.Item2 : controls[cntr - 1].Item2;
                Point3D? ctrl1 = cntr == ends.Length - 1 ? extraControl.Item1 : controls[cntr].Item1;

                int lastIndex = cntr == ends.Length - 1 ? 0 : cntr + 1;

                retVal[cntr] = new BezierSegment3D(cntr, lastIndex, UtilityCore.Iterate<Point3D>(ctrl0, ctrl1).ToArray(), ends);
            }

            return retVal;
        }
        private void TestAxeSimple1(AxeSimple1 arg)
        {
            BezierSegment3D[][] segmentSets = new BezierSegment3D[5][];

            PrepFor3D();

            #region Lines

            for (int cntr = 0; cntr < 5; cntr++)
            {
                if (!chkAxe3D.IsChecked.Value && cntr != 2)
                {
                    continue;
                }

                #region scale, z

                double zL, zR, scaleX, scaleY;

                switch (cntr)
                {
                    case 0:
                    case 4:
                        zL = arg.Z2L;
                        zR = arg.Z2R;
                        scaleX = arg.Scale2X;
                        scaleY = arg.Scale2Y;
                        break;

                    case 1:
                    case 3:
                        zL = zR = arg.Z1;
                        scaleX = arg.Scale1X;
                        scaleY = arg.Scale1Y;
                        break;

                    case 2:
                        zL = zR = 0;
                        scaleX = scaleY = 1;
                        break;

                    default:
                        throw new ApplicationException("Unknown cntr: " + cntr.ToString());
                }

                if (cntr < 2)
                {
                    zL *= -1d;
                    zR *= -1d;
                }

                #endregion

                Point3D[] endPoints = new[]
                    {
                        new Point3D(-arg.leftX, -arg.leftY * scaleY, zL),     // top left
                        new Point3D(-arg.leftX, arg.leftY * scaleY, zL),     // bottom left
                        new Point3D(arg.rightX * scaleX, -arg.rightY * scaleY, zR),       // top right
                        new Point3D(arg.rightX * scaleX, arg.rightY * scaleY, zR),        // bottom right
                    };

                BezierSegment3D[] segments = TestAxeSimple1_Segments(endPoints, arg);
                segmentSets[cntr] = segments;

                DrawBezierLines(segments, chkAxeLine.IsChecked.Value, chkAxeControl.IsChecked.Value, chkAxeEnd.IsChecked.Value);
            }

            #endregion
            #region Plates

            if (chkAxe3D.IsChecked.Value)
            {
                Color edgeColor = Colors.GhostWhite;
                Color middleColor = Colors.DimGray;

                int squareCount = 8;

                DrawBezierPlates(squareCount, segmentSets[0], segmentSets[1], middleColor, false);

                DrawBezierPlates(squareCount, new[] { segmentSets[1][0], segmentSets[1][1] }, new[] { segmentSets[2][0], segmentSets[2][1] }, middleColor, false);
                DrawBezierPlate(squareCount, segmentSets[1][2], segmentSets[2][2], edgeColor, true);

                DrawBezierPlates(squareCount, new[] { segmentSets[2][0], segmentSets[2][1] }, new[] { segmentSets[3][0], segmentSets[3][1] }, middleColor, false);
                DrawBezierPlate(squareCount, segmentSets[2][2], segmentSets[3][2], edgeColor, true);

                DrawBezierPlates(squareCount, segmentSets[3], segmentSets[4], middleColor, false);

                // End cap plates
                if (arg.isCenterFilled)
                {
                    for (int cntr = 0; cntr < 2; cntr++)
                    {
                        int index = cntr == 0 ? 0 : 4;

                        DrawBezierPlate(squareCount, segmentSets[index][0], segmentSets[index][1], middleColor, false);        // top - bottom

                        BezierSegment3D extraSeg = new BezierSegment3D(segmentSets[index][2].EndIndex0, segmentSets[index][2].EndIndex1, null, segmentSets[index][2].AllEndPoints);
                        DrawBezierPlate(squareCount, extraSeg, segmentSets[index][2], middleColor, false);     // edge
                    }
                }
                else
                {
                    DrawBezierPlates(squareCount, segmentSets[0], segmentSets[4], middleColor, false);
                }
            }

            #endregion
        }
Exemple #22
0
 public static Point3D[] GetPoints(int count, BezierSegment3D segment)
 {
     return GetPoints(count, UtilityCore.Iterate<Point3D>(segment.EndPoint0, segment.ControlPoints, segment.EndPoint1).ToArray());
 }
        private static BezierSegment3D[] TestAxeSimple1_Segments(Point3D[] endPoints, AxeSimple1 arg)
        {
            const int TOPLEFT = 0;
            const int BOTTOMLEFT = 1;
            const int TOPRIGHT = 2;
            const int BOTTOMRIGHT = 3;

            // Edge
            Point3D controlTR = BezierUtil.GetControlPoint_End(endPoints[TOPRIGHT], endPoints[BOTTOMRIGHT], endPoints[TOPLEFT], true, arg.edgeAngle, arg.edgePercent);
            Point3D controlBR = BezierUtil.GetControlPoint_End(endPoints[BOTTOMRIGHT], endPoints[TOPRIGHT], endPoints[BOTTOMLEFT], true, arg.edgeAngle, arg.edgePercent);
            BezierSegment3D edge = new BezierSegment3D(TOPRIGHT, BOTTOMRIGHT, new[] { controlTR, controlBR }, endPoints);

            // Bottom
            Point3D controlBL = BezierUtil.GetControlPoint_End(endPoints[BOTTOMLEFT], endPoints[BOTTOMRIGHT], endPoints[TOPRIGHT], arg.leftAway, arg.leftAngle, arg.leftPercent);
            controlBR = BezierUtil.GetControlPoint_End(endPoints[BOTTOMRIGHT], endPoints[BOTTOMLEFT], endPoints[TOPRIGHT], arg.rightAway, arg.rightAngle, arg.rightPercent);
            BezierSegment3D bottom = new BezierSegment3D(BOTTOMLEFT, BOTTOMRIGHT, new[] { controlBL, controlBR }, endPoints);

            // Top
            Point3D controlTL = BezierUtil.GetControlPoint_End(endPoints[TOPLEFT], endPoints[TOPRIGHT], endPoints[BOTTOMRIGHT], arg.leftAway, arg.leftAngle, arg.leftPercent);
            controlTR = BezierUtil.GetControlPoint_End(endPoints[TOPRIGHT], endPoints[TOPLEFT], endPoints[BOTTOMRIGHT], arg.rightAway, arg.rightAngle, arg.rightPercent);
            BezierSegment3D top = new BezierSegment3D(TOPLEFT, TOPRIGHT, new[] { controlTL, controlTR }, endPoints);

            return new[] { bottom, top, edge };
        }
Exemple #24
0
        private static Tuple<double[], BezierSegment3D[][], double[], BezierSegment3D[][]> ConvertToBezier(double[] axisX, double[] axisY, double[] valuesZ)
        {
            #region validate

            // X length
            if (axisX == null || axisX.Length < 2)
            {
                throw new ArgumentException(string.Format("axisX must have at least 2 items: len={0}", axisX == null ? "null" : axisX.Length.ToString()));
            }

            // Y length
            if (axisY == null || axisY.Length < 2)
            {
                throw new ArgumentException(string.Format("axisY must have at least 2 items: len={0}", axisY == null ? "null" : axisY.Length.ToString()));
            }

            // Z area
            if (valuesZ == null || valuesZ.Length != axisX.Length * axisY.Length)
            {
                throw new ArgumentException(string.Format("valuesZ is invalid length: values={0}, axis1={1}, axis2={2}", valuesZ == null ? "null" : valuesZ.Length.ToString(), axisX.Length, axisY.Length));
            }

            // X equality
            if (Enumerable.Range(0, axisX.Length - 1).Any(o => axisX[o].IsNearValue(axisX[o + 1])))
            {
                throw new ArgumentException("Values can't be the same in x axis");
            }

            // Y equality
            if (Enumerable.Range(0, axisY.Length - 1).Any(o => axisY[o].IsNearValue(axisY[o + 1])))
            {
                throw new ArgumentException("Values can't be the same in y axis");
            }

            #endregion

            bool isAccendingX = axisX[1] > axisX[0];
            bool isAccendingY = axisY[1] > axisY[0];

            #region validate

            // X ascending
            if (Enumerable.Range(0, axisX.Length - 1).Any(o => isAccendingX ? axisX[o + 1] < axisX[o] : axisX[o + 1] > axisX[o]))
            {
                throw new ArgumentException("The values in axisX must all ascend or descend");
            }

            // Y ascending
            if (Enumerable.Range(0, axisY.Length - 1).Any(o => isAccendingY ? axisY[o + 1] < axisY[o] : axisY[o + 1] > axisY[o]))
            {
                throw new ArgumentException("The values in axisX must all ascend or descend");
            }

            #endregion

            #region ensure ascending X

            if (!isAccendingX)
            {
                axisX = axisX.Reverse().ToArray();

                double[] newZ = new double[valuesZ.Length];

                for (int oldX = 0; oldX < axisX.Length; oldX++)
                {
                    int newX = axisX.Length - 1 - oldX;

                    for (int y = 0; y < axisY.Length; y++)
                    {
                        int yIndex = y * axisX.Length;
                        newZ[yIndex + newX] = valuesZ[yIndex + oldX];
                    }
                }

                valuesZ = newZ;
            }

            #endregion
            #region ensure ascending Y

            if (!isAccendingY)
            {
                axisY = axisY.Reverse().ToArray();

                double[] newZ = new double[valuesZ.Length];

                for (int oldY = 0; oldY < axisY.Length; oldY++)
                {
                    int newY = axisY.Length - 1 - oldY;

                    int yIndexOld = oldY * axisX.Length;
                    int yIndexNew = newY * axisX.Length;

                    for (int x = 0; x < axisX.Length; x++)
                    {
                        newZ[yIndexNew + x] = valuesZ[yIndexOld + x];
                    }
                }

                valuesZ = newZ;
            }

            #endregion

            BezierSegment3D[][] horizontal = new BezierSegment3D[axisY.Length][];     // there is a horizontal set for each y
            BezierSegment3D[][] vertical = new BezierSegment3D[axisX.Length][];

            //TODO: Make an option of this that figures out the percent to use:
            //if you pass in .25, that is the max.
            //  if both segments are equal length then it will be .25 for each
            //  if they are different lengths, the smaller will use .25.  the larger will use the ratio of lengths*.25
            //BezierSegmentDef.GetBezierSegments();

            #region horizontal

            for (int y = 0; y < axisY.Length; y++)
            {
                int yIndex = y * axisX.Length;

                Point3D[] ends = Enumerable.Range(0, axisX.Length).
                    Select(x => new Point3D(axisX[x], axisY[y], valuesZ[yIndex + x])).
                    ToArray();

                horizontal[y] = BezierUtil.GetBezierSegments(ends);
            }

            #endregion
            #region vertical

            for (int x = 0; x < axisX.Length; x++)
            {
                Point3D[] ends = Enumerable.Range(0, axisY.Length).
                    Select(y => new Point3D(axisX[x], axisY[y], valuesZ[(y * axisX.Length) + x])).
                    ToArray();

                vertical[x] = BezierUtil.GetBezierSegments(ends);
            }

            #endregion

            return Tuple.Create(axisX, horizontal, axisY, vertical);
        }
        private void TestAxeSimple2(Curves_AxeSimple2 arg)
        {
            BezierSegment3D[][] segmentSets = new BezierSegment3D[5][];

            Curves_AxeSimple2[] argLevels = new Curves_AxeSimple2[5];

            argLevels[2] = arg;     // Edge
            #region Middle

            argLevels[1] = UtilityCore.Clone(arg);

            // Right
            argLevels[1].EndTR = new Point3D(argLevels[1].EndTR.X * .8, argLevels[1].EndTR.Y * .9, .15);

            Vector3D offsetTR = new Point3D(argLevels[1].EndTR.X, argLevels[1].EndTR.Y, 0) - arg.EndTR;
            Quaternion angleTR = Math3D.GetRotation((arg.EndTL - arg.EndTR), offsetTR);

            Vector3D rotated = (arg.EndBL_1 - arg.EndBR).ToUnit() * offsetTR.Length;
            rotated = rotated.GetRotatedVector(angleTR.Axis, angleTR.Angle * -1.3);

            argLevels[1].EndBR = new Point3D(argLevels[1].EndBR.X + rotated.X, argLevels[1].EndBR.Y + rotated.Y, .15);      // can't just use percents of coordinates.  Instead use the same offset angle,distance that top left had

            // Left
            argLevels[1].EndTL = new Point3D(argLevels[1].EndTL.X, argLevels[1].EndTL.Y * .95, .3);

            if (argLevels[1].EndBL_2 == null)
            {
                argLevels[1].EndBL_1 = new Point3D(argLevels[1].EndBL_1.X, argLevels[1].EndBL_1.Y * .9, .3);
            }
            else
            {
                Vector3D offsetBL1 = arg.EndBR - arg.EndBL_1;
                double lengthBL1 = (new Point3D(argLevels[1].EndBR.X, argLevels[1].EndBR.Y, 0) - arg.EndBR).Length;
                offsetBL1 = offsetBL1.ToUnit() * (offsetBL1.Length - lengthBL1);

                argLevels[1].EndBL_1 = argLevels[1].EndBR - offsetBL1;
                argLevels[1].EndBL_1 = new Point3D(argLevels[1].EndBL_1.X, argLevels[1].EndBL_1.Y, .18);

                argLevels[1].EndBL_2 = new Point3D(argLevels[1].EndBL_2.Value.X, argLevels[1].EndBL_2.Value.Y * .9, .3);
            }

            argLevels[3] = argLevels[1].CloneNegateZ();

            #endregion
            #region Far

            argLevels[0] = UtilityCore.Clone(arg);

            argLevels[0].EndTL = new Point3D(argLevels[0].EndTL.X, argLevels[0].EndTL.Y * .7, .4);

            argLevels[0].EndTR = new Point3D(argLevels[0].EndTR.X * .5, argLevels[0].EndTR.Y * .6, .25);

            if (argLevels[0].EndBL_2 == null)
            {
                argLevels[0].EndBR = new Point3D(argLevels[0].EndBR.X * .5, argLevels[0].EndBR.Y * .6, .25);
                argLevels[0].EndBL_1 = new Point3D(argLevels[0].EndBL_1.X, argLevels[0].EndBL_1.Y * .6, .4);
            }
            else
            {
                // Bottom Right
                Vector3D offset = (argLevels[1].EndBR - argLevels[1].EndBL_1) * .5;
                Point3D startPoint = argLevels[1].EndBL_1 + offset;     // midway along bottom edge

                offset = argLevels[1].EndTR - startPoint;

                argLevels[0].EndBR = startPoint + (offset * .15);       // from midway point toward upper right point
                argLevels[0].EndBR = new Point3D(argLevels[0].EndBR.X, argLevels[0].EndBR.Y, .25);      // fix z

                // Left of bottom right (where the circle cutout ends)
                offset = argLevels[1].EndBR - argLevels[1].EndBL_1;
                argLevels[0].EndBL_1 = Math3D.GetClosestPoint_Line_Point(argLevels[0].EndBR, offset, argLevels[0].EndBL_1);

                offset *= .05;
                Point3D minBL1 = argLevels[0].EndBR - offset;
                Vector3D testOffset = argLevels[0].EndBL_1 - argLevels[0].EndBR;
                if (Vector3D.DotProduct(testOffset, offset) < 0 || testOffset.LengthSquared < offset.LengthSquared)
                {
                    argLevels[0].EndBL_1 = minBL1;
                }

                // Bottom Left
                argLevels[0].EndBL_2 = new Point3D(argLevels[0].EndBL_2.Value.X, argLevels[0].EndBL_2.Value.Y * .6, .4);

                // Reduce the curve a bit
                argLevels[0].B2AngleL = argLevels[0].B2AngleL * .9;
                argLevels[0].B2PercentL = argLevels[0].B2PercentL * .95;

                argLevels[0].B2AngleR = argLevels[0].B2AngleR * .85;
                argLevels[0].B2PercentR = argLevels[0].B2PercentR * .95;
            }

            argLevels[4] = argLevels[0].CloneNegateZ();

            #endregion

            PrepFor3D();

            #region Lines

            for (int cntr = 0; cntr < 5; cntr++)
            {
                if (!chkAxe3D.IsChecked.Value && cntr != 2)
                {
                    continue;
                }

                Curves_AxeSimple2 argCurrent = argLevels[cntr];

                BezierSegment3D[] segments = TestAxeSimple2_Segments(argCurrent);
                segmentSets[cntr] = segments;

                DrawBezierLines(segments, chkAxeLine.IsChecked.Value, chkAxeControl.IsChecked.Value, chkAxeEnd.IsChecked.Value);
            }

            #endregion
            #region Plates

            if (chkAxe3D.IsChecked.Value)
            {
                Color edgeColor = Colors.GhostWhite;
                Color middleColor = Colors.DimGray;

                int numSegments = segmentSets[0].Length;

                int squareCount = 20;

                // Z to Z
                DrawBezierPlates(squareCount, segmentSets[0], segmentSets[1], middleColor, false);

                if (numSegments == 3)
                {
                    DrawBezierPlates(squareCount, new[] { segmentSets[1][0], segmentSets[1][2] }, new[] { segmentSets[2][0], segmentSets[2][2] }, middleColor, false);
                    DrawBezierPlate(squareCount, segmentSets[1][1], segmentSets[2][1], edgeColor, true);

                    DrawBezierPlates(squareCount, new[] { segmentSets[2][0], segmentSets[2][2] }, new[] { segmentSets[3][0], segmentSets[3][2] }, middleColor, false);
                    DrawBezierPlate(squareCount, segmentSets[2][1], segmentSets[3][1], edgeColor, true);
                }
                else
                {
                    DrawBezierPlates(squareCount, new[] { segmentSets[1][0], segmentSets[1][3] }, new[] { segmentSets[2][0], segmentSets[2][3] }, middleColor, false);
                    DrawBezierPlates(squareCount, new[] { segmentSets[1][1], segmentSets[1][2] }, new[] { segmentSets[2][1], segmentSets[2][2] }, edgeColor, true);

                    DrawBezierPlates(squareCount, new[] { segmentSets[2][0], segmentSets[2][3] }, new[] { segmentSets[3][0], segmentSets[3][3] }, middleColor, false);
                    DrawBezierPlates(squareCount, new[] { segmentSets[2][1], segmentSets[2][2] }, new[] { segmentSets[3][1], segmentSets[3][2] }, edgeColor, true);
                }

                DrawBezierPlates(squareCount, segmentSets[3], segmentSets[4], middleColor, false);

                // End cap plates
                for (int cntr = 0; cntr < 2; cntr++)
                {
                    int index = cntr == 0 ? 0 : 4;

                    // Turn the end cap into a polygon, then triangulate it
                    Point3D[] endCapPoly = BezierUtil.GetPath(squareCount, segmentSets[index].Select(o => new[] { o }).ToArray());       // Call the jagged array overload so that the individual bezier end points don't get smoothed out

                    TriangleIndexed[] endCapTriangles = Math2D.GetTrianglesFromConcavePoly3D(endCapPoly);
                    if (cntr == 0)
                    {
                        endCapTriangles = endCapTriangles.Select(o => new TriangleIndexed(o.Index0, o.Index2, o.Index1, o.AllPoints)).ToArray();        // need to do this so the normals point in the proper direction
                    }

                    DrawPolyPlate(endCapTriangles, middleColor, false);

                    //AddLines(endCapTriangles.Select(o => Tuple.Create(o.GetCenterPoint(), o.GetCenterPoint() + o.Normal)), _controlLineC, 2);
                }
            }

            #endregion
        }
Exemple #26
0
        public static Point3D GetPoint(double percent, BezierSegment3D[] bezier)
        {
            //TODO: If the bezier is closed, make it circular
            if (percent < 0) return bezier[0].EndPoint0;

            double totalLength = bezier.Sum(o => o.Length_quick);

            double fromPercent = 0d;
            for(int cntr = 0; cntr < bezier.Length; cntr++)
            {
                double toPercent = fromPercent + (bezier[cntr].Length_quick / totalLength);

                if(percent >= fromPercent && percent <= toPercent)
                {
                    double localPercent = ((percent - fromPercent) * totalLength) / bezier[cntr].Length_quick;

                    return GetPoint(localPercent, bezier[cntr]);
                }

                fromPercent = toPercent;
            }

            return bezier[bezier.Length - 1].EndPoint1;
        }
Exemple #27
0
        private static BezierSegment3D[][] GetModel_Symetrical_Curves(AxeSymetricalProps arg)
        {
            BezierSegment3D[][] retVal = new BezierSegment3D[5][];

            //TODO: Come up with a transform based on arg's extremes and dna.Scale
            Transform3D transform = Transform3D.Identity;

            for (int cntr = 0; cntr < 5; cntr++)
            {
                #region scale, z

                double zL, zR, scaleX, scaleY;

                switch (cntr)
                {
                    case 0:
                    case 4:
                        zL = arg.Z2L;
                        zR = arg.Z2R;
                        scaleX = arg.Scale2X;
                        scaleY = arg.Scale2Y;
                        break;

                    case 1:
                    case 3:
                        zL = zR = arg.Z1;
                        scaleX = arg.Scale1X;
                        scaleY = arg.Scale1Y;
                        break;

                    case 2:
                        zL = zR = 0;
                        scaleX = scaleY = 1;
                        break;

                    default:
                        throw new ApplicationException("Unknown cntr: " + cntr.ToString());
                }

                if (cntr < 2)
                {
                    zL *= -1d;
                    zR *= -1d;
                }

                #endregion

                Point3D[] endPoints = new[]
                    {
                        new Point3D(arg.leftX, -arg.leftY * scaleY, zL),     // top left
                        new Point3D(arg.leftX, arg.leftY * scaleY, zL),     // bottom left
                        new Point3D(arg.rightX * scaleX, -arg.rightY * scaleY, zR),       // top right
                        new Point3D(arg.rightX * scaleX, arg.rightY * scaleY, zR),        // bottom right
                    }.Select(o => transform.Transform(o)).ToArray();

                BezierSegment3D[] segments = GetModel_Symetrical_Segments(endPoints, arg);
                retVal[cntr] = segments;
            }

            return retVal;
        }