double TileSetLLByPixelArea::calcTriangleNDCAreaVisible(Plane const &clip_plane, osg::Matrixd const &mvp, std::vector<osg::Vec3d> const &tri, std::vector<osg::Vec2d> const &tri_ndc) const { bool ok; double area=0.0; // NDC bounding rectangle static const std::vector<osg::Vec2d> ndc_rect = { osg::Vec2d(-1.0,-1.0), // bl osg::Vec2d( 1.0,-1.0), // br osg::Vec2d( 1.0, 1.0), // tr osg::Vec2d(-1.0, 1.0) // tl }; std::vector<osg::Vec3d> inside; std::vector<osg::Vec3d> outside; GeometryResult const result = CalcTrianglePlaneClip(tri, clip_plane, inside, outside); if(result == GeometryResult::CLIP_OUTSIDE) { // Completely outside the near plane if(CalcTriangleAARectIntersection(tri_ndc,ndc_rect)) { area += CalcTriangleArea(tri_ndc[0],tri_ndc[1],tri_ndc[2]); } } else if(result == GeometryResult::CLIP_XSEC) { // Triangle was clipped against the clip plane. // Use the outside tri or quad to calculate area std::vector<osg::Vec2d> list_ndc; for(auto const & vx : outside) { list_ndc.push_back(ConvWorldToNDC(mvp,vx,ok)); } if(list_ndc.size() > 3) { // outside is a quad if(CalcQuadAARectIntersection(list_ndc,ndc_rect)) { area += CalcTriangleArea(list_ndc[0],list_ndc[1],list_ndc[2]); area += CalcTriangleArea(list_ndc[0],list_ndc[2],list_ndc[3]); } } else { // outside is a tri if(CalcTriangleAARectIntersection(list_ndc,ndc_rect)) { area += CalcTriangleArea(list_ndc[0],list_ndc[1],list_ndc[2]); } } } return area; }
double TileSetLLByPixelArea::calcTriangleNDCAreaFull(Plane const &clip_plane, osg::Matrixd const &mvp, std::vector<osg::Vec3d> const &tri, std::vector<osg::Vec2d> const &tri_ndc) const { bool ok; double area=0.0; std::vector<osg::Vec3d> inside; std::vector<osg::Vec3d> outside; GeometryResult const result = CalcTrianglePlaneClip(tri, clip_plane, inside, outside); if(result == GeometryResult::CLIP_OUTSIDE) { // Completely outside the near plane area += CalcTriangleArea(tri_ndc[0],tri_ndc[1],tri_ndc[2]); } else if(result == GeometryResult::CLIP_XSEC) { // Triangle was clipped against the clip plane. // Use the outside tri or quad to calculate area std::vector<osg::Vec2d> list_ndc; for(auto const & vx : outside) { list_ndc.push_back(ConvWorldToNDC(mvp,vx,ok)); } if(list_ndc.size() > 3) { // outside is a quad area += CalcTriangleArea(list_ndc[0],list_ndc[1],list_ndc[2]); area += CalcTriangleArea(list_ndc[0],list_ndc[2],list_ndc[3]); } else { // outside is a tri area += CalcTriangleArea(list_ndc[0],list_ndc[1],list_ndc[2]); } } return area; }
double CalcFaceArea (FacePtr pFace) { SidePtr pS; // to loop over a Face's Sides double Area; // Face area Loc3DTD FC; // Face centroid CalcFaceCentroidFromNodes ( pFace ); FC = pFace->Centroid; Area = 0.0; pS = pFace->p1stSide; while (pS != NULL) { Area = Area + CalcTriangleArea (FC, pS->pNode1->Loc3D, pS->pNode2->Loc3D); pS = pS->pFsNextS; } return (Area); }
/** * 多角形の面積を計算. */ double MathUtil::CalcPolygonArea (sxsdk::shade_interface& shade, std::vector<sxsdk::vec3>& polygon) { if (polygon.size() < 3) return 0.0; // 三角形分割を行う. ::m_triangleIndex.clear(); ::CDivideTrianglesOutput divC; shade.divide_polygon(divC, polygon.size(), &(polygon[0]), true); const int triCou = ::m_triangleIndex.size() / 3; double area = 0.0; int iPos = 0; for (int i = 0; i < triCou; i++, iPos += 3) { const int i0 = ::m_triangleIndex[iPos + 0]; const int i1 = ::m_triangleIndex[iPos + 1]; const int i2 = ::m_triangleIndex[iPos + 2]; area += CalcTriangleArea(polygon[i0], polygon[i1], polygon[i2]); } return area; }
void TileSetLLByPixelArea::calcTileNDCArea(Eval const &eval, double &ndc_area, double &surf_area_m2) const { // Find a quads that are completely visible // (not clipped) and calculate both its pixel // and surface areas ndc_area = 0.0; surf_area_m2 = 0.0; // For each quad for(size_t i=0; i < eval.list_ix.size(); i+=6) { // Ignore quads that face away from the camera if((eval.list_quad_nx[i/6]*m_view_dirn) >= -0.01) { // TODO experiment adjusting threshold continue; } bool bad_tri=false; // Try converting first tri to NDC std::vector<osg::Vec3d> const tri0 = { eval.list_vx[eval.list_ix[i+0]], eval.list_vx[eval.list_ix[i+1]], eval.list_vx[eval.list_ix[i+2]] }; std::vector<osg::Vec2d> tri0_ndc(3); for(size_t j=0; j < 3; j++) { if(!ConvWorldToNDC(m_mvp,tri0[j],tri0_ndc[j])) { bad_tri=true; break; } } if(bad_tri) { continue; } // Try converting second tri to NDC std::vector<osg::Vec3d> const tri1 = { eval.list_vx[eval.list_ix[i+3]], eval.list_vx[eval.list_ix[i+4]], eval.list_vx[eval.list_ix[i+5]] }; std::vector<osg::Vec2d> tri1_ndc(3); for(size_t j=0; j < 3; j++) { if(!ConvWorldToNDC(m_mvp,tri1[j],tri1_ndc[j])) { bad_tri=true; break; } } if(bad_tri) { continue; } // Add NDC area double tri0_area = CalcTriangleArea(tri0_ndc[0],tri0_ndc[1],tri0_ndc[2]); double tri1_area = CalcTriangleArea(tri1_ndc[0],tri1_ndc[1],tri1_ndc[2]); ndc_area += tri0_area; ndc_area += tri1_area; // Add surface area std::vector<LLA> const tri0_lla = { eval.list_lla[eval.list_ix[i+0]], eval.list_lla[eval.list_ix[i+1]], eval.list_lla[eval.list_ix[i+2]] }; // lon range for surface area auto list_lon_ranges = CalcLonRange(tri0_lla); if(list_lon_ranges.size() > 1) { // We might get two ranges due to numerical // precision issues near the antemeridian; // discard the smaller range double range0 = list_lon_ranges[0].second- list_lon_ranges[0].first; double range1 = list_lon_ranges[1].second- list_lon_ranges[1].first; if(range0 > range1) { list_lon_ranges.pop_back(); } else { list_lon_ranges.erase(list_lon_ranges.begin()); } } // lat range for surface area std::pair<double,double> lat_range(90.0,-90.0); for(auto const &lla : tri0_lla) { lat_range.first = std::min(lat_range.first,lla.lat); lat_range.second = std::max(lat_range.second,lla.lat); } GeoBounds const bounds(list_lon_ranges[0].first, list_lon_ranges[0].second, lat_range.first, lat_range.second); // std::cout << "####: ndirn: " << (eval.list_quad_nx[i/6]*m_view_dirn) << std::endl; // std::cout << "####: tri0_area: " << tri0_area << ", tri1_area: " << tri1_area << std::endl; // std::cout << "####: bounds.lon [" << bounds.minLon << "," << bounds.maxLon << "]" << std::endl; // std::cout << "####: bounds.lat [" << bounds.minLat << "," << bounds.maxLat << "]" << std::endl; // std::cout << "####: bounds.area: " << CalcGeoBoundsArea(bounds) << std::endl; surf_area_m2 += CalcGeoBoundsArea(bounds); } }