void IdwInterpolator::_buildModel() { _index.reset(); if (_p < 0.0) { NelderMead optimizer(1, new IdwOptimizeFunction(*this), _stopDelta); Vector result; result.prepare(1); _p = 1.0; result[0] = _p; optimizer.step(result, -estimateError()); _p = 4.0; result[0] = _p; optimizer.step(result, -estimateError()); int iterations = 0; while (optimizer.done() == false && iterations <= _maxAllowedPerLoopOptimizationIterations) { double e = -estimateError(); //cout << "error: " << e << " count: " << iterations << endl; result = optimizer.step(result, e); iterations++; _p = result[0]; } if (iterations > _iterations) { _iterations = iterations; } } }
void IdwInterpolator::_buildModel() { _index.reset(); if (_p < 0.0) { NelderMead optimizer(1, new IdwOptimizeFunction(*this), _stopDelta); Vector result; result.prepare(1); _p = 1.0; result[0] = _p; optimizer.step(result, -estimateError()); _p = 4.0; result[0] = _p; optimizer.step(result, -estimateError()); int count = 0; while (optimizer.done() == false) { double e = -estimateError(); cout << "error: " << e << " count: " << count++ << endl; result = optimizer.step(result, e); _p = result[0]; } } }
void KernelEstimationInterpolator::_buildModel() { const DataFrame& df = *_df; _index.reset(); if (_sigma < 0) { // calculate the standard deviation in x double mean = 0; size_t n = df.getNumDataVectors(); for (size_t i = 0; i < n; ++i) { double v = df.getDataVector(i)[_indColumns[0]]; mean += v; } mean /= df.getNumDataVectors(); double sumDiff = 0; for (size_t i = 0; i < n; ++i) { double v = df.getDataVector(i)[_indColumns[0]]; sumDiff += (v - mean) * (v - mean); } double sdx = sqrt(1.0 / (n - 1) * sumDiff); // calculate a reasonable starting point w/ silverman's rule of thumb. Put a minimum at 1m to // prevent some edge conditions. double silvermans = max(1.0, 1.06 * sdx * pow(n, -.2)); NelderMead optimizer(1, new OptimizeFunction(*this), _stopDelta); Vector result; result.prepare(1); // silverman's rule of thumb tends to over estimate and we're faster at evaluating smaller sigma // so start with two smallish values to seed nelder-mead. _sigma = silvermans * 0.6; result[0] = _sigma; optimizer.step(result, -estimateError()); _sigma = silvermans * 0.2; result[0] = _sigma; optimizer.step(result, -estimateError()); while (optimizer.done() == false) { double e = -estimateError(); result = optimizer.step(result, e); _sigma = result[0]; } } }
/* genEllipticPath: * Approximate an elliptical arc via Beziers of given degree * threshold indicates quality of approximation * if isSlice is true, the path begins and ends with line segments * to the center of the ellipse. * Returned path must be freed by the caller. */ static Ppolyline_t *genEllipticPath(ellipse_t * ep, int degree, double threshold, boolean isSlice) { double dEta; double etaB; double cosEtaB; double sinEtaB; double aCosEtaB; double bSinEtaB; double aSinEtaB; double bCosEtaB; double xB; double yB; double xBDot; double yBDot; double t; double alpha; Ppolyline_t *path = NEW(Ppolyline_t); // find the number of Bezier curves needed boolean found = FALSE; int i, n = 1; while ((!found) && (n < 1024)) { double dEta = (ep->eta2 - ep->eta1) / n; if (dEta <= 0.5 * M_PI) { double etaB = ep->eta1; found = TRUE; for (i = 0; found && (i < n); ++i) { double etaA = etaB; etaB += dEta; found = (estimateError(ep, degree, etaA, etaB) <= threshold); } } n = n << 1; } dEta = (ep->eta2 - ep->eta1) / n; etaB = ep->eta1; cosEtaB = cos(etaB); sinEtaB = sin(etaB); aCosEtaB = ep->a * cosEtaB; bSinEtaB = ep->b * sinEtaB; aSinEtaB = ep->a * sinEtaB; bCosEtaB = ep->b * cosEtaB; xB = ep->cx + aCosEtaB * ep->cosTheta - bSinEtaB * ep->sinTheta; yB = ep->cy + aCosEtaB * ep->sinTheta + bSinEtaB * ep->cosTheta; xBDot = -aSinEtaB * ep->cosTheta - bCosEtaB * ep->sinTheta; yBDot = -aSinEtaB * ep->sinTheta + bCosEtaB * ep->cosTheta; if (isSlice) { moveTo(path, ep->cx, ep->cy); lineTo(path, xB, yB); } else { moveTo(path, xB, yB); } t = tan(0.5 * dEta); alpha = sin(dEta) * (sqrt(4 + 3 * t * t) - 1) / 3; for (i = 0; i < n; ++i) { double xA = xB; double yA = yB; double xADot = xBDot; double yADot = yBDot; etaB += dEta; cosEtaB = cos(etaB); sinEtaB = sin(etaB); aCosEtaB = ep->a * cosEtaB; bSinEtaB = ep->b * sinEtaB; aSinEtaB = ep->a * sinEtaB; bCosEtaB = ep->b * cosEtaB; xB = ep->cx + aCosEtaB * ep->cosTheta - bSinEtaB * ep->sinTheta; yB = ep->cy + aCosEtaB * ep->sinTheta + bSinEtaB * ep->cosTheta; xBDot = -aSinEtaB * ep->cosTheta - bCosEtaB * ep->sinTheta; yBDot = -aSinEtaB * ep->sinTheta + bCosEtaB * ep->cosTheta; if (degree == 1) { lineTo(path, xB, yB); #if DO_QUAD } else if (degree == 2) { double k = (yBDot * (xB - xA) - xBDot * (yB - yA)) / (xADot * yBDot - yADot * xBDot); quadTo(path, (xA + k * xADot), (yA + k * yADot), xB, yB); #endif } else { curveTo(path, (xA + alpha * xADot), (yA + alpha * yADot), (xB - alpha * xBDot), (yB - alpha * yBDot), xB, yB); } } endPath(path, isSlice); return path; }