Java Geometry空間幾何數(shù)據(jù)的處理應(yīng)用

先了解幾個(gè)基本概念奶赔,有助于了解本文應(yīng)用場(chǎng)景

地理信息系統(tǒng)(Geographic Information System或 Geo-Information system,GIS)有時(shí)又稱(chēng)為“地學(xué)信息系統(tǒng)”。它是一種特定的十分重要的空間信息系統(tǒng)。它是在計(jì)算機(jī)硬、軟件系統(tǒng)支持下,對(duì)整個(gè)或部分地球表層(包括大氣層)空間中的有關(guān)地理分布數(shù)據(jù)進(jìn)行采集豪诲、儲(chǔ)存管理挂绰、運(yùn)算屎篱、分析顯示描述的技術(shù)系統(tǒng)

  • ArcGIS平臺(tái)

ArcGIS產(chǎn)品線為用戶提供一個(gè)可伸縮的葵蒂,全面的GIS平臺(tái)交播。ArcObjects包含了許多的可編程組件,從細(xì)粒度的對(duì)象(例如單個(gè)的幾何對(duì)象)到粗粒度的對(duì)象(例如與現(xiàn)有ArcMap文檔交互的地圖對(duì)象)涉及面極廣践付,這些對(duì)象為開(kāi)發(fā)者集成了全面的GIS功能秦士。

  • Geometry數(shù)據(jù)類(lèi)型

Geometry是一種空間幾何數(shù)據(jù)類(lèi)型,常用于描述空間幾何信息永高,例如坐標(biāo)點(diǎn)隧土、線、面乏梁、三維信息等次洼。
也就是說(shuō)关贵,GIS一般使用Geometry數(shù)據(jù)類(lèi)型來(lái)存儲(chǔ)及展示地理信息遇骑。
常見(jiàn)的支持Geometry的數(shù)據(jù)庫(kù)有Oracle、SqlServer揖曾、Mysql落萎、PostgreSQL
Sql-Server中支持的Geometry文檔以及Sql-Server中可選擇的地理數(shù)據(jù)類(lèi)型如圖

  • 應(yīng)用場(chǎng)景示例

    如圖亥啦,該應(yīng)用主要為使用ArcGIS做地理信息系統(tǒng),使用SqlServer作為空間數(shù)據(jù)庫(kù)练链,使用Java搭建后臺(tái)服務(wù)處理數(shù)據(jù)翔脱,使用JS的Vue結(jié)合ArcGIS的API做前端的渲染,成功的將地理信息高亮標(biāo)識(shí)在地圖上

本文關(guān)注點(diǎn):使用java對(duì)Geometry數(shù)據(jù)進(jìn)行處理媒鼓,附帶對(duì)arcgis系統(tǒng)一些簡(jiǎn)單使用說(shuō)明 簡(jiǎn)單描述一個(gè)gis應(yīng)用系統(tǒng)的處理流程


1. 使用ArcGIS創(chuàng)建地理數(shù)據(jù)庫(kù)届吁,發(fā)布GIS服務(wù)

數(shù)據(jù)庫(kù)和 ArcGIS Enterprise
如何注冊(cè)數(shù)據(jù)庫(kù)到 ArcGIS Server 站點(diǎn)
發(fā)布地圖服務(wù)
通過(guò)以上的文檔,我們可以創(chuàng)建一個(gè)地理數(shù)據(jù)庫(kù)绿鸣,并將數(shù)據(jù)庫(kù)通過(guò)arcgis進(jìn)行連接疚沐,發(fā)布為一個(gè)Restful服務(wù)


訪問(wèn)該接口,如圖


image.png

那這個(gè)接口提供了那些功能呢潮模?
支持的操作大概如下:
Supported Operations: Query Apply Edits Add Features Update Features Delete Features Calculate Validate SQL Generate Renderer Return Updates Iteminfo Thumbnail Metadata

由ArcGIS提供的這些服務(wù)亮蛔,我們可以以可視化的方式,對(duì)空間地理信息進(jìn)行查詢及展示
后面我們將做進(jìn)一步的說(shuō)明


2. 空間數(shù)據(jù)以及WKT熟知文本

