Пример #1
0
def readPolyhedronOFF(filename):
    f = open(filename, "r")
    line = f.readline()
    assert line[:3].lower() == "off"
    while line[0] == "#":
        line = f.readline()
    stuff = line.split()
    assert len(stuff) == 3
    nv, nf, ne = int(stuff[0]), int(stuff[1]), int(stuff[2])

    # Read the vertex positions.
    verts = vector_of_Vector()
    for i in xrange(nv):
        line = f.readline()
        stuff = line.split()
        assert len(stuff) == 3
        verts.append(Vector(float(stuff[0]), float(stuff[1]), float(stuff[2])))
    
    # Read the face vertex indices.
    facets = vector_of_vector_of_unsigned()
    for i in xrange(nf):
        line = f.readline()
        stuff = line.split()
        assert len(stuff) >= 4
        n = int(stuff[0])
        facets.push_back(vector_of_unsigned(n))
        for j in xrange(n):
            k = int(stuff[j+1])
            assert k < nv
            facets[-1][j] = k
    
    # Build the polyhedron and we're done.
    poly = Polyhedron(verts, facets)
    return poly
Пример #2
0
def readPolyhedronOBJ(filename):
    f = open(filename, "r")
    verts = vector_of_Vector()
    facets = vector_of_vector_of_unsigned()
    for line in f:
        stuff = line.split()
        if stuff:
            if stuff[0] == "v":
                assert len(stuff) == 4
                verts.append(Vector(float(stuff[1]), float(stuff[2]), float(stuff[3])))
            elif stuff[0] == "f":
                assert len(stuff) >= 4
                facets.append(vector_of_unsigned())
                for x in stuff[1:]:
                    facets[-1].append(int(x.split("/")[0]) - 1)
    f.close()
    nverts = len(verts)
    for i in xrange(len(facets)):
        for j in xrange(len(facets[i])):
            assert facets[i][j] < nverts
    poly = Polyhedron(verts, facets)
    return poly
Пример #3
0
    def __init__(self,
                 n,
                 rho,
                 rmin,
                 rmax,
                 gradrho = None,
                 maxIterations = 100,
                 centroidFrac = 1.0,
                 fracTol = 1.0e-3,
                 tessellationBaseDir = ".",
                 tessellationFileName = None,
                 nNodePerh = 2.01,
                 offset = (0.0, 0.0, 0.0),
                 rejecter = None,
                 randomseed = 492739149274,
                 maxNodesPerDomain = 1000,
                 seedPositions = None,
                 enforceConstantMassPoints = False,
                 cacheFileName = None):
        
        from Spheral3d import vector_of_Vector, Vector
        from GenerateNodeDistribution3d import GenerateIcosahedronMatchingProfile3d
        SphericallyConformalMap = GenerateIcosahedronMatchingProfile3d(n=n,
                                                                       densityProfileMethod=rho,
                                                                       rmin=rmin,
                                                                       rmax=rmax,
                                                                       nNodePerh=nNodePerh,
                                                                       offset=offset,
                                                                       rejecter=rejecter)
        n = len(SphericallyConformalMap.positions)
        # this is a serialized list, so it needs to be broken up to each processor
        # no degeneracies allowed!
        seedPositions = vector_of_Vector()
        nprocs = mpi.procs
        nlocal = int(n/nprocs)
        nrem   = n - nlocal*nprocs
        myn    = nlocal
        if mpi.rank == nprocs-1:
            myn += nrem
        for i in xrange(myn):
            j = i + mpi.rank*nlocal
            seedPositions.append(Vector(SphericallyConformalMap.positions[j][0],
                                        SphericallyConformalMap.positions[j][1],
                                        SphericallyConformalMap.positions[j][2]))
        
        
        # Now construct boundaries based on rmin and rmax
        bpoints = vector_of_Vector()
        nshell = 300 # fix this later
        for i in xrange(1,nshell+1):
            h = -1.0+(2.0*(i-1.0)/(nshell-1.0))
            t = acos(h)
            if (i>1 and i<nshell):
                p = (p + 3.8/sqrt(nshell)*1.0/sqrt(1.0-h*h)) % (2.0*pi)
            else:
                p = 0
            bpoints.append(Vector(rmax*sin(t)*cos(p),
                                  rmax*sin(t)*sin(p),
                                  rmax*cos(t)))
        bound1 = Polyhedron(bpoints)

        if (rmin > 0.0):
            for i in xrange(nshell):
                bpoints[i] *= rmin/rmax
            bound2 = Polyhedron(bpoints)
        
        # The base generator does most of the work.
        MedialGeneratorBase.__init__(self,
                                     ndim = 3,
                                     n = n,
                                     rho = rho,
                                     boundary = bound1,
                                     gradrho = gradrho,
                                     holes = bound2 if (rmin>0.0) else [],
                                     centroidFrac = centroidFrac,
                                     maxIterations = maxIterations,
                                     fracTol = fracTol,
                                     tessellationBaseDir = tessellationBaseDir,
                                     tessellationFileName = tessellationFileName,
                                     nNodePerh = nNodePerh,
                                     randomseed = randomseed,
                                     maxNodesPerDomain = maxNodesPerDomain,
                                     seedPositions = seedPositions,
                                     enforceConstantMassPoints = enforceConstantMassPoints,
                                     cacheFileName = cacheFileName)
    
        # Convert to our now regrettable standard coordinate storage for generators.
        self.x = [x.x + offset[0] for x in self.pos]
        self.y = [x.y + offset[1] for x in self.pos]
        self.z = [x.z + offset[2] for x in self.pos]
        del self.pos
        
        # If the user provided a "rejecter", give it a pass
        # at the nodes.
        if rejecter:
            self.x, self.y, self.z, self.m, self.H, self.vol, self.surface = rejecter(self.x,
                                                                                      self.y,
                                                                                      self.z,
                                                                                      self.m,
                                                                                      self.H,
                                                                                      self.vol,
                                                                                      self.surface)

        # Initialize the base class, taking into account the fact we've already broken
        # up the nodes between domains.
        NodeGeneratorBase.__init__(self, False,
                                   self.x, self.y, self.z, self.m, self.H, self.vol, self.surface)
        return
