geotools应用-JTS生产四叉树索引和R树索引

geotools应用-JTS生产四叉树索引和R树索引geotools 介绍 geotools 官网 https geotools org Geotools 是一个 java 类库 它提供了很多的标准类和方法来处理空间数据 同时这个类库是构建在 OGC 标准之上的 是 OGC 思想的一种实现 而 OGC 是国际标准 所以 geotools 将来必定会成为开源空间数据处理的主要工具 目前的大部分开源软件 如 udig geoserver 等 对空间数据的处理都是由 geoto

微信搜索:“二十同学” 公众号,欢迎关注一条不一样的成长之路

geotools介绍

geotools官网https://geotools.org/

Geotools是一个java类库,它提供了很多的标准类和方法来处理空间数据,同时这个类库是构建在OGC标准之上的,是OGC思想的一种实现。而OGC是国际标准,所以geotools将来必定会成为开源空间数据处理的主要工具,目前的大部分开源软件,如udig,geoserver等,对空间数据的处理都是由geotools来做支撑。而其他很多的web服务,命令行工具和桌面程序都可以由geotools来实现。

JTS介绍

JTS是加拿大的 Vivid Solutions 做的一套开放源码的 Java API。它提供了一套空间数据操作的核心算法,为在兼容OGC标准的空间对象模型中进行基础的几何操作提供2D空间谓词API。

     Point           MultiPoint      LineString           LinearRing  封闭的线条      MultiLineString    多条线      Polygon      MultiPolygon               GeometryCollection  包括点,线,面

里面最主要的几个类,GeometryFactory,Geometry,Envelope以及上面提到的几种常用数据类型。

Geometry类:所有的空间数据类型,点,线,面,多点,环,多边形等等都是继承自Geometry类的。 
Envelope类:该类就是描述一个空间几何对象的外包矩形,由max_x,max_y,min_x,min_y组成。

3、空间关系

空间关系主要是由九交模型来描述的,九交模型的讲解可以参考:九交模型的讲解

至于在JTS中的对应的关系,就是以下几种: 

相等(Equals):

几何形状拓扑上相等。

脱节(Disjoint):

几何形状没有共有的点。

相交(Intersects):

几何形状至少有一个共有点(区别于脱节)

接触(Touches):

几何形状有至少一个公共的边界点,但是没有内部点。

交叉(Crosses):

几何形状共享一些但不是所有的内部点。

内含(Within):

几何形状A的线都在几何形状B内部。

包含(Contains):

几何形状B的线都在几何形状A内部(区别于内含)

重叠(Overlaps):

几何形状共享一部分但不是所有的公共点,而且相交处有他们自己相同的区域。

对Geometry操作