好的擎厢,我們有了數(shù)據(jù)庫(kù)究流,也有了arcgis提供的服務(wù),現(xiàn)在該如何新增空間數(shù)據(jù)呢动遭?
先通過(guò)WKT了解下空間數(shù)據(jù)Geometry大概長(zhǎng)什么樣

WKT芬探,是一種文本標(biāo)記語(yǔ)言,用于表示矢量幾何對(duì)象厘惦、空間參照系統(tǒng)及空間參照系統(tǒng)之間的轉(zhuǎn)換灯节。它的二進(jìn)制表示方式,亦即WKB(well-known binary)則勝于在傳輸和在數(shù)據(jù)庫(kù)中存儲(chǔ)相同的信息绵估。該格式由開(kāi)放地理空間聯(lián)盟(OGC)制定炎疆。

WKT可以表示的幾何對(duì)象包括:點(diǎn),線国裳,多邊形形入,TIN(不規(guī)則三角網(wǎng))及多面體》熳螅可以通過(guò)幾何集合的方式來(lái)表示不同維度的幾何對(duì)象亿遂。
幾何物體的坐標(biāo)可以是2D(x,y),3D(x,y,z),4D(x,y,z,m),加上一個(gè)屬于線性參照系統(tǒng)的m值。
以下為幾何WKT字串樣例:
POINT(6 10)
LINESTRING(3 4,10 50,20 25)
POLYGON((1 1,5 1,5 5,1 5,1 1),(2 2,2 3,3 3,3 2,2 2))
MULTIPOINT(3.5 5.6, 4.8 10.5)
MULTILINESTRING((3 4,10 50,20 25),(-5 -8,-10 -8,-15 -4))
MULTIPOLYGON(((1 1,5 1,5 5,1 5,1 1),(2 2,2 3,3 3,3 2,2 2)),((6 3,9 2,9 4,6 3)))
GEOMETRYCOLLECTION(POINT(4 6),LINESTRING(4 6,7 10))
POINT ZM (1 1 5 60)
POINT M (1 1 80)
POINT EMPTY
MULTIPOLYGON EMPTY

到這里我們清楚了渺杉,所謂空間數(shù)據(jù)就是一個(gè)或一組坐標(biāo)蛇数,這個(gè)坐標(biāo)或坐標(biāo)組有類(lèi)型(POINT點(diǎn)LINESTRING線POLYGON面),通過(guò)這些坐標(biāo)是越,GIS系統(tǒng)可以完整地定位查詢繪制這些坐標(biāo)信息


3. 向空間數(shù)據(jù)庫(kù)插入數(shù)據(jù)

那數(shù)據(jù)庫(kù)如何新增這些空間數(shù)據(jù)呢耳舅?
先了解一下SQLSERVER空間數(shù)據(jù)的插入語(yǔ)句長(zhǎng)啥樣

--GEOM是類(lèi)型為Geometry的字段--
--我們向該字段新增了一條3D的多邊形數(shù)據(jù)--
--geometry :: STGeomFromText () 是由SQLSERVER提供的函數(shù),它能將WKT文本轉(zhuǎn)換為數(shù)據(jù)庫(kù)geometry類(lèi)型的數(shù)據(jù)--
INSERT INTO [dbo].[TEST_GEO_TABLE] ( [GEOM] )
VALUES
    ( geometry :: STGeomFromText ( 
    'POLYGON ((
        113.507259000000005 22.24814946 8, 
        113.507188600000006 22.248088559999999 9, 
        113.507117399999998 22.24802743 10, 
        113.507046099999997 22.24796624 11, 
        113.507017300000001 22.247888209999999 12
        ))',4326 )
    );

也就是說(shuō)倚评,將坐標(biāo)轉(zhuǎn)化為WKT文本浦徊,我們就可以插入空間數(shù)據(jù)馏予。接下來(lái)我們要考慮的是如何產(chǎn)生WKT文本


4. 使用Java創(chuàng)建Geometry對(duì)象

4.1 常見(jiàn)Geometry的JavaAPI

