double NBHeightMapper::getZ(const Position& geo) const { if (!ready()) { WRITE_WARNING("Cannot supply height since no height data was loaded"); return 0; } if (myRaster != 0) { double result = -1e6; if (myBoundary.around(geo)) { const int xSize = int((myBoundary.xmax() - myBoundary.xmin()) / mySizeOfPixel.x() + .5); const double normX = (geo.x() - myBoundary.xmin()) / mySizeOfPixel.x(); const double normY = (geo.y() - myBoundary.ymax()) / mySizeOfPixel.y(); PositionVector corners; corners.push_back(Position(floor(normX) + 0.5, floor(normY) + 0.5, myRaster[(int)normY * xSize + (int)normX])); if (normX - floor(normX) > 0.5) { corners.push_back(Position(floor(normX) + 1.5, floor(normY) + 0.5, myRaster[(int)normY * xSize + (int)normX + 1])); } else { corners.push_back(Position(floor(normX) - 0.5, floor(normY) + 0.5, myRaster[(int)normY * xSize + (int)normX - 1])); } if (normY - floor(normY) > 0.5) { corners.push_back(Position(floor(normX) + 0.5, floor(normY) + 1.5, myRaster[((int)normY + 1) * xSize + (int)normX])); } else { corners.push_back(Position(floor(normX) + 0.5, floor(normY) - 0.5, myRaster[((int)normY - 1) * xSize + (int)normX])); } result = Triangle(corners).getZ(Position(normX, normY)); } if (result > -1e5 && result < 1e5) { return result; } } // coordinates in degrees hence a small search window float minB[2]; float maxB[2]; minB[0] = (float)geo.x() - 0.00001f; minB[1] = (float)geo.y() - 0.00001f; maxB[0] = (float)geo.x() + 0.00001f; maxB[1] = (float)geo.y() + 0.00001f; QueryResult queryResult; int hits = myRTree.Search(minB, maxB, queryResult); Triangles result = queryResult.triangles; assert(hits == (int)result.size()); UNUSED_PARAMETER(hits); // only used for assertion for (Triangles::iterator it = result.begin(); it != result.end(); it++) { const Triangle* triangle = *it; if (triangle->contains(geo)) { return triangle->getZ(geo); } } WRITE_WARNING("Could not get height data for coordinate " + toString(geo)); return 0; }
bool detect(vector<Triangle_3> &a, vector<Triangle_3> &b) { std::vector<Box> boxes; triangles.clear(); for ( Iterator i = a.begin(); i != a.end(); ++i) triangles.push_back(*i); for ( Iterator i = b.begin(); i != b.end(); ++i) triangles.push_back(*i); for(Iterator i = triangles.begin(); i!= triangles.end(); ++i) boxes.push_back( Box( i->bbox(), i)); // Run the self intersection algorithm with all defaults CGAL::box_self_intersection_d( boxes.begin(), boxes.end(), report_inters); return true; }
int main(int argc, char*argv[]) { std::ifstream in((argc>1)?argv[1]:"data/triangles.xyz"); Triangles triangles; Triangle_3 t; while(in >> t){ triangles.push_back(t); } // Create the corresponding vector of bounding boxes std::vector<Box> boxes; for ( Iterator i = triangles.begin(); i != triangles.end(); ++i) boxes.push_back( Box( i->bbox(), i)); // Create the corresponding vector of pointers to bounding boxes std::vector<Box *> ptr; for ( std::vector<Box>::iterator i = boxes.begin(); i != boxes.end(); ++i) ptr.push_back( &*i); // Run the self intersection algorithm with all defaults on the // indirect pointers to bounding boxes. Avoids copying the boxes. CGAL::box_self_intersection_d( ptr.begin(), ptr.end(), Report(triangles)); return 0; }
int main() { // Create 10 random triangles typedef CGAL::Random_points_in_cube_3<Point_3> Pts; typedef CGAL::Creator_uniform_3< Point_3, Triangle_3> Creator; typedef CGAL::Join_input_iterator_3<Pts,Pts,Pts,Creator> Triangle_gen; Pts points( 1); // in centered cube [-1,1)^3 Triangle_gen triangle_gen( points, points, points); CGAL::cpp11::copy_n( triangle_gen, 10, std::back_inserter(triangles)); // Create the corresponding vector of bounding boxes std::vector<Box> boxes; for ( Iterator i = triangles.begin(); i != triangles.end(); ++i) boxes.push_back( Box( i->bbox(), i)); // Create the corresponding vector of pointers to bounding boxes std::vector<Box *> ptr; for ( std::vector<Box>::iterator i = boxes.begin(); i != boxes.end(); ++i) ptr.push_back( &*i); // Run the self intersection algorithm with all defaults on the // indirect pointers to bounding boxes. Avoids copying the boxes. CGAL::box_self_intersection_d( ptr.begin(), ptr.end(), report_inters); return 0; }
static IGL_INLINE bool intersect_other_helper( const Eigen::PlainObjectBase<DerivedVA> & VA, const Eigen::PlainObjectBase<DerivedFA> & FA, const Eigen::PlainObjectBase<DerivedVB> & VB, const Eigen::PlainObjectBase<DerivedFB> & FB, const RemeshSelfIntersectionsParam & params, Eigen::PlainObjectBase<DerivedIF> & IF, Eigen::PlainObjectBase<DerivedVVAB> & VVAB, Eigen::PlainObjectBase<DerivedFFAB> & FFAB, Eigen::PlainObjectBase<DerivedJAB> & JAB, Eigen::PlainObjectBase<DerivedIMAB> & IMAB) { using namespace std; using namespace Eigen; typedef typename DerivedFA::Index Index; // 3D Primitives typedef CGAL::Point_3<Kernel> Point_3; typedef CGAL::Segment_3<Kernel> Segment_3; typedef CGAL::Triangle_3<Kernel> Triangle_3; typedef CGAL::Plane_3<Kernel> Plane_3; typedef CGAL::Tetrahedron_3<Kernel> Tetrahedron_3; // 2D Primitives typedef CGAL::Point_2<Kernel> Point_2; typedef CGAL::Segment_2<Kernel> Segment_2; typedef CGAL::Triangle_2<Kernel> Triangle_2; // 2D Constrained Delaunay Triangulation types typedef CGAL::Triangulation_vertex_base_2<Kernel> TVB_2; typedef CGAL::Constrained_triangulation_face_base_2<Kernel> CTAB_2; typedef CGAL::Triangulation_data_structure_2<TVB_2,CTAB_2> TDS_2; typedef CGAL::Exact_intersections_tag Itag; // Axis-align boxes for all-pairs self-intersection detection typedef std::vector<Triangle_3> Triangles; typedef typename Triangles::iterator TrianglesIterator; typedef typename Triangles::const_iterator TrianglesConstIterator; typedef CGAL::Box_intersection_d::Box_with_handle_d<double,3,TrianglesIterator> Box; typedef std::map<Index,std::vector<std::pair<Index,CGAL::Object> > > OffendingMap; typedef std::map<std::pair<Index,Index>,std::vector<Index> > EdgeMap; typedef std::pair<Index,Index> EMK; Triangles TA,TB; // Compute and process self intersections mesh_to_cgal_triangle_list(VA,FA,TA); mesh_to_cgal_triangle_list(VB,FB,TB); // http://www.cgal.org/Manual/latest/doc_html/cgal_manual/Box_intersection_d/Chapter_main.html#Section_63.5 // Create the corresponding vector of bounding boxes std::vector<Box> A_boxes,B_boxes; const auto box_up = [](Triangles & T, std::vector<Box> & boxes) -> void { boxes.reserve(T.size()); for ( TrianglesIterator tit = T.begin(); tit != T.end(); ++tit) { boxes.push_back(Box(tit->bbox(), tit)); } }; box_up(TA,A_boxes); box_up(TB,B_boxes); OffendingMap offendingA,offendingB; //EdgeMap edge2facesA,edge2facesB; std::list<int> lIF; const auto cb = [&](const Box &a, const Box &b) -> void { using namespace std; // index in F and T int fa = a.handle()-TA.begin(); int fb = b.handle()-TB.begin(); const Triangle_3 & A = *a.handle(); const Triangle_3 & B = *b.handle(); if(CGAL::do_intersect(A,B)) { // There was an intersection lIF.push_back(fa); lIF.push_back(fb); if(params.first_only) { throw IGL_FIRST_HIT_EXCEPTION; } if(!params.detect_only) { CGAL::Object result = CGAL::intersection(A,B); push_result(FA,fa,fb,result,offendingA); push_result(FB,fb,fa,result,offendingB); } } }; try{ CGAL::box_intersection_d( A_boxes.begin(), A_boxes.end(), B_boxes.begin(), B_boxes.end(), cb); }catch(int e) { // Rethrow if not FIRST_HIT_EXCEPTION if(e != IGL_FIRST_HIT_EXCEPTION) { throw e; } // Otherwise just fall through } // Convert lIF to Eigen matrix assert(lIF.size()%2 == 0); IF.resize(lIF.size()/2,2); { int i=0; for( list<int>::const_iterator ifit = lIF.begin(); ifit!=lIF.end(); ) { IF(i,0) = (*ifit); ifit++; IF(i,1) = (*ifit); ifit++; i++; } } if(!params.detect_only) { // Obsolete, now remesh_intersections expects a single mesh // remesh_intersections(VA,FA,TA,offendingA,VVA,FFA,JA,IMA); // remesh_intersections(VB,FB,TB,offendingB,VVB,FFB,JB,IMB); // Combine mesh and offending maps DerivedVA VAB(VA.rows()+VB.rows(),3); VAB<<VA,VB; DerivedFA FAB(FA.rows()+FB.rows(),3); FAB<<FA,(FB.array()+VA.rows()); Triangles TAB; TAB.reserve(TA.size()+TB.size()); TAB.insert(TAB.end(),TA.begin(),TA.end()); TAB.insert(TAB.end(),TB.begin(),TB.end()); OffendingMap offending; //offending.reserve(offendingA.size() + offendingB.size()); for (const auto itr : offendingA) { // Remap offenders in FB to FAB auto offenders = itr.second; for(auto & offender : offenders) { offender.first += FA.rows(); } offending[itr.first] = offenders; } for (const auto itr : offendingB) { // Store offenders for FB according to place in FAB offending[FA.rows() + itr.first] = itr.second; } remesh_intersections( VAB,FAB,TAB,offending,params.stitch_all,VVAB,FFAB,JAB,IMAB); } return IF.rows() > 0; }
NiSkinPartition::NiSkinPartition(Ref<NiTriBasedGeom> shape, int maxBonesPerPartition, int maxBonesPerVertex ) { NiSkinInstanceRef skinInst = shape->GetSkinInstance(); if ( skinInst == NULL ) { throw runtime_error( "You must bind a skin before setting generating skin partitions. No NiSkinInstance found." ); } NiSkinDataRef skinData = skinInst->GetSkinData(); if ( skinData == NULL ) { throw runtime_error( "You must bind a skin before setting generating skin partitions. No NiSkinData found." ); } NiTriBasedGeomDataRef geomData = DynamicCast<NiTriBasedGeomData>(shape->GetData() ); if ( geomData == NULL ) { throw runtime_error( "Attempted to generate a skin partition on a mesh with no geometry data." ); } // read in the weights from NiSkinData vector<Vector3> verts = geomData->GetVertices(); vector< BoneWeightList > weights; if (verts.empty()){ throw runtime_error( "Attempted to generate a skin partition on a mesh with no vertices." ); } Triangles triangles = geomData->GetTriangles(); if (triangles.empty()) { throw runtime_error( "Attempted to generate a skin partition on a mesh with no triangles." ); } weights.resize( verts.size() ); int numBones = skinData->GetBoneCount(); for ( int bone = 0; bone < numBones; bone++ ) { vector<SkinWeight> vertexWeights = skinData->GetBoneWeights(bone); for (int r = 0; r < int(vertexWeights.size()); ++r ){ int vertex = vertexWeights[r].index; float weight = vertexWeights[r].weight; if ( vertex >= int(weights.size()) ) throw runtime_error( "bad NiSkinData - vertex count does not match" ); weights[vertex].insert( weights[vertex].end(), BoneWeight(bone, weight) ); } } // count min and max bones per vertex int minBones, maxBones; minBones = maxBones = weights[0].size(); for(vector< BoneWeightList >::iterator itr = weights.begin(); itr != weights.end(); ++itr ){ int n = (*itr).size(); minBones = min(n, minBones); maxBones = max(n, maxBones); } if ( minBones <= 0 ) throw runtime_error( "bad NiSkinData - some vertices have no weights at all" ); // reduce vertex influences if necessary if ( maxBones > maxBonesPerVertex ) { int c = 0; for ( vector< BoneWeightList >::iterator it = weights.begin(); it != weights.end(); ++it ) { BoneWeightList & lst = *it; if ( int(lst.size()) > maxBonesPerVertex ) c++; while ( int(lst.size()) > maxBonesPerVertex ) { int j = 0; float weight = lst.front().second; for ( int i = 0; i < int(lst.size()); i++ ) { if ( lst[i].second < weight ) j = i; } BoneWeightList::iterator jit = lst.begin() + j; lst.erase( jit ); } float totalWeight = 0; for (BoneWeightList::iterator bw = lst.begin(); bw != lst.end(); ++bw) { totalWeight += (*bw).second; } for (BoneWeightList::iterator bw = lst.begin(); bw != lst.end(); ++bw) { (*bw).second /= totalWeight; } } //qWarning() << "reduced" << c << "vertices to" << maxBonesPerVertex << "bone influences (maximum number of bones per vertex was" << maxBones << ")"; } maxBones = maxBonesPerVertex; // reduces bone weights so that the triangles fit into the partitions typedef multimap<int,int> matchmap; typedef pair<matchmap::iterator, matchmap::iterator> matchrange; matchmap match; bool doMatch = true; BoneList tribones; int cnt = 0; for (Triangles::iterator itr = triangles.begin(); itr != triangles.end(); ++itr) { Triangle& tri = (*itr); do { tribones.clear(); for ( int c = 0; c < 3; c++ ) { BoneWeightList& bwl = weights[tri[c]]; for (BoneWeightList::iterator bw = bwl.begin(); bw != bwl.end(); ++bw) { if ( tribones.end() == find(tribones.begin(), tribones.end(), (*bw).first ) ) tribones.insert(tribones.end(), (*bw).first ); } } if ( int(tribones.size()) > maxBonesPerPartition ) { // sum up the weights for each bone // bones with weight == 1 can't be removed map<int, float> sum; vector<int> nono; for ( int t = 0; t < 3; t++ ) { BoneWeightList& bwl = weights[tri[t]]; if ( bwl.size() == 1 ) nono.insert(nono.end(), bwl.front().first ); for (BoneWeightList::iterator bw = bwl.begin(); bw != bwl.end(); ++bw) { sum[ (*bw).first ] += (*bw).second; } } // select the bone to remove float minWeight = 5.0; int minBone = -1; for (map<int, float>::iterator sitr = sum.begin(); sitr != sum.end(); ++sitr) { int b = (*sitr).first; if ( (find(nono.begin(), nono.end(), b) == nono.end()) && sum[b] < minWeight) { minWeight = sum[b]; minBone = b; } } if ( minBone < 0 ) // this shouldn't never happen throw runtime_error( "internal error 0x01" ); // do a vertex match detect if ( doMatch ) { for ( size_t a = 0; a < verts.size(); a++ ) { match.insert(matchmap::value_type(a, a)); for ( size_t b = a + 1; b < verts.size(); b++ ) { if ( verts[a] == verts[b] && weights[a] == weights[b] ) { match.insert(matchmap::value_type(a, b)); match.insert(matchmap::value_type(b, a)); } } } } // now remove that bone from all vertices of this triangle and from all matching vertices too for ( int t = 0; t < 3; t++ ) { bool rem = false; matchrange range = match.equal_range(tri[t]); for (matchmap::iterator itr = range.first; itr != range.second; ++itr) { int v = (*itr).second; BoneWeightList & bws = weights[ v ]; BoneWeightList::iterator it = bws.begin(); while ( it != bws.end() ) { BoneWeight & bw = *it; if ( bw.first == minBone ) { it = bws.erase(it); rem = true; } else { ++it; } } float totalWeight = 0; for (BoneWeightList::iterator bw = bws.begin(); bw != bws.end(); ++bw) { totalWeight += (*bw).second; } if ( totalWeight == 0 ) throw runtime_error( "internal error 0x02" ); // normalize for (BoneWeightList::iterator bw = bws.begin(); bw != bws.end(); ++bw) { (*bw).second /= totalWeight; } } if ( rem ) cnt++; } } } while ( int(tribones.size()) > maxBonesPerPartition ); } //if ( cnt > 0 ) // qWarning() << "removed" << cnt << "bone influences"; PartitionList& parts = skinPartitionBlocks; // split the triangles into partitions while ( ! triangles.empty() ) { SkinPartition part; Triangles::iterator it = triangles.begin(); while ( it != triangles.end() ) { Triangle & tri = *it; BoneList tribones; for ( int c = 0; c < 3; c++ ) { BoneWeightList& bws = weights[tri[c]]; for (BoneWeightList::iterator bw = bws.begin(); bw != bws.end(); ++bw) { if ( tribones.end() == find(tribones.begin(), tribones.end(), (*bw).first ) ) tribones.push_back( (*bw).first ); } } if ( part.bones.empty() || containsBones( part.bones, tribones ) ) { mergeBones( part.bones, tribones ); part.triangles.push_back( tri ); it = triangles.erase(it); } else { ++it; } } parts.push_back( part ); } //qWarning() << parts.size() << "small partitions"; // merge partitions bool merged; do { merged = false; // Working backwards through this list minimizes numbers of swaps //for ( int p2 = int(parts.size()-1); p2 >= 0 && ! merged; --p2 ) //{ // Partition& part2 = parts[p2]; // for ( int p1 = int(p2-1); p1 >= 0 && ! merged; --p1 ) // { // Partition& part1 = parts[p1]; for ( int p1 = 0; p1 < int(parts.size()) && ! merged; p1++ ) { Partition& part1 = parts[p1]; for ( int p2 = p1+1; p2 < int(parts.size()) && ! merged; p2++ ) { Partition& part2 = parts[p2]; BoneList mergedBones = part1.bones; mergeBones( mergedBones, part2.bones ); if ( int(mergedBones.size()) <= maxBonesPerPartition ) { PartitionList::iterator p2i = parts.begin() + p2; part1.bones = mergedBones; part1.triangles.insert(part1.triangles.end(), (*p2i).triangles.begin(), (*p2i).triangles.end()); parts.erase(p2i); merged = true; } } } } while ( merged ); //qWarning() << parts.size() << "partitions"; // start writing NiSkinPartition for ( int p = 0; p < int(parts.size()); p++ ) { Partition& part = parts[p]; BoneList& bones = part.bones; sort( bones.begin(), bones.end() ); Triangles& triangles = part.triangles; vector<unsigned short>& vertices = part.vertexMap; for( Triangles::iterator tri = triangles.begin(); tri != triangles.end(); ++tri) { for ( int t = 0; t < 3; t++ ) { if ( vertices.end() == find(vertices.begin(), vertices.end(), (*tri)[t] ) ) vertices.push_back( (*tri)[t] ); } } sort( vertices.begin(), vertices.end() ); part.numVertices = vertices.size(); part.hasVertexMap = true; // map the vertices for ( int tri = 0; tri < int(triangles.size()); tri++ ) { for ( int t = 0; t < 3; t++ ) { triangles[tri][t] = indexOf(vertices.begin(), vertices.end(), triangles[tri][t]); } } SetWeightsPerVertex(p, maxBones); EnableVertexWeights(p, true); EnableVertexBoneIndices(p, true); // strippify the triangles NiTriStripsDataRef data = new NiTriStripsData(triangles, true); int nstrips = data->GetStripCount(); SetStripCount( p, nstrips ); for ( int i=0; i<nstrips; ++i ) { SetStrip(p, i, data->GetStrip(i)); } //// Special case for pre-stripped data //unsigned short *data = new unsigned short[triangles.size() * 3 * 2]; //for (size_t i=0; i< triangles.size(); i++) { // data[i * 3 + 0] = triangles[i][0]; // data[i * 3 + 1] = triangles[i][1]; // data[i * 3 + 2] = triangles[i][2]; //} //PrimitiveGroup * groups = 0; //unsigned short numGroups = 0; //// GF 3+ //SetCacheSize(CACHESIZE_GEFORCE3); //// don't generate hundreds of strips //SetStitchStrips(true); //GenerateStrips(data, triangles.size()*3, &groups, &numGroups); //delete [] data; //if (groups) { // SetStripCount(p, numGroups); // for (int g=0; g<numGroups; g++) { // if (groups[g].type == PT_STRIP) { // vector<Niflib::unsigned short> strip(groups[g].numIndices); // for (size_t s=0; s<groups[g].numIndices; s++) // strip[s] = groups[g].indices[s]; // SetStrip(p, g, strip); // } // } // delete [] groups; //} // fill in vertex weights and bones for (size_t v = 0; v < vertices.size(); ++v) { BoneWeightList& bwl = weights[vertices[v]]; for ( int b = 0; b < maxBones; b++ ) { part.boneIndices[v][b] = (int(bwl.size()) > b) ? indexOf(bones.begin(), bones.end(), bwl[b].first) : 0 ; part.vertexWeights[v][b] = (int(bwl.size()) > b ? bwl[b].second : 0.0f); } } } }