void Model::storeActiveNodeGeometry() { if (activeNode == nullptr) return; QSet<Structure::Node*> nodes; nodes << activeNode; // Apply to group if in any for(auto g : groupsOf(activeNode->id)){ for(auto nid : g){ nodes << getNode(nid); } } for(auto n : nodes) { // Store initial node and mesh geometries n->property["restNodeGeometry"].setValue(n->controlPoints()); n->property["restNodeCentroid"].setValue(n->center()); auto mesh = getMesh(n->id); Array1D_Vector3 meshPoints; for (auto v : mesh->vertices()) meshPoints.push_back(mesh->vertex_coordinates()[v]); n->property["restMeshGeometry"].setValue(meshPoints); } }
void Model::createSheetFromPoints(QVector<QVector3D> &points) { if (points.size() < 2) return; // Convert corner points to Vector3 Array1D_Vector3 cp; for(auto p : points) cp.push_back(Vector3(p[0],p[1],p[2])); // midpoint of diagonal Vector3 center = 0.5 * (cp[1] + cp[2]); // Extent Vector3 du = cp[0] - cp[2], dv = cp[0] - cp[1]; double u = du.norm(), v = dv.norm(); // Create sheet auto newSheetGeometry = NURBS::NURBSRectangled::createSheet(u, v, center, du.normalized(), dv.normalized()); QString newSheetID = QString("sheetNode%1").arg((nodes.empty()? -1 : nodes.back()->property["index"].toInt())+1); auto newSheet = new Structure::Sheet(newSheetGeometry, newSheetID); // Add sheet activeNode = this->addNode(newSheet); generateSurface(); }
void Model::modifyLastAdded(QVector<QVector3D> &guidePoints) { if (guidePoints.size() < 2 || activeNode == nullptr) return; Structure::Curve* curve = dynamic_cast<Structure::Curve*>(activeNode); Structure::Sheet* sheet = dynamic_cast<Structure::Sheet*>(activeNode); auto fp = guidePoints.takeFirst(); Vector3 axis(fp.x(),fp.y(),fp.z()); int skipAxis = -1; if (axis.isApprox(-Vector3::UnitX())) skipAxis = 0; if (axis.isApprox(-Vector3::UnitY())) skipAxis = 1; if (axis.isApprox(Vector3::UnitZ())) skipAxis = 2; // Smooth curve guidePoints = GeometryHelper::smooth(GeometryHelper::uniformResampleCount(guidePoints, 20), 5); // Convert to Vector3 Array1D_Vector3 gpoint; for(auto p : guidePoints) gpoint.push_back(Vector3(p[0],p[1],p[2])); if(curve) { auto oldPoints = curve->controlPoints(); auto newPoints = oldPoints; for(size_t i = 0; i < oldPoints.size(); i++){ for(int j = 0; j < 3; j++){ if(j == skipAxis) newPoints[i][j] = oldPoints[i][j]; else newPoints[i][j] = gpoint[i][j]; } } curve->setControlPoints(newPoints); } if(sheet) { auto oldPoints = sheet->controlPoints(); auto newPoints = oldPoints; Vector3 centroid = sheet->position(Eigen::Vector4d(0.5, 0.5, 0, 0)); Vector3 delta = gpoint.front() - centroid; for(size_t i = 0; i < oldPoints.size(); i++){ for (int j = 0; j < 3; j++){ if (j == skipAxis) continue; newPoints[i][j] += delta[j]; } } sheet->setControlPoints(newPoints); sheet->surface.quads.clear(); } generateSurface(); }
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; }
Array1D_Vector3 Sheet::discretizedAsCurve(Scalar resolution) { // Return a representative curve along the longest side at the middle of the sheet NURBS::NURBSCurved curve; Vector3 uDir = surface.mCtrlPoint.front().back() - surface.mCtrlPoint.front().front(); Vector3 vDir = surface.mCtrlPoint.back().front() - surface.mCtrlPoint.front().front(); double projux = abs(dot(Vector3d(1,0,0), uDir.normalized())); double projvx = abs(dot(Vector3d(1,0,0), vDir.normalized())); //bool isU = uDir.norm() > vDir.norm(); bool isU = projux > projvx; if( isU ) { int v = (surface.mNumUCtrlPoints - 1) * 0.5; curve = NURBS::NURBSCurved(surface.GetControlPointsV(v), surface.GetControlWeightsV(v)); } else { int u = (surface.mNumVCtrlPoints - 1) * 0.5; curve = NURBS::NURBSCurved(surface.GetControlPointsU(u), surface.GetControlWeightsU(u)); } Array1D_Vector3 result; Scalar curveLength = curve.GetLength(0,1); // Degenerate cases bool validControlPoints = std::isfinite(curve.mCtrlPoint.front().x()); if( !validControlPoints ){ result.clear(); for(int i = 0; i < 4; i++) result.push_back(Vector3(0,0,0)); return result; } if( !std::isfinite(curveLength) || curveLength < resolution ) return curve.mCtrlPoint; int np = qMax(2.0, 1.0 + (curveLength / resolution)); curve.SubdivideByLength(np, result); return result; }
void Model::createCurveFromPoints(QVector<QVector3D> & points) { if(points.size() < 2) return; // Nicer curve points = GeometryHelper::smooth(GeometryHelper::uniformResampleCount(points, 20), 5); // Create curve Array1D_Vector3 controlPoints; for(auto p : points) controlPoints.push_back(Vector3(p[0],p[1],p[2])); auto newCurveGeometry = NURBS::NURBSCurved::createCurveFromPoints(controlPoints); QString newCurveID = QString("curveNode%1").arg((nodes.empty()? -1 : nodes.back()->property["index"].toInt())+1); auto newCurve = new Structure::Curve(newCurveGeometry, newCurveID); // Add curve activeNode = this->addNode(newCurve); generateSurface(); }
void TaskSheet::executeMorphSheet( double t ) { Structure::Node * n = node(); Structure::Sheet * sheet = (Structure::Sheet *)n; // Decode SheetEncoding cpCoords = property["cpCoords"].value<SheetEncoding>(); SheetEncoding cpCoordsT = property["cpCoordsT"].value<SheetEncoding>(); RMF::Frame sframe = property["sframe"].value<RMF::Frame>(); RMF::Frame tframe = property["tframe"].value<RMF::Frame>(); QVector<double> rot = property["rotation"].value< QVector<double> >(); Eigen::Quaterniond rotation(rot[0],rot[1],rot[2],rot[3]), eye = Eigen::Quaterniond::Identity(); // Source sheet Eigen::Vector3d R = (sframe.r), S = (sframe.s), T = (sframe.t); R = eye.slerp(t, rotation) * R; S = eye.slerp(t, rotation) * S; T = eye.slerp(t, rotation) * T; RMF::Frame curFrame ((R),(S),(T)); curFrame.center = tframe.center = AlphaBlend(t, sframe.center, tframe.center); Array1D_Vector3 newPnts = Sheet::decodeSheet( cpCoords, curFrame.center, curFrame.r, curFrame.s, curFrame.t ); Array1D_Vector3 newPntsT = Sheet::decodeSheet( cpCoordsT, tframe.center, tframe.r, tframe.s, tframe.t ); Array1D_Vector3 blendedPnts; for(int i = 0; i < (int)newPnts.size(); i++) { blendedPnts.push_back( AlphaBlend(t, newPnts[i], newPntsT[i]) ); } sheet->setControlPoints( blendedPnts ); }