Пример #1
0
def test_no_duplicates():
    def sphere(x, y, z):
        return np.sqrt((x - 4)**2 + (y - 4)**2 + (z - 4)**2) - 4

    vertices, _ = mcubes.marching_cubes_func((2, 2, 2), (9, 9, 9), 20, 20, 20,
                                             sphere, 0)

    assert len(vertices) == len(np.unique(vertices, axis=0))
Пример #2
0
def sphere2():
    # Create the volume
    f = lambda x, y, z: x**2 + y**2 + z**2

    # Extract the 16-isosurface
    vertices, triangles = mcubes.marching_cubes_func((-10,-10,-10), (10,10,10),100, 100, 100, f, 16)

    # Export the result to sphere2.dae
    mcubes.export_mesh(vertices, triangles, "sphere2.dae", "MySphere")
Пример #3
0
def evaluate(dimX,dimY,dimZ):
    vertices, triangles = mcubes.marching_cubes_func(
            (boundingArea['minX'],boundingArea['minY'],boundingArea['minZ']), 
            (boundingArea['maxX'], boundingArea['maxY'], boundingArea['maxZ']),  # Bounds
            dimX, dimY, dimZ,                                                    # Number of samples in each dimension
            implicit,                                                            # Implicit function
            0)                                                                   # Isosurface value                                                                

    # Export the result to sphere2.dae
    mcubes.export_mesh(vertices, triangles, "/Users/Emscape/Documents/Blender Projects/result.dae", "MLS result")
    print("Done. Result saved in 'result.dae'.")
Пример #4
0
def test_invalid_input():
    def func(x, y, z):
        return x**2 + y**2 + z**2 - 1

    mcubes.marching_cubes_func((-1.5, -1.5, -1.5), (1.5, 1.5, 1.5), 10, 10, 10,
                               func, 0)

    with pytest.raises(ValueError):
        mcubes.marching_cubes_func((0, 0, 0), (0, 0, 0), 10, 10, 10, func, 0)

    with pytest.raises(ValueError):
        mcubes.marching_cubes_func((-1.5, -1.5, -1.5), (1.5, 1.5, 1.5), 1, 10,
                                   10, func, 0)

    with pytest.raises(Exception):
        mcubes.marching_cubes_func((-1.5, -1.5), (1.5, 1.5, 1.5), 10, 10, 10,
                                   func, 0)

    with pytest.raises(Exception):
        mcubes.marching_cubes_func((-1.5, -1.5, -1.5), (1.5, 1.5), 10, 10, 10,
                                   func, 0)
Пример #5
0
def test_sphere():
    x, y, z = np.mgrid[:100, :100, :100]
    u = (x - 50)**2 + (y - 50)**2 + (z - 50)**2 - 25**2

    def func(x, y, z):
        return (x - 50)**2 + (y - 50)**2 + (z - 50)**2 - 25**2

    vertices1, triangles1 = mcubes.marching_cubes(u, 0.0)
    vertices2, triangles2 = mcubes.marching_cubes_func(
        (0, 0, 0), (99, 99, 99), 100, 100, 100, func, 0.0)

    assert_allclose(vertices1, vertices2)
    assert_array_equal(triangles1, triangles2)
Пример #6
0
def main():
    logging.info("Example 2: Isosurface in Python function...")
    logging.info("(this might take a while...)")
    samples = 200
    bounds = 8
    t = time.time()
    # Extract the 16-isosurface
    vertices, triangles = mcubes.marching_cubes_func(
        (-0, -0, -0),
        (bounds, bounds, bounds),
        samples, samples, samples,
        f,  # Implicit function
        16)  # Isosurface value
    logging.info("mesh completed in %f seconds" % (time.time() - t))

    logging.debug("vertices: {} length: {}".format(type(vertices), len(vertices)))
    logging.debug(vertices)
    logging.debug("triangles: {} length: {}".format(type(triangles), len(triangles)))
    logging.debug(triangles)

    meshexport.export(vertices, triangles)
