mesh parse_stl(const std::string& file) { std::ifstream stl(file, std::ios::in | std::ios::binary); mesh mesh; if (stl.is_open()) { // skip header stl.seekg(80, std::ifstream::beg); uint32_t num_tri = 0; stl.read(reinterpret_cast<char*>(&num_tri), sizeof(uint32_t)); for (uint32_t i = 0; i < num_tri; i++) { // skip face normals stl.seekg(3 * sizeof(float), std::ifstream::cur); glm::vec3 a, b, c; stl.read(reinterpret_cast<char*>(&a), sizeof(a)); stl.read(reinterpret_cast<char*>(&b), sizeof(b)); stl.read(reinterpret_cast<char*>(&c), sizeof(c)); stl.seekg(sizeof(uint16_t), std::ifstream::cur); mesh.add_triangle(a, b, c); } } else { THROW_IF(!stl.is_open(),error_type::file_not_found); } mesh.calculate_normals(); mesh.centralize(); return mesh; }
void add_pixels_clamped_mvi(const int16_t *block, uint8_t *pixels, ptrdiff_t line_size) { int h = 8; /* Keep this function a leaf function by generating the constants manually (mainly for the hack value ;-). */ uint64_t clampmask = zap(-1, 0xaa); /* 0x00ff00ff00ff00ff */ uint64_t signmask = zap(-1, 0x33); signmask ^= signmask >> 1; /* 0x8000800080008000 */ do { uint64_t shorts0, pix0, signs0; uint64_t shorts1, pix1, signs1; shorts0 = ldq(block); shorts1 = ldq(block + 4); pix0 = unpkbw(ldl(pixels)); /* Signed subword add (MMX paddw). */ signs0 = shorts0 & signmask; shorts0 &= ~signmask; shorts0 += pix0; shorts0 ^= signs0; /* Clamp. */ shorts0 = maxsw4(shorts0, 0); shorts0 = minsw4(shorts0, clampmask); /* Next 4. */ pix1 = unpkbw(ldl(pixels + 4)); signs1 = shorts1 & signmask; shorts1 &= ~signmask; shorts1 += pix1; shorts1 ^= signs1; shorts1 = maxsw4(shorts1, 0); shorts1 = minsw4(shorts1, clampmask); stl(pkwb(shorts0), pixels); stl(pkwb(shorts1), pixels + 4); pixels += line_size; block += 8; } while (--h); }
/* These functions were the base for the optimized assembler routines, and remain here for documentation purposes. */ static void put_pixels_clamped_mvi(const int16_t *block, uint8_t *pixels, ptrdiff_t line_size) { int i = 8; uint64_t clampmask = zap(-1, 0xaa); /* 0x00ff00ff00ff00ff */ do { uint64_t shorts0, shorts1; shorts0 = ldq(block); shorts0 = maxsw4(shorts0, 0); shorts0 = minsw4(shorts0, clampmask); stl(pkwb(shorts0), pixels); shorts1 = ldq(block + 4); shorts1 = maxsw4(shorts1, 0); shorts1 = minsw4(shorts1, clampmask); stl(pkwb(shorts1), pixels + 4); pixels += line_size; block += 8; } while (--i); }
// --------------------------------------------------------------------------- // A PLACER DANS STYLEMGR // ------------ bool bMacMapType::make_style(){ _bTrace_("bMacMapType::make_style",false); char path[PATH_MAX]; CFURLRef url; switch(_kind){ case kBaseKindPoint: url=CFBundleCopyResourceURL(CFBundleGetMainBundle(),CFSTR("default_point_style"),CFSTR("xml"),NULL); break; case kBaseKindPolyline: url=CFBundleCopyResourceURL(CFBundleGetMainBundle(),CFSTR("default_line_style"),CFSTR("xml"),NULL); break; case kBaseKindText: url=CFBundleCopyResourceURL(CFBundleGetMainBundle(),CFSTR("default_text_style"),CFSTR("xml"),NULL); break; case kBaseKindPolygon: url=CFBundleCopyResourceURL(CFBundleGetMainBundle(),CFSTR("default_surf_style"),CFSTR("xml"),NULL); break; case kBaseKindRaster: url=CFBundleCopyResourceURL(CFBundleGetMainBundle(),CFSTR("default_raster_style"),CFSTR("xml"),NULL); break; default: _te_("bad type kind "+_kind); return(false); break; } if(!url){ _te_("url == NULL"); return(false); } CFStringRef cfs=CFURLCopyFileSystemPath(url,kCFURLPOSIXPathStyle); CFRelease(url); CFStringGetCString(cfs,path,PATH_MAX,kCFStringEncodingMacRoman); CFRelease(cfs); void* buffer; int sz; bStdFile stl(path,"r"); if(stl.status()){ _te_("stl.status()="+stl.status()); return(false); } stl.mount((char**)&buffer,&sz); _bse.set_param("styles","default.xml",buffer,sz); free(buffer); return(true); }
int facetsToSTL(const string& out, const shared_ptr<DemField>& dem, const string& solid, int mask, bool append){ auto particleOk=[&](const shared_ptr<Particle>&p){ return (mask==0 || (p->mask & mask)) && (p->shape->isA<Facet>()); }; std::ofstream stl(out,append?(std::ofstream::app|std::ofstream::binary):std::ofstream::binary); // binary better, anyway if(!stl.good()) throw std::runtime_error("Failed to open output file "+out+" for writing."); int num=0; stl<<"solid "<<solid<<"\n"; for(const auto& p: *dem->particles){ if(!particleOk(p)) continue; const auto& f=p->shape->cast<Facet>(); Vector3r normal=f.getNormal().normalized(); stl<<" facet normal "<<normal.x()<<" "<<normal.y()<<" "<<normal.z()<<"\n"; stl<<" outer loop\n"; for(const auto& n: f.nodes) stl<<" vertex "<<n->pos[0]<<" "<<n->pos[1]<<" "<<n->pos[2]<<"\n"; stl<<" endloop\n"; stl<<" endfacet\n"; num+=1; } stl<<"endsolid "<<solid<<"\n"; stl.close(); return num; }
void helper_ocbi(uint32_t address) { memory_content **current = &(env->movcal_backup); while (*current) { uint32_t a = (*current)->address; if ((a & ~0x1F) == (address & ~0x1F)) { memory_content *next = (*current)->next; stl(a, (*current)->value); if (next == 0) { env->movcal_backup_tail = current; } free (*current); *current = next; break; } } }
void _gts_face_to_stl(GtsTriangle* t,_gts_face_to_stl_data* data){ GtsVertex* v[3]; Vector3r n; gts_triangle_vertices(t,&v[0],&v[1],&v[2]); if(data->clipCell && data->scene->isPeriodic){ for(short ax:{0,1,2}){ Vector3r p(GTS_POINT(v[ax])->x,GTS_POINT(v[ax])->y,GTS_POINT(v[ax])->z); if(!data->scene->cell->isCanonical(p)) return; } } gts_triangle_normal(t,&n[0],&n[1],&n[2]); n.normalize(); std::ofstream& stl(data->stl); stl<<" facet normal "<<n[0]<<" "<<n[1]<<" "<<n[2]<<"\n"; stl<<" outer loop\n"; for(GtsVertex* _v: v){ stl<<" vertex "<<GTS_POINT(_v)->x<<" "<<GTS_POINT(_v)->y<<" "<<GTS_POINT(_v)->z<<"\n"; } stl<<" endloop\n"; stl<<" endfacet\n"; data->numTri+=3; }
int main(int argc, char *argv[]) { QApplication a(argc, argv); QLabel ww; ww.setPixmap(QPixmap("qt-logo.png")); //qDebug("wid=%d", (int)ww.winId()); QVBoxLayout vl; ww.setLayout(&vl); QAeroWidget aero_widget; //w.setWindowFlags(Qt::Window | Qt::WindowStaysOnTopHint); aero_widget.setEffect(QAeroWidget::Aero); aero_widget.setEffectOpacity(0.1); QLabel text(&aero_widget); text.setText("<font color=#ff0000 size=22>Aero Widget</font>"); QAeroWidget blur_widget; blur_widget.setEffect(QAeroWidget::Blur); blur_widget.setEffectOpacity(0.1); QLabel bl(&blur_widget); bl.setText("<font color=#ff00ff size=22>Blur Widget</font>"); QAeroWidget st_widget; st_widget.setEffect(QAeroWidget::SemiTransparent); st_widget.setEffectOpacity(0.1); QLabel stl(&st_widget); stl.setText("<font color=#ffff00 size=22>SemiTransparent Widget</font>"); QLabel normal_text; normal_text.setText("<font color=#0000ff size=22>Normal Widget</font>"); vl.addWidget(&aero_widget); vl.addWidget(&blur_widget); vl.addWidget(&st_widget); vl.addWidget(&normal_text); ww.show(); QAeroWidget aero_window; aero_window.setEffect(QAeroWidget::Aero); //aero_window.setEffectOpacity(0.618); //aero_window.setWindowFlags(Qt::FramelessWindowHint); QLabel text_aw(&aero_window); text_aw.setText("<font color=#ff0000 size=22>Aero Window</font>"); aero_window.show(); aero_window.resize(text_aw.size()); QAeroWidget blur_window; blur_window.setEffect(QAeroWidget::Blur); QLabel text_awbb(&blur_window); text_awbb.setText("<font color=#ff0000 size=22>Blur Window</font>"); blur_window.show(); blur_window.resize(text_awbb.size()); QAeroWidget semitransparent_window; semitransparent_window.setEffect(QAeroWidget::SemiTransparent); semitransparent_window.setEffectOpacity(0.618); QLabel text_semitransparent_window(&semitransparent_window); text_semitransparent_window.setText("<font color=#ff0000 size=22>SemiTransparent Window</font>"); semitransparent_window.show(); semitransparent_window.resize(text_semitransparent_window.size()); return a.exec(); }
int spheroidsToSTL(const string& out, const shared_ptr<DemField>& dem, Real tol, const string& solid, int mask, bool append, bool clipCell, bool merge){ if(tol==0 || isnan(tol)) throw std::runtime_error("tol must be non-zero."); #ifndef WOO_GTS if(merge) throw std::runtime_error("woo.triangulated.spheroidsToSTL: merge=True only possible in builds with the 'gts' feature."); #endif // first traversal to find reference radius auto particleOk=[&](const shared_ptr<Particle>&p){ return (mask==0 || (p->mask & mask)) && (p->shape->isA<Sphere>() || p->shape->isA<Ellipsoid>() || p->shape->isA<Capsule>()); }; int numTri=0; if(tol<0){ LOG_DEBUG("tolerance is negative, taken as relative to minimum radius."); Real minRad=Inf; for(const auto& p: *dem->particles){ if(particleOk(p)) minRad=min(minRad,p->shape->equivRadius()); } if(isinf(minRad) || isnan(minRad)) throw std::runtime_error("Minimum radius not found (relative tolerance specified); no matching particles?"); tol=-minRad*tol; LOG_DEBUG("Minimum radius "<<minRad<<"."); } LOG_DEBUG("Triangulation tolerance is "<<tol); std::ofstream stl(out,append?(std::ofstream::app|std::ofstream::binary):std::ofstream::binary); // binary better, anyway if(!stl.good()) throw std::runtime_error("Failed to open output file "+out+" for writing."); Scene* scene=dem->scene; if(!scene) throw std::logic_error("DEM field has not associated scene?"); // periodicity, cache that for later use AlignedBox3r cell; /* wasteful memory-wise, but we need to store the whole triangulation in case *merge* is in effect, when it is only an intermediary result and will not be output as-is */ vector<vector<Vector3r>> ppts; vector<vector<Vector3i>> ttri; vector<Particle::id_t> iid; for(const auto& p: *dem->particles){ if(!particleOk(p)) continue; const auto sphere=dynamic_cast<Sphere*>(p->shape.get()); const auto ellipsoid=dynamic_cast<Ellipsoid*>(p->shape.get()); const auto capsule=dynamic_cast<Capsule*>(p->shape.get()); vector<Vector3r> pts; vector<Vector3i> tri; if(sphere || ellipsoid){ Real r=sphere?sphere->radius:ellipsoid->semiAxes.minCoeff(); // 1 is for icosahedron int tess=ceil(M_PI/(5*acos(1-tol/r))); LOG_DEBUG("Tesselation level for #"<<p->id<<": "<<tess); tess=max(tess,0); auto uSphTri(CompUtils::unitSphereTri20(/*0 for icosahedron*/max(tess-1,0))); const auto& uPts=std::get<0>(uSphTri); // unit sphere point coords pts.resize(uPts.size()); const auto& node=(p->shape->nodes[0]); Vector3r scale=(sphere?sphere->radius*Vector3r::Ones():ellipsoid->semiAxes); for(size_t i=0; i<uPts.size(); i++){ pts[i]=node->loc2glob(uPts[i].cwiseProduct(scale)); } tri=std::get<1>(uSphTri); // this makes a copy, but we need out own for capsules } if(capsule){ #ifdef WOO_VTK int subdiv=max(4.,ceil(M_PI/(acos(1-tol/capsule->radius)))); std::tie(pts,tri)=VtkExport::triangulateCapsule(static_pointer_cast<Capsule>(p->shape),subdiv); #else throw std::runtime_error("Triangulation of capsules is (for internal and entirely fixable reasons) only available when compiled with the 'vtk' features."); #endif } // do not write out directly, store first for later ppts.push_back(pts); ttri.push_back(tri); LOG_TRACE("#"<<p->id<<" triangulated: "<<tri.size()<<","<<pts.size()<<" faces,vertices."); if(scene->isPeriodic){ // make sure we have aabb, in skewed coords and such if(!p->shape->bound){ // this is a bit ugly, but should do the trick; otherwise we would recompute all that ourselves here if(sphere) Bo1_Sphere_Aabb().go(p->shape); else if(ellipsoid) Bo1_Ellipsoid_Aabb().go(p->shape); else if(capsule) Bo1_Capsule_Aabb().go(p->shape); } assert(p->shape->bound); const AlignedBox3r& box(p->shape->bound->box); AlignedBox3r cell(Vector3r::Zero(),scene->cell->getSize()); // possibly in skewed coords // central offset Vector3i off0; scene->cell->canonicalizePt(p->shape->nodes[0]->pos,off0); // computes off0 Vector3i off; // offset from the original cell //cerr<<"#"<<p->id<<" at "<<p->shape->nodes[0]->pos.transpose()<<", off0="<<off0<<endl; for(off[0]=off0[0]-1; off[0]<=off0[0]+1; off[0]++) for(off[1]=off0[1]-1; off[1]<=off0[1]+1; off[1]++) for(off[2]=off0[2]-1; off[2]<=off0[2]+1; off[2]++){ Vector3r dx=scene->cell->intrShiftPos(off); //cerr<<" off="<<off.transpose()<<", dx="<<dx.transpose()<<endl; AlignedBox3r boxOff(box); boxOff.translate(dx); //cerr<<" boxOff="<<boxOff.min()<<";"<<boxOff.max()<<" | cell="<<cell.min()<<";"<<cell.max()<<endl; if(boxOff.intersection(cell).isEmpty()) continue; // copy the entire triangulation, offset by dx vector<Vector3r> pts2(pts); for(auto& p: pts2) p+=dx; vector<Vector3i> tri2(tri); // same topology ppts.push_back(pts2); ttri.push_back(tri2); LOG_TRACE(" offset "<<off.transpose()<<": #"<<p->id<<": "<<tri2.size()<<","<<pts2.size()<<" faces,vertices."); } } } if(!merge){ LOG_DEBUG("Will export (unmerged) "<<ppts.size()<<" particles to STL."); stl<<"solid "<<solid<<"\n"; for(size_t i=0; i<ppts.size(); i++){ const auto& pts(ppts[i]); const auto& tri(ttri[i]); LOG_TRACE("Exporting "<<i<<" with "<<tri.size()<<" faces."); for(const Vector3i& t: tri){ Vector3r pp[]={pts[t[0]],pts[t[1]],pts[t[2]]}; // skip triangles which are entirely out of the canonical periodic cell if(scene->isPeriodic && clipCell && (!scene->cell->isCanonical(pp[0]) && !scene->cell->isCanonical(pp[1]) && !scene->cell->isCanonical(pp[2]))) continue; numTri++; Vector3r n=(pp[1]-pp[0]).cross(pp[2]-pp[1]).normalized(); stl<<" facet normal "<<n.x()<<" "<<n.y()<<" "<<n.z()<<"\n"; stl<<" outer loop\n"; for(auto p: {pp[0],pp[1],pp[2]}){ stl<<" vertex "<<p[0]<<" "<<p[1]<<" "<<p[2]<<"\n"; } stl<<" endloop\n"; stl<<" endfacet\n"; } } stl<<"endsolid "<<solid<<"\n"; stl.close(); return numTri; } #if WOO_GTS /***** Convert all triangulation to GTS surfaces, find their distances, isolate connected components, merge these components incrementally and write to STL *****/ // total number of points const size_t N(ppts.size()); // bounds for collision detection struct Bound{ Bound(Real _coord, int _id, bool _isMin): coord(_coord), id(_id), isMin(_isMin){}; Bound(): coord(NaN), id(-1), isMin(false){}; // just for allocation Real coord; int id; bool isMin; bool operator<(const Bound& b) const { return coord<b.coord; } }; vector<Bound> bounds[3]={vector<Bound>(2*N),vector<Bound>(2*N),vector<Bound>(2*N)}; /* construct GTS surface objects; all objects must be deleted explicitly! */ vector<GtsSurface*> ssurf(N); vector<vector<GtsVertex*>> vvert(N); vector<vector<GtsEdge*>> eedge(N); vector<AlignedBox3r> boxes(N); for(size_t i=0; i<N; i++){ LOG_TRACE("** Creating GTS surface for #"<<i<<", with "<<ttri[i].size()<<" faces, "<<ppts[i].size()<<" vertices."); AlignedBox3r box; // new surface object ssurf[i]=gts_surface_new(gts_surface_class(),gts_face_class(),gts_edge_class(),gts_vertex_class()); // copy over all vertices vvert[i].reserve(ppts[i].size()); eedge[i].reserve(size_t(1.5*ttri[i].size())); // each triangle consumes 1.5 edges, for closed surfs for(size_t v=0; v<ppts[i].size(); v++){ vvert[i].push_back(gts_vertex_new(gts_vertex_class(),ppts[i][v][0],ppts[i][v][1],ppts[i][v][2])); box.extend(ppts[i][v]); } // create faces, and create edges on the fly as needed std::map<std::pair<int,int>,int> edgeIndices; for(size_t t=0; t<ttri[i].size(); t++){ //const Vector3i& t(ttri[i][t]); //LOG_TRACE("Face with vertices "<<ttri[i][t][0]<<","<<ttri[i][t][1]<<","<<ttri[i][t][2]); Vector3i eIxs; for(int a:{0,1,2}){ int A(ttri[i][t][a]), B(ttri[i][t][(a+1)%3]); auto AB=std::make_pair(min(A,B),max(A,B)); auto ABI=edgeIndices.find(AB); if(ABI==edgeIndices.end()){ // this edge not created yet edgeIndices[AB]=eedge[i].size(); // last index eIxs[a]=eedge[i].size(); //LOG_TRACE(" New edge #"<<eIxs[a]<<": "<<A<<"--"<<B<<" (length "<<(ppts[i][A]-ppts[i][B]).norm()<<")"); eedge[i].push_back(gts_edge_new(gts_edge_class(),vvert[i][A],vvert[i][B])); } else { eIxs[a]=ABI->second; //LOG_TRACE(" Found edge #"<<ABI->second<<" for "<<A<<"--"<<B); } } //LOG_TRACE(" New face: edges "<<eIxs[0]<<"--"<<eIxs[1]<<"--"<<eIxs[2]); GtsFace* face=gts_face_new(gts_face_class(),eedge[i][eIxs[0]],eedge[i][eIxs[1]],eedge[i][eIxs[2]]); gts_surface_add_face(ssurf[i],face); } // make sure the surface is OK if(!gts_surface_is_orientable(ssurf[i])) LOG_ERROR("Surface of #"+to_string(iid[i])+" is not orientable (expect troubles)."); if(!gts_surface_is_closed(ssurf[i])) LOG_ERROR("Surface of #"+to_string(iid[i])+" is not closed (expect troubles)."); assert(!gts_surface_is_self_intersecting(ssurf[i])); // copy bounds LOG_TRACE("Setting bounds of surf #"<<i); boxes[i]=box; for(int ax:{0,1,2}){ bounds[ax][2*i+0]=Bound(box.min()[ax],/*id*/i,/*isMin*/true); bounds[ax][2*i+1]=Bound(box.max()[ax],/*id*/i,/*isMin*/false); } } /* broad-phase collision detection between GTS surfaces only those will be probed with exact algorithms below and merged if needed */ for(int ax:{0,1,2}) std::sort(bounds[ax].begin(),bounds[ax].end()); vector<Bound>& bb(bounds[0]); // run the search along x-axis, does not matter really std::list<std::pair<int,int>> int0; // broad-phase intersections for(size_t i=0; i<2*N; i++){ if(!bb[i].isMin) continue; // only start with lower bound // go up to the upper bound, but handle overflow safely (no idea why it would happen here) as well for(size_t j=i+1; j<2*N && bb[j].id!=bb[i].id; j++){ if(bb[j].isMin) continue; // this is handled by symmetry #if EIGEN_VERSION_AT_LEAST(3,2,5) if(!boxes[bb[i].id].intersects(boxes[bb[j].id])) continue; // no intersection along all axes #else // old, less elegant if(boxes[bb[i].id].intersection(boxes[bb[j].id]).isEmpty()) continue; #endif int0.push_back(std::make_pair(min(bb[i].id,bb[j].id),max(bb[i].id,bb[j].id))); LOG_TRACE("Broad-phase collision "<<int0.back().first<<"+"<<int0.back().second); } } /* narrow-phase collision detection between GTS surface this must be done via gts_surface_inter_new, since gts_surface_distance always succeeds */ std::list<std::pair<int,int>> int1; for(const std::pair<int,int> ij: int0){ LOG_TRACE("Testing narrow-phase collision "<<ij.first<<"+"<<ij.second); #if 0 GtsRange gr1, gr2; gts_surface_distance(ssurf[ij.first],ssurf[ij.second],/*delta ??*/(gfloat).2,&gr1,&gr2); if(gr1.min>0 && gr2.min>0) continue; LOG_TRACE(" GTS reports collision "<<ij.first<<"+"<<ij.second<<" (min. distances "<<gr1.min<<", "<<gr2.min); #else GtsSurface *s1(ssurf[ij.first]), *s2(ssurf[ij.second]); GNode* t1=gts_bb_tree_surface(s1); GNode* t2=gts_bb_tree_surface(s2); GtsSurfaceInter* I=gts_surface_inter_new(gts_surface_inter_class(),s1,s2,t1,t2,/*is_open_1*/false,/*is_open_2*/false); GSList* l=gts_surface_intersection(s1,s2,t1,t2); // list of edges describing intersection int n1=g_slist_length(l); // extra check by looking at number of faces of the intersected surface #if 1 GtsSurface* s12=gts_surface_new(gts_surface_class(),gts_face_class(),gts_edge_class(),gts_vertex_class()); gts_surface_inter_boolean(I,s12,GTS_1_OUT_2); gts_surface_inter_boolean(I,s12,GTS_2_OUT_1); int n2=gts_surface_face_number(s12); gts_object_destroy(GTS_OBJECT(s12)); #endif gts_bb_tree_destroy(t1,TRUE); gts_bb_tree_destroy(t2,TRUE); gts_object_destroy(GTS_OBJECT(I)); g_slist_free(l); if(n1==0) continue; #if 1 if(n2==0){ LOG_ERROR("n1==0 but n2=="<<n2<<" (no narrow-phase collision)"); continue; } #endif LOG_TRACE(" GTS reports collision "<<ij.first<<"+"<<ij.second<<" ("<<n<<" edges describe the intersection)"); #endif int1.push_back(ij); } /* connected components on the graph: graph nodes are 0…(N-1), graph edges are in int1 see http://stackoverflow.com/a/37195784/761090 */ typedef boost::subgraph<boost::adjacency_list<boost::vecS,boost::vecS,boost::undirectedS,boost::property<boost::vertex_index_t,int>,boost::property<boost::edge_index_t,int>>> Graph; Graph graph(N); for(const auto& ij: int1) boost::add_edge(ij.first,ij.second,graph); vector<size_t> clusters(boost::num_vertices(graph)); size_t numClusters=boost::connected_components(graph,clusters.data()); for(size_t n=0; n<numClusters; n++){ // beginning cluster #n // first, count how many surfaces are in this cluster; if 1, things are easier int numThisCluster=0; int cluster1st=-1; for(size_t i=0; i<N; i++){ if(clusters[i]!=n) continue; numThisCluster++; if(cluster1st<0) cluster1st=(int)i; } GtsSurface* clusterSurf=NULL; LOG_DEBUG("Cluster "<<n<<" has "<<numThisCluster<<" surfaces."); if(numThisCluster==1){ clusterSurf=ssurf[cluster1st]; } else { clusterSurf=ssurf[cluster1st]; // surface of the cluster itself LOG_TRACE(" Initial cluster surface from "<<cluster1st<<"."); /* composed surface */ for(size_t i=0; i<N; i++){ if(clusters[i]!=n || ((int)i)==cluster1st) continue; LOG_TRACE(" Adding "<<i<<" to the cluster"); // ssurf[i] now belongs to cluster #n // trees need to be rebuild every time anyway, since the merged surface keeps changing in every cycle //if(gts_surface_face_number(clusterSurf)==0) LOG_ERROR("clusterSurf has 0 faces."); //if(gts_surface_face_number(ssurf[i])==0) LOG_ERROR("Surface #"<<i<<" has 0 faces."); GNode* t1=gts_bb_tree_surface(clusterSurf); GNode* t2=gts_bb_tree_surface(ssurf[i]); GtsSurfaceInter* I=gts_surface_inter_new(gts_surface_inter_class(),clusterSurf,ssurf[i],t1,t2,/*is_open_1*/false,/*is_open_2*/false); GtsSurface* merged=gts_surface_new(gts_surface_class(),gts_face_class(),gts_edge_class(),gts_vertex_class()); gts_surface_inter_boolean(I,merged,GTS_1_OUT_2); gts_surface_inter_boolean(I,merged,GTS_2_OUT_1); gts_object_destroy(GTS_OBJECT(I)); gts_bb_tree_destroy(t1,TRUE); gts_bb_tree_destroy(t2,TRUE); if(gts_surface_face_number(merged)==0){ LOG_ERROR("Cluster #"<<n<<": 0 faces after fusing #"<<i<<" (why?), adding #"<<i<<" separately!"); // this will cause an extra 1-particle cluster to be created clusters[i]=numClusters; numClusters+=1; } else { // not from global vectors (cleanup at the end), explicit delete! if(clusterSurf!=ssurf[cluster1st]) gts_object_destroy(GTS_OBJECT(clusterSurf)); clusterSurf=merged; } } } #if 0 LOG_TRACE(" GTS surface cleanups..."); pygts_vertex_cleanup(clusterSurf,.1*tol); // cleanup 10× smaller than tolerance pygts_edge_cleanup(clusterSurf); pygts_face_cleanup(clusterSurf); #endif LOG_TRACE(" STL: cluster "<<n<<" output"); stl<<"solid "<<solid<<"_"<<n<<"\n"; /* output cluster to STL here */ _gts_face_to_stl_data data(stl,scene,clipCell,numTri); gts_surface_foreach_face(clusterSurf,(GtsFunc)_gts_face_to_stl,(gpointer)&data); stl<<"endsolid\n"; if(clusterSurf!=ssurf[cluster1st]) gts_object_destroy(GTS_OBJECT(clusterSurf)); } // this deallocates also edges and vertices for(size_t i=0; i<ssurf.size(); i++) gts_object_destroy(GTS_OBJECT(ssurf[i])); return numTri; #endif /* WOO_GTS */ }
bool KstFilterDialogI::saveInputs(KstCPluginPtr plugin, KstSharedPtr<Plugin> p) { KstReadLocker vl(&KST::vectorList.lock()); KstWriteLocker scl(&KST::scalarList.lock()); KstWriteLocker stl(&KST::stringList.lock()); const QValueList<Plugin::Data::IOValue>& itable = p->data()._inputs; for (QValueList<Plugin::Data::IOValue>::ConstIterator it = itable.begin(); it != itable.end(); ++it) { if ((*it)._type == Plugin::Data::IOValue::TableType) { if ((*it)._name == p->data()._filterInputVector) { KstVectorPtr v = *KST::vectorList.findTag(_yvector); if (!v) { return false; } plugin->inputVectors().insert((*it)._name, v); } else { QObject *field = _w->_pluginInputOutputFrame->child((*it)._name.latin1(), "VectorSelector"); if (field) { VectorSelector *vs = static_cast<VectorSelector*>(field); KstVectorPtr v = *KST::vectorList.findTag(vs->selectedVector()); if (!v) { return false; } plugin->inputVectors().insert((*it)._name, v); } } } else if ((*it)._type == Plugin::Data::IOValue::StringType) { QObject *field = _w->_pluginInputOutputFrame->child((*it)._name.latin1(), "StringSelector"); if (field) { StringSelector *ss = static_cast<StringSelector*>(field); KstStringPtr s = *KST::stringList.findTag(ss->selectedString()); if (s == *KST::stringList.end()) { QString val = ss->_string->currentText(); // create orphan string KstStringPtr newString = new KstString(KstObjectTag(ss->_string->currentText(), KstObjectTag::orphanTagContext), 0L, val, true); plugin->inputStrings().insert((*it)._name, newString); } else { return false; } } } else if ((*it)._type == Plugin::Data::IOValue::PidType) { // Nothing } else { QObject *field = _w->_pluginInputOutputFrame->child((*it)._name.latin1(), "ScalarSelector"); if (field) { ScalarSelector *ss = static_cast<ScalarSelector*>(field); KstScalarPtr s = *KST::scalarList.findTag(ss->selectedScalar()); if (s == *KST::scalarList.end()) { bool ok; double val = ss->_scalar->currentText().toDouble(&ok); if (ok) { // create orphan scalar KstScalarPtr newScalar = new KstScalar(KstObjectTag(ss->_scalar->currentText(), KstObjectTag::orphanTagContext), 0L, val, true, false); plugin->inputScalars().insert((*it)._name, newScalar); } else { return false; } } else { plugin->inputScalars().insert((*it)._name, s); } } } } return true; }
void stl(int type, char *message_format, ...) { int loopa, loopb, freeable = 1, bufferlen = STL_BUFFERLEN_STEP, formatting, ret; char *buffer = NULL, *buffer_temp = NULL; FILE *outdest; va_list arguments; if(type == STL_INFO && STL_SUPRESS_ALL_INFO == TRUE) return; if(message_format == NULL) { stl(STL_ERROR, "Internal Program Error! NULL message?"); return; } //We're going to try and grab some memory so we can do neat things. if((buffer = malloc(bufferlen * sizeof(char))) == NULL) { //We couldn't get any memory, so give up on that. freeable = 0; buffer = message_format; stl(STL_ERROR, "Out Of Memory!"); } else //We got our text buffer. Now we can populate it and perform a format conversion. { //Perform a format conversion, increasing the size of our buffer until we have enough. formatting = 1; while(formatting) { //Format conversion. va_start(arguments, message_format); ret = vsnprintf(buffer, bufferlen, message_format, arguments); va_end(arguments); //Did the format conversion succeed? Did it fit in the buffer? if(ret >= 0 && ret < bufferlen) { formatting = 0; //All done. } else //The formatting failed! Need more memory! { //We need to increase the size of the buffer. bufferlen = bufferlen + STL_BUFFERLEN_STEP; if((buffer_temp = realloc(buffer, bufferlen)) == NULL) { free(buffer); //We couldn't get enough memory, so give up on that. freeable = 0; buffer = message_format; stl(STL_ERROR, "Out Of Memory!"); formatting = 0; } else //We succeeded in reallocating. buffer = buffer_temp; } } if(freeable) //Are we still working on our own buffer? { loopb = 0; for(loopa = 0; buffer[loopa]; loopa++) { if(buffer[loopa] >= 32 && buffer[loopa] <= 126) //Strip out ALL non-printable ASCII. { if(loopa != loopb) buffer[loopb] = buffer[loopa]; loopb++; } } buffer[loopb] = '\0'; } } //Check the output destination. outdest = stl_logoutput(TRUE, NULL); //Make sure outdest is not set to syslog if syslog support is not built in. #ifndef SYSLOG if(outdest == STL_OUTPUT_SYSLOG) outdest = stderr; #endif //Actually output the log line. if(buffer != NULL) { switch(type) { case STL_INFO: #ifdef SYSLOG if(outdest == STL_OUTPUT_SYSLOG) syslog(LOG_INFO, "%s", buffer); #endif if(outdest != STL_OUTPUT_SYSLOG) fprintf(outdest, "%s: Info: %s\n", stl_logname(NULL), buffer); break; case STL_WARNING: #ifdef SYSLOG if(outdest == STL_OUTPUT_SYSLOG) syslog(LOG_WARNING, "%s", buffer); #endif if(outdest != STL_OUTPUT_SYSLOG) fprintf(outdest, "%s: Warning: %s\n", stl_logname(NULL), buffer); break; case STL_ERROR: #ifdef SYSLOG if(outdest == STL_OUTPUT_SYSLOG) syslog(LOG_ERR, "%s", buffer); #endif if(outdest != STL_OUTPUT_SYSLOG) fprintf(outdest, "%s: Error: %s\n", stl_logname(NULL), buffer); break; default: stl(STL_WARNING, "Internal Program Error: Somebody sent a message without a valid message type! The errant message follows:"); #ifdef SYSLOG if(outdest == STL_OUTPUT_SYSLOG) syslog(LOG_WARNING, "%s", buffer); #endif if(outdest != STL_OUTPUT_SYSLOG) fprintf(outdest, "%s: Unknown Notice: %s\n", stl_logname(NULL), buffer); break; } if(outdest != STL_OUTPUT_SYSLOG) fflush(NULL); } if(freeable) free(buffer); return; }