Exemplo n.º 1
0
// ------------------------------------------------------------------------------------------------
void ConvertAxisPlacement(IfcVector3& axis, IfcVector3& pos, const IfcAxis1Placement& in)
{
	ConvertCartesianPoint(pos,in.Location);
	if (in.Axis) {
		ConvertDirection(axis,in.Axis.Get());
	}
	else {
		axis = IfcVector3(0.f,0.f,1.f);
	}
}
Exemplo n.º 2
0
// ------------------------------------------------------------------------------------------------
void ProcessPolyLine(const IfcPolyline& def, TempMesh& meshout, ConversionData& /*conv*/)
{
    // this won't produce a valid mesh, it just spits out a list of vertices
    IfcVector3 t;
    for(const IfcCartesianPoint& cp : def.Points) {
        ConvertCartesianPoint(t,cp);
        meshout.verts.push_back(t);
    }
    meshout.vertcnt.push_back(static_cast<unsigned int>(meshout.verts.size()));
}
Exemplo n.º 3
0
// ------------------------------------------------------------------------------------------------
void ConvertAxisPlacement(IfcMatrix4& out, const IfcAxis2Placement2D& in)
{
	IfcVector3 loc;
	ConvertCartesianPoint(loc,in.Location);

	IfcVector3 x(1.f,0.f,0.f);
	if (in.RefDirection) {
		ConvertDirection(x,*in.RefDirection.Get());
	}

	const IfcVector3 y = IfcVector3(x.y,-x.x,0.f);

	IfcMatrix4::Translation(loc,out);
	AssignMatrixAxes(out,x,y,IfcVector3(0.f,0.f,1.f));
}
Exemplo n.º 4
0
// ------------------------------------------------------------------------------------------------
void ConvertTransformOperator(IfcMatrix4& out, const IfcCartesianTransformationOperator& op)
{
	IfcVector3 loc;
	ConvertCartesianPoint(loc,op.LocalOrigin);

	IfcVector3 x(1.f,0.f,0.f),y(0.f,1.f,0.f),z(0.f,0.f,1.f);
	if (op.Axis1) {
		ConvertDirection(x,*op.Axis1.Get());
	}
	if (op.Axis2) {
		ConvertDirection(y,*op.Axis2.Get());
	}
	if (const IfcCartesianTransformationOperator3D* op2 = op.ToPtr<IfcCartesianTransformationOperator3D>()) {
		if(op2->Axis3) {
			ConvertDirection(z,*op2->Axis3.Get());
		}
	}

	IfcMatrix4 locm;
	IfcMatrix4::Translation(loc,locm);	
	AssignMatrixAxes(out,x,y,z);


	IfcVector3 vscale;
	if (const IfcCartesianTransformationOperator3DnonUniform* nuni = op.ToPtr<IfcCartesianTransformationOperator3DnonUniform>()) {
		vscale.x = nuni->Scale?op.Scale.Get():1.f;
		vscale.y = nuni->Scale2?nuni->Scale2.Get():1.f;
		vscale.z = nuni->Scale3?nuni->Scale3.Get():1.f;
	}
	else {
		const IfcFloat sc = op.Scale?op.Scale.Get():1.f;
		vscale = IfcVector3(sc,sc,sc);
	}

	IfcMatrix4 s;
	IfcMatrix4::Scaling(vscale,s);

	out = locm * out * s;
}
Exemplo n.º 5
0
// ------------------------------------------------------------------------------------------------
void ConvertAxisPlacement(IfcMatrix4& out, const IfcAxis2Placement3D& in)
{
	IfcVector3 loc;
	ConvertCartesianPoint(loc,in.Location);

	IfcVector3 z(0.f,0.f,1.f),r(1.f,0.f,0.f),x;

	if (in.Axis) { 
		ConvertDirection(z,*in.Axis.Get());
	}
	if (in.RefDirection) {
		ConvertDirection(r,*in.RefDirection.Get());
	}

	IfcVector3 v = r.Normalize();
	IfcVector3 tmpx = z * (v*z);

	x = (v-tmpx).Normalize();
	IfcVector3 y = (z^x);

	IfcMatrix4::Translation(loc,out);
	AssignMatrixAxes(out,x,y,z);
}
Exemplo n.º 6
0
// ------------------------------------------------------------------------------------------------
void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const IfcPolygonalBoundedHalfSpace* hs, TempMesh& result, 
													   const TempMesh& first_operand, 
													   ConversionData& conv)
{
	ai_assert(hs != NULL);

	const IfcPlane* const plane = hs->BaseSurface->ToPtr<IfcPlane>();
	if(!plane) {
		IFCImporter::LogError("expected IfcPlane as base surface for the IfcHalfSpaceSolid");
		return;
	}

	// extract plane base position vector and normal vector
	IfcVector3 p,n(0.f,0.f,1.f);
	if (plane->Position->Axis) {
		ConvertDirection(n,plane->Position->Axis.Get());
	}
	ConvertCartesianPoint(p,plane->Position->Location);

	if(!IsTrue(hs->AgreementFlag)) {
		n *= -1.f;
	}

	n.Normalize();

	// obtain the polygonal bounding volume
	boost::shared_ptr<TempMesh> profile = boost::shared_ptr<TempMesh>(new TempMesh());
	if(!ProcessCurve(hs->PolygonalBoundary, *profile.get(), conv)) {
		IFCImporter::LogError("expected valid polyline for boundary of boolean halfspace");
		return;
	}

	IfcMatrix4 proj_inv;
	ConvertAxisPlacement(proj_inv,hs->Position);

	// and map everything into a plane coordinate space so all intersection
	// tests can be done in 2D space.
	IfcMatrix4 proj = proj_inv;
	proj.Inverse();

	// clip the current contents of `meshout` against the plane we obtained from the second operand
	const std::vector<IfcVector3>& in = first_operand.verts;
	std::vector<IfcVector3>& outvert = result.verts;

	std::vector<unsigned int>::const_iterator begin = first_operand.vertcnt.begin(), 
		end = first_operand.vertcnt.end(), iit;

	outvert.reserve(in.size());
	result.vertcnt.reserve(first_operand.vertcnt.size());

	std::vector<size_t> intersected_boundary_segments;
	std::vector<IfcVector3> intersected_boundary_points;

	// TODO: the following algorithm doesn't handle all cases. 
	unsigned int vidx = 0;
	for(iit = begin; iit != end; vidx += *iit++) {
		if (!*iit) {
			continue;
		}

		unsigned int newcount = 0;
		bool was_outside_boundary = !PointInPoly(proj * in[vidx], profile->verts);

		// used any more?
		//size_t last_intersected_boundary_segment;
		IfcVector3 last_intersected_boundary_point;

		bool extra_point_flag = false;
		IfcVector3 extra_point;

		IfcVector3 enter_volume;
		bool entered_volume_flag = false;

		for(unsigned int i = 0; i < *iit; ++i) {
			// current segment: [i,i+1 mod size] or [*extra_point,i] if extra_point_flag is set
			const IfcVector3& e0 = extra_point_flag ? extra_point : in[vidx+i];
			const IfcVector3& e1 = extra_point_flag ? in[vidx+i] : in[vidx+(i+1)%*iit];

			// does the current segment intersect the polygonal boundary?
			const IfcVector3& e0_plane = proj * e0;
			const IfcVector3& e1_plane = proj * e1;

			intersected_boundary_segments.clear();
			intersected_boundary_points.clear();

			const bool is_outside_boundary = !PointInPoly(e1_plane, profile->verts);
			const bool is_boundary_intersection = is_outside_boundary != was_outside_boundary;
			
			IntersectsBoundaryProfile(e0_plane, e1_plane, profile->verts, 
				intersected_boundary_segments, 
				intersected_boundary_points);
		
			ai_assert(!is_boundary_intersection || !intersected_boundary_segments.empty());

			// does the current segment intersect the plane?
			// (no extra check if this is an extra point)
			IfcVector3 isectpos;
			const Intersect isect =  extra_point_flag ? Intersect_No : IntersectSegmentPlane(p,n,e0,e1,isectpos);

#ifdef _DEBUG
			if (isect == Intersect_Yes) {
				const IfcFloat f = fabs((isectpos - p)*n);
				ai_assert(f < 1e-5);
			}
#endif

			const bool is_white_side = (e0-p)*n >= -1e-6;

			// e0 on good side of plane? (i.e. we should keep all geometry on this side)
			if (is_white_side) {
				// but is there an intersection in e0-e1 and is e1 in the clipping
				// boundary? In this case, generate a line that only goes to the
				// intersection point.
				if (isect == Intersect_Yes  && !is_outside_boundary) {
					outvert.push_back(e0);
					++newcount;

					outvert.push_back(isectpos);
					++newcount;
					
					/*
					// this is, however, only a line that goes to the plane, but not
					// necessarily to the point where the bounding volume on the
					// black side of the plane is hit. So basically, we need another 
					// check for [isectpos-e1], which should yield an intersection
					// point.
					extra_point_flag = true;
					extra_point = isectpos;

					was_outside_boundary = true; 
					continue; */

					// [isectpos, enter_volume] potentially needs extra points.
					// For this, we determine the intersection point with the
					// bounding volume and project it onto the plane. 
					/*
					const IfcVector3& enter_volume_proj = proj * enter_volume;
					const IfcVector3& enter_isectpos = proj * isectpos;

					intersected_boundary_segments.clear();
					intersected_boundary_points.clear();

					IntersectsBoundaryProfile(enter_volume_proj, enter_isectpos, profile->verts, 
						intersected_boundary_segments, 
						intersected_boundary_points);

					if(!intersected_boundary_segments.empty()) {

						vec = vec + ((p - vec) * n) * n;
					}
					*/				

					//entered_volume_flag = true;
				}
				else {
					outvert.push_back(e0);
					++newcount;
				}
			}
			// e0 on bad side of plane, e1 on good (i.e. we should remove geometry on this side,
			// but only if it is within the bounding volume).
			else if (isect == Intersect_Yes) {
				// is e0 within the clipping volume? Insert the intersection point
				// of [e0,e1] and the plane instead of e0.
				if(was_outside_boundary) {
					outvert.push_back(e0);
				}
				else {
					if(entered_volume_flag) {
						const IfcVector3& fix_point = enter_volume + ((p - enter_volume) * n) * n;
						outvert.push_back(fix_point);
						++newcount;
					}

					outvert.push_back(isectpos);	
				}
				entered_volume_flag = false;
				++newcount;
			}
			else { // no intersection with plane or parallel; e0,e1 are on the bad side
			
				// did we just pass the boundary line to the poly bounding?
				if (is_boundary_intersection) {

					// and are now outside the clipping boundary?
					if (is_outside_boundary) {
						// in this case, get the point where the clipping boundary
						// was entered first. Then, get the point where the clipping
						// boundary volume was left! These two points with the plane
						// normal form another plane that intersects the clipping
						// volume. There are two ways to get from the first to the
						// second point along the intersection curve, try to pick the
						// one that lies within the current polygon.

						// TODO this approach doesn't handle all cases

						// ...

						IfcFloat d = 1e20;
						IfcVector3 vclosest;
						BOOST_FOREACH(const IfcVector3& v, intersected_boundary_points) {
							const IfcFloat dn = (v-e1_plane).SquareLength();
							if (dn < d) {
								d = dn;
								vclosest = v;
							}
						}

						vclosest = proj_inv * vclosest;
						if(entered_volume_flag) {
							const IfcVector3& fix_point = vclosest + ((p - vclosest) * n) * n;
							outvert.push_back(fix_point);
							++newcount;

							entered_volume_flag = false;
						}

						outvert.push_back(vclosest);
						++newcount;

						//outvert.push_back(e1);
						//++newcount;
					}
					else {
						entered_volume_flag = true;

						// we just entered the clipping boundary. Record the point
						// and the segment where we entered and also generate this point.
						//last_intersected_boundary_segment = intersected_boundary_segments.front();
						//last_intersected_boundary_point = intersected_boundary_points.front();

						outvert.push_back(e0);
						++newcount;

						IfcFloat d = 1e20;
						IfcVector3 vclosest;
						BOOST_FOREACH(const IfcVector3& v, intersected_boundary_points) {
							const IfcFloat dn = (v-e0_plane).SquareLength();
							if (dn < d) {
								d = dn;
								vclosest = v;
							}
						}

						enter_volume = proj_inv * vclosest;
						outvert.push_back(enter_volume);
						++newcount;
					}
				}				
				// if not, we just keep the vertex
				else if (is_outside_boundary) {
					outvert.push_back(e0);
					++newcount;

					entered_volume_flag = false;
				}
			}

			was_outside_boundary = is_outside_boundary;
			extra_point_flag = false;
		}