Пример #7
0
    def get_plot(self, var, value, plottype, colorscale="Viridis", sym="F", log="F", vmin="", vmax=""):
        '''
        Return a plotly figure object for the plottype requested.
        var, value, and plottype are required variables.
        -var = name of plot variable
        -value = position of slice or isosurface value
        -plottype = 2D-alt, 2D-lon, 2D-lat, 3D-alt, iso
        -colorscale = Viridis [default], Cividis, Rainbow, or BlueRed
        -sym = F [default] for symetric colorscale around 0
        -log = F [default] for log10() of plot value
        -vmin,vmax = minimum and maximum value for contour values, empty is min/max
        '''

        # Common code blocks for all plots
        txtbot = "Model: GITM v" + str(self.codeversion) + ",  Run: " + self.runname
        units=self.variables[var]['units']
        txtbar = var + " [" + units + "]"
        time=self.dtvalue.strftime("%Y/%m/%d %H:%M:%S UT")

        if plottype == "2D-alt":
            # Check if altitude entered is valid
            if value < self.altmin or value > self.altmax:
                print('Altitude is out of range: alt=',value,\
                      ' min/max=',self.altmin,'/',self.altmax)
                return

            # Set grid for plot
            altkm=value/1000.
            ilon = np.linspace(0, 360, 361)
            ilat = np.linspace(-90, 90, 181)
            ialt = np.array([value])
            xx, yy = np.meshgrid(np.array(ilon), np.array(ilat))
            grid = np.ndarray(shape=(np.size(np.reshape(xx,-1)),3), dtype=np.float32)
            grid[:,0] = np.reshape(xx,-1)
            grid[:,1] = np.reshape(yy,-1)
            grid[:,2] = value
            test = self.variables[var]['interpolator'](grid)
            result = np.reshape(test,(ilat.shape[0],ilon.shape[0]))
            if log == "T":
                txtbar = "log<br>"+txtbar
                result = np.log10(result)
            if sym == "T":
                cmax = np.max(np.absolute(result))
                if vmax != "":
                    cmax = abs(float(vmax))
                if vmin != "":
                    cmax = max(cmax,abs(float(vmin)))
                cmin = -cmax
            else:
                cmax = np.max(result)
                cmin = np.min(result)
                if vmax != "":
                    cmax = float(vmax)
                if vmin != "":
                    cmin = float(vmin)

            def plot_var(lon = ilon, lat = ilat):
                return result
            plotvar = Kamodo(plot_var = plot_var)

            fig = plotvar.plot(plot_var = dict())
            #fig.update_xaxes(nticks=7,title_text="",scaleanchor='y')
            fig.update_xaxes(tick0=0.,dtick=45.,title_text="")
            fig.update_yaxes(tick0=0.,dtick=45,title_text="")
            if colorscale == "BlueRed":
                fig.update_traces(colorscale="RdBu", reversescale=True)
            elif colorscale == "Rainbow":
                fig.update_traces(
                    colorscale=[[0.00, 'rgb(0,0,255)'],
                                [0.25, 'rgb(0,255,255)'],
                                [0.50, 'rgb(0,255,0)'],
                                [0.75, 'rgb(255,255,0)'],
                                [1.00, 'rgb(255,0,0)']]
                )
            else:
                fig.update_traces(colorscale=colorscale)
            fig.update_traces(
                zmin=cmin, zmax=cmax,
                ncontours=201,
                colorbar=dict(title=txtbar, tickformat=".3g"),
                contours=dict(coloring="fill", showlines=False)
            )
            if log == "T":
                fig.update_traces(
                    hovertemplate="Lon: %{x:.0f}<br>Lat: %{y:.0f}<br><b>log("+var+"): %{z:.4g}</b><extra></extra>"
                )
            else:
                fig.update_traces(
                    hovertemplate="Lon: %{x:.0f}<br>Lat: %{y:.0f}<br><b>"+var+": %{z:.4g}</b><extra></extra>"
                )                
            fig.update_layout(
                title=dict(text="Altitude="+"{:.0f}".format(altkm)+" km,  Time = " + time,
                           yref="container", yanchor="top", y=0.95),
                title_font_size=16,
                annotations=[
                    dict(text="Lon [degrees]", x=0.5, y=-0.13, showarrow=False,
                         xref="paper", yref="paper", font=dict(size=12)),
                    dict(text="Lat [degrees]", x=-0.1, y=0.5, showarrow=False,
                         xref="paper", yref="paper", font=dict(size=12), textangle=-90),
                    dict(text=txtbot, x=0.0, y=0.0, ax=0, ay=0, xanchor="left",
                         xshift=-65, yshift=-42, xref="paper", yref="paper",
                         font=dict(size=16, family="sans serif", color="#000000"))
                ],
                height=340
            )
            return fig

        if plottype == "2D-lat":
            # Check if latitude entered is valid
            if value < -90. or value > 90.:
                print('Latitude is out of range: lat=',value,' min/max= -90./90.')
                return

            # Set grid for plot
            ilon = np.linspace(0, 360, 361)
            ilat = np.array([value])
            ialt = np.linspace(self.altmin, self.altmax, 300)
            xx, yy = np.meshgrid(np.array(ilon), np.array(ialt))
            grid = np.ndarray(shape=(np.size(np.reshape(xx,-1)),3), dtype=np.float32)
            grid[:,0] = np.reshape(xx,-1)
            grid[:,1] = value
            grid[:,2] = np.reshape(yy,-1)
            test = self.variables[var]['interpolator'](grid)
            result = np.reshape(test,(ialt.shape[0],ilon.shape[0]))
            if log == "T":
                txtbar = "log<br>"+txtbar
                result = np.log10(result)
            if sym == "T" and vmin == "" and vmax == "":
                cmax = np.max(np.absolute(result))
                cmin = -cmax
            else:
                cmax = np.max(result)
                cmin = np.min(result)
                if vmax != "":
                    cmax = float(vmax)
                if vmin != "":
                    cmin = float(vmin)

            ialt = ialt/1000.
            def plot_var(lon = ilon, alt = ialt):
                return result
            plotvar = Kamodo(plot_var = plot_var)

            fig = plotvar.plot(plot_var = dict())
            #fig.update_xaxes(nticks=7,title_text="",scaleanchor='y')
            fig.update_xaxes(tick0=0.,dtick=45.,title_text="")
            fig.update_yaxes(title_text="")
            if colorscale == "BlueRed":
                fig.update_traces(colorscale="RdBu", reversescale=True)
            elif colorscale == "Rainbow":
                fig.update_traces(
                    colorscale=[[0.00, 'rgb(0,0,255)'],
                                [0.25, 'rgb(0,255,255)'],
                                [0.50, 'rgb(0,255,0)'],
                                [0.75, 'rgb(255,255,0)'],
                                [1.00, 'rgb(255,0,0)']]
                )
            else:
                fig.update_traces(colorscale=colorscale)
            fig.update_traces(
                zmin=cmin, zmax=cmax,
                ncontours=201,
                colorbar=dict(title=txtbar, tickformat=".3g"),
                contours=dict(coloring="fill", showlines=False)
            )
            if log == "T":
                fig.update_traces(
                    hovertemplate="Lon: %{x:.0f}<br>Alt: %{y:.0f}<br><b>log("+var+"): %{z:.4g}</b><extra></extra>"
                )
            else:
                fig.update_traces(
                    hovertemplate="Lon: %{x:.0f}<br>Alt: %{y:.0f}<br><b>"+var+": %{z:.4g}</b><extra></extra>"
                )                
            fig.update_layout(
                title=dict(text="Latitude="+"{:.1f}".format(value)+" degrees,  Time = " + time,
                           yref="container", yanchor="top", y=0.95),
                title_font_size=16,
                annotations=[
                    dict(text="Lon [degrees]", x=0.5, y=-0.13, showarrow=False,
                         xref="paper", yref="paper", font=dict(size=12)),
                    dict(text="Altitude [km]", x=-0.1, y=0.5, showarrow=False,
                         xref="paper", yref="paper", font=dict(size=12), textangle=-90),
                    dict(text=txtbot, x=0.0, y=0.0, ax=0, ay=0, xanchor="left",
                         xshift=-65, yshift=-42, xref="paper", yref="paper",
                         font=dict(size=16, family="sans serif", color="#000000"))
                ],
                height=340
            )
            return fig

        if plottype == "2D-lon":
            # Check if longitude entered is valid
            if value < 0. or value > 360.:
                print('Latitude is out of range: lat=',value,' min/max= 0./360.')
                return

            # Set grid for plot
            ilon = np.array([value])
            ilat = np.linspace(-90, 90, 181)
            ialt = np.linspace(self.altmin, self.altmax, 300)
            xx, yy = np.meshgrid(np.array(ilat), np.array(ialt))
            grid = np.ndarray(shape=(np.size(np.reshape(xx,-1)),3), dtype=np.float32)
            grid[:,0] = value
            grid[:,1] = np.reshape(xx,-1)
            grid[:,2] = np.reshape(yy,-1)
            test = self.variables[var]['interpolator'](grid)
            result = np.reshape(test,(ialt.shape[0],ilat.shape[0]))
            if log == "T":
                txtbar = "log<br>"+txtbar
                result = np.log10(result)
            if sym == "T" and vmin == "" and vmax == "":
                cmax = np.max(np.absolute(result))
                cmin = -cmax
            else:
                cmax = np.max(result)
                cmin = np.min(result)
                if vmax != "":
                    cmax = float(vmax)
                if vmin != "":
                    cmin = float(vmin)

            ialt = ialt/1000.
            def plot_var(lat = ilat, alt = ialt):
                return result
            plotvar = Kamodo(plot_var = plot_var)

            fig = plotvar.plot(plot_var = dict())
            #fig.update_xaxes(nticks=7,title_text="",scaleanchor='y')
            fig.update_xaxes(tick0=0.,dtick=30.,title_text="")
            fig.update_yaxes(title_text="")
            if colorscale == "BlueRed":
                fig.update_traces(colorscale="RdBu", reversescale=True)
            elif colorscale == "Rainbow":
                fig.update_traces(
                    colorscale=[[0.00, 'rgb(0,0,255)'],
                                [0.25, 'rgb(0,255,255)'],
                                [0.50, 'rgb(0,255,0)'],
                                [0.75, 'rgb(255,255,0)'],
                                [1.00, 'rgb(255,0,0)']]
                )
            else:
                fig.update_traces(colorscale=colorscale)
            fig.update_traces(
                zmin=cmin, zmax=cmax,
                ncontours=201,
                colorbar=dict(title=txtbar, tickformat=".3g"),
                contours=dict(coloring="fill", showlines=False)
            )
            if log == "T":
                fig.update_traces(
                    hovertemplate="Lat: %{x:.0f}<br>Alt: %{y:.0f}<br><b>log("+var+"): %{z:.4g}</b><extra></extra>"
                )
            else:
                fig.update_traces(
                    hovertemplate="Lat: %{x:.0f}<br>Alt: %{y:.0f}<br><b>"+var+": %{z:.4g}</b><extra></extra>"
                )                
            fig.update_layout(
                title=dict(text="Longitude="+"{:.1f}".format(value)+" degrees,  Time = " + time,
                           yref="container", yanchor="top", y=0.95),
                title_font_size=16,
                annotations=[
                    dict(text="Lat [degrees]", x=0.5, y=-0.13, showarrow=False,
                         xref="paper", yref="paper", font=dict(size=12)),
                    dict(text="Altitude [km]", x=-0.1, y=0.5, showarrow=False,
                         xref="paper", yref="paper", font=dict(size=12), textangle=-90),
                    dict(text=txtbot, x=0.0, y=0.0, ax=0, ay=0, xanchor="left",
                         xshift=-65, yshift=-42, xref="paper", yref="paper",
                         font=dict(size=16, family="sans serif", color="#000000"))
                ],
                height=340
            )
            return fig

        if plottype == "3D-alt":
            # Check if altitude entered is valid
            if value < self.altmin or value > self.altmax:
                print('Altitude is out of range: alt=',value,\
                      ' min/max=',self.altmin,'/',self.altmax)
                return

            # Set grid for plot
            altkm=value/1000.
            ilon = np.linspace(0, 360, 361)
            ilat = np.linspace(-90, 90, 181)
            ialt = np.array([value])
            xx, yy = np.meshgrid(np.array(ilon), np.array(ilat))
            grid = np.ndarray(shape=(np.size(np.reshape(xx,-1)),3), dtype=np.float32)
            grid[:,0] = np.reshape(xx,-1)
            grid[:,1] = np.reshape(yy,-1)
            grid[:,2] = value
            test = self.variables[var]['interpolator'](grid)
            result = np.reshape(test,(ilat.shape[0],ilon.shape[0]))
            if log == "T":
                txtbar = "log<br>"+txtbar
                result = np.log10(result)
            r = value + 6.3781E6
            x=-(r*np.cos(yy*np.pi/180.)*np.cos(xx*np.pi/180.))/6.3781E6
            y=-(r*np.cos(yy*np.pi/180.)*np.sin(xx*np.pi/180.))/6.3781E6
            z= (r*np.sin(yy*np.pi/180.))/6.3781E6
            if sym == "T" and vmin == "" and vmax == "":
                cmax = np.max(np.absolute(result))
                cmin = -cmax
            else:
                cmax = np.max(result)
                cmin = np.min(result)
                if vmax != "":
                    cmax = float(vmax)
                if vmin != "":
                    cmin = float(vmin)

            def plot_var(x = x, y = y, z = z):
                return result
            plotvar = Kamodo(plot_var = plot_var)

            fig = plotvar.plot(plot_var = dict())
            fig.update_scenes(xaxis=dict(title=dict(text="X [Re]")),
                              yaxis=dict(title=dict(text="Y [Re]")),
                              zaxis=dict(title=dict(text="Z [Re]")))
            if colorscale == "BlueRed":
                fig.update_traces(colorscale="RdBu", reversescale=True)
            elif colorscale == "Rainbow":
                fig.update_traces(
                    colorscale=[[0.00, 'rgb(0,0,255)'],
                                [0.25, 'rgb(0,255,255)'],
                                [0.50, 'rgb(0,255,0)'],
                                [0.75, 'rgb(255,255,0)'],
                                [1.00, 'rgb(255,0,0)']]
                )
            else:
                fig.update_traces(colorscale=colorscale)
            fig.update_traces(
                cmin=cmin, cmax=cmax,
                colorbar=dict(title=txtbar, tickformat=".3g")
            )
            fig.update_traces(
                hovertemplate="X [Re]: %{x:.3f}<br>Y [Re]: %{y:.3f}<br>Z [Re]: %{z:.3f}<extra></extra>"
            )
            fig.update_layout(
                title=dict(text="Altitude="+"{:.0f}".format(altkm)+" km,  Time = " + time,
                           yref="container", yanchor="top", x=0.01, y=0.95),
                title_font_size=16,
                annotations=[
                    dict(text=txtbot, x=0.0, y=0.0, ax=0, ay=0, xanchor="left",
                         xshift=0, yshift=-20, xref="paper", yref="paper",
                         font=dict(size=16, family="sans serif", color="#000000"))
                ],
                margin=dict(l=0),
                width=600
            )
            x1=[0., 0.]
            y1=[0., 0.]
            z1=[-1.2, 1.2]
            fig.add_scatter3d(mode='lines',x=x1,y=y1,z=z1,line=dict(width=4,color='black'),
                              showlegend=False,hovertemplate='Polar Axis<extra></extra>')
            r = value + 10000. + 6.3781E6
            x2=-(r*np.cos(ilon*np.pi/180.))/6.3781E6
            y2=-(r*np.sin(ilon*np.pi/180.))/6.3781E6
            z2=0.*ilon
            fig.add_scatter3d(mode='lines',x=x2,y=y2,z=z2,line=dict(width=2,color='black'),
                              showlegend=False,hovertemplate='Equator<extra></extra>')
            x3=-(r*np.cos(ilat*np.pi/180.))/6.3781E6
            y3=0.*ilat
            z3=(r*np.sin(ilat*np.pi/180.))/6.3781E6
            fig.add_scatter3d(mode='lines',x=x3,y=y3,z=z3,line=dict(width=2,color='black'),
                              showlegend=False,hovertemplate='prime meridian<extra></extra>')
            return fig

        if plottype == "iso":
            # Check if value entered is valid (checking before possible log scale)
            cmin=np.min(self.variables[var]['data'])
            cmax=np.max(self.variables[var]['data'])
            if value < cmin or value > cmax:
                print('Iso value is out of range: iso=',value,' min/max=',cmin,cmax)
                sys.exit("Exiting ...")
                return

            # Determine altitude start, stop, number for use in isosurface
            step=10000. # 10000. m altitude step size
            alt1=(step*round(self.alt[2]/step))
            alt2=self.alt[(self.alt.shape[0]-3)]
            nalt=round((alt2-alt1)/step)
            alt2=alt1+step*nalt
            nalt=1+int(nalt)
            
            # Set function for interpolation
            gridp = np.ndarray(shape=(1,3), dtype=np.float32)
            def finterp(x,y,z):
                gridp[0,:] = [x,y,z]
                return self.variables[var]['interpolator'](gridp)

            # Extract the isosurface as vertices and triangulated connectivity
            import mcubes
            verts, tri = mcubes.marching_cubes_func(
                (0, -90, alt1), (360, 90, alt2),  # Bounds (min:x,y,z), (max:x,y,z)
                73, 37, nalt,                     # Number of samples in each dimension
                finterp,                          # Implicit function of x,y,z
                value)                            # Isosurface value

            # Process output for creating plots, including face or vertex colors
            X, Y, Z = verts[:,:3].T
            I, J, K = tri.T
            
            # Update cmin, cmax for log, sym, vmin, vmax values if set
            if sym == "T":
                if vmax != "":
                    cmax = abs(float(vmax))
                if vmin != "":
                    cmax = max(cmax,abs(float(vmin)))
                cmin = -cmax
            else:
                if vmax != "":
                    cmax = float(vmax)
                if vmin != "":
                    cmin = float(vmin)
            dvalue=value
            if log == "T":
                dvalue=np.log10(value)
                cmin=np.log10(cmin)
                cmax=np.log10(cmax)
                txtbar = "log<br>"+txtbar
            
            # Create fig and update with modifications to customize plot
            fig=go.Figure(data=[go.Mesh3d(
                name='ISO',
                x=X,
                y=Y,
                z=Z,
                i=I,
                j=J,
                k=K,
                intensity=np.linspace(dvalue,dvalue,X.shape[0]),
                cmin=cmin, cmax=cmax,
                showscale=True,
                opacity=0.6,
                colorbar=dict(title=txtbar, tickformat=".3g"),
                hovertemplate="Isosurface<br>"+var+"="+"{:.3g}".format(value)+" "+units+"<br><extra></extra>",
            )])
            if colorscale == "BlueRed":
                fig.update_traces(colorscale="RdBu", reversescale=True)
            elif colorscale == "Rainbow":
                fig.update_traces(
                    colorscale=[[0.00, 'rgb(0,0,255)'],
                                [0.25, 'rgb(0,255,255)'],
                                [0.50, 'rgb(0,255,0)'],
                                [0.75, 'rgb(255,255,0)'],
                                [1.00, 'rgb(255,0,0)']]
                )
            else:
                fig.update_traces(colorscale=colorscale)
            fig.update_scenes(
                xaxis=dict(title=dict(text="Lon [degrees]"),tick0=0.,dtick=45.),
                yaxis=dict(title=dict(text="Lat [degrees]"),tick0=0.,dtick=45.),
                zaxis=dict(title=dict(text="Alt [km]"))
            )
            fig.update_layout(
                scene_camera_eye=dict(x=.1, y=-1.8, z=1.5),
                scene_aspectmode='manual',
                scene_aspectratio=dict(x=2, y=1, z=1),
                scene_xaxis=dict(range=[0,360]),
                scene_yaxis=dict(range=[-90,90]),
                scene_zaxis=dict(range=[alt1,alt2]),
                title=dict(text="Isosurface of "+var+"="+\
                           "{:.3g}".format(value)+" "+units+"<br>"+"Time = "+time,
                           yref="container", yanchor="top", x=0.01, y=0.95),
                title_font_size=16,
                annotations=[
                    dict(text=txtbot, x=0.0, y=0.0, ax=0, ay=0, xanchor="left",
                         xshift=0, yshift=-20, xref="paper", yref="paper",
                         font=dict(size=16, family="sans serif", color="#000000"))
                ],
                margin=dict(l=10,t=80),
            )
            
            return fig

        if plottype == "iso1":
            # This method keeps all the data local, resulting in huge storage
            #   as well as corrupted html divs.
            
            ilon = np.linspace(0, 360, 73) #181
            ilat = np.linspace(-90, 90, 37) #91
            step=10000. # 5000.
            alt1=(step*round(self.alt[2]/step))
            alt2=self.alt[(self.alt.shape[0]-3)]
            nalt=round((alt2-alt1)/step)
            alt2=alt1+step*nalt
            nalt=1+int(nalt)
            ialt = np.linspace(alt1, alt2, nalt)
            xx,yy,zz = np.meshgrid(np.array(ilon),np.array(ilat),np.array(ialt))
            grid = np.ndarray(shape=(np.size(np.reshape(xx,-1)),3), dtype=np.float32)
            grid[:,0] = np.reshape(xx,-1)
            grid[:,1] = np.reshape(yy,-1)
            grid[:,2] = np.reshape(zz,-1)
            test = self.variables[var]['interpolator'](grid)
            result = np.reshape(test,(ilat.shape[0],ilon.shape[0],ialt.shape[0]))
            isovalue=value
            if log == "T":
                isovalue=np.log10(value)
                txtbar = "log<br>"+txtbar
                result = np.log10(result)
            if sym == "T":
                cmax = np.max(np.absolute(result))
                if vmax != "":
                    cmax = abs(float(vmax))
                if vmin != "":
                    cmax = max(cmax,abs(float(vmin)))
                cmin = -cmax
            else:
                cmax = np.max(result)
                cmin = np.min(result)
                if vmax != "":
                    cmax = float(vmax)
                if vmin != "":
                    cmin = float(vmin)

            # Check if value entered is valid (checking before possible log scale)
            if value < np.min(test) or value > np.max(test):
                print('Iso value is out of range: iso=',value,\
                      ' min/max=',np.min(test),'/',np.max(test))
                sys.exit("Exiting ...")
                return

            slicevalue=0.
            fig1 = go.Figure(data=go.Isosurface(
                x=xx.flatten(),
                y=yy.flatten(),
                z=zz.flatten()/1000.,
                value=result.flatten(),
                opacity=0.6,
                isomin=cmin,
                isomax=cmax,
                surface=dict(count=2, fill=1., pattern='all'),
                caps=dict(x_show=False, y_show=False, z_show=False),
                showscale=True, # show colorbar
                colorbar=dict(title=txtbar, tickformat=".3g"),
                slices_y=dict(show=True, locations=[slicevalue]),
            ))
            fig1.update_traces(
                hovertemplate="<b>Slice</b><br>Lon: %{x:.0f}<br>Lat: %{y:.0f}<br>Alt: %{z:.0f}km<br><extra></extra>"
            )
            if colorscale == "BlueRed":
                fig1.update_traces(colorscale="RdBu", reversescale=True)
            elif colorscale == "Rainbow":
                fig1.update_traces(
                    colorscale=[[0.00, 'rgb(0,0,255)'],
                                [0.25, 'rgb(0,255,255)'],
                                [0.50, 'rgb(0,255,0)'],
                                [0.75, 'rgb(255,255,0)'],
                                [1.00, 'rgb(255,0,0)']]
                )
            else:
                fig1.update_traces(colorscale=colorscale)
            fig2 = go.Figure(data=go.Isosurface(
                x=xx.flatten(),
                y=yy.flatten(),
                z=zz.flatten()/1000.,
                value=result.flatten(),
                opacity=1.,
                colorscale=[[0.0, '#777777'],[1.0, '#777777']],
                isomin=isovalue,
                isomax=isovalue,
                surface=dict(count=1, fill=1., pattern='all'),
                caps=dict(x_show=False, y_show=False, z_show=False),
                showscale=False, # remove colorbar
                hovertemplate="<b>Isosurface</b><br>Lon: %{x:.0f}<br>Lat: %{y:.0f}<br>Alt: %{z:.0f}km<extra></extra>"
            ))
            fig2.update_scenes(
                xaxis=dict(title=dict(text="Lon [degrees]"),tick0=0.,dtick=45.),
                yaxis=dict(title=dict(text="Lat [degrees]"),tick0=0.,dtick=45.),
                zaxis=dict(title=dict(text="Alt [km]"))
            )
            fig2.update_layout(
                scene_camera_eye=dict(x=.1, y=-1.8, z=1.5),
                scene_aspectmode='manual',
                scene_aspectratio=dict(x=2, y=1, z=1),
                title=dict(text="Latitude="+"{:.0f}".format(slicevalue)+
                           " slice through the data<br>"+
                           "Isosurface of "+var+"="+"{:.0f}".format(isovalue)+units+"<br>"+
                           "Time = " + time,
                           yref="container", yanchor="top", x=0.01, y=0.95),
                title_font_size=16,
                annotations=[
                    dict(text=txtbot, x=0.0, y=0.0, ax=0, ay=0, xanchor="left",
                         xshift=0, yshift=-20, xref="paper", yref="paper",
                         font=dict(size=16, family="sans serif", color="#000000"))
                ],
                margin=dict(l=10,t=80),
            )
            fig2.add_trace(fig1.data[0])
            
            return fig2

        print('Unknown plottype (',plottype,') returning.')
        return