wkt文本僅僅是一個(gè)字符串而已,直接將坐標(biāo)點(diǎn)拼接成符合WKT格式的字符串不就可以了嗎盔性?
道理是這個(gè)道理霞丧,要做好可就難了。

  • 拼接工作量巨大
  • 拼接過(guò)程容易出錯(cuò)
  • 拼接的結(jié)果不一定合法可用
    我們需要一套JAVA API對(duì)數(shù)據(jù)進(jìn)行處理冕香,能夠方便的創(chuàng)建Geometry對(duì)象蛹尝,進(jìn)行地理信息的繪制、創(chuàng)建悉尾、驗(yàn)證等等功能

市面上常見(jiàn)的GeometryApi有

Esri/geometry-api-java

locationtech/jts (推薦)

Esri是Arcgis官方提供的javaSDK箩言,可惜功能不多,甚至不能提供基本的空間計(jì)算功能焕襟。
jts功能較為齊全陨收,資料也相對(duì)豐富一點(diǎn)

點(diǎn)擊上面鏈接可以訪問(wèn)其Github地址,本文將以jts為例進(jìn)行說(shuō)明


4.2 JTS的部分API使用方式

    @Test
    public void geoTest() throws ParseException {
        /**
         * GeometryFactory工廠鸵赖,參數(shù)一:數(shù)據(jù)精度 參數(shù)二空間參考系SRID
         */
        GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(PrecisionModel.FLOATING), 4326);

        /**
         * 熟知文本W(wǎng)KT閱讀器务漩,可以將WKT文本轉(zhuǎn)換為Geometry對(duì)象
         */
        WKTReader wktReader = new WKTReader(geometryFactory);

        /**
         * Geometry對(duì)象,包含Point它褪、LineString饵骨、Polygon等子類(lèi)
         */
        Geometry geometry = wktReader.read("POINT (113.53896635 22.36429837)");

        /**
         * 將二進(jìn)制流的形式讀取Geometry對(duì)象
         */
        WKBReader wkbReader = new WKBReader(geometryFactory);

        /**
         * 單純的一個(gè)坐標(biāo)點(diǎn),單點(diǎn)可以創(chuàng)建Point茫打,多點(diǎn)可以創(chuàng)建LineString居触、Polygon等
         */
        Coordinate coordinate = new Coordinate(1.00, 2.00);
        Point point = geometryFactory.createPoint(coordinate);

        Polygon polygon = geometryFactory.createPolygon(new Coordinate[]{
                new Coordinate(1, 2),
                new Coordinate(1, 2),
                new Coordinate(1, 2),
                new Coordinate(1, 2),
                new Coordinate(1, 2),
        });
        Geometry geometry1 = point;
        Geometry geometry2 = polygon;

        /**
         * WKT輸出器,將Geometry對(duì)象寫(xiě)出為WKT文本
         */
        WKTWriter wktWriter = new WKTWriter();
        String write = wktWriter.write(point);
    }

4.3 JTS中Geometry數(shù)據(jù)類(lèi)型的子類(lèi)

image.png

根據(jù)github中相關(guān)文檔介紹老赤,我們已經(jīng)可以在項(xiàng)目中引入相關(guān)坐標(biāo)轮洋,并創(chuàng)建Geometry對(duì)象,構(gòu)造WKT文本了


5. 使用JAVA向空間數(shù)據(jù)庫(kù)新增數(shù)據(jù)

根據(jù)上面測(cè)試類(lèi)中Api的使用抬旺,讓我們總結(jié)幾個(gè)要點(diǎn)

  • 工廠類(lèi)對(duì)象只需初始化一次弊予,應(yīng)放在配置類(lèi)注入到Spring容器中
  • 由前端或Excel導(dǎo)入相關(guān)坐標(biāo)數(shù)據(jù),生成Geometry對(duì)象
  • 持久化Geometry對(duì)象到SqlServer

本例中推薦兩種方式進(jìn)行Geometry對(duì)象的持久化:

  1. 獲取Geometry對(duì)象的WKT文本开财,再使用SqlServer提供的geometry :: STGeomFromText ()函數(shù)將WKT文本存儲(chǔ)為數(shù)據(jù)庫(kù)Geometry類(lèi)型
  2. 將jts包中Geometry對(duì)象轉(zhuǎn)換成SqlServer JDBC包中的Geometry對(duì)象汉柒,將Geometry對(duì)象以二進(jìn)制的形式持久化到數(shù)據(jù)庫(kù)

