/** * Returns how many times ray from point (x,y) cross cubic curve */ public static int crossCubic(double x1, double y1, double cx1, double cy1, double cx2, double cy2, double x2, double y2, double x, double y) { // LEFT/RIGHT/UP/EMPTY if ((x < x1 && x < cx1 && x < cx2 && x < x2) || (x > x1 && x > cx1 && x > cx2 && x > x2) || (y > y1 && y > cy1 && y > cy2 && y > y2) || (x1 == cx1 && cx1 == cx2 && cx2 == x2)) { return 0; } // DOWN if (y < y1 && y < cy1 && y < cy2 && y < y2 && x != x1 && x != x2) { if (x1 < x2) { return x1 < x && x < x2 ? 1 : 0; } return x2 < x && x < x1 ? -1 : 0; } // INSIDE CubicCurve c = new CubicCurve(x1, y1, cx1, cy1, cx2, cy2, x2, y2); double px = x - x1; double py = y - y1; double[] res = new double[3]; int rc = c.solvePoint(res, px); return c.cross(res, rc, py, py); }
public void DeferredUpdate() { lock (this) { if (!_dirty) { return; } _dirty = false; } FromMatrix = MatrixD.CreateWorld(From.Position, CorrectTangent(From.Tangent), From.Up); ToMatrix = MatrixD.CreateWorld(To.Position, CorrectTangent(To.Tangent), To.Up); var ext = Math.Max((FromMatrix.Translation - ToMatrix.Translation).Length() / 3, 1f); var d1 = default(Vector3D); var d2 = default(Vector3D); if (Mode != CurveMode.Linear) { if (_ctl0.HasValue) { d1 = Vector3D.Transform(_ctl0.Value, FromMatrix); } else { d1 = FromMatrix.Translation + (FromMatrix.Forward * ext); } if (_ctl1.HasValue) { d2 = Vector3D.Transform(_ctl1.Value, ToMatrix); } else { d2 = ToMatrix.Translation - (ToMatrix.Forward * ext); } } switch (Mode) { case CurveMode.Linear: Curve = new LinearCurve(From.Position, To.Position); break; case CurveMode.QuadraticBez: Curve = new QuadraticCurve(FromMatrix.Translation, (d1 + d2) / 2, ToMatrix.Translation); break; case CurveMode.CubicBez: Curve = new CubicCurve(FromMatrix.Translation, d1, d2, ToMatrix.Translation); break; default: throw new Exception($"Unsupported curve mode {Mode}"); } CurveUpdated?.Invoke(this); }
/** * Returns how many times ray from point (x,y) cross cubic curve */ public static int crossCubic(double x1, double y1, double cx1, double cy1, double cx2, double cy2, double x2, double y2, double x, double y) { // LEFT/RIGHT/UP/EMPTY if ((x < x1 && x < cx1 && x < cx2 && x < x2) || (x > x1 && x > cx1 && x > cx2 && x > x2) || (y > y1 && y > cy1 && y > cy2 && y > y2) || (x1 == cx1 && cx1 == cx2 && cx2 == x2)) { return(0); } // DOWN if (y < y1 && y < cy1 && y < cy2 && y < y2 && x != x1 && x != x2) { if (x1 < x2) { return(x1 < x && x < x2 ? 1 : 0); } return(x2 < x && x < x1 ? -1 : 0); } // INSIDE CubicCurve c = new CubicCurve(x1, y1, cx1, cy1, cx2, cy2, x2, y2); double px = x - x1; double py = y - y1; double[] res = new double[3]; int rc = c.solvePoint(res, px); return(c.cross(res, rc, py, py)); }
private void GenerateMap() { PerlinNoise perlin = new PerlinNoise(); var contrast = new CubicCurve(); images = new Texture2D[map_width][]; for (int x = 0; x < map_width; x++) { images[x] = new Texture2D[map_height]; for (int y = 0; y < map_height; y++) { var n = perlin.GetPoint(x * 0.1, y * 0.1); n = CubicCurve.Contrast(n); images[x][y] = ChooseTile(n); } } }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// private void Next(bool doNext) { int level; if (_holdIndex >= _holdEnd) { if (doNext) { _src.Next(); } if (_src.IsDone()) { _done = true; return; } _holdType = _src.CurrentSegment(_intHold); for (int i = 0; i < _intHold.Length; i++) { _hold[i] = _intHold[i]; } _levelIndex = 0; _levels[0] = 0; } switch (_holdType) { case SEG_MOVETO: case SEG_LINETO: _curx = _hold[0]; _cury = _hold[1]; if (_holdType == SEG_MOVETO) { _movx = _curx; _movy = _cury; } _holdIndex = 0; _holdEnd = 0; break; case SEG_CLOSE: _curx = _movx; _cury = _movy; _holdIndex = 0; _holdEnd = 0; break; case SEG_QUADTO: if (_holdIndex >= _holdEnd) { // Move the coordinates to the end of the array. _holdIndex = _hold.Length - 6; _holdEnd = _hold.Length - 2; _hold[_holdIndex + 0] = _curx; _hold[_holdIndex + 1] = _cury; _hold[_holdIndex + 2] = _hold[0]; _hold[_holdIndex + 3] = _hold[1]; _hold[_holdIndex + 4] = _curx = _hold[2]; _hold[_holdIndex + 5] = _cury = _hold[3]; } level = _levels[_levelIndex]; while (level < _limit) { for (int i = 0; i < _intHold.Length; i++) { _intHold[i] = (int)(_hold[i] + .5); } if (QuadCurve.GetFlatnessSq(_intHold, _holdIndex) < _squareflat) { break; } EnsureHoldCapacity(4); QuadCurve.Subdivide(_hold, _holdIndex, _hold, _holdIndex - 4, _hold, _holdIndex); _holdIndex -= 4; // Now that we have subdivided, we have constructed // two curves of one depth lower than the original // curve. One of those curves is in the place of // the former curve and one of them is in the next // set of held coordinate slots. We now set both // curves level values to the next higher level. level++; _levels[_levelIndex] = level; _levelIndex++; _levels[_levelIndex] = level; } // This curve segment is flat enough, or it is too deep // in recursion levels to try to flatten any more. The // two coordinates at holdIndex+4 and holdIndex+5 now // contain the endpoint of the curve which can be the // endpoint of an approximating line segment. _holdIndex += 4; _levelIndex--; break; case SEG_CUBICTO: if (_holdIndex >= _holdEnd) { // Move the coordinates to the end of the array. _holdIndex = _hold.Length - 8; _holdEnd = _hold.Length - 2; _hold[_holdIndex + 0] = _curx; _hold[_holdIndex + 1] = _cury; _hold[_holdIndex + 2] = _hold[0]; _hold[_holdIndex + 3] = _hold[1]; _hold[_holdIndex + 4] = _hold[2]; _hold[_holdIndex + 5] = _hold[3]; _hold[_holdIndex + 6] = _curx = _hold[4]; _hold[_holdIndex + 7] = _cury = _hold[5]; } level = _levels[_levelIndex]; while (level < _limit) { for (int i = 0; i < _intHold.Length; i++) { _intHold[i] = (int)(_hold[i] + .5); } if (CubicCurve.GetFlatnessSq(_intHold, _holdIndex) < _squareflat) { break; } EnsureHoldCapacity(6); CubicCurve.Subdivide(_hold, _holdIndex, _hold, _holdIndex - 6, _hold, _holdIndex); _holdIndex -= 6; // Now that we have subdivided, we have constructed // two curves of one depth lower than the original // curve. One of those curves is in the place of // the former curve and one of them is in the next // set of held coordinate slots. We now set both // curves level values to the next higher level. level++; _levels[_levelIndex] = level; _levelIndex++; _levels[_levelIndex] = level; } // This curve segment is flat enough, or it is too deep // in recursion levels to try to flatten any more. The // two coordinates at holdIndex+6 and holdIndex+7 now // contain the endpoint of the curve which can be the // endpoint of an approximating line segment. _holdIndex += 6; _levelIndex--; break; } }
internal CubicIterator(CubicCurve q, AffineTransform at) { _cubic = q; _affine = at; }
/** * Returns how many times rectangle stripe cross cubic curve or the are intersect */ public static int intersectCubic(double x1, double y1, double cx1, double cy1, double cx2, double cy2, double x2, double y2, double rx1, double ry1, double rx2, double ry2) { // LEFT/RIGHT/UP if ((rx2 < x1 && rx2 < cx1 && rx2 < cx2 && rx2 < x2) || (rx1 > x1 && rx1 > cx1 && rx1 > cx2 && rx1 > x2) || (ry1 > y1 && ry1 > cy1 && ry1 > cy2 && ry1 > y2)) { return 0; } // DOWN if (ry2 < y1 && ry2 < cy1 && ry2 < cy2 && ry2 < y2 && rx1 != x1 && rx1 != x2) { if (x1 < x2) { return x1 < rx1 && rx1 < x2 ? 1 : 0; } return x2 < rx1 && rx1 < x1 ? -1 : 0; } // INSIDE CubicCurve c = new CubicCurve(x1, y1, cx1, cy1, cx2, cy2, x2, y2); double px1 = rx1 - x1; double py1 = ry1 - y1; double px2 = rx2 - x1; double py2 = ry2 - y1; double[] res1 = new double[3]; double[] res2 = new double[3]; int rc1 = c.solvePoint(res1, px1); int rc2 = c.solvePoint(res2, px2); // LEFT/RIGHT if (rc1 == 0 && rc2 == 0) { return 0; } double minX = px1 - DELTA; double maxX = px2 + DELTA; // Build bound -------------------------------------------------------- double[] bound = new double[40]; int bc = 0; // Add roots bc = c.addBound(bound, bc, res1, rc1, minX, maxX, false, 0); bc = c.addBound(bound, bc, res2, rc2, minX, maxX, false, 1); // Add extrimal points rc2 = c.solveExtremX(res2); bc = c.addBound(bound, bc, res2, rc2, minX, maxX, true, 2); rc2 = c.solveExtremY(res2); bc = c.addBound(bound, bc, res2, rc2, minX, maxX, true, 4); // Add start and end if (rx1 < x1 && x1 < rx2) { bound[bc++] = 0.0; bound[bc++] = 0.0; bound[bc++] = 0.0; bound[bc++] = 6; } if (rx1 < x2 && x2 < rx2) { bound[bc++] = 1.0; bound[bc++] = c.ax; bound[bc++] = c.ay; bound[bc++] = 7; } // End build bound ---------------------------------------------------- int cross = crossBound(bound, bc, py1, py2); if (cross != UNKNOWN) { return cross; } return c.cross(res1, rc1, py1, py2); }
/** * Returns how many times rectangle stripe cross cubic curve or the are intersect */ public static int intersectCubic(double x1, double y1, double cx1, double cy1, double cx2, double cy2, double x2, double y2, double rx1, double ry1, double rx2, double ry2) { // LEFT/RIGHT/UP if ((rx2 < x1 && rx2 < cx1 && rx2 < cx2 && rx2 < x2) || (rx1 > x1 && rx1 > cx1 && rx1 > cx2 && rx1 > x2) || (ry1 > y1 && ry1 > cy1 && ry1 > cy2 && ry1 > y2)) { return(0); } // DOWN if (ry2 < y1 && ry2 < cy1 && ry2 < cy2 && ry2 < y2 && rx1 != x1 && rx1 != x2) { if (x1 < x2) { return(x1 < rx1 && rx1 < x2 ? 1 : 0); } return(x2 < rx1 && rx1 < x1 ? -1 : 0); } // INSIDE CubicCurve c = new CubicCurve(x1, y1, cx1, cy1, cx2, cy2, x2, y2); double px1 = rx1 - x1; double py1 = ry1 - y1; double px2 = rx2 - x1; double py2 = ry2 - y1; double[] res1 = new double[3]; double[] res2 = new double[3]; int rc1 = c.solvePoint(res1, px1); int rc2 = c.solvePoint(res2, px2); // LEFT/RIGHT if (rc1 == 0 && rc2 == 0) { return(0); } double minX = px1 - DELTA; double maxX = px2 + DELTA; // Build bound -------------------------------------------------------- double[] bound = new double[40]; int bc = 0; // Add roots bc = c.addBound(bound, bc, res1, rc1, minX, maxX, false, 0); bc = c.addBound(bound, bc, res2, rc2, minX, maxX, false, 1); // Add extrimal points rc2 = c.solveExtremX(res2); bc = c.addBound(bound, bc, res2, rc2, minX, maxX, true, 2); rc2 = c.solveExtremY(res2); bc = c.addBound(bound, bc, res2, rc2, minX, maxX, true, 4); // Add start and end if (rx1 < x1 && x1 < rx2) { bound[bc++] = 0.0; bound[bc++] = 0.0; bound[bc++] = 0.0; bound[bc++] = 6; } if (rx1 < x2 && x2 < rx2) { bound[bc++] = 1.0; bound[bc++] = c.ax; bound[bc++] = c.ay; bound[bc++] = 7; } // End build bound ---------------------------------------------------- int cross = crossBound(bound, bc, py1, py2); if (cross != UNKNOWN) { return(cross); } return(c.cross(res1, rc1, py1, py2)); }