Пример #8
0
print("Example 2: Isosurface in Python function...")
print("(this might take a while...)")

# Create the volume


def f(x, y, z):
    return x**2 + y**2 + z**2


# Extract the 16-isosurface
vertices2, triangles2 = mcubes.marching_cubes_func(
    (-10, -10, -10),
    (10, 10, 10),  # Bounds
    100,
    100,
    100,  # Number of samples in each dimension
    f,  # Implicit function
    16)  # Isosurface value

# Export the result to sphere2.dae
mcubes.export_mesh(vertices2, triangles2, "sphere2.dae", "MySphere")
print("Done. Result saved in 'sphere2.dae'.")

try:
    print("Plotting mesh...")
    from mayavi import mlab
    mlab.triangular_mesh(vertices1[:, 0], vertices1[:, 1], vertices1[:, 2],
                         triangles1)
    print("Done.")
    mlab.show()
out triangles s
"""

import numpy as np
import sys
mcubes_path = r"/usr/local/lib/python3.5/dist-packages"  #it depend on your OS but just paste the path where is scipy
if not mcubes_path in sys.path:
    sys.path.append(mcubes_path)
import mcubes
import math


# Create the volume
def f(x, y, z):
    res = ((x - factor) * (x - factor) + y * y + z * z - 1) * (
        (x + factor) * (x + factor) + y * y + z * z - 1) - 0.3
    return res


# Extract the 16-isosurface
verts, tri = mcubes.marching_cubes_func(
    (-bounds, -bounds, -bounds),
    (bounds, bounds, bounds),  # Bounds
    samples,
    samples,
    samples,  # Number of samples in each dimension
    f,  # Implicit function
    iso_val)  # Isosurface value

vertices, triangles = [verts.tolist()], [tri.tolist()]
Пример #10
0
def main(context):

#1. Dimension of bounding box of object (USED TO SAMPLE 3D GRID)  #
##################################################    #


    #1. HERE THE BOUNDARIES OF THE OBJECT ARE COMPUTED ---
    name = context.active_object.data.name


    xDimensionsHalve = bpy.data.objects[name].dimensions.x/2  
    xMin = 0 - xDimensionsHalve
    xMax = 0 + xDimensionsHalve

    yDimensionsHalve = bpy.data.objects[name].dimensions.y/2
    yMin = 0 - yDimensionsHalve
    yMax = 0 + yDimensionsHalve

    zDimensionsHalve = bpy.data.objects[name].dimensions.z/2
    zMin = 0 - zDimensionsHalve
    zMax = 0 + zDimensionsHalve



#2. COMPUTE MLS FUNCTION ##########################   #
##################################################    #

    #0. Define Help functions:
    #
    #Wendland weight function
    def Wendland ( r , h ):
         return (1 - r/h)**4*(4*r/h+1)

    #b^T for degree 0, 1 or 2.
    def ChooseB (degree, point):
        x = point[0]
        y = point[1]
        z = point[2]
        if degree == 0:
             A = np.matrix([[1]])        
        elif degree == 1:
             A = np.matrix([[1],  [x], [y], [z], [x*y], [x*z], [y*z], [x*y*z]])
        elif degree == 2:
             A = np.matrix([[1], [x], [y], [z], [x**2], [y**2], [z**2], [x*y], [x*z], [y*z], [x**2*y], [x**2*z], [x*y**2], [x*z**2], [y**2*z], [y*z**2], [x*y*z], [x**2*y*z], [x*y**2*z], [x*y*z**2], [x**2*y**2], [x**2*z**2], [y**2*z**2], [x**2*y**2*z], [x**2*y*z**2], [x*y**2*z**2], [x**2*y**2*z**2]])
        return np.transpose(A)

    #Checks whether a point P is within a range of the given point C
    #which in 3D means is within the sphere with C as its center and the specified
    #, range as its radius
    def insideSphere(C, R, P):
        return ( P[0]- C[0] ) ** 2 + (P[1]- C[1]) ** 2 + (P[2]-C[2]) ** 2 < R**2 

    #Gets the appropriate length that matches to a degree k
    def matchingLengthofDegreeK(k):
        if k == 0:
             l = 1
        elif k == 1:
             l = 8
        elif k == 2:
             l = 27
        return l  

    #Can be used for visualization purposes
    def makeMaterial(name, diffuse, specular, alpha):
        mat = bpy.data.materials.new(name)
        mat.diffuse_color = diffuse
        mat.diffuse_shader = 'LAMBERT'
        mat.diffuse_intensity = 1.0
        return mat

    def setMaterial(ob, mat):
        me = ob.data
        me.materials.append(mat)

    #1. SETUP EPSILON, POINTCLOUD POINTS (FIRST n POINTS), POINTCLOUD POINT NORMALS and N (NECESSARY VARIABLES FOR COMPUTING CONSTRAINT POINTS), POINTCLOUD CENTER --- 
    #
    #Computes N (amount of points in pointCloud)
    PointCloud_points = []
    PointCloud_points  = context.active_object.data.vertices
    N = len(PointCloud_points )

    #Computes Normals of point cloud points
    PointCloud_point_normals = []
    for n in context.active_object['vertex_normal_list']:
        PointCloud_point_normals.append(np.array([n[0], n[1], n[2]]))


    #Fixes an ε value, for instance ε = 0.01 times the diagonal of the bounding box to the object. EXPERIMENTABLE PARAMETER
    v1 =  np.array((xMin, yMin,zMax))
    v2 =  np.array((xMax, yMax,zMin))
    diagonalOfBoundingBox = np.linalg.norm(v1-v2)
    epsilon = 0.01 * diagonalOfBoundingBox

    #2. IMPLEMENT SPATIAL INDEX: KD-TREE ---
    #
    #Computes a Spatial Index: KD-TREE from the PointCloud_points
    #(for faster nearest neighborhood calculations)
    kd = mathutils.kdtree.KDTree(N)
    for index, point in enumerate(PointCloud_points):
        kd.insert(point.co, index)
        
    #Must have been called before using any of the kd.find methods.
    kd.balance()


    #Compute the origin of the axis aligned bounding box
    origin = mathutils.Vector((0,0,0))
    for index, point in enumerate(PointCloud_points):
         origin += point.co

    origin /= N 
    polyDegree = 0
    def MLS(x , y ,z):
                 P = np.array([x ,  y,  z])
                 #Get closest points Pi within wendland radius from P. EXPERIMENTABLE PARAMETER
                 wendlandRadius = diagonalOfBoundingBox/20
                 pointsWithinRange = kd.find_range(P, wendlandRadius)
                 numpyPointsWithinRange = []
                 redPoints = []
                 redPointsEpsilonValues = []
                 greenPoints = []
                 greenPointsEpsilonValues = []
                 for (co,index, dist) in pointsWithinRange:
                     Ni = PointCloud_point_normals[index]
                     pos = co
                     PiNumpy = np.array((pos[0], pos[1], pos[2]))
                     epsilonBackup = epsilon
                     result = PiNumpy + epsilonBackup*Ni  
                     #Range to look for closest points from Pi+N. EXPERIMENTABLE PARAMETER              
                     Range = diagonalOfBoundingBox/20
                     Pi_Not_Closest = True
                     #Change datatype of Pi, to make computations easier
                     Pi = pos 
                     #Check whether Pi is the closest point to Pi+N
                     while Pi_Not_Closest :
                         #Calculates distances between Pi+N = result and the points that are within a range distance from Pi+N
                         dist, closestPos = min([(np.linalg.norm(result - co), co) for (co,index, dist) in kd.find_range(result, Range)])
  
                         #If Pi is not the closest point to Pi+N, 
                         # divide ε by 2 and recompute pi+N until this is the case
                         if closestPos != Pi:
                             epsilonBackup /= 2
                             result = Pi + epsilonBackup * Ni
                         else:
                             Pi_Not_Closest = False
                             break    

                     #check whether the green and red point are within wendlandRadius of P  
                     if insideSphere(C = P, R = wendlandRadius, P = result - 2*(epsilonBackup * Ni)):
                         greenPoints.append(result - 2*(epsilonBackup * Ni))
                         greenPointsEpsilonValues.append(- epsilonBackup)

                     if insideSphere(C = P, R = wendlandRadius ,P = result):                      
                         redPoints.append((result))
                         redPointsEpsilonValues.append(epsilonBackup)
                     numpyPointsWithinRange.append(PiNumpy)

                 #Create lists of the Pi's and Di's belonging to P
                 PointsPi = numpyPointsWithinRange + redPoints + greenPoints
                 PointsDi = [0]*len(pointsWithinRange) + redPointsEpsilonValues + greenPointsEpsilonValues

                 #sqrt(ti) = sqrt(theta(|P-Pi|)) (see MLS reference sheet: http://www.cs.uu.nl/docs/vakken/ddm/MLS%20Reference%20Sheet.pdf)
                 sqrtTiValues = [] 
                 #smoothing value for wendland weight function. EXPERIMENTABLE PARAMETER
                 h = 1
                 for Pi in PointsPi: 
                     value = np.sqrt(Wendland(np.linalg.norm(P-Pi), h))        
                     sqrtTiValues.append(value)
                 # A is a one-column matrix filled by sqrtTi multiplied with b^T
                 A = np.empty((0,matchingLengthofDegreeK(polyDegree)))
                 for index, sqrtTi in enumerate(sqrtTiValues):
                     #Here we choose B for a degree 0, 1 or 2. EXPERIMENTABLE PARAMETER
                     bT = ChooseB(polyDegree, PointsPi[index])
                     value = sqrtTi*bT
                     A = np.insert(A, index, value, 0)

                    
                 # r = sqrtTi_x_Di
                 r = np.empty((0, len(sqrtTiValues)))
                 for index, sqrtTi in enumerate(sqrtTiValues):
                     r = np.insert(r, index, sqrtTi * PointsDi[index])
                 

                 if(len(A) != 0):
                     A_T = np.transpose(A)
                     A_T_x_A = np.dot(A_T, A)        
                     A_T_x_r = np.dot(A_T, r)
                     #a = (A^T*A)^-1 * A^T*r
                     a = np.dot(np.linalg.inv(A_T_x_A), A_T_x_r)
                     #Finally add a to the samples    
                     return np.dot(ChooseB(polyDegree, [x,y,z]), a)

                 else:
                     return 10000

    def f(x, y, z):
        return MLS(x, y, z)


    #4. INPUTS SAMPLED GRID TO MARCHING CUBES PLUGIN ---
    #
    lowerLeft = origin - mathutils.Vector((diagonalOfBoundingBox/2*0.9, diagonalOfBoundingBox/2*0.9, diagonalOfBoundingBox/2*0.9))
    upperRight = origin + mathutils.Vector((diagonalOfBoundingBox/2*1.1, diagonalOfBoundingBox/2*1.1, diagonalOfBoundingBox/2*1.1))

    vertices, triangles = mcubes.marching_cubes_func((lowerLeft[0], lowerLeft[1], lowerLeft[2]),(upperRight[0], upperRight[1], upperRight[2]), 100, 100, 100, f, 0)

    # Export the result
    mcubes.export_mesh(vertices, triangles, "C:\\Users\\jaswir\\Documents\\GameTechnology\\3DM\\3DM_Practical1\\DAE_Files\\Bunnyk1.dae", "Bunny_k1")
Пример #11
0
import numpy as np
import sys
import math
import os
try:
    mcubes_path = r"/usr/local/lib/python3.5/dist-packages" #it depend on your OS but just paste the path where is mcubes
    if not mcubes_path in sys.path:
        sys.path.append(mcubes_path)    
    import mcubes
except:
    os.system('pip3 install pymcubes')
# Create the volume
def f(x, y, z):
    return (z**3 / (math.sin(z*y+x)) + 3**x)**3

# Create a data volume (30 x 30 x 30)
#X, Y, Z = np.mgrid[:100, :100, :100]
# u = (X-50)**2 + (Y-50)**2 + (Z-50)**2 - 25**2

# Extract the 0-isosurface
#verts, tri = mcubes.marching_cubes(u, 0)

# Extract the 16-isosurface
verts, tri = mcubes.marching_cubes_func(
        (-bounds, -bounds, -bounds), (bounds, bounds, bounds),  # Bounds
        samples, samples, samples,              # Number of samples in each dimension
        f,                          # Implicit function
        iso_val)                         # Isosurface value

vertices, triangles = verts.tolist(), tri.tolist()
Пример #12
0
# Export the result to sphere.dae
mcubes.export_mesh(vertices1, triangles1, "sphere1.dae", "MySphere")

print("Done. Result saved in 'sphere1.dae'.")

print("Example 2: Isosurface in Python function...")
print("(this might take a while...)")

# Create the volume
def f(x, y, z):
    return x**2 + y**2 + z**2

# Extract the 16-isosurface
vertices2, triangles2 = mcubes.marching_cubes_func(
        (-10,-10,-10), (10,10,10),  # Bounds
        100, 100, 100,              # Number of samples in each dimension
        f,                          # Implicit function
        16)                         # Isosurface value

# Export the result to sphere2.dae
mcubes.export_mesh(vertices2, triangles2, "sphere2.dae", "MySphere")
print("Done. Result saved in 'sphere2.dae'.")

try:
    print("Plotting mesh...")
    from mayavi import mlab
    mlab.triangular_mesh(
        vertices1[:, 0], vertices1[:, 1], vertices1[:, 2],
        triangles1)
    print("Done.")
    mlab.show()