void DeformationPath::badMorphing() { for(double t = 0; t <= 1.0; t += scheduler->timeStep) { // Current nodes geometry QMap<Structure::Node*, Array1D_Vector3> startGeometry; for(auto n : scheduler->activeGraph->nodes) { if(n->property["taskTypeReal"].toInt() == Task::GROW) { Array1D_Vector3 pnts = n->controlPoints(); Vector3 p = pnts.front(); Array1D_Vector3 newpnts(pnts.size(), p); for(auto & p: newpnts) p += Eigen::Vector3d(starlab::uniformRand(), starlab::uniformRand(), starlab::uniformRand()) * 1e-5; n->setControlPoints(newpnts); } if(n->property["taskTypeReal"].toInt() == Task::SHRINK) { auto tn = scheduler->targetGraph->getNode( n->property["correspond"].toString() ); Array1D_Vector3 pnts = tn->controlPoints(); Vector3 p = pnts[pnts.size() / 2]; Array1D_Vector3 newpnts(pnts.size(), p); for(auto & p: newpnts) p += Eigen::Vector3d(starlab::uniformRand(), starlab::uniformRand(), starlab::uniformRand()) * 1e-5; tn->setControlPoints(newpnts); } startGeometry[n] = n->controlPoints(); } // Morph nodes for(auto n : scheduler->activeGraph->nodes) { auto tn = scheduler->targetGraph->getNode( n->property["correspond"].toString() ); if(!tn) continue; Array1D_Vector3 finalGeometry = tn->controlPoints(); Array1D_Vector3 newGeometry; for(int i = 0; i < (int) finalGeometry.size(); i++) newGeometry.push_back( AlphaBlend(t, startGeometry[n][i], Vector3(finalGeometry[i])) ); n->setControlPoints( newGeometry ); n->property["t"].setValue( t ); if(t > 0.5 && n->property["taskTypeReal"].toInt() == Task::SHRINK) n->property["shrunk"].setValue( true ); } scheduler->allGraphs.push_back( new Structure::Graph( *scheduler->activeGraph ) ); } property["progressDone"] = true; }
/* ||>*----*----*----*----* | | | | | --> | | | | | ||>*----*----*----*----* Sigma | | | | | --> | | | | | ||>*----*----*----*----* ^ */ NuTo::BSplineSurface buildRect2D(double x0, double y0, double Height, double Length) { /** Knots and control points **/ int numElementsX = 1; int numElementsY = 1; Eigen::Vector2i degree(2, 2); int numKnotsX = 2 * (degree(0) + 1) + numElementsX - 1; int numKnotsY = 2 * (degree(1) + 1) + numElementsY - 1; Eigen::VectorXd knotsX(numKnotsX); Eigen::VectorXd knotsY(numKnotsY); for (int i = 0; i <= degree(0); i++) knotsX(i) = 0.; for (int i = degree(0) + 1; i <= degree(0) + numElementsX - 1; i++) knotsX(i) = knotsX(i - 1) + 1. / numElementsX; for (int i = degree(0) + numElementsX; i < numKnotsX; i++) knotsX(i) = 1; for (int i = 0; i <= degree(1); i++) knotsY(i) = 0.; for (int i = degree(1) + 1; i <= degree(1) + numElementsY - 1; i++) knotsY(i) = knotsY(i - 1) + 1. / numElementsY; for (int i = degree(1) + numElementsY; i < numKnotsY; i++) knotsY(i) = 1; int numControlPointsX = (numKnotsX - 1) - degree(0); int numControlPointsY = (numKnotsY - 1) - degree(1); Eigen::Matrix<Eigen::VectorXd, Eigen::Dynamic, Eigen::Dynamic> controlPoints(numControlPointsY, numControlPointsX); double incrx = (Length / (numControlPointsX - 1)); double incry = (Height / (numControlPointsY - 1)); for (int i = 0; i < numControlPointsY; i++) { for (int j = 0; j < numControlPointsX; j++) { controlPoints(i, j) = Eigen::Vector2d(x0 + incrx * j, y0 + incry * i); } } Eigen::MatrixXd weights(numControlPointsY, numControlPointsX); weights.setOnes(numControlPointsY, numControlPointsX); return NuTo::BSplineSurface(degree, knotsX, knotsY, controlPoints, weights); }
DenseMatrix BSpline::getControlPoints() const { int nc = coefficients.size(); DenseMatrix controlPoints(nc, numVariables + 1); controlPoints.block(0, 0, nc, numVariables) = knotaverages; controlPoints.block(0, numVariables, nc, 1) = coefficients; return controlPoints; }
void GraphicsPainter::drawSpline(const QList<Point3f> &points, float radius, int order) { if(points.size() < 2){ return; } // calculate axis and up vectors (needed to calculate control points) QVector<Vector3f> axisVectors(points.size()); axisVectors[0] = (points[1] - points[0]).normalized(); QVector<Vector3f> upVectors(points.size()); if(points.size() > 2) upVectors[0] = (points[1] - points[0]).cross(points[2] - points[1]).normalized(); else upVectors[0] = Vector3f::UnitZ(); for(int i = 1; i < points.size(); i++){ Vector3f axis = points[i] - points[i-1]; if(i != (points.size() - 1)){ float angle = chemkit::geometry::angle(axis.cast<Real>(), (points[i+1] - points[i]).cast<Real>()); Vector3f rotationAxis = (points[i] - points[i-1]).cross(points[i+1] - points[i]).normalized(); axis = chemkit::geometry::rotate(axis, rotationAxis, angle / 2.0f); } axisVectors[i] = axis.normalized(); Vector3f rotationAxis = axisVectors[i-1].cross(axisVectors[i]); float angle = chemkit::geometry::angle(axis.cast<Real>(), axisVectors[i-1].cast<Real>()); Vector3f up = chemkit::geometry::rotate(upVectors[i-1], rotationAxis, angle); up.normalize(); upVectors[i] = up; } // calculate control points QVector<Point3f> controlPoints(points.size() * 9); for(int i = 0; i < points.size(); i++){ const Point3f &point = points.at(i); Vector3f upVector = upVectors[i]; Vector3f rightVector = upVector.cross(axisVectors[i]).normalized(); // 8 points around a square surrounding point // right Point3f right = point + (rightVector * radius); controlPoints[i*9+0] = right; // bottom right Point3f bottomRight = right + (upVector * -radius); controlPoints[i*9+1] = bottomRight; // bottom Point3f bottom = point + (upVector * -radius); controlPoints[i*9+2] = bottom; // bottom left Point3f bottomLeft = bottom + (rightVector * -radius); controlPoints[i*9+3] = bottomLeft; // left Point3f left = point + (rightVector * -radius); controlPoints[i*9+4] = left; // top left Point3f topLeft = left + (upVector * radius); controlPoints[i*9+5] = topLeft; // top Point3f top = point + (upVector * radius); controlPoints[i*9+6] = top; // top right Point3f topRight = top + (rightVector * radius); controlPoints[i*9+7] = topRight; // right (again) controlPoints[i*9+8] = right; } // build knot vector QVector<float> uKnots(points.size() + order); for(int i = 0; i < uKnots.size(); i++){ if(i < order) uKnots[i] = 0; else if(i > (points.size()) - 1) uKnots[i] = (points.size() + order) - 2 * order + 1; else uKnots[i] = (i - order + 1); } QVector<float> vKnots(12); vKnots[0] = 0; vKnots[1] = 0; vKnots[2] = 0; vKnots[3] = chemkit::constants::Pi / 2.0; vKnots[4] = chemkit::constants::Pi / 2.0; vKnots[5] = chemkit::constants::Pi; vKnots[6] = chemkit::constants::Pi; vKnots[7] = 3.0 * chemkit::constants::Pi / 2.0; vKnots[8] = 3.0 * chemkit::constants::Pi / 2.0; vKnots[9] = 2.0 * chemkit::constants::Pi; vKnots[10] = 2.0 * chemkit::constants::Pi; vKnots[11] = 2.0 * chemkit::constants::Pi; drawNurbsSurface(controlPoints, uKnots, vKnots, order, 3); drawCircle(points.first(), radius * 1.08, -axisVectors.first()); drawCircle(points.last(), radius * 1.08, axisVectors.last()); }
void Apsis::Map::raise(float amount) { // Every tile this touches is raised a little bit Apsis::Tile* tile; float old_height; if (_x != _width && _z != _height) { // Bottom Right tile = atIndex(_x, _z); old_height = tile->cornerHeight(Apsis::TOP_LEFT); tile->cornerHeight(Apsis::TOP_LEFT, old_height + amount); } if (_x != 0 && _z != _height) { // Bottom Left tile = atIndex(_x-1, _z); old_height = tile->cornerHeight(Apsis::TOP_RIGHT); tile->cornerHeight(Apsis::TOP_RIGHT, old_height + amount); } if (_x != _width && _z != 0) { // Top Right tile = atIndex(_x, _z-1); old_height = tile->cornerHeight(Apsis::BOT_LEFT); tile->cornerHeight(Apsis::BOT_LEFT, old_height + amount); } if (_x != 0 && _z != 0) { // Top Left tile = atIndex(_x-1, _z-1); old_height = tile->cornerHeight(Apsis::BOT_RIGHT); tile->cornerHeight(Apsis::BOT_RIGHT, old_height + amount); } // Regenerate curve points along this point // Horizontal Point* line; Point* first; Point* second; line = new Point[_width+1]; first = new Point[_width]; second = new Point[_width]; for (unsigned int x = 0; x < _width; x++) { tile = atIndex(x, _z); line[x].x = (float)x; line[x].y = tile->cornerHeight(Apsis::TOP_LEFT); line[x].z = 0.0f; // does not matter } line[_width].x = (float)_width; line[_width].y = tile->cornerHeight(Apsis::TOP_RIGHT); line[_width].z = 0.0f; controlPoints(line, first, second, _width+1); // Pass control points back to tiles for (unsigned int x = 0; x < _width; x++) { tile = atIndex(x, _z); tile->firstControl(Apsis::TOP_LEFT, first[x].y); tile->secondControl(Apsis::TOP_LEFT, second[x].y); if (_z != 0) { tile = atIndex(x, _z-1); tile->firstControl(Apsis::BOT_RIGHT, first[x].y); tile->secondControl(Apsis::BOT_RIGHT, second[x].y); } } delete [] first; delete [] second; delete [] line; // Vertical line = new Point[_height+1]; first = new Point[_height+1]; second = new Point[_height+1]; for (unsigned int z = 0; z < _height; z++) { tile = atIndex(_x, z); line[z].x = (float)z; // does not matter line[z].y = tile->cornerHeight(Apsis::TOP_LEFT); line[z].z = 0.0f; } line[_height].x = (float)_height; line[_height].y = tile->cornerHeight(Apsis::BOT_LEFT); line[_height].z = 0.0f; controlPoints(line, first, second, _height+1); // Pass control points back to tiles for (unsigned int z = 0; z < _height; z++) { tile = atIndex(_x, z); tile->firstControl(Apsis::BOT_LEFT, first[z].y); tile->secondControl(Apsis::BOT_LEFT, second[z].y); if (_x != 0) { tile = atIndex(_x-1, z); tile->firstControl(Apsis::TOP_RIGHT, first[z].y); tile->secondControl(Apsis::TOP_RIGHT, second[z].y); } } delete [] first; delete [] second; delete [] line; }