int TriMesh2D::get_containing_tri(const Vec2f& point) const { Vec2f cell = (point - accel_origin)*inv_accel_dx; unsigned int offset = (int)cell[0] + accel_ni * (int)cell[1]; if(offset < accel_grid.size()) { for(unsigned int i = 0; i < accel_grid[offset].size(); ++i) if(point_in_tri(point, accel_grid[offset][i])) return accel_grid[offset][i]; } return -1; }
void tri_grid::assign_points_from_grid(ncdata* nc_input_data, int perim) { // relative coordinates for the 5 points of a grid box const int n_gp = 5; const FP_TYPE x_pts[5] = {0,-1,1,1,-1}; const FP_TYPE y_pts[5] = {0,-1,-1,1,1}; FP_TYPE lon_d = nc_input_data->get_lon_d(); FP_TYPE lat_d = nc_input_data->get_lat_d(); FP_TYPE lon_s = nc_input_data->get_lon_s(); FP_TYPE lat_s = nc_input_data->get_lat_s(); FP_TYPE rot_pole_lon, rot_pole_lat; if (nc_input_data->has_rotated_grid()) { rot_pole_lon = nc_input_data->get_rotated_grid()->get_rotated_pole_longitude(); rot_pole_lat = nc_input_data->get_rotated_grid()->get_rotated_pole_latitude(); } // get the coordinates from the ncdata file and add to the quad trees for (int j=perim; j<nc_input_data->get_lat_len()-perim; j++) { for (int i=perim; i<nc_input_data->get_lon_len()-perim; i++) { FP_TYPE lon_b = lon_s + i*lon_d; FP_TYPE lat_b = lat_s + j*lat_d; for (int k=0; k<n_gp; k++) { // get the lon as the corners of a grid box FP_TYPE lon = lon_b + x_pts[k] * lon_d * 0.49999; FP_TYPE lat = lat_b + y_pts[k] * lat_d * 0.49999; // extra conversion for rotated grid if (nc_input_data->has_rotated_grid()) { FP_TYPE glob_lon, glob_lat; Rot2Global(lat, lon, rot_pole_lat, rot_pole_lon, glob_lat, glob_lon); lat = glob_lat; lon = glob_lon; } // convert to Cartesian coordinates vector_3D cart_coords = model_to_cart(lon, lat); // determine which triangle (head node) this point is in for (unsigned int tri=0; tri<triangles.size(); tri++) if (point_in_tri(&cart_coords, triangles[tri]->get_root()->get_data())) triangles[tri]->get_root()->get_data()->add_index(i,j, cart_coords); } } } }
LABEL tri_grid::get_triangle_for_point(vector_3D* P) { // determine which of the 20 base triangles the point is in int base_tri = -1; for (unsigned int tri=0; tri<triangles.size(); tri++) if (point_in_tri(P, triangles[tri]->get_root()->get_data())) { base_tri = tri; break; } // not found so find by distance if (base_tri == -1) { FP_TYPE min_dist = 2e20; int min_base = -1; FP_TYPE P_lon, P_lat; cart_to_model(*P, P_lon, P_lat); for (unsigned int tri=0; tri<triangles.size(); tri++) { FP_TYPE T_lon, T_lat; cart_to_model(triangles[tri]->get_root()->get_data()->centroid(), T_lon, T_lat); FP_TYPE dist = haversine(P_lon, P_lat, T_lon, T_lat, 1.0); if (dist < min_dist) { dist = min_dist; min_base = tri; } } base_tri = min_base; } // get the base node QT_TRI_NODE* current_node = get_base_tri(base_tri); bool found = false; while (not found) { if (current_node->is_leaf()) { found = true; break; } else { bool found_in_child = false; for (int i=0; i<4; i++) { QT_TRI_NODE* current_child = current_node->get_child(i); if (point_in_tri(P, current_child->get_data())) { current_node = current_child; found_in_child = true; break; } } // not found by point inclusion - find by minimum distance if (not found_in_child) { FP_TYPE min_dist = 2e20; int min_child = -1; FP_TYPE P_lon, P_lat; cart_to_model(*P, P_lon, P_lat); for (int i=0; i<4; i++) { FP_TYPE T_lon, T_lat; cart_to_model(current_node->get_child(i)->get_data()->centroid(), T_lon, T_lat); FP_TYPE dist = haversine(P_lon, P_lat, T_lon, T_lat, 1.0); if (dist < min_dist) { dist = min_dist; min_child = i; } } current_node = current_node->get_child(min_child); } } } return current_node->get_data()->get_label(); }
void tri_grid::split_triangle(QT_TRI_NODE* triangle, int max_pts, int max_levs) { // split the triangle indicated by PTI (parent triangle index) into four // new triangles and insert the 3 new force points into the point cloud // and the triangle definition into the HTMA containing the references to // the force points int iM[3]; // indices to new points in the point cloud for (int i=0; i<3; i++) { int j = i<2 ? i+1 : 0; // get the two points of the current triangle edge and create a mid point force_point MP = (PC[(*(triangle->get_data()))[i]] + PC[(*(triangle->get_data()))[j]]) * 0.5; // normalise the mid point MP *= 1.0 / MP.mag(); // add to the point cloud iM[i] = PC_ADD_SPLIT(MP); } // new points have been created - now add the four new triangles indexed_force_tri_3D* ift = triangle->get_data(); // get the current label LABEL c_label = ift->get_label(); // calculate the multiplier long int mp = (long int)(pow(10, c_label.max_level+2)); triangle->add_child(indexed_force_tri_3D(&PC, (*ift)[0], iM[0], iM[2], LABEL(c_label.label+1*mp, c_label.max_level+1))); triangle->add_child(indexed_force_tri_3D(&PC, iM[0], (*ift)[1], iM[1], LABEL(c_label.label+2*mp, c_label.max_level+1))); triangle->add_child(indexed_force_tri_3D(&PC, iM[1], (*ift)[2], iM[2], LABEL(c_label.label+3*mp, c_label.max_level+1))); triangle->add_child(indexed_force_tri_3D(&PC, iM[0], iM[1], iM[2], LABEL(c_label.label+4*mp, c_label.max_level+1))); // check whether the triangles should contain one of the indexed points const std::list<grid_index>* grid_index_list = triangle->get_data()->get_grid_indices(); for (std::list<grid_index>::const_iterator gii = grid_index_list->begin(); gii != grid_index_list->end(); gii++) { // get the actual triangle from the quad tree // check for point inclusion of current grid index bool pit = false; for (int i=0; i<4; i++) { // need to check each child triangle indexed_force_tri_3D* child_tri = triangle->get_child(i)->get_data(); if (point_in_tri(&(gii->cart_coord), child_tri)) { child_tri->add_index(gii->i, gii->j, gii->cart_coord); pit = true; } } // if not added then add to nearest FP_TYPE min_dist = 1e10; int min_tri_idx = -1; if (not pit) { for (int i=0; i<4; i++) { // calculate distance between point and centroid indexed_force_tri_3D* child_tri = triangle->get_child(i)->get_data(); FP_TYPE dist = (child_tri->centroid() - gii->cart_coord).mag(); if (dist < min_dist) min_tri_idx = i; } // add to the child tri the point is nearest to triangle->get_child(min_tri_idx)->get_data()->add_index(gii->i, gii->j, gii->cart_coord); } } // check whether each child should be split again for (int i=0; i<4; i++) { if ((triangle->get_child(i)->get_data()->get_number_of_indices() > max_pts || // this ensures that any (for example level 7) levels with triangles in a previous level still get split triangle->get_level() > max_levs-3) && triangle->get_level() < (max_levs-1)) // recursive split split_triangle(triangle->get_child(i), max_pts, max_levs); } }