Пример #4
0
    def __init__(self,
                 surface,
                 lconstant,
                 lextrude,
                 nextrude,
                 dltarget,
                 dstarget,
                 rho,
                 flags=None,
                 nNodePerh=2.01,
                 SPH=False):
        self.surface = surface
        surfaceFacets = surface.facets
        surfaceVertices = surface.vertices
        vertexNorms = surface.vertexUnitNorms
        facetNeighbors = surface.facetFacetConnectivity

        assert lconstant <= lextrude

        # Figure out the extent and resolution of the ratioed region.
        nconstant = int(lconstant / dltarget + 0.5)
        lratioed = lextrude - lconstant
        nratioed = nextrude - nconstant

        # Get the facets we need to extrude.
        if flags is None:
            facets = surfaceFacets
            realFacetIDs = range(len(facets))
            flags = [1] * len(facets)
        else:
            assert len(flags) == len(surfaceFacets)
            realFacetIDs = [
                fi for fi in xrange(len(surfaceFacets)) if (flags[fi] == 1)
            ]
            facets = [surfaceFacets[i] for i in realFacetIDs]

        # Find the maximum extent we need to use to cover the volumes of all extruded
        # facets.
        ymin, ymax, zmin, zmax = 1e200, -1e200, 1e200, -1e200
        for f in facets:
            nhat = f.normal
            T = rotationMatrix(nhat)
            p = f.position
            verts = [T * (surfaceVertices[i] - p) for i in f.ipoints]
            ymin = min(ymin, min([v.y for v in verts]))
            ymax = max(ymax, max([v.y for v in verts]))
            zmin = min(zmin, min([v.z for v in verts]))
            zmax = max(zmax, max([v.z for v in verts]))

        # Find the ratio needed for the spacing in the x direction.
        # We have to check for ratio=1 explicitly, since the series sum
        # doesn't work in that case.
        if abs(lratioed - nratioed * dltarget) < 1e-5 * lratioed:
            ratio = 1.0
            l = lratioed
            dx = dltarget
        else:
            stuff = [0.0] * (nratioed + 1)
            stuff[0:1] = [dltarget - lratioed, -lratioed]
            stuff[-1] = dltarget
            p = P(stuff, [1.0e-3, 1.0e10], [1.0e-3, 1.0e10])
            complex_ratio = p.roots()[-1]
            assert complex_ratio.imag == 0.0
            ratio = complex_ratio.real

            # Unfortunately the root finding above isn't 100% accurate, so we
            # adjust the initial step size to get the correct total length.
            l = dltarget * (1.0 - ratio**nratioed) / (1.0 - ratio)
            dx = dltarget  # * lratioed/l
        if mpi.rank == 0:
            print "FacetedSurfaceGenerator: selected ratio=%g, dxfirst=%g, l=%g." % (
                ratio, dx, l)

        # Build the template values we'll use to stamp into each facet volume.
        rt, mt, Ht = [], [], []
        dxi = dx
        xi = 0.5 * dx
        ix = -1
        while xi > -lextrude:
            ix += 1
            if ix < nconstant:
                dxi = dx  # lconstant/nconstant
            else:
                dxi = dx * ratio**(ix - nconstant)
            xi -= dxi
            ds = min(2.0 * dstarget, max(dstarget, dxi))
            ny = max(1, int((ymax - ymin) / ds + 0.5))
            nz = max(1, int((zmax - zmin) / ds + 0.5))
            dy = (ymax - ymin) / ny
            dz = (zmax - zmin) / nz
            for iy in xrange(ny):
                yi = ymin + (iy + 0.5) * dy
                for iz in xrange(nz):
                    zi = zmin + (iz + 0.5) * dz
                    rt.append(Vector(xi, yi, zi))
                    mt.append(rho * dxi * dy * dz)
                    Ht.append(
                        SymTensor(1.0 / (nNodePerh * dxi), 0.0, 0.0, 0.0,
                                  1.0 / (nNodePerh * dy), 0.0, 0.0, 0.0,
                                  1.0 / (nNodePerh * dz)))
        if mpi.rank == 0:
            print "FacetedSurfaceGenerator: built template block of %i points per facet." % len(
                rt)

        # Figure out a crude partitioning of the facets between processors.
        if len(facets) > mpi.procs:
            ndomain0 = len(facets) / mpi.procs
            remainder = len(facets) % mpi.procs
            assert remainder < mpi.procs
            ndomain = ndomain0
            if mpi.rank < remainder:
                ndomain += 1
            imin = mpi.rank * ndomain0 + min(mpi.rank, remainder)
            imax = imin + ndomain
        else:
            if mpi.rank < len(facets):
                imin = mpi.rank
                imax = imin + 1
            else:
                imin = 0
                imax = 0

        # We need all the extruded facet polyhedra.  In general these may be intersecting!
        print "FacetedSurfaceGenerator: building extruded facets..."
        self.extrudedFacets, localExtrudedFacets = [], []
        for i in xrange(imin, imax):
            f = facets[i]
            p = f.position
            verts = vector_of_Vector()
            for ip in f.ipoints:
                fphat = (p - surfaceVertices[ip]).unitVector()
                vi = surfaceVertices[ip] + fphat * 0.05 * dstarget
                verts.append(vi)
                verts.append(vi - vertexNorms[ip] * lextrude)
            localExtrudedFacets.append(Polyhedron(verts))  # Better be convex!
        for i in xrange(mpi.procs):
            self.extrudedFacets.extend(mpi.bcast(localExtrudedFacets, i))
        assert len(self.extrudedFacets) == len(facets)

        # Now walk the facets and build our values.
        print "FacetedSurfaceGenerator: seeding points..."
        self.x, self.y, self.z, self.m, self.H, self.nodes2facets = [], [], [], [], [], []
        for i in xrange(imin, imax):
            f = facets[i]
            fi = realFacetIDs[i]
            neighbors = facetNeighbors[fi]
            p = f.position
            nhat = f.normal
            T = rotationMatrix(nhat)
            Ti = T.Transpose()
            for j in xrange(len(rt)):
                rj = Ti * rt[j] + p
                if self.extrudedFacets[i].contains(
                        rj):  # and surface.contains(rj):
                    stuff = [(surfaceFacets[k].distance(rj), k)
                             for k in neighbors if flags[k] == 1]
                    stuff.sort()
                    if stuff[0][1] == fi:
                        self.x.append(rj.x)
                        self.y.append(rj.y)
                        self.z.append(rj.z)
                        self.m.append(mt[j])
                        self.H.append(SymTensor(Ht[j]))
                        self.H[-1].rotationalTransform(Ti)
                        self.nodes2facets.append(fi)
        self.rho = [rho] * len(self.x)

        # Invoke the base class to finish up.
        NodeGeneratorBase.__init__(self, False, self.x, self.y, self.z, self.m,
                                   self.H, self.rho, self.nodes2facets)

        return