import org.geotools.geometry.jts.JTSFactoryFinder; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryCollection; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.LinearRing; import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.Polygon; import com.vividsolutions.jts.geom.MultiPolygon; import com.vividsolutions.jts.geom.MultiLineString; import com.vividsolutions.jts.geom.MultiPoint; import com.vividsolutions.jts.io.ParseException; import com.vividsolutions.jts.io.WKTReader; / * Class GeometryDemo.java * Description Geometry 几何实体的创建,读取操作 */ public class GeometryDemo { private GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory( null ); / * create a point * @return */ public Point createPoint(){ Coordinate coord = new Coordinate(109.013388, 32.); Point point = geometryFactory.createPoint( coord ); return point; } / * create a rectangle(矩形) * @return */ public Envelope createEnvelope(){ Envelope envelope = new Envelope(0,1,0,2); return envelope; } / * create a point by WKT * @return * @throws ParseException */ public Point createPointByWKT() throws ParseException{ WKTReader reader = new WKTReader( geometryFactory ); Point point = (Point) reader.read("POINT (109.013388 32.)"); return point; } / * create multiPoint by wkt * @return */ public MultiPoint createMulPointByWKT()throws ParseException{ WKTReader reader = new WKTReader( geometryFactory ); MultiPoint mpoint = (MultiPoint) reader.read("MULTIPOINT(109.013388 32.,119.32488 31.)"); return mpoint; } / * * create a line * @return */ public LineString createLine(){ Coordinate[] coords = new Coordinate[] {new Coordinate(2, 2), new Coordinate(2, 2)}; LineString line = geometryFactory.createLineString(coords); return line; } / * create a line by WKT * @return * @throws ParseException */ public LineString createLineByWKT() throws ParseException{ WKTReader reader = new WKTReader( geometryFactory ); LineString line = (LineString) reader.read("LINESTRING(0 0, 2 0)"); return line; } / * create multiLine * @return */ public MultiLineString createMLine(){ Coordinate[] coords1 = new Coordinate[] {new Coordinate(2, 2), new Coordinate(2, 2)}; LineString line1 = geometryFactory.createLineString(coords1); Coordinate[] coords2 = new Coordinate[] {new Coordinate(2, 2), new Coordinate(2, 2)}; LineString line2 = geometryFactory.createLineString(coords2); LineString[] lineStrings = new LineString[2]; lineStrings[0]= line1; lineStrings[1] = line2; MultiLineString ms = geometryFactory.createMultiLineString(lineStrings); return ms; } / * create multiLine by WKT * @return * @throws ParseException */ public MultiLineString createMLineByWKT()throws ParseException{ WKTReader reader = new WKTReader( geometryFactory ); MultiLineString line = (MultiLineString) reader.read("MULTILINESTRING((0 0, 2 0),(1 1,2 2))"); return line; } / * create a polygon(多边形) by WKT * @return * @throws ParseException */ public Polygon createPolygonByWKT() throws ParseException{ WKTReader reader = new WKTReader( geometryFactory ); Polygon polygon = (Polygon) reader.read("POLYGON((20 10, 30 0, 40 10, 30 20, 20 10))"); return polygon; } / * create multi polygon by wkt * @return * @throws ParseException */ public MultiPolygon createMulPolygonByWKT() throws ParseException{ WKTReader reader = new WKTReader( geometryFactory ); MultiPolygon mpolygon = (MultiPolygon) reader.read("MULTIPOLYGON(((40 10, 30 0, 40 10, 30 20, 40 10),(30 10, 30 0, 40 10, 30 20, 30 10)))"); return mpolygon; } / * create GeometryCollection contain point or multiPoint or line or multiLine or polygon or multiPolygon * @return * @throws ParseException */ public GeometryCollection createGeoCollect() throws ParseException{ LineString line = createLine(); Polygon poly = createPolygonByWKT(); Geometry g1 = geometryFactory.createGeometry(line); Geometry g2 = geometryFactory.createGeometry(poly); Geometry[] garray = new Geometry[]{g1,g2}; GeometryCollection gc = geometryFactory.createGeometryCollection(garray); return gc; } / * create a Circle 创建一个圆,圆心(x,y) 半径RADIUS * @param x * @param y * @param RADIUS * @return */ public Polygon createCircle(double x, double y, final double RADIUS){ final int SIDES = 32;//圆上面的点个数 Coordinate coords[] = new Coordinate[SIDES+1]; for( int i = 0; i < SIDES; i++){ double angle = ((double) i / (double) SIDES) * Math.PI * 2.0; double dx = Math.cos( angle ) * RADIUS; double dy = Math.sin( angle ) * RADIUS; coords[i] = new Coordinate( (double) x + dx, (double) y + dy ); } coords[SIDES] = coords[0]; LinearRing ring = geometryFactory.createLinearRing( coords ); Polygon polygon = geometryFactory.createPolygon( ring, null ); return polygon; } / * @param args * @throws ParseException */ public static void main(String[] args) throws ParseException { GeometryDemo gt = new GeometryDemo(); Polygon p = gt.createCircle(0, 1, 2); //圆上所有的坐标(32个) Coordinate coords[] = p.getCoordinates(); for(Coordinate coord:coords){ System.out.println(coord.x+","+coord.y); } Envelope envelope = gt.createEnvelope(); System.out.println(envelope.centre()); } }

建立四叉树索引

public static void main(String[] args) { //创建四叉树索引 Quadtree quatree = new Quadtree(); PointInfo info = new PointInfo(); quatree.insert(new Envelope(new Coordinate(, )), info); } 

Quatree 提供了三个搜索方法,分别如下:

public List query(Envelope searchEnv) { / * the items that are matched are the items in quads which overlap the * search envelope */ ArrayListVisitor visitor = new ArrayListVisitor(); query(searchEnv, visitor); return visitor.getItems(); } public void query(Envelope searchEnv, ItemVisitor visitor) { / * the items that are matched are the items in quads which overlap the * search envelope */ root.visit(searchEnv, visitor); } / * Return a list of all items in the Quadtree */ public List queryAll() { List foundItems = new ArrayList(); root.addAllItems(foundItems); return foundItems; }

每个函数的含义分别表示搜索范围搜索,范围过滤搜索和全部搜索。范围搜索只要给出一个矩形框,然后传入即可。

 List 
  
    points = quatree.query(new Envelope(new Coordinate( , ))); for (PointInfo pointInfo : points) { // 结果只有一个点 System.out.println(pointInfo.getName()); } // 调整经纬度,看周围有什么 System.out.println("只能够调整经纬度,来看周围有什么,相当于地图上的周边搜索的概念"); points = quatree.query(new Envelope(new Coordinate(, ), new Coordinate(, ))); for (PointInfo pointInfo : points) { System.out.println(pointInfo.getName()); } 
  

建立R数索引

package util; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map.Entry; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.CoordinateSequences; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.LinearRing; import com.vividsolutions.jts.geom.MultiPoint; import com.vividsolutions.jts.geom.Polygon; import com.vividsolutions.jts.geom.impl.CoordinateArraySequence; import com.vividsolutions.jts.index.strtree.STRtree; import config.GeoConfig; import dao.QueryTrail; import entity.CompareValue; import entity.GPSPoint; import entity.Grid; import entity.Line; import entity.Point; import io.vertx.core.Vertx; import io.vertx.core.buffer.Buffer; import io.vertx.core.json.JsonObject; import io.vertx.ext.web.client.HttpResponse; import io.vertx.ext.web.client.WebClient; public class SpatialUtil { static String result=new String(); public static void getPolygonofWuhan(String[] args) { Vertx vertx = Vertx.vertx(); WebClient client = WebClient.create(vertx); client.get(80, "restapi.amap.com", "/v3/config/district?keywords=%E6%AD%A6%E6%B1%89&subdistrict=0&key=高德地图API申请的Token&extensions=all") .send(ar -> { if (ar.succeeded()) { // Obtain response HttpResponse 
  
    response = ar.result(); result = response.bodyAsString(); JsonObject jo = new JsonObject(result); result = jo.getJsonArray("districts").getJsonObject(0).getString("polyline"); GeometryFactory factory=new GeometryFactory(); String[] xyStrings=result.replace("|", ";").split(";"); List 
   
     list=new ArrayList<>(); for(String xy:xyStrings){ String[] s_arr=xy.split(","); double[] d_xy=new double[2]; d_xy[0]=Double.parseDouble(s_arr[0]); d_xy[1]=Double.parseDouble(s_arr[1]); Coordinate coor=new Coordinate(d_xy[0], d_xy[1]); list.add(coor); } Coordinate[] coor_arr=list.toArray(new Coordinate[0]); MultiPoint multiPoint=factory.createMultiPoint(coor_arr); Geometry env=multiPoint.getEnvelope(); Coordinate[] MBR=env.getCoordinates(); for(int i=0;i 
    
      =min){ return CompareValue.IN; }else{ return CompareValue.GT; } } / * 建立网格 * @return */ public static HashMap 
     
       createGrids(){ HashMap 
      
        gridMap=new HashMap<>(); double left_top_x=Double.parseDouble(PropertiesUtil.getProperties("common", "left-top").split(",")[0]); double left_top_y=Double.parseDouble(PropertiesUtil.getProperties("common", "left-top").split(",")[1]); double right_bottom_x=Double.parseDouble(PropertiesUtil.getProperties("common", "right-bottom").split(",")[0]); double right_bottom_y=Double.parseDouble(PropertiesUtil.getProperties("common", "right-bottom").split(",")[1]); int rows=Integer.parseInt(PropertiesUtil.getProperties("common", "rows")); int cols=Integer.parseInt(PropertiesUtil.getProperties("common", "cols")); double interval_x=Double.parseDouble(ParseDataType.parseD2s((right_bottom_x-left_top_x)/(cols*1.0),6)); double interval_y=Double.parseDouble(ParseDataType.parseD2s((left_top_y-right_bottom_y)/(rows*1.0),6)); for(int i=0;i 
       
         createGridIndex(){ HashMap 
        
          gridmap=createGrids(); int cols=Integer.parseInt(PropertiesUtil.getProperties("common", "cols")); int rows=Integer.parseInt(PropertiesUtil.getProperties("common", "rows")); String rbPt_s=PropertiesUtil.getProperties("common", "right-bottom"); Point rbPt=new Point(); rbPt.setX(Double.parseDouble(rbPt_s.split(",")[0])); rbPt.setY(Double.parseDouble(rbPt_s.split(",")[1])); String ltPt_s=PropertiesUtil.getProperties("common", "left-top"); Point ltPt=new Point(); ltPt.setX(Double.parseDouble(ltPt_s.split(",")[0])); ltPt.setY(Double.parseDouble(ltPt_s.split(",")[1])); double range_x=rbPt.getX()-ltPt.getX(); double range_y=ltPt.getY()-rbPt.getY(); QueryTrail query=new QueryTrail(); HashMap 
         
           map=query.getLine(); GeoConfig config=new GeoConfig(); config.setMaxGeoRange(Double.parseDouble(PropertiesUtil.getProperties("common", "maxGeoRange"))); config.setMinGeoRange(Double.parseDouble(PropertiesUtil.getProperties("common", "minGeoRange"))); GeometryFactory factory=new GeometryFactory(); for(Entry 
          
            entry:map.entrySet()){ Line templine=entry.getValue().sort(true); List 
           
             list=templine.filter(config); for(Line line:list){ List 
            
              gpslist=line.getCoors(); List 
             
               coors=new ArrayList<>(); for(GPSPoint xy:gpslist){ double x=xy.getX(); double y=xy.getY(); Coordinate coor=new Coordinate(x, y); coors.add(coor); } Coordinate[] coor_arr=coors.toArray(new Coordinate[0]); if(coor_arr.length>1){ LineString l_s=factory.createLineString(coor_arr); Envelope env=l_s.getEnvelopeInternal(); double max_x=env.getMaxX(); double min_x=env.getMinX(); double max_y=env.getMaxY(); double min_y=env.getMinY(); int max_j=(int)((max_x-ltPt.getX())/range_x*cols); int max_i=(int)((ltPt.getY()-max_y)/range_y*rows); int min_j=(int)((min_x-ltPt.getX())/range_x*cols); int min_i=(int)((ltPt.getY()-min_y)/range_y*rows); a:for(int i=max_i;i<=min_i;i++){ for(int j=min_j;j<=max_j;j++){ Grid grid=gridmap.get(String.valueOf(rows)+"_"+String.valueOf(cols)+"_"+String.valueOf(i*cols+j+1)); Coordinate[] coor_arr1=new Coordinate[5]; coor_arr1[0]=new Coordinate(grid.getLefttop().getX(), grid.getLefttop().getY()); coor_arr1[1]=new Coordinate(grid.getLefttop().getX(), grid.getRightbottom().getY()); coor_arr1[2]=new Coordinate(grid.getRightbottom().getX(), grid.getRightbottom().getY()); coor_arr1[3]=new Coordinate(grid.getRightbottom().getX(), grid.getLefttop().getY()); coor_arr1[4]=new Coordinate(grid.getLefttop().getX(), grid.getLefttop().getY()); CoordinateArraySequence seq=new CoordinateArraySequence(coor_arr1); LinearRing ring = new LinearRing(seq, new GeometryFactory()); Polygon poly=new Polygon(ring, null, new GeometryFactory()); if(l_s.crosses(poly)||poly.covers(l_s)){ grid.addLine(line); break a; } } } }else{ GPSPoint point=gpslist.get(0); int j=(int)((point.getX()-ltPt.getX())/range_x*cols); int i=(int)((ltPt.getY()-point.getY())/range_y*rows); Grid grid=gridmap.get(String.valueOf(rows)+"_"+String.valueOf(cols)+"_"+String.valueOf(i*cols+j+1)); grid.addLine(line); } } } System.out.println("网格索引创建成功!"); return gridmap; } / * 建立R树索引 * @return */ public static STRtree createRtree(){ QueryTrail query=new QueryTrail(); HashMap 
              
                map=query.getLine(); GeoConfig config=new GeoConfig(); config.setMaxGeoRange(Double.parseDouble(PropertiesUtil.getProperties("common", "maxGeoRange"))); config.setMinGeoRange(Double.parseDouble(PropertiesUtil.getProperties("common", "minGeoRange"))); STRtree tree=new STRtree(); for(Entry 
               
                 entry:map.entrySet()){ Line templine=entry.getValue().sort(true); List 
                
                  list=templine.filter(config); for(Line line:list){ GeometryFactory factory=new GeometryFactory(); List 
                 
                   coors=new ArrayList<>(); List 
                  
                    gpslist=line.getCoors(); for(GPSPoint xy:gpslist){ double x=xy.getX(); double y=xy.getY(); Coordinate coor=new Coordinate(x, y); coors.add(coor); } Coordinate[] coor_arr=coors.toArray(new Coordinate[0]); if(coor_arr.length>1){ LineString lineStr=factory.createLineString(coor_arr); Envelope env=lineStr.getEnvelopeInternal(); tree.insert(env, lineStr); }else{ com.vividsolutions.jts.geom.Point point=factory.createPoint(coor_arr[0]); Envelope env=point.getEnvelopeInternal(); tree.insert(env, point); } } } tree.build(); System.out.println("R树索引创建成功!"); return tree; } / * R树查询 * @param tree * @param searchGeo * @return */ public static List 
                   
                     query(STRtree tree,Geometry searchGeo){ List 
                    
                      result=new ArrayList<>(); @SuppressWarnings("rawtypes") List list=tree.query(searchGeo.getEnvelopeInternal()); for(int i=0;i 
                      
                     
                    
                   
                  
                 
                
               
              
             
            
           
          
         
        
       
      
     
    
  

common.properties:

#两点间最大间隔(经纬度差值,目前按照江的宽度) maxGeoRange=0.002 #maxGeoRange=0.012 #两点间最小间隔(经纬度差值,目前按照地图上一栋楼的宽度) minGeoRange=0.0005 #minGeoRange=0.0017 #武汉市外包矩形的范围 #左上角 left-top=113.,31.36127 #左下角 left-bottom=113.,29. #右上角 right-top=115.082574,31.36127 #右下角 right-bottom=115.082574,29. #设定的网格的行数 rows=10 #设定的网格的列数 cols=10 #坐标保留小数点后几位 CoorAbs=10000
package entity; import java.util.Date; / * 点,描述点的位置,所属网格和所属线条 * @author KingWang * */ public class GPSPoint extends Point{ private Date date=new Date(); private Grid grid=new Grid(); private Line line=new Line(); public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public Grid getGrid() { return grid; } public void setGrid(Grid grid) { this.grid = grid; } public Line getLine() { return line; } public void setLine(Line line) { this.line = line; } } 
package entity; import java.util.HashSet; public class Grid { private int index=0; private int col=0; private int row=0; private Point lefttop=new Point(); private Point rightbottom=new Point(); private HashSet 
  
    set=new HashSet<>(); public int getIndex() { return index; } public void setIndex(int index) { this.index = index; } public int getCol() { return col; } public void setCol(int col) { this.col = col; } public int getRow() { return row; } public void setRow(int row) { this.row = row; } public Point getLefttop() { return lefttop; } public void setLefttop(Point lefttop) { this.lefttop = lefttop; } public Point getRightbottom() { return rightbottom; } public void setRightbottom(Point rightbottom) { this.rightbottom = rightbottom; } public HashSet 
   
     getSet() { return set; } public void setSet(HashSet 
    
      set) { this.set = set; } public void addLine(Line line){ this.set.add(line); } } 
     
    
  
package entity; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Random; import java.util.concurrent.CopyOnWriteArrayList; import config.GeoConfig; import util.SpatialUtil; / * 线,点串,描述整条轨迹 * @author KingWang * */ public class Line { / * 轨迹的id */ private String id=""; / * 按照顺序存储点轨迹 */ private List 
  
    coors=new ArrayList<>(); / * 经过的网格,按照轨迹顺序存储 */ private List 
   
     grids=new ArrayList<>(); public String getId() { return id; } public void setId(String id) { this.id = id; } public List 
    
      getCoors() { return coors; } public void setCoors(List 
     
       coors) { this.coors = coors; } public List 
      
        getGrids() { return grids; } public void setGrids(List 
       
         grids) { this.grids = grids; } public void addPoint(GPSPoint p){ this.coors.add(p); } public void removePoint(int index){ this.coors.remove(index); } public Line sort(boolean isTimeAsc){ List 
        
          list=this.getCoors(); Collections.sort(list, (point1,point2)->{ if(point1.getDate().after(point2.getDate())){ if(isTimeAsc){ return 1; }else{ return -1; } }else{ if(isTimeAsc){ return -1; }else{ return 1; } } }); return this; } / * 对线坐标串进行粗处理,太密的点删掉,太远的点打断成两段 * @param config * @return */ public List 
         
           filter(GeoConfig config){ List 
          
            resultList=new ArrayList<>(); List 
           
             list=new CopyOnWriteArrayList<>(this.getCoors()); Point lastPt=new Point(); int i=0; int lastCutIndex=0; for(GPSPoint point:list){ if(i>0&&SpatialUtil.inTolerance(lastPt,point,config)==CompareValue.GT){ List 
            
              list_temp=new ArrayList<>(); list_temp.addAll(list.subList(lastCutIndex, i)); Line line_temp=new Line(); line_temp.setCoors(list_temp); line_temp.setId(String.valueOf(System.currentTimeMillis()+new Random().nextInt(10))); resultList.add(line_temp); lastCutIndex=i; }else if(i>0&&SpatialUtil.inTolerance(lastPt, point, config)==CompareValue.LT){ list.remove(i); i--; } lastPt=point; i++; } if(lastCutIndex==i){ Line line_temp=new Line(); line_temp.setCoors(this.getCoors()); line_temp.setId(String.valueOf(System.currentTimeMillis()+new Random().nextInt(10))); resultList.add(line_temp); }else{ List 
             
               list_temp=new ArrayList<>(); list_temp.addAll(list.subList(lastCutIndex, i)); Line line_temp=new Line(); line_temp.setCoors(list_temp); line_temp.setId(String.valueOf(System.currentTimeMillis()+new Random().nextInt(10))); resultList.add(line_temp); } return resultList; } } 
              
             
            
           
          
         
        
       
      
     
    
  
package entity; import config.GeoConfig; / * 点,描述点的位置 * @author KingWang * */ public class Point { private double x=0.0; private double y=0.0; public double getX() { return x; } public void setX(double x) { this.x = x; } public double getY() { return y; } public void setY(double y) { this.y = y; } } 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/220347.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 下午8:42
下一篇 2026年3月17日 下午8:43


相关推荐

  • idea 2022.01 破解 激活码[最新免费获取]

    (idea 2022.01 破解 激活码)最近有小伙伴私信我,问我这边有没有免费的intellijIdea的激活码,然后我将全栈君台教程分享给他了。激活成功之后他一直表示感谢,哈哈~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html4K…

    2022年4月1日
    224
  • 2026年OpenClaw(Clawdbot)AI Agent 全栈教程:云端+本地部署+监控仪表盘,运维效率翻倍

    2026年OpenClaw(Clawdbot)AI Agent 全栈教程:云端+本地部署+监控仪表盘,运维效率翻倍

    2026年3月13日
    4
  • 送别林俊旸,阿里千问“急行军”

    送别林俊旸,阿里千问“急行军”

    2026年3月13日
    2
  • 协议: DTMF相关FAQ

    协议: DTMF相关FAQQ WhatisDTMF A nbsp 双音多频信号 Dual ToneMulti Frequency DTMF 电话系统中电话机与交换机之间的一种用户信令 通常用于发送被叫号码 在使用双音多频信号之前 电话系统中使用一连串的断续脉冲来传送被叫号码 称为脉冲拨号 脉冲拨号需要电信局中的操作员手工完成长途接续 双音多频信号是贝尔实验室发明的 其目的是为了自动完成长途呼叫 nbsp 双

    2026年3月17日
    2
  • lightroom cc 2015 mac的快捷键

    lightroom cc 2015 mac的快捷键Lightroom是一款非常专业的图形图像软件,使用它可以加快对图片后期处理的速度。如果这些快捷键你都知道的话?可以帮你节省很多时间,大大提高工作效率。还没有了解全面的不妨仔细看一下!全面了解的也可以看看还有什么疏漏的地方!lightroomcc2015mac快捷按键▪数字0:取消等级1~5:在图库模块中为选中的照片设置等级;6~9:在图库模块中为选中的照片设置色彩标…

    2022年5月26日
    48
  • Python写入Excel文件-多种实现方式(测试成功,附代码)

    目录xlsxwriter库储存数据到excel简介示例:写入excel更多添加工作表样式:写入单元格数据插入图片写入超链接插入图表pandas库储存数据到excel简介示例:写入excelopenpyxl库储存数据到excel示例:写入excel更多打开已有文件根据数字得到字母,根据字母得到数字删除工作表查看表名和选择表(sheet)设置单元格风格xlsxwriter库储存数据到excel简介功能比较强:支..

    2022年4月3日
    422

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号