inline void correct_multi_polygon(O& o) { for (typename O::iterator it = o.begin(); it != o.end(); it++) { correct_polygon(*it); } }
// this method will also construct the triangles/polygons in the new mesh // if we accept planar polygons, we just save them // also, we could just create new vertices every time, and merge only in the end; // could be too expensive, and the tolerance for merging could be an // interesting topic int Intx2MeshOnSphere::findNodes(EntityHandle red, int nsRed, EntityHandle blue, int nsBlue, double * iP, int nP) { // first of all, check against red and blue vertices // if (dbg_1) { std::cout << "red, blue, nP, P " << mb->id_from_handle(red) << " " << mb->id_from_handle(blue) << " " << nP << "\n"; for (int n = 0; n < nP; n++) std::cout << " \t" << iP[2 * n] << "\t" << iP[2 * n + 1] << "\n"; } // get the edges for the red triangle; the extra points will be on those edges, saved as // lists (unordered) std::vector<EntityHandle> redEdges(nsRed);// int i = 0; for (i = 0; i < nsRed; i++) { EntityHandle v[2] = { redConn[i], redConn[(i + 1) % nsRed] }; std::vector<EntityHandle> adj_entities; ErrorCode rval = mb->get_adjacencies(v, 2, 1, false, adj_entities, Interface::INTERSECT); if (rval != MB_SUCCESS || adj_entities.size() < 1) return 0; // get out , big error redEdges[i] = adj_entities[0]; // should be only one edge between 2 nodes } // these will be in the new mesh, mbOut // some of them will be handles to the initial vertices from blue or red meshes (lagr or euler) EntityHandle * foundIds = new EntityHandle[nP]; for (i = 0; i < nP; i++) { double * pp = &iP[2 * i]; // iP+2*i // project the point back on the sphere CartVect pos; reverse_gnomonic_projection(pp[0], pp[1], R, plane, pos); int found = 0; // first, are they on vertices from red or blue? // priority is the red mesh (mb2?) int j = 0; EntityHandle outNode = (EntityHandle) 0; for (j = 0; j < nsRed && !found; j++) { //int node = redTri.v[j]; double d2 = dist2(pp, &redCoords2D[2 * j]); if (d2 < epsilon_1) { foundIds[i] = redConn[j]; // no new node found = 1; if (dbg_1) std::cout << " red node j:" << j << " id:" << mb->id_from_handle(redConn[j]) << " 2d coords:" << redCoords2D[2 * j] << " " << redCoords2D[2 * j + 1] << " d2: " << d2 << " \n"; } } for (j = 0; j < nsBlue && !found; j++) { //int node = blueTri.v[j]; double d2 = dist2(pp, &blueCoords2D[2 * j]); if (d2 < epsilon_1) { // suspect is blueConn[j] corresponding in mbOut foundIds[i] = blueConn[j]; // no new node found = 1; if (dbg_1) std::cout << " blue node " << j << " " << mb->id_from_handle(blueConn[j]) << " d2:" << d2 << " \n"; } } if (!found) { // find the edge it belongs, first, on the red element // for (j = 0; j < nsRed; j++) { int j1 = (j + 1) % nsRed; double area = area2D(&redCoords2D[2 * j], &redCoords2D[2 * j1], pp); if (dbg_1) std::cout << " edge " << j << ": " << mb->id_from_handle(redEdges[j]) << " " << redConn[j] << " " << redConn[j1] << " area : " << area << "\n"; if (fabs(area) < epsilon_1/2) { // found the edge; now find if there is a point in the list here //std::vector<EntityHandle> * expts = extraNodesMap[redEdges[j]]; int indx = -1; indx = RedEdges.index(redEdges[j]); std::vector<EntityHandle> * expts = extraNodesVec[indx]; // if the points pp is between extra points, then just give that id // if not, create a new point, (check the id) // get the coordinates of the extra points so far int nbExtraNodesSoFar = expts->size(); CartVect * coords1 = new CartVect[nbExtraNodesSoFar]; mb->get_coords(&(*expts)[0], nbExtraNodesSoFar, &(coords1[0][0])); //std::list<int>::iterator it; for (int k = 0; k < nbExtraNodesSoFar && !found; k++) { //int pnt = *it; double d2 = (pos - coords1[k]).length_squared(); if (d2 < epsilon_1) { found = 1; foundIds[i] = (*expts)[k]; if (dbg_1) std::cout << " found node:" << foundIds[i] << std::endl; } } if (!found) { // create a new point in 2d (at the intersection) //foundIds[i] = m_num2dPoints; //expts.push_back(m_num2dPoints); // need to create a new node in mbOut // this will be on the edge, and it will be added to the local list mb->create_vertex(pos.array(), outNode); (*expts).push_back(outNode); foundIds[i] = outNode; found = 1; if (dbg_1) std::cout << " new node: " << outNode << std::endl; } delete[] coords1; } } } if (!found) { std::cout << " red quad: "; for (int j1 = 0; j1 < nsRed; j1++) { std::cout << redCoords2D[2 * j1] << " " << redCoords2D[2 * j1 + 1] << "\n"; } std::cout << " a point pp is not on a red quad " << *pp << " " << pp[1] << " red quad " << mb->id_from_handle(red) << " \n"; delete[] foundIds; return 1; } } if (dbg_1) { std::cout << " candidate polygon: nP" << nP << " plane: " << plane << "\n"; for (int i1 = 0; i1 < nP; i1++) std::cout << iP[2 * i1] << " " << iP[2 * i1 + 1] << " " << foundIds[i1] << "\n"; } // first, find out if we have nodes collapsed; shrink them // we may have to reduce nP // it is possible that some nodes are collapsed after intersection only // nodes will always be in order (convex intersection) correct_polygon(foundIds, nP); // now we can build the triangles, from P array, with foundIds // we will put them in the out set if (nP >= 3) { EntityHandle polyNew; mb->create_element(MBPOLYGON, foundIds, nP, polyNew); mb->add_entities(outSet, &polyNew, 1); // tag it with the index ids from red and blue sets int id = rs1.index(blue); // index starts from 0 mb->tag_set_data(blueParentTag, &polyNew, 1, &id); id = rs2.index(red); mb->tag_set_data(redParentTag, &polyNew, 1, &id); static int count=0; count++; mb->tag_set_data(countTag, &polyNew, 1, &count); if (dbg_1) { std::cout << "Count: " << count << "\n"; std::cout << " polygon " << mb->id_from_handle(polyNew) << " nodes: " << nP << " :"; for (int i1 = 0; i1 < nP; i1++) std::cout << " " << mb->id_from_handle(foundIds[i1]); std::cout << " plane: " << plane << "\n"; std::vector<CartVect> posi(nP); mb->get_coords(foundIds, nP, &(posi[0][0])); for (int i1 = 0; i1 < nP; i1++) std::cout << foundIds[i1]<< " " << posi[i1] << "\n"; std::stringstream fff; fff << "file0" << count<< ".vtk"; mb->write_mesh(fff.str().c_str(), &outSet, 1); } } delete[] foundIds; foundIds = NULL; return 0; }