Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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);
}
Exemplo n.º 3
0
/* 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);
}
Exemplo n.º 4
0
// ---------------------------------------------------------------------------
// 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);
}
Exemplo n.º 5
0
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;
}
Exemplo n.º 6
0
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;
	}
    }
}
Exemplo n.º 7
0
	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;
	}
Exemplo n.º 8
0
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();
}
Exemplo n.º 9
0
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;
}
Exemplo n.º 11
0
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;
	}