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 static BezierSegment3D[] GetModel_Symetrical_Segments(Point3D[] endPoints, AxeSymetricalProps 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 }); }
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); } }
private static BezierSegment3D[] GetModel_Second_Segments(AxeSecondProps 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()); }
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 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 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 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); } }
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 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); }