環(huán)境:
本例代碼基于JTS、SpringBoot责鳍、Mybatis-Plus碾褂、mssql-jdbc環(huán)境


6. 使用TypeHandler映射自定義對(duì)象字段插入Geometry數(shù)據(jù)

6.1 自定義TypeHandler

當(dāng)我們使用Mybatis框架時(shí),Mybatis提供了自定義類(lèi)型轉(zhuǎn)換器TypeHandler實(shí)現(xiàn)特殊對(duì)象與Sql字段的映射關(guān)系

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.WKTReader;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * @author wangqichang
 * @since 2019/8/28
 */
@Slf4j
@MappedTypes(value = {Geometry.class})
public class GeometryTypeHandler extends BaseTypeHandler<Geometry> {

    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, Geometry geometry, JdbcType jdbcType) throws SQLException {
        /**
         * 獲取jts包對(duì)象的wkt文本历葛,再轉(zhuǎn)換成sqlserver的Geometry對(duì)象
         * 調(diào)用ps的setBytes()方法正塌,以二進(jìn)制持久化該geometry對(duì)象
         */
        com.microsoft.sqlserver.jdbc.Geometry geo = com.microsoft.sqlserver.jdbc.Geometry.STGeomFromText(geometry.toText(), geometry.getSRID());
        preparedStatement.setBytes(i, geo.STAsBinary());
    }

    @Override
    public Geometry getNullableResult(ResultSet resultSet, String s) {
        try {
            /**
             * 從ResultSet中讀取二進(jìn)制轉(zhuǎn)換為SqlServer的Geometry對(duì)象
             * 使用jts的WKTReader將wkt文本轉(zhuǎn)成jts的Geometryd對(duì)象
             */
            com.microsoft.sqlserver.jdbc.Geometry geometry1 = com.microsoft.sqlserver.jdbc.Geometry.STGeomFromWKB(resultSet.getBytes(s));
            String s1 = geometry1.toString();
            WKTReader wktReader = SpringContextUtil.getBean(WKTReader.class);
            Geometry read = wktReader.read(s1);
            return read;
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new ServiceException(e.getMessage());
        }
    }

    @Override
    public Geometry getNullableResult(ResultSet resultSet, int i) throws SQLException {
        return null;
    }

    @Override
    public Geometry getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
        return null;
    }
}

6.2 實(shí)體對(duì)象

實(shí)體對(duì)象如下:

  • objectid為Integer類(lèi)型,非自增(此字段為Arcgis維護(hù),不能修改)@TableId是mybatis-plus插件的注解传货,告知插件該字段為主鍵字段屎鳍,字段名為OBJECT宏娄,主鍵策略為用戶輸入
  • shape為jts的Geometry對(duì)象(該對(duì)象JSON序列化結(jié)果非常嚇人问裕,所以使用@JsonIgnore修飾)
  • @KeySequence也是mybatis-plus的插件,作用是標(biāo)識(shí)該對(duì)象需要使用的主鍵序列名孵坚。此處我實(shí)現(xiàn)了一個(gè)IKeyGenerator粮宛,作用類(lèi)似于插入數(shù)據(jù)前查詢Oracle的序列名以填充主鍵。
@Data
@TableName("LINE_WELL")
@KeySequence(value = "LINE_WELL",clazz = Integer.class)
public class Well extends MyGeometry implements Serializable {

    @TableId(value = "OBJECTID", type = IdType.INPUT)
    private Integer objectid;

    @JsonIgnore
    protected Geometry shape;
}

6.3 自定義主鍵生成策略

