std::tuple<vector<shared_ptr<Node>>,vector<shared_ptr<Particle>>> SphereClumpGeom::makeParticles(const shared_ptr<Material>& mat, const Vector3r& clumpPos, const Quaternionr& clumpOri, int mask, Real scale){ ensureOk(); assert(centers.size()==radii.size()); const auto N=centers.size(); if(N==1){ // fast path for a single sphere (do not clump at all) auto s=DemFuncs::makeSphere(radii[0]*scale,mat); s->mask=mask; s->shape->nodes[0]->pos=(isnan(clumpPos.maxCoeff())?centers[0]:clumpPos); // natural or forced position return std::make_tuple(vector<shared_ptr<Node>>({s->shape->nodes[0]}),vector<shared_ptr<Particle>>({s})); } vector<shared_ptr<Particle>> par(N); auto n=make_shared<Node>(); auto cd=make_shared<ClumpData>(); n->setData<DemData>(cd); n->pos=(isnan(clumpPos.maxCoeff())?pos:clumpPos); n->ori=clumpOri; cd->nodes.resize(N); cd->relPos.resize(N); cd->relOri.resize(N); for(size_t i=0; i<N; i++){ par[i]=DemFuncs::makeSphere(radii[i]*scale,mat); par[i]->mask=mask; cd->nodes[i]=par[i]->shape->nodes[0]; cd->nodes[i]->getData<DemData>().setClumped(n); // sets flag and assigned master node cd->relPos[i]=(centers[i]-pos)*scale; cd->relOri[i]=ori.conjugate(); // nice to set, but not really important } // sets particles in global space based on relPos, relOri ClumpData::applyToMembers(n); // set clump properties assert(!isnan(volume)); cd->setClump(); assert(cd->isClump()); // scale = length scale (but not density scale) cd->mass=mat->density*volume*pow(scale,3); cd->inertia=mat->density*inertia*pow(scale,5); cd->equivRad=equivRad; return std::make_tuple(vector<shared_ptr<Node>>({n}),par); }
void ActReactGlRep::renderDoubleArrow(const Vector3r& pos, const Vector3r& arr, bool posStart, const Vector3r& offset, const Vector3r& color){ if(isnan(color.maxCoeff())) return; if(posStart){ GLUtils::GLDrawArrow(pos+offset,pos+offset+arr,color); GLUtils::GLDrawArrow(pos-offset,pos-offset-arr,color); } else { GLUtils::GLDrawArrow(pos+offset-arr,pos+offset,color); GLUtils::GLDrawArrow(pos-offset+arr,pos-offset,color); } }
void TraceVisRep::render(const shared_ptr<Node>& n, const GLViewInfo* glInfo){ if(isHidden() || !tracer) return; if(!tracer->glSmooth) glDisable(GL_LINE_SMOOTH); else glEnable(GL_LINE_SMOOTH); glDisable(GL_LIGHTING); bool scale=(glInfo->renderer->dispScale!=Vector3r::Ones() && glInfo->renderer->scaleOn && n->hasData<GlData>()); glLineWidth(tracer->glWidth); const bool periodic=glInfo->scene->isPeriodic; Vector3i prevPeriod=Vector3i::Zero(); // silence gcc warning maybe-uninitialized int nSeg=0; // number of connected vertices (used when trace is interruped by NaN) glBegin(GL_LINE_STRIP); for(size_t i=0; i<pts.size(); i++){ size_t ix; // FIXME: use getPointData here (copied code) // compressed start from the very beginning, till they reach the write position if(flags&FLAG_COMPRESS){ ix=i; if(ix>=writeIx) break; // cycle through the array } else { ix=(writeIx+i)%pts.size(); } if(!isnan(pts[ix][0])){ Vector3r color; if(isnan(scalars[ix])){ // if there is no scalar and no scalar should be saved, color by history position if(tracer->scalar==Tracer::SCALAR_NONE) color=tracer->lineColor->color((flags&FLAG_COMPRESS ? i*1./writeIx : i*1./pts.size())); // if other scalars are saved, use noneColor to not destroy tracer->lineColor range by auto-adjusting to bogus else color=tracer->noneColor; } else color=tracer->lineColor->color(scalars[ix]); if(isnan(color.maxCoeff())){ if(nSeg>0){ glEnd(); glBegin(GL_LINE_STRIP); nSeg=0; } // break line, if there was something already continue; // point skipped completely } glColor3v(color); Vector3r pt(pts[ix]); if(periodic){ // canonicalize the point, store the period Vector3i currPeriod; pt=glInfo->scene->cell->canonicalizePt(pt,currPeriod); // if the period changes between these two points, split the line (and don't render the segment in-between for simplicity) if(i>0 && currPeriod!=prevPeriod){ if(nSeg>0){ glEnd(); glBegin(GL_LINE_STRIP); nSeg=0; } // only if there was sth already // point not skipped, only line interruped, so keep going } prevPeriod=currPeriod; } if(!scale) glVertex3v(pt); else{ const auto& gl=n->getData<GlData>(); // don't scale if refpos is invalid if(isnan(gl.refPos.maxCoeff())) glVertex3v(pt); // x+(s-1)*(x-x0) else glVertex3v((pt+((glInfo->renderer->dispScale-Vector3r::Ones()).array()*(pt-gl.refPos).array()).matrix()).eval()); } nSeg++; } } glEnd(); }