void Foam::patchInjectionBase::updateMesh(const polyMesh& mesh) { // Set/cache the injector cells const polyPatch& patch = mesh.boundaryMesh()[patchId_]; const pointField& points = patch.points(); cellOwners_ = patch.faceCells(); // Triangulate the patch faces and create addressing DynamicList<label> triToFace(2*patch.size()); DynamicList<scalar> triMagSf(2*patch.size()); DynamicList<face> triFace(2*patch.size()); DynamicList<face> tris(5); // Set zero value at the start of the tri area list triMagSf.append(0.0); forAll(patch, facei) { const face& f = patch[facei]; tris.clear(); f.triangles(points, tris); forAll(tris, i) { triToFace.append(facei); triFace.append(tris[i]); triMagSf.append(tris[i].mag(points)); } }
void Foam::stl<Type>::write ( const fileName& samplePath, const fileName& timeDir, const fileName& surfaceName, const pointField& points, const faceList& faces, const fileName& fieldName, const Field<Type>& values, const bool verbose ) const { fileName surfaceDir(samplePath/timeDir); if (!exists(surfaceDir)) { mkDir(surfaceDir); } fileName planeFName(surfaceDir/fieldName + '_' + surfaceName + ".stl"); if (verbose) { Info<< "Writing field " << fieldName << " to " << planeFName << endl; } // Convert faces to triangles. DynamicList<labelledTri> tris(faces.size()); forAll(faces, i) { const face& f = faces[i]; faceList triFaces(f.nTriangles(points)); label nTris = 0; f.triangles(points, nTris, triFaces); forAll(triFaces, triI) { const face& tri = triFaces[triI]; tris.append(labelledTri(tri[0], tri[1], tri[2], 0)); } } triSurface ( tris.shrink(), geometricSurfacePatchList ( 1, geometricSurfacePatch ( "patch", // geometricType string::validate<word>(fieldName), // fieldName 0 // index ) ), points ).write(planeFName); }
void csBSPTree::Build (CS::TriangleIndicesStream<int>& triangles, const csVector3* vertices) { const size_t triComponents = triangles.GetRemainingComponents(); csDirtyAccessArray<csPlane3> planes ((triComponents+2)/3); csArray<int> triidx; csDirtyAccessArray<csTriangle> tris ((triComponents+2)/3); while (triangles.HasNext()) { CS::TriangleT<int> t (triangles.Next()); planes.Push (csPlane3 (vertices[t.a], vertices[t.b], vertices[t.c])); triidx.Push (int (tris.Push (t))); } Build (tris.GetArray(), planes.GetArray(), tris.GetSize(), vertices, triidx); }
bool PhysicsGeometry::load(FS::IFile& file) { Header header; file.read(&header, sizeof(header)); if (header.m_magic != HEADER_MAGIC || header.m_version > (uint32)Versions::LAST) { return false; } auto* phy_manager = m_resource_manager.get(ResourceManager::PHYSICS); PhysicsSystem& system = static_cast<PhysicsGeometryManager*>(phy_manager)->getSystem(); uint32 num_verts; Array<Vec3> verts(getAllocator()); file.read(&num_verts, sizeof(num_verts)); verts.resize(num_verts); file.read(&verts[0], sizeof(verts[0]) * verts.size()); m_is_convex = header.m_convex != 0; if (!m_is_convex) { physx::PxTriangleMeshGeometry* geom = LUMIX_NEW(getAllocator(), physx::PxTriangleMeshGeometry)(); m_geometry = geom; uint32 num_indices; Array<uint32> tris(getAllocator()); file.read(&num_indices, sizeof(num_indices)); tris.resize(num_indices); file.read(&tris[0], sizeof(tris[0]) * tris.size()); physx::PxTriangleMeshDesc meshDesc; meshDesc.points.count = num_verts; meshDesc.points.stride = sizeof(physx::PxVec3); meshDesc.points.data = &verts[0]; meshDesc.triangles.count = num_indices / 3; meshDesc.triangles.stride = 3 * sizeof(physx::PxU32); meshDesc.triangles.data = &tris[0]; OutputStream writeBuffer(getAllocator()); system.getCooking()->cookTriangleMesh(meshDesc, writeBuffer); InputStream readBuffer(writeBuffer.data, writeBuffer.size); geom->triangleMesh = system.getPhysics()->createTriangleMesh(readBuffer); } else { physx::PxConvexMeshGeometry* geom = LUMIX_NEW(getAllocator(), physx::PxConvexMeshGeometry)(); m_geometry = geom; physx::PxConvexMeshDesc meshDesc; meshDesc.points.count = verts.size(); meshDesc.points.stride = sizeof(Vec3); meshDesc.points.data = &verts[0]; meshDesc.flags = physx::PxConvexFlag::eCOMPUTE_CONVEX; OutputStream writeBuffer(getAllocator()); bool status = system.getCooking()->cookConvexMesh(meshDesc, writeBuffer); if (!status) { LUMIX_DELETE(getAllocator(), geom); m_geometry = nullptr; return false; } InputStream readBuffer(writeBuffer.data, writeBuffer.size); physx::PxConvexMesh* mesh = system.getPhysics()->createConvexMesh(readBuffer); geom->convexMesh = mesh; } m_size = file.size(); return true; }
/// @par /// /// See the #rcConfig documentation for more information on the configuration parameters. /// /// @see rcAllocPolyMeshDetail, rcPolyMesh, rcCompactHeightfield, rcPolyMeshDetail, rcConfig bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompactHeightfield& chf, const float sampleDist, const float sampleMaxError, rcPolyMeshDetail& dmesh) { rcAssert(ctx); ctx->startTimer(RC_TIMER_BUILD_POLYMESHDETAIL); if (mesh.nverts == 0 || mesh.npolys == 0) return true; const int nvp = mesh.nvp; const float cs = mesh.cs; const float ch = mesh.ch; const float* orig = mesh.bmin; const int borderSize = mesh.borderSize; rcIntArray edges(64); rcIntArray tris(512); rcIntArray stack(512); rcIntArray samples(512); float verts[256*3]; rcHeightPatch hp; int nPolyVerts = 0; int maxhw = 0, maxhh = 0; rcScopedDelete<int> bounds = (int*)rcAlloc(sizeof(int)*mesh.npolys*4, RC_ALLOC_TEMP); if (!bounds) { ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'bounds' (%d).", mesh.npolys*4); return false; } rcScopedDelete<float> poly = (float*)rcAlloc(sizeof(float)*nvp*3, RC_ALLOC_TEMP); if (!poly) { ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'poly' (%d).", nvp*3); return false; } // Find max size for a polygon area. for (int i = 0; i < mesh.npolys; ++i) { const unsigned short* p = &mesh.polys[i*nvp*2]; int& xmin = bounds[i*4+0]; int& xmax = bounds[i*4+1]; int& ymin = bounds[i*4+2]; int& ymax = bounds[i*4+3]; xmin = chf.width; xmax = 0; ymin = chf.height; ymax = 0; for (int j = 0; j < nvp; ++j) { if(p[j] == RC_MESH_NULL_IDX) break; const unsigned short* v = &mesh.verts[p[j]*3]; xmin = rcMin(xmin, (int)v[0]); xmax = rcMax(xmax, (int)v[0]); ymin = rcMin(ymin, (int)v[2]); ymax = rcMax(ymax, (int)v[2]); nPolyVerts++; } xmin = rcMax(0,xmin-1); xmax = rcMin(chf.width,xmax+1); ymin = rcMax(0,ymin-1); ymax = rcMin(chf.height,ymax+1); if (xmin >= xmax || ymin >= ymax) continue; maxhw = rcMax(maxhw, xmax-xmin); maxhh = rcMax(maxhh, ymax-ymin); } hp.data = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxhw*maxhh, RC_ALLOC_TEMP); if (!hp.data) { ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'hp.data' (%d).", maxhw*maxhh); return false; } dmesh.nmeshes = mesh.npolys; dmesh.nverts = 0; dmesh.ntris = 0; dmesh.meshes = (unsigned int*)rcAlloc(sizeof(unsigned int)*dmesh.nmeshes*4, RC_ALLOC_PERM); if (!dmesh.meshes) { ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.meshes' (%d).", dmesh.nmeshes*4); return false; } int vcap = nPolyVerts+nPolyVerts/2; int tcap = vcap*2; dmesh.nverts = 0; dmesh.verts = (float*)rcAlloc(sizeof(float)*vcap*3, RC_ALLOC_PERM); if (!dmesh.verts) { ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.verts' (%d).", vcap*3); return false; } dmesh.ntris = 0; dmesh.tris = (unsigned char*)rcAlloc(sizeof(unsigned char)*tcap*4, RC_ALLOC_PERM); if (!dmesh.tris) { ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.tris' (%d).", tcap*4); return false; } for (int i = 0; i < mesh.npolys; ++i) { const unsigned short* p = &mesh.polys[i*nvp*2]; // Store polygon vertices for processing. int npoly = 0; for (int j = 0; j < nvp; ++j) { if(p[j] == RC_MESH_NULL_IDX) break; const unsigned short* v = &mesh.verts[p[j]*3]; poly[j*3+0] = v[0]*cs; poly[j*3+1] = v[1]*ch; poly[j*3+2] = v[2]*cs; npoly++; } // Get the height data from the area of the polygon. hp.xmin = bounds[i*4+0]; hp.ymin = bounds[i*4+2]; hp.width = bounds[i*4+1]-bounds[i*4+0]; hp.height = bounds[i*4+3]-bounds[i*4+2]; getHeightData(chf, p, npoly, mesh.verts, borderSize, hp, stack, mesh.regs[i]); // Build detail mesh. int nverts = 0; if (!buildPolyDetail(ctx, poly, npoly, sampleDist, sampleMaxError, chf, hp, verts, nverts, tris, edges, samples)) { return false; } // Move detail verts to world space. for (int j = 0; j < nverts; ++j) { verts[j*3+0] += orig[0]; verts[j*3+1] += orig[1] + chf.ch; // Is this offset necessary? verts[j*3+2] += orig[2]; } // Offset poly too, will be used to flag checking. for (int j = 0; j < npoly; ++j) { poly[j*3+0] += orig[0]; poly[j*3+1] += orig[1]; poly[j*3+2] += orig[2]; } // Store detail submesh. const int ntris = tris.size()/4; dmesh.meshes[i*4+0] = (unsigned int)dmesh.nverts; dmesh.meshes[i*4+1] = (unsigned int)nverts; dmesh.meshes[i*4+2] = (unsigned int)dmesh.ntris; dmesh.meshes[i*4+3] = (unsigned int)ntris; // Store vertices, allocate more memory if necessary. if (dmesh.nverts+nverts > vcap) { while (dmesh.nverts+nverts > vcap) vcap += 256; float* newv = (float*)rcAlloc(sizeof(float)*vcap*3, RC_ALLOC_PERM); if (!newv) { ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'newv' (%d).", vcap*3); return false; } if (dmesh.nverts) memcpy(newv, dmesh.verts, sizeof(float)*3*dmesh.nverts); rcFree(dmesh.verts); dmesh.verts = newv; } for (int j = 0; j < nverts; ++j) { dmesh.verts[dmesh.nverts*3+0] = verts[j*3+0]; dmesh.verts[dmesh.nverts*3+1] = verts[j*3+1]; dmesh.verts[dmesh.nverts*3+2] = verts[j*3+2]; dmesh.nverts++; } // Store triangles, allocate more memory if necessary. if (dmesh.ntris+ntris > tcap) { while (dmesh.ntris+ntris > tcap) tcap += 256; unsigned char* newt = (unsigned char*)rcAlloc(sizeof(unsigned char)*tcap*4, RC_ALLOC_PERM); if (!newt) { ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'newt' (%d).", tcap*4); return false; } if (dmesh.ntris) memcpy(newt, dmesh.tris, sizeof(unsigned char)*4*dmesh.ntris); rcFree(dmesh.tris); dmesh.tris = newt; } for (int j = 0; j < ntris; ++j) { const int* t = &tris[j*4]; dmesh.tris[dmesh.ntris*4+0] = (unsigned char)t[0]; dmesh.tris[dmesh.ntris*4+1] = (unsigned char)t[1]; dmesh.tris[dmesh.ntris*4+2] = (unsigned char)t[2]; dmesh.tris[dmesh.ntris*4+3] = getTriFlags(&verts[t[0]*3], &verts[t[1]*3], &verts[t[2]*3], poly, npoly); dmesh.ntris++; } } ctx->stopTimer(RC_TIMER_BUILD_POLYMESHDETAIL); return true; }
// error: !=0 si erreur fatale static RESP_STRUCT readtable(htsmoduleStruct * str, FILE * fp, RESP_STRUCT trans, int *error) { char rname[1024]; unsigned short int length; int j; *error = 0; // pas d'erreur trans.file_position = -1; trans.type = (int) (unsigned char) fgetc(fp); switch (trans.type) { case HTS_CLASS: strcpy(trans.name, "Class"); trans.index1 = readshort(fp); break; case HTS_FIELDREF: strcpy(trans.name, "Field Reference"); trans.index1 = readshort(fp); readshort(fp); break; case HTS_METHODREF: strcpy(trans.name, "Method Reference"); trans.index1 = readshort(fp); readshort(fp); break; case HTS_INTERFACE: strcpy(trans.name, "Interface Method Reference"); trans.index1 = readshort(fp); readshort(fp); break; case HTS_NAMEANDTYPE: strcpy(trans.name, "Name and Type"); trans.index1 = readshort(fp); readshort(fp); break; case HTS_STRING: // CONSTANT_String strcpy(trans.name, "String"); trans.index1 = readshort(fp); break; case HTS_INTEGER: strcpy(trans.name, "Integer"); for(j = 0; j < 4; j++) fgetc(fp); break; case HTS_FLOAT: strcpy(trans.name, "Float"); for(j = 0; j < 4; j++) fgetc(fp); break; case HTS_LONG: strcpy(trans.name, "Long"); for(j = 0; j < 8; j++) fgetc(fp); break; case HTS_DOUBLE: strcpy(trans.name, "Double"); for(j = 0; j < 8; j++) fgetc(fp); break; case HTS_ASCIZ: case HTS_UNICODE: if (trans.type == HTS_ASCIZ) strcpy(trans.name, "HTS_ASCIZ"); else strcpy(trans.name, "HTS_UNICODE"); { char BIGSTK buffer[1024]; char *p; p = &buffer[0]; //fflush(fp); trans.file_position = ftell(fp); length = readshort(fp); if (length < HTS_URLMAXSIZE) { // while ((length > 0) && (length<500)) { while(length > 0) { *p++ = fgetc(fp); length--; } *p = '\0'; //#if JDEBUG // if(tris(buffer)==1) printf("%s\n ",buffer); // if(tris(buffer)==2) printf("%s\n ",printname(buffer)); //#endif if (tris(str->opt, buffer) == 1) str->addLink(str, buffer); /* trans.file_position */ else if (tris(str->opt, buffer) == 2) str->addLink(str, printname(rname, buffer)); strcpy(trans.name, buffer); } else { // gros pb while((length > 0) && (!feof(fp))) { fgetc(fp); length--; } if (!feof(fp)) { trans.type = -1; } else { sprintf(str->err_msg, "Internal stucture error (ASCII)"); *error = 1; } return (trans); } } break; default: // printf("Type inconnue\n"); // on arrête tout sprintf(str->err_msg, "Internal structure unknown (type %d)", trans.type); *error = 1; return (trans); break; } return (trans); }
bool rcBuildPolyMeshDetail(const rcPolyMesh& mesh, const rcCompactHeightfield& chf, const float sampleDist, const float sampleMaxError, rcPolyMeshDetail& dmesh) { rcTimeVal startTime = rcGetPerformanceTimer(); if (mesh.nverts == 0 || mesh.npolys == 0) return true; const int nvp = mesh.nvp; const float cs = mesh.cs; const float ch = mesh.ch; const float* orig = mesh.bmin; rcIntArray edges(64); rcIntArray tris(512); rcIntArray idx(512); rcIntArray stack(512); rcIntArray samples(512); float verts[256*3]; float* poly = 0; int* bounds = 0; rcHeightPatch hp; int nPolyVerts = 0; int maxhw = 0, maxhh = 0; bounds = new int[mesh.npolys*4]; if (!bounds) { if (rcGetLog()) rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'bounds' (%d).", mesh.npolys*4); goto failure; } poly = new float[nvp*3]; if (!bounds) { if (rcGetLog()) rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'poly' (%d).", nvp*3); goto failure; } // Find max size for a polygon area. for (int i = 0; i < mesh.npolys; ++i) { const unsigned short* p = &mesh.polys[i*nvp*2]; int& xmin = bounds[i*4+0]; int& xmax = bounds[i*4+1]; int& ymin = bounds[i*4+2]; int& ymax = bounds[i*4+3]; xmin = chf.width; xmax = 0; ymin = chf.height; ymax = 0; for (int j = 0; j < nvp; ++j) { if(p[j] == 0xffff) break; const unsigned short* v = &mesh.verts[p[j]*3]; xmin = rcMin(xmin, (int)v[0]); xmax = rcMax(xmax, (int)v[0]); ymin = rcMin(ymin, (int)v[2]); ymax = rcMax(ymax, (int)v[2]); nPolyVerts++; } xmin = rcMax(0,xmin-1); xmax = rcMin(chf.width,xmax+1); ymin = rcMax(0,ymin-1); ymax = rcMin(chf.height,ymax+1); if (xmin >= xmax || ymin >= ymax) continue; maxhw = rcMax(maxhw, xmax-xmin); maxhh = rcMax(maxhh, ymax-ymin); } hp.data = new unsigned short[maxhw*maxhh]; if (!hp.data) { if (rcGetLog()) rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'hp.data' (%d).", maxhw*maxhh); goto failure; } dmesh.nmeshes = mesh.npolys; dmesh.nverts = 0; dmesh.ntris = 0; dmesh.meshes = new unsigned short[dmesh.nmeshes*4]; if (!dmesh.meshes) { if (rcGetLog()) rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.meshes' (%d).", dmesh.nmeshes*4); goto failure; } int vcap = nPolyVerts+nPolyVerts/2; int tcap = vcap*2; dmesh.nverts = 0; dmesh.verts = new float[vcap*3]; if (!dmesh.verts) { if (rcGetLog()) rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.verts' (%d).", vcap*3); goto failure; } dmesh.ntris = 0; dmesh.tris = new unsigned char[tcap*4]; if (!dmesh.tris) { if (rcGetLog()) rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.tris' (%d).", tcap*4); goto failure; } for (int i = 0; i < mesh.npolys; ++i) { const unsigned short* p = &mesh.polys[i*nvp*2]; // Find polygon bounding box. int npoly = 0; for (int j = 0; j < nvp; ++j) { if(p[j] == 0xffff) break; const unsigned short* v = &mesh.verts[p[j]*3]; poly[j*3+0] = orig[0] + v[0]*cs; poly[j*3+1] = orig[1] + v[1]*ch; poly[j*3+2] = orig[2] + v[2]*cs; npoly++; } // Get the height data from the area of the polygon. hp.xmin = bounds[i*4+0]; hp.ymin = bounds[i*4+2]; hp.width = bounds[i*4+1]-bounds[i*4+0]; hp.height = bounds[i*4+3]-bounds[i*4+2]; getHeightData(chf, p, npoly, mesh.verts, hp, stack); // Build detail mesh. int nverts = 0; if (!buildPolyDetail(poly, npoly, mesh.regs[i], sampleDist, sampleMaxError, chf, hp, verts, nverts, tris, edges, idx, samples)) { goto failure; } // Offset detail vertices, unnecassary? for (int j = 0; j < nverts; ++j) verts[j*3+1] += chf.ch; // Store detail submesh. const int ntris = tris.size()/4; dmesh.meshes[i*4+0] = dmesh.nverts; dmesh.meshes[i*4+1] = (unsigned short)nverts; dmesh.meshes[i*4+2] = dmesh.ntris; dmesh.meshes[i*4+3] = (unsigned short)ntris; // Store vertices, allocate more memory if necessary. if (dmesh.nverts+nverts > vcap) { while (dmesh.nverts+nverts > vcap) vcap += 256; float* newv = new float[vcap*3]; if (!newv) { if (rcGetLog()) rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'newv' (%d).", vcap*3); goto failure; } if (dmesh.nverts) memcpy(newv, dmesh.verts, sizeof(float)*3*dmesh.nverts); delete [] dmesh.verts; dmesh.verts = newv; } for (int j = 0; j < nverts; ++j) { dmesh.verts[dmesh.nverts*3+0] = verts[j*3+0]; dmesh.verts[dmesh.nverts*3+1] = verts[j*3+1]; dmesh.verts[dmesh.nverts*3+2] = verts[j*3+2]; dmesh.nverts++; } // Store triangles, allocate more memory if necessary. if (dmesh.ntris+ntris > tcap) { while (dmesh.ntris+ntris > tcap) tcap += 256; unsigned char* newt = new unsigned char[tcap*4]; if (!newt) { if (rcGetLog()) rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'newt' (%d).", tcap*4); goto failure; } if (dmesh.ntris) memcpy(newt, dmesh.tris, sizeof(unsigned char)*4*dmesh.ntris); delete [] dmesh.tris; dmesh.tris = newt; } for (int j = 0; j < ntris; ++j) { const int* t = &tris[j*4]; dmesh.tris[dmesh.ntris*4+0] = (unsigned char)t[0]; dmesh.tris[dmesh.ntris*4+1] = (unsigned char)t[1]; dmesh.tris[dmesh.ntris*4+2] = (unsigned char)t[2]; dmesh.tris[dmesh.ntris*4+3] = getTriFlags(&verts[t[0]*3], &verts[t[1]*3], &verts[t[2]*3], poly, npoly); dmesh.ntris++; } } delete [] bounds; delete [] poly; rcTimeVal endTime = rcGetPerformanceTimer(); if (rcGetBuildTimes()) rcGetBuildTimes()->buildDetailMesh += rcGetDeltaTimeUsec(startTime, endTime); return true; failure: delete [] bounds; delete [] poly; return false; }
// returns the verts of an empty box, centered on the origin which is surrounded by triangles void generate_box_space( moab::EntityHandle surf, double A_f, std::vector<moab::EntityHandle> &box_verts, int axis ) { int x_idx, y_idx; //set the indices of the cartesian vectors based on the constant axis for this surface switch(axis){ case 0: x_idx = 1; y_idx = 2; break; case 1: x_idx = 0; y_idx = 2; break; case 2: x_idx = 0; y_idx = 1; break; default: std::cout << "Value of axis muxt be 0, 1, or 2" << std::endl; assert(false); } std::vector<moab::EntityHandle> corners; moab::ErrorCode rval = mbi->get_entities_by_type( surf, MBVERTEX, corners ); MB_CHK_ERR_CONT(rval); double surface_area = polygon_area( corners ); //going to start taking advantage of knowing the geometry here... double surface_side = sqrt(surface_area); double cube_area = 6*surface_area; //now create the vertices for the new regions //based on surface area, get the length of one of the center-square sides if( A_f == 1 ) { std::vector<moab::EntityHandle> ordered_corners; order_corner_verts(corners, ordered_corners); box_verts = ordered_corners; return; } double hv_area = A_f*cube_area/6; //divide by 6 because this surface represents all surfaces of the cube if ( hv_area >= surface_area ) std::cout << "ERROR: Area fraction must be less than 1/6 for now. " << surf << std::endl; assert( hv_area < surface_area ); double hv_side = sqrt(hv_area); //get the move distance for the given area. double box_bump_dist = 0.5 * (surface_side - hv_side); double dam_bump_short = 0.25 * (surface_side - hv_side); double dam_bump_long = 0.5 * surface_side; //vectors for the dam nodes and the inner vert points std::vector<moab::EntityHandle> nd, /*north dam tri verts*/ sd, /*south dam tri verts*/ ed, /*east dam tri verts*/ wd; /*west dam tri verts*/ moab::EntityHandle ndv, /*north dam vertex*/ sdv, /*south dam vertex*/ edv, /*east dam vertex*/ wdv; /*west dam vertex*/ std::vector<moab::EntityHandle> box; /* inner box vert list */ //loop over the original verts (corners) and create the needed vertices for(std::vector<moab::EntityHandle>::iterator i=corners.begin(); i!=corners.end(); i++) { //first get the coordinates of this corner moab::CartVect coords; mbi->get_coords( &(*i), 1, coords.array() ); //need three cartesian vectors telling us where to put the verts, two for the dam points, one for the inner point. moab::CartVect to_ewdam, to_nsdam, to_box; to_ewdam[axis] = 0; to_nsdam[axis] = 0; to_box[axis] = 0; //only moving on the x-y plane here //always want to create this vert //using the fact that we're centered on the origin here... //x-points if( coords[x_idx] < 0 ){ to_box[x_idx] = box_bump_dist; } else { to_box[x_idx] = -box_bump_dist; } //y-points if( coords[y_idx] < 0 ){ to_box[y_idx]= box_bump_dist; } else { to_box[y_idx] = -box_bump_dist; } //create the inner point moab::EntityHandle box_vert; mbi->create_vertex( (coords+to_box).array(), box_vert); box.push_back(box_vert); //figure out which dams we're adjacent to std::vector<moab::EntityHandle> *nsdam = &nd, *ewdam = &ed; moab::EntityHandle *nsdam_vert = &ndv, *ewdam_vert = &edv; //set the north-south dam based on our y location if( coords[y_idx] < 0) { nsdam_vert = &sdv; nsdam = &sd; } else { nsdam_vert = &ndv; nsdam = &nd; } //set the east-west dam based on our x location if( coords[x_idx] < 0) { ewdam_vert = &wdv; ewdam = &wd; } else { ewdam_vert = &edv; ewdam = &ed; } //////NORTH-SOUTH DAM\\\\\\\ //if the dams already have info from another corner, no need to create it's point, //just add this corner to the dam triangle if( 0 != nsdam->size() && NULL != nsdam_vert ) { nsdam->push_back(*i); } // if the dam has no info, then we'll create it else { //set the dam coordinates if ( coords[x_idx] < 0 ) to_nsdam[x_idx] = dam_bump_long; else to_nsdam[x_idx] = -dam_bump_long; if ( coords[y_idx] < 0 ) to_nsdam[y_idx] = dam_bump_short; else to_nsdam[y_idx] = -dam_bump_short; //create the dam vertex mbi->create_vertex( (coords+to_nsdam).array(), *nsdam_vert); //now add this corner and the dam vert to the dam verts list nsdam->push_back(*nsdam_vert); nsdam->push_back(*i); } //////EAST-WEST DAM\\\\\\\ //if the dams already have info from another corner, no need to create it's point, //just add this corner to the dam triangle if( 0 != ewdam->size() && NULL != ewdam_vert ) { ewdam->push_back(*i); } // if the dam has no info, then we'll create it else { //set the dam coordinates if ( coords[x_idx] < 0 ) to_ewdam[x_idx] = dam_bump_short; else to_ewdam[x_idx] = -dam_bump_short; if ( coords[y_idx] < 0 ) to_ewdam[y_idx] = dam_bump_long; else to_ewdam[y_idx] = -dam_bump_long; //create the dam vertex mbi->create_vertex( (coords+to_ewdam).array(), *ewdam_vert); //now add this corner and the dam vert to the dam verts list //order of push back is reversed here in comparison to north-south dam for correct normal ewdam->push_back(*i); ewdam->push_back(*ewdam_vert); } //dam info should now all be set //there are always two triangles to create that connect the dam //to the corner, we'll do that now moab::CartVect corner_coords; mbi->get_coords(&(*i), 1, corner_coords.array()); moab::EntityHandle tri1_verts[3] = {*i, *nsdam_vert, box_vert}; moab::EntityHandle tri2_verts[3] = {*i, *ewdam_vert, box_vert}; if( coords[x_idx] < 0 ) { if ( coords[y_idx] > 0 ) { tri1_verts[1] = *nsdam_vert; tri1_verts[2] = box_vert; tri2_verts[1] = box_vert; tri2_verts[2] = *ewdam_vert; } else { tri1_verts[1] = box_vert; tri1_verts[2] = *nsdam_vert; } } else { if ( coords[y_idx] > 0 ) { tri1_verts[1] = box_vert; tri1_verts[2] = *nsdam_vert; } else { tri2_verts[1] = box_vert; tri2_verts[2] = *ewdam_vert; } } std::vector<moab::EntityHandle> tris(2); mbi->create_element( MBTRI, &tri1_verts[0], 3, tris[0] ); mbi->create_element( MBTRI, &tri2_verts[0], 3, tris[1] ); //now we'll add these to the set mbi->add_entities( surf, &tri1_verts[0], 3 ); mbi->add_entities( surf, &tri2_verts[0], 3 ); mbi->add_entities( surf, &(tris[0]), tris.size() ); } //now we should have all of the info needed to create our dam triangles std::vector<moab::EntityHandle> dam_tris(4); assert( nd.size()==3 ); moab::EntityHandle temp = nd[1]; nd[1] = nd[2]; nd[2] = temp; temp = wd[1]; wd[1] = wd[2]; wd[2] = temp; mbi->create_element( MBTRI, &(nd[0]), nd.size(), dam_tris[0]); mbi->create_element( MBTRI, &(sd[0]), sd.size(), dam_tris[1]); mbi->create_element( MBTRI, &(ed[0]), ed.size(), dam_tris[2]); mbi->create_element( MBTRI, &(wd[0]), wd.size(), dam_tris[3]); //add these to the surface mbi->add_entities( surf, &(dam_tris[0]), dam_tris.size() ); //re-order the M verts std::vector<moab::EntityHandle> ordered_box(4); order_corner_verts(box, ordered_box); box_verts = ordered_box; //now that the middle box is ordered we can add the triangles that //connect the dams to to the box box_verts.push_back(box_verts[0]); // psuedo-loop to make creating these tris easier moab::EntityHandle all_dam_verts[4] = { wdv, ndv, edv, sdv }; std::vector<moab::EntityHandle> last_few_tris(4); //create triangle that connect the box to the dams for(unsigned int i = 0; i < last_few_tris.size(); i++) { moab::EntityHandle tri_verts[3] = { box_verts[i], all_dam_verts[i], box_verts[i+1] }; mbi->create_element( MBTRI, &(tri_verts[0]), 3, last_few_tris[i]); } //now add these to the surface mbi->add_entities( surf, &last_few_tris[0], 4); box_verts = ordered_box; } // end generate_box_space