void FBXScene::ProcessNode(FbxNode* pNode, FbxNodeAttribute::EType attributeType) { if( !pNode ) return; FbxNodeAttribute* pNodeAttribute = pNode->GetNodeAttribute(); if (pNodeAttribute) { if( pNodeAttribute->GetAttributeType() == attributeType ) { switch(pNodeAttribute->GetAttributeType()) { case FbxNodeAttribute::eSkeleton: { ProcessSkeleton(pNode); break; } case FbxNodeAttribute::eMesh: { ProcessMesh(pNode); break; } case FbxNodeAttribute::eNurbsCurve: { ProcessCurve(pNode); break; } default: break; }; } } for( int i = 0; i < pNode->GetChildCount(); ++i ) { ProcessNode(pNode->GetChild(i), attributeType); } }
// ------------------------------------------------------------------------------------------------ void ProcessOpenProfile(const IfcArbitraryOpenProfileDef& def, TempMesh& meshout, ConversionData& conv) { ProcessCurve(def.Curve,meshout,conv); }
// ------------------------------------------------------------------------------------------------ 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; }
// ------------------------------------------------------------------------------------------------ void ProcessClosedProfile(const IfcArbitraryClosedProfileDef& def, TempMesh& meshout, ConversionData& conv) { ProcessCurve(def.OuterCurve,meshout,conv); }
void MPointCreator::ProcessPoints( const MHTRouteCandidate::PointData& rData1, const MHTRouteCandidate::RouteSegment& rSegment1, const MHTRouteCandidate::PointData& rData2, std::vector<const SimpleLine*>& vecCurvesBetweenPoints) { Point Pt1(false); if (rData1.GetPointProjection() != NULL) Pt1 = *(rData1.GetPointProjection()); else Pt1 = rData1.GetPointGPS(); Point Pt2(false); if (rData2.GetPointProjection() != NULL) Pt2 = *(rData2.GetPointProjection()); else Pt2 = rData2.GetPointGPS(); if (AlmostEqual(Pt1, Pt2)) { Interval<Instant> TimeInterval(rData1.GetTime(), rData2.GetTime(), true, rData1.GetTime() == rData2.GetTime()); AttributePtr<UPoint> pUPoint(new UPoint(TimeInterval, Pt1, Pt1)); m_pResMPoint->Add(*pUPoint); assert(vecCurvesBetweenPoints.size() == 0); } else { const shared_ptr<IMMNetworkSection>& pSection1 = rData1.GetSection(); const shared_ptr<IMMNetworkSection>& pSection2 = rData2.GetSection(); if (pSection1 == NULL || !pSection1->IsDefined() || pSection2 == NULL || !pSection2->IsDefined()) { // at least one point is offroad Interval<Instant> TimeInterval( rData1.GetTime(), rData2.GetTime(), true, rData1.GetTime() == rData2.GetTime()); AttributePtr<UPoint> pUPoint(new UPoint(TimeInterval, Pt1, Pt2)); m_pResMPoint->Add(*pUPoint); } else if (pSection1 == pSection2) // Same section { const SimpleLine* pSectionCurve = pSection1->GetCurve(); AttributePtr<SimpleLine> pSubline(new SimpleLine(0)); MMUtil::SubLine(pSectionCurve, Pt1, Pt2, pSection1->GetCurveStartsSmaller(), m_dNetworkScale, *pSubline); if (pSubline->IsDefined() && pSubline->StartPoint().IsDefined() && pSubline->EndPoint().IsDefined()) { Interval<Instant> TimeInterval( rData1.GetTime(), rData2.GetTime(), true, rData1.GetTime() == rData2.GetTime()); //assert(AlmostEqual(Pt1, pSubline->StartPoint())); ProcessCurve(*pSubline, TimeInterval); } } else // different sections { // Calculate total length of curves const SimpleLine* pSection1Curve = pSection1->GetCurve(); AttributePtr<SimpleLine> pSubline1(new SimpleLine(0)); MMUtil::SubLine(pSection1Curve, Pt1, !rSegment1.HasUTurn() ? pSection1->GetEndPoint() : pSection1->GetStartPoint(), pSection1->GetCurveStartsSmaller(), m_dNetworkScale, *pSubline1); double dLenCurve1 = MMUtil::CalcLengthCurve(pSubline1.get(), m_dNetworkScale); const SimpleLine* pSection2Curve = pSection2->GetCurve(); AttributePtr<SimpleLine> pSubline2(new SimpleLine(0)); MMUtil::SubLine(pSection2Curve, pSection2->GetStartPoint(), Pt2, pSection2->GetCurveStartsSmaller(), m_dNetworkScale, *pSubline2); double dLenCurve2 = MMUtil::CalcLengthCurve(pSubline2.get(), m_dNetworkScale); double dLength = dLenCurve1 + dLenCurve2; const size_t nCurves = vecCurvesBetweenPoints.size(); for (size_t i = 0; i < nCurves; ++i) { dLength += MMUtil::CalcLengthCurve(vecCurvesBetweenPoints[i], m_dNetworkScale); } // Total time DateTime Duration = rData2.GetTime() - rData1.GetTime(); Duration.Abs(); // Process first curve DateTime TimeEnd(rData1.GetTime()); if (!pSubline1 || AlmostEqual(dLenCurve1, 0.0)) { Interval<Instant> TimeInterval(rData1.GetTime(), TimeEnd, true, true); AttributePtr<UPoint> pUPoint(new UPoint(TimeInterval, Pt1, Pt1)); m_pResMPoint->Add(*pUPoint); } else { TimeEnd = rData1.GetTime() + DateTime(datetime::durationtype, (uint64_t)(((Duration.millisecondsToNull() / dLength) * dLenCurve1) + .5)); Interval<Instant> TimeInterval(rData1.GetTime(), TimeEnd, true, rData1.GetTime() == TimeEnd); ProcessCurve(*pSubline1, TimeInterval, dLenCurve1); } // Process curves in between for (size_t i = 0; i < nCurves; ++i) { const SimpleLine* pCurve = vecCurvesBetweenPoints[i]; if (pCurve == NULL) continue; double dLenCurve = MMUtil::CalcLengthCurve(pCurve, m_dNetworkScale); if (AlmostEqual(dLenCurve, 0.0)) continue; DateTime TimeStart = TimeEnd; TimeEnd = TimeStart + DateTime(datetime::durationtype, (uint64_t)(((Duration.millisecondsToNull() / dLength) * dLenCurve) + .5)); Interval<Instant> TimeInterval(TimeStart, TimeEnd, true, false); ProcessCurve(*pCurve, TimeInterval, dLenCurve); } // Process last curve if (!pSubline2 || AlmostEqual(dLenCurve2, 0.0)) { DateTime TimeStart = TimeEnd; TimeEnd = rData2.GetTime(); Interval<Instant> TimeInterval(TimeStart, TimeEnd, true, true); AttributePtr<UPoint> pUPoint(new UPoint(TimeInterval, Pt2, Pt2)); m_pResMPoint->Add(*pUPoint); } else { assert(TimeEnd.millisecondsToNull() <= rData2.GetTime().millisecondsToNull()); DateTime TimeStart = TimeEnd; TimeEnd = rData2.GetTime(); Interval<Instant> TimeInterval(TimeStart, TimeEnd, true, false); ProcessCurve(*pSubline2, TimeInterval, dLenCurve2); } } } }