public static Direction GetNormal(PointUV uv, double p, double q, double circleAngle, Vector inverseOffset, bool isInverted) { double delta = 0.001; var deltaU = VectorUV.Create(delta, 0); var deltaV = VectorUV.Create(0, delta); PointUV uv00 = uv - deltaU; PointUV uv01 = uv + deltaU; PointUV uv10 = uv - deltaV; PointUV uv11 = uv + deltaV; Point pCenter = Lawson.Evaluate(uv, p, q, circleAngle, inverseOffset, isInverted); var pxxs = new Point[] { Lawson.Evaluate(uv00, p, q, circleAngle, inverseOffset, isInverted), Lawson.Evaluate(uv01, p, q, circleAngle, inverseOffset, isInverted), Lawson.Evaluate(uv10, p, q, circleAngle, inverseOffset, isInverted), Lawson.Evaluate(uv11, p, q, circleAngle, inverseOffset, isInverted) }; var sum = Vector.Zero; foreach (Point pxx in pxxs) { sum += pxx - pCenter; } if (sum != Vector.Zero) { return(sum.Direction); } return(Vector.Cross(pxxs[1] - pxxs[0], pxxs[1] - pxxs[2]).Direction); }
public static Graphic GetGraphic(double p, double q, double circleAngle, Vector inverseOffset) { var graphics = new List <Graphic>(); int bandCount = 2; int iSteps = bandCount * 32; //32 int jSteps = 34; //34 double uStep = 2 * Math.PI / iSteps; double vStep = 2 * Math.PI / jSteps; bool uSwap = false, vSwap = false; for (int j = 0; j < jSteps; j++) { double v = 2 * Math.PI * j / jSteps; for (int i = 0; i < iSteps; i++) { double u = 2 * Math.PI * i / iSteps; Direction n00, n10, n11, n01; Point p00 = Lawson.Evaluate(PointUV.Create(u, v), p, q, circleAngle, inverseOffset, true, out n00); Point p10 = Lawson.Evaluate(PointUV.Create(u + uStep, v), p, q, circleAngle, inverseOffset, true, out n10); Point p11 = Lawson.Evaluate(PointUV.Create(u + uStep, v + vStep), p, q, circleAngle, inverseOffset, true, out n11); Point p01 = Lawson.Evaluate(PointUV.Create(u, v + vStep), p, q, circleAngle, inverseOffset, true, out n01); var facetVertices = new List <FacetVertex>(); facetVertices.Add(new FacetVertex(p00, n00)); facetVertices.Add(new FacetVertex(p10, n10)); facetVertices.Add(new FacetVertex(p11, n11)); facetVertices.Add(new FacetVertex(p01, n01)); var facets = new List <Facet>(); facets.Add(new Facet(0, 1, 2)); facets.Add(new Facet(0, 2, 3)); HSBColor hsbFill = new HSBColor(Window.ActiveWindow.ActiveLayer.GetColor(null)); hsbFill.H = (float)(u / 2 / Math.PI * 360); hsbFill.A = vSwap ? 127 : 255; HSBColor hsbLine = new HSBColor(System.Drawing.Color.MidnightBlue); hsbLine.H = (float)(u / 2 / Math.PI * 360); var style = new GraphicStyle { EnableDepthBuffer = true, LineColor = hsbLine.Color, LineWidth = 1, FillColor = hsbFill.Color }; graphics.Add(Graphic.Create(style, MeshPrimitive.Create(facetVertices, facets))); uSwap = !uSwap; } vSwap = !vSwap; } return(Graphic.Create(null, null, graphics)); }
protected override void OnExecute(Command command, ExecutionContext context, System.Drawing.Rectangle buttonRect) { const int count = 24; double p = 0.5; double q = 1; double circleAngle = Math.PI / 2; Vector inverseOffset = Vector.Create(0.5, 0, 0); Part mainPart = Window.ActiveWindow.Scene as Part; Point[] baseCirclePoints = new Point[count]; for (int i = 0; i < count; i++) { double u = (double)i / count * 2 * Math.PI; Point[] vPoints = new Point[3]; for (int j = 0; j < 3; j++) { vPoints[j] = Lawson.Evaluate(PointUV.Create((double)j / 3 * 2 * Math.PI, u), p, q, circleAngle, inverseOffset, true); if (j == 0) { baseCirclePoints[i] = vPoints[j]; } } Circle circle = Circle.CreateThroughPoints( Plane.Create(Frame.Create(vPoints[0], Vector.Cross(vPoints[1] - vPoints[0], vPoints[2] - vPoints[0]).Direction)), vPoints[0], vPoints[1], vPoints[2] ); DesignCurve.Create(mainPart, CurveSegment.Create(circle)); //ShapeHelper.CreateTorus(circle.Frame.Origin, circle.Frame.DirZ, circle.Radius * 2, } Circle baseCircle = Circle.CreateThroughPoints( Plane.Create(Frame.Create(baseCirclePoints[0], Vector.Cross(baseCirclePoints[1] - baseCirclePoints[0], baseCirclePoints[2] - baseCirclePoints[0]).Direction)), baseCirclePoints[0], baseCirclePoints[1], baseCirclePoints[2] ); DesignCurve.Create(mainPart, CurveSegment.Create(baseCircle)); }
public static Direction GetNormal(PointUV uv, double p, double q, double circleAngle, Vector inverseOffset, bool isInverted) { double delta = 0.001; var deltaU = VectorUV.Create(delta, 0); var deltaV = VectorUV.Create(0, delta); PointUV uv00 = uv - deltaU; PointUV uv01 = uv + deltaU; PointUV uv10 = uv - deltaV; PointUV uv11 = uv + deltaV; Vector du = Lawson.Evaluate(uv00, p, q, circleAngle, inverseOffset, isInverted) - Lawson.Evaluate(uv01, p, q, circleAngle, inverseOffset, isInverted) ; Vector dv = Lawson.Evaluate(uv10, p, q, circleAngle, inverseOffset, isInverted) - Lawson.Evaluate(uv11, p, q, circleAngle, inverseOffset, isInverted) ; return(Vector.Cross(du, dv).Direction); }
public void Iterate() { Iteration++; var newVParameters = new CircularList <CircularList <double> >(iSteps * 2); var backupVParameters = new CircularList <CircularList <double> >(iSteps * 2); var newTabAngles = new CircularList <CircularList <double> >(iSteps * 2); for (int i = 0; i < iSteps * 2; i++) { newVParameters.Add(new CircularList <double>(jSteps)); backupVParameters.Add(new CircularList <double>(jSteps)); newTabAngles.Add(new CircularList <double>(jSteps)); for (int j = 0; j < jSteps; j++) { newVParameters[i].Add(vParameters[i][j]); backupVParameters[i].Add(vParameters[i][j]); newTabAngles[i].Add(tabAngles[i][j]); } } double cumulativeErrorTally = 0; MaxError = 0; for (int i = 0; i < iSteps * 2; i++) { for (int j = 0; j < jSteps; j++) { bool swap = j % 2 == 0; int iOtherDir = swap ? -1 : 1; int iOther = i + iOtherDir; Circle baseCircle = GetTabFromPoints(true, i, j, iOther); Circle circle0 = GetTabFromPoints(true, iOther, j - 1, i); Circle circle1 = GetTabFromPoints(true, iOther, j + 1, i); double distance0 = (baseCircle.Frame.Origin - circle0.Frame.Origin).Magnitude - baseCircle.Radius - circle0.Radius; double distance1 = (baseCircle.Frame.Origin - circle1.Frame.Origin).Magnitude - baseCircle.Radius - circle1.Radius; cumulativeErrorTally += distance0 * distance0 + distance1 * distance1; MaxError = Math.Max(Math.Abs(distance0), MaxError); MaxError = Math.Max(Math.Abs(distance1), MaxError); double angleAdjust = (distance0 + distance1) / 2 * AngleForce / GetSpanAt(i, j) / baseCircle.Radius; // / GetSpanAt(i, j) / baseCircle.Radius; // / baseCircle.Radius; newTabAngles[i][j] -= angleAdjust; newTabAngles[i][j - 1] -= angleAdjust / 2; newTabAngles[i][j + 1] -= angleAdjust / 2; double iAngle = AddInHelper.AngleBetween( circle0.Frame.Origin - baseCircle.Frame.Origin, circle1.Frame.Origin - baseCircle.Frame.Origin ); double vOffset = (distance1 - distance0) * VForce; //double uAngleOffset = -(Math.PI / 2 - Math.Abs(iAngle)) * UAngleForce; double uAngleOffset = -(Math.PI * 2 / 3 - Math.Abs(iAngle)) * UAngleForce; Circle circleV = GetTabFromPoints(true, iOther, j, i); double distanceV = (baseCircle.Frame.Origin - circleV.Frame.Origin).Magnitude - baseCircle.Radius - circleV.Radius; double uTouchOffset = -distanceV * UTouchForce; double averageOffset = 0; double averageAngle = 0; double count = 0; #if false for (int ii = i - 1; ii <= i + 1; ii++) { for (int jj = j - 2; jj <= j + 2; jj++) { if (i == ii && j == jj) { continue; } double weight = (double)1 / (Math.Pow(i - ii, 2) + Math.Pow(j - jj, 2)); averageOffset += GetSpanAt(ii, jj) * weight; averageAngle += GetTabFromPoints(true, i, j, j % 2 == 0 ? i - 1 : i + 1).Radius *weight; count += weight; } } averageOffset = averageOffset / count - GetSpanAt(i, j); averageOffset *= -AverageVForce / 2; averageAngle = averageAngle / count - baseCircle.Radius; newTabAngles[i][j] += averageAngle * AverageTabAngleForce; #elif true foreach (int ii in new int[] { i, iOther }) { foreach (int jj in new int[] { j - 1, j + 1 }) { averageAngle += GetTabFromPoints(true, ii, jj, ii == i ? iOther : i).Radius; count++; } } averageOffset += GetSpanAt(i - 1, j); averageOffset += GetSpanAt(i + 1, j); averageOffset += GetSpanAt(i, j - 1); averageOffset += GetSpanAt(i, j + 1); averageOffset /= 4; averageOffset = averageOffset / count - GetSpanAt(i, j); averageOffset *= -AverageVForce / 2; averageAngle = averageAngle / count - baseCircle.Radius; newTabAngles[i][j] -= averageAngle * AverageTabAngleForce; #else Point midpointV = GetFivePointNurbsAverage(new int[, ] { { i, j - 2 }, { i, j - 1 }, { i, j }, { i, j + 1 }, { i, j + 2 } }); Point midpointD0 = GetFivePointNurbsAverage(new int[, ] { { i - iOtherDir, j - 2 }, { i, j - 1 }, { i, j }, { i + iOtherDir, j + 1 }, { i + 2 * iOtherDir, j + 2 } }); Point midpointD1 = GetFivePointNurbsAverage(new int[, ] { { i - iOtherDir, j + 2 }, { i, j + 1 }, { i, j }, { i + iOtherDir, j - 1 }, { i + 2 * iOtherDir, j - 2 } }); Point midpointU = GetFivePointNurbsAverage(new int[, ] { { i - 2 * iOtherDir, j }, { i - iOtherDir, j }, { i, j }, { i + iOtherDir, j }, { i + 2 * iOtherDir, j } }); averageOffset = (midpointV.Y + midpointU.Y) / 2 - GetSpanAt(i, j); averageOffset *= -AverageVForce / 2; averageAngle = (midpointV.X + 2 * midpointD0.X + 2 * midpointD1.X) / 5 - tabAngles[i][j]; newTabAngles[i][j] += averageAngle * AverageTabAngleForce; #endif double size = 1; // (points[i][j + 1] - points[i][j]).Magnitude; double slip = (uAngleOffset + averageOffset + uTouchOffset) * size; newVParameters[i][j] += vOffset + slip; newVParameters[i][j + 1] += vOffset - slip; newVParameters[i][j - 1] += (vOffset + slip) / 2; newVParameters[i][j + 2] += (vOffset - slip) / 2; // double oldSpan = (points[i][j + 1] - points[i][j]).Magnitude; // double newSpan = (points[i][j + 1] - points[i][j]).Magnitude; Trace.WriteIf(Iteration % 400 == 0, tabAngles[i][j] + " "); // Trace.WriteIf(Iteration % 400 == 0, iAngle + " "); // Trace.WriteIf(Iteration % 400 == 0, GetSpanAt(i,j) + " "); } Trace.WriteLineIf(Iteration % 400 == 0, ""); } for (int i = 0; i < iSteps * 2; i++) { for (int j = 0; j < jSteps; j++) { newTabAngles[i][j] = Math.Max(Math.PI / 2, newTabAngles[i][j]); newTabAngles[i][j] = Math.Min(Math.PI * 3 / 4, newTabAngles[i][j]); double l1 = backupVParameters[i][j + 1] - backupVParameters[i][j]; double l2 = newVParameters[i][j + 1] - newVParameters[i][j]; double b1 = Math.PI - tabAngles[i][j]; double a = l1 / l2 / Math.Tan(b1 / 2) * (1 + 1 / Math.Cos(b1 / 2)); double phi = 2 * Math.Atan(1 / a); tabAngles[i][j] = Math.PI - 2 * phi; //double b2 = 2 * Math.Asin(l2 / l1 * Math.Sin(b1 / 2)); //tabAngles[i][j] = Math.PI - b2; } } for (int i = 0; i < iSteps * 2; i++) { // make intersecting tabs identical //double angle = ( // newTabAngles[i][0] + // newTabAngles[i + iSteps][0] + // newTabAngles[i + iSteps / 2][jSteps / 2] + // newTabAngles[i + 3 * iSteps / 2][jSteps / 2] //) / 4; //newTabAngles[i][0] = angle; //newTabAngles[i + iSteps][0] = angle; //newTabAngles[i + iSteps / 2][jSteps / 2] = angle; //newTabAngles[i + 3 * iSteps / 2][jSteps / 2] = angle; double span = ( (newVParameters[i][1] - newVParameters[i][0]) + (newVParameters[i + iSteps][1] - newVParameters[i + iSteps][0]) + (newVParameters[i + iSteps / 2][jSteps / 2 + 1] - newVParameters[i + iSteps / 2][jSteps / 2]) + (newVParameters[i + 3 * iSteps / 2][jSteps / 2 + 1] - newVParameters[i + 3 * iSteps / 2][jSteps / 2]) ) / 8; newVParameters[i][0] = -span; newVParameters[i][1] = span; newVParameters[i + iSteps][0] = -span; newVParameters[i + iSteps][1] = span; newVParameters[i + iSteps / 2][jSteps / 2] = Math.PI - span; newVParameters[i + iSteps / 2][jSteps / 2 + 1] = Math.PI + span; newVParameters[i + 3 * iSteps / 2][jSteps / 2] = Math.PI - span; newVParameters[i + 3 * iSteps / 2][jSteps / 2 + 1] = Math.PI + span; } // Average antipodal points // for l(i, j), // l(i, j) == l(-i, pi+j)* == l(i+2pi, -j) == l(-i-2pi, pi-j)* // Where * means x=x, y=-y, z=-z for (int i = 0; i < iSteps * 2; i++) { for (int j = 0; j < jSteps / 2; j++) { double average = ( newVParameters[i][j] + newVParameters[-i][j + jSteps / 2] - Math.PI + (j < 2 ? 0 : 2 * Math.PI) - newVParameters[i + iSteps][-j + 1] + Math.PI - newVParameters[-i - iSteps][-j + jSteps / 2 + 1] ) / 4; newVParameters[i][j] = average; newVParameters[-i][j + jSteps / 2] = average + Math.PI; newVParameters[i + iSteps][-j + 1] = (j < 2 ? 0 : 2 * Math.PI) - average; newVParameters[-i - iSteps][-j + jSteps / 2 + 1] = Math.PI - average; average = ( tabAngles[i][j] + tabAngles[-i][j + jSteps / 2 + 1] + tabAngles[i + iSteps][-j] + tabAngles[-i - iSteps][-j + jSteps / 2 + 1] ) / 4; tabAngles[i][j] = average; tabAngles[-i][j + jSteps / 2 + 1] = average; tabAngles[i + iSteps][-j] = average; tabAngles[-i - iSteps][-j + jSteps / 2 + 1] = average; } } CumulativeError = Math.Sqrt(cumulativeErrorTally / (iSteps * 2 * jSteps * 2)); // Trace.WriteLine(lastCumulativeError); // We're not calculating the points for the last iteration. Whatevs. vParameters = newVParameters; tabAngles = newTabAngles; for (int i = 0; i < iSteps * 2; i++) { double u = 2 * Math.PI * (double)i / iSteps; for (int j = 0; j < jSteps; j++) { points[i][j] = Lawson.Evaluate(PointUV.Create(vParameters[i][j], u), p, q, circleAngle, inverseOffset, true) * scale; // Trace.WriteLine(string.Format("{0} {1} {2}", i, j, tabAngles[i][j])); } } }