在arcgis中卖宠,空間表中的主鍵字段為int巍杈,并且非自增,不能進(jìn)行修改扛伍。當(dāng)修改為自增時(shí)arcgis會(huì)出現(xiàn)一些錯(cuò)誤筷畦。因此,java后臺(tái)插入空間數(shù)據(jù)需要自己完成主鍵的查詢生成刺洒。
IKeyGenerator是Mybatis-Plus提供的接口鳖宾。此實(shí)現(xiàn)的作用是,當(dāng)指定這個(gè)主鍵生成策略時(shí)逆航,mp框架將會(huì)在新增數(shù)據(jù)前調(diào)用此實(shí)現(xiàn)鼎文,將結(jié)果賦值給對(duì)象的ID(類(lèi)似于Oracle的序列)
注意,該類(lèi)需要注入到Spring容器中

import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;

/**
 * @author wangqichang
 * @since 2019/8/30
 */
public class SqlServerKeyGenerator implements IKeyGenerator {
    @Override
    public String executeSql(String incrementerName) {
        return "select max(OBJECTID)+1 from " + incrementerName;
    }
}

6.4 Geometry對(duì)象持久化

當(dāng)我們調(diào)用mybatis-plus提供的方法持久化對(duì)象

 String str = "POLYGON ((113.52048666400003 22.248443089000034, 113.5206744190001 22.24822462700007, 113.52082998700007 22.248343788000057, 113.52060468200011 22.248547355000028, 113.52048666400003 22.248443089000034))";
        Geometry read = null;
        try {
            /**
             * 這里使用wkt文本生成了一個(gè)jts包下的Geometry對(duì)象
             */
            read = SpringContextUtil.getBean(WKTReader.class).read(str);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Well well = new Well();
        well.setShape(read);
        //這里是Mybatis-Plus提供的save接口因俐,調(diào)用其內(nèi)部實(shí)現(xiàn)直接儲(chǔ)存對(duì)象
        wellService.save(well);
        System.out.println("持久化成功");

執(zhí)行日志如下:
數(shù)據(jù)插入前執(zhí)行了SqlServerKeyGenerator中的sql獲取主鍵
插入代碼中字段shape為Geometry對(duì)象的二進(jìn)制

2019-08-30 15:54:23.541  INFO 8484 --- [nio-8905-exec-1] jdbc.sqltiming                           : SELECT max(OBJECTID) + 1 FROM LINE_WELL 
 {executed in 4 msec}
2019-08-30 15:54:23.631  INFO 8484 --- [nio-8905-exec-1] jdbc.sqltiming                           : INSERT INTO LINE_WELL (OBJECTID, shape) VALUES (3, '<byte[]>') 
 {executed in 17 msec}

7. 手寫(xiě)xml插入Geometry數(shù)據(jù)

使用SqlServer提供的函數(shù)geometry :: STGeomFromText( #{wktText},4326)將Geometry轉(zhuǎn)換成WKT文本再進(jìn)行插入

    <insert id="insertCorridorBySql" parameterType="com.zh.xxx.entity.xxx" useGeneratedKeys="true"
            keyProperty="objectid">
        INSERT INTO [LINE_CORRIDOR] (
         shape
        )
        values (
        geometry :: STGeomFromText( #{wktText},4326)
        )
    </insert>

注意,wktText是一個(gè)非表字段的臨時(shí)字段拇惋,我在此定義了一個(gè)父類(lèi),所有包含Geometry的空間表實(shí)體均繼承此類(lèi)抹剩,用于處理wkt文本

import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.WKTWriter;

import java.io.Serializable;

/**
 * 針對(duì)Geometry獲取Wkt文本字段做處理的Geometry父類(lèi)撑帖,getWktText替代getText,輸出三維wkt文本
 * 針對(duì)sql_server無(wú)法識(shí)別POLYGON Z 語(yǔ)法,對(duì)wkt文本進(jìn)行替換
 */
@Data
public class MyGeometry implements Serializable {

    /**
     * 三維wkt輸出澳眷,默認(rèn)為2D不帶Z
     */
    @TableField(exist = false)
    @JsonIgnore
    private WKTWriter wktWriter = new WKTWriter(3);

    /**
     * sql_server 與 jts wkt不兼容問(wèn)題
     */
    @TableField(exist = false)
    @JsonIgnore
    private static final String THREE_D_PRIFIX = "POLYGON Z";
    @TableField(exist = false)
    @JsonIgnore
    private static final String TWO_D_PRIFIX = "POLYGON";

    @JsonIgnore
    protected Geometry shape;


    @TableField(exist = false)
    @JsonIgnore
    private String wktText;

    public String getWktText() {
        if (StrUtil.isBlank(wktText)){
            if (getShape() != null) {
                String wkt = wktWriter.write(shape);
                if (wkt.startsWith(THREE_D_PRIFIX)) {
                    wktText = StrUtil.replace(wkt, THREE_D_PRIFIX, TWO_D_PRIFIX);
                } else {
                    wktText = wkt;
                }
            }
        }
        return wktText;
    }
}

8 采坑記錄:

8.1 jts與sqlserver識(shí)別的wkt不兼容

[2019-07-01 16:40:20,637] [ERROR] [http-nio-8905-exec-5] jdbc.audit 111 7. PreparedStatement.execute() INSERT INTO [zhundergroundcableline].[dbo].[LINE_CORRIDOR] ( [Shape] ) values ( geometry :: STGeomFromText( 'POLYGON Z((113.5079365 22.24850034 
0, 113.5078521 22.24845659 0, 113.5077674 22.24841271 0, 113.5076826 22.24836872 0, 113.5075978 22.24832498 0))',4326) ) 

com.microsoft.sqlserver.jdbc.SQLServerException: 在執(zhí)行用戶定義例程或聚合“geometry”期間出現(xiàn) .NET Framework 錯(cuò)誤: 
System.FormatException: 24142: 在位置 8 處應(yīng)為 "("磷仰,但輸入中實(shí)際為 "Z"。
System.FormatException: 
   在 Microsoft.SqlServer.Types.WellKnownTextReader.RecognizeToken(Char token)
   在 Microsoft.SqlServer.Types.SqlGeometry.GeometryFromText(OpenGisType type, SqlChars text, Int32 srid)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末境蔼,一起剝皮案震驚了整個(gè)濱河市灶平,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌箍土,老刑警劉巖逢享,帶你破解...
    沈念sama閱讀 211,561評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異吴藻,居然都是意外死亡瞒爬,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)侧但,“玉大人矢空,你說(shuō)我怎么就攤上這事≠骱幔” “怎么了屁药?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,162評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)柏锄。 經(jīng)常有香客問(wèn)我酿箭,道長(zhǎng),這世上最難降的妖魔是什么趾娃? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,470評(píng)論 1 283
  • 正文 為了忘掉前任缭嫡,我火速辦了婚禮,結(jié)果婚禮上抬闷,老公的妹妹穿的比我還像新娘妇蛀。我一直安慰自己,他們只是感情好笤成,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布评架。 她就那樣靜靜地躺著,像睡著了一般疹启。 火紅的嫁衣襯著肌膚如雪古程。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,806評(píng)論 1 290
  • 那天喊崖,我揣著相機(jī)與錄音挣磨,去河邊找鬼。 笑死荤懂,一個(gè)胖子當(dāng)著我的面吹牛茁裙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播节仿,決...
    沈念sama閱讀 38,951評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼晤锥,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了廊宪?” 一聲冷哼從身側(cè)響起矾瘾,我...
    開(kāi)封第一講書(shū)人閱讀 37,712評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎箭启,沒(méi)想到半個(gè)月后壕翩,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,166評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡傅寡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評(píng)論 2 327
  • 正文 我和宋清朗相戀三年放妈,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了北救。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,643評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡芜抒,死狀恐怖珍策,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情宅倒,我是刑警寧澤攘宙,帶...
    沈念sama閱讀 34,306評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站唉堪,受9級(jí)特大地震影響模聋,放射性物質(zhì)發(fā)生泄漏肩民。R本人自食惡果不足惜唠亚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望持痰。 院中可真熱鬧灶搜,春花似錦、人聲如沸工窍。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,745評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)患雏。三九已至鹏溯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間淹仑,已是汗流浹背丙挽。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,983評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留匀借,地道東北人颜阐。 一個(gè)月前我還...
    沈念sama閱讀 46,351評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像吓肋,于是被迫代替她去往敵國(guó)和親凳怨。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容