Commits

chunquedong committed e5f4d8d Draft

optimize dataSource for point

  • Participants
  • Parent commits aa25a9a

Comments (0)

Files changed (6)

chunmap/ctrl/fan/tools/SelectTool.fan

   Void select(Envelope env)
   {
     features := Feature[,]
+    cond := Condition
+    {
+      it.envelope = env
+    }
     map.layers.eachr |lyr|
     {
       if (lyr is VectorLayer && layerFilter(lyr))
       {
         VectorLayer vl := lyr
-        vl.dataSource.each(Condition.empty) |f|
+        vl.dataSource.each(cond) |f|
         {
           if (!multiSelect && features.size >0) {}
           else

chunmap/database/fan/PointGridFeatureSet.fan

+//
+// Copyright (c) 2009-2011, chunquedong
+//
+// This file is part of ChunMap project
+// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE version 3.0
+//
+// History:
+//   2011-11-30  Jed Young  Creation
+//
+
+using chunmapData
+using chunmapModel
+using slanActor
+using slanOrm::Context
+
+**
+** GridIndex dataSource for Point
+**
+class PointGridFeatureSet : FeatureSet
+{
+  Cache cache
+  DataProvider provider
+  GridIndex index
+
+  new make(DataProvider provider)
+    : super(provider.envelope, provider.schema)
+  {
+    this.provider = provider
+    cache = Cache(500, false)
+    index = GridIndex(Envelope(-180f, -90f, 180f, 90f), provider.indexDeep)
+  }
+
+  override This add(Feature f) { addCache(f); provider.context.insert(f); return this }
+  override Feature? remove(Feature f)
+  {
+    removeCache(f)
+    provider.context.deleteById(provider.schema, f.id)
+    return f
+  }
+
+  Void update(Feature f)
+  {
+    provider.context.update(f)
+    removeCache(f)
+    addCache(f)
+  }
+
+  override Void each(Condition condition, |Feature| filter)
+  {
+    if (condition.envelope == null) throw UnsupportedErr()
+    keys := index.findKeys(condition.envelope)
+    keys.each |skey|
+    {
+      dataUnit := getData(skey)
+      dataUnit.features.each |Feature f|
+      {
+        if (condition.envelope == null || condition.envelope.intersects(f.envelope))
+        {
+          filter(f)
+        }
+      }
+    }
+  }
+
+  private Bool addCache(Feature f)
+  {
+    skey := index.pointAt((f->geometry as GeoPoint).point)
+    DataUnit? obj := cache.get(skey)
+    if (obj != null)
+    {
+      obj.features.add(f)
+      return true
+    }
+    return false
+  }
+
+  private Bool removeCache(Feature f)
+  {
+    skey := index.pointAt((f->geometry as GeoPoint).point)
+    DataUnit? obj := cache.get(skey)
+    if (obj != null)
+    {
+      obj.features.remove(f)
+      return true
+    }
+    return false
+  }
+
+  private DataUnit getData(Str skey)
+  {
+    obj := cache.get(skey)
+    if (obj == null)
+    {
+      obj = provider.find(skey)
+      cache.set(skey, obj)
+    }
+    return obj
+  }
+
+  override Feature? find(Condition condition, |Feature->Bool| filter)
+  {
+    if (condition.envelope == null) throw UnsupportedErr()
+    keys := index.findKeys(envelope)
+
+    Feature? result := null
+    keys.find |skey|
+    {
+      dataUnit := getData(skey)
+      result = dataUnit.features.find |Feature f->Bool|
+      {
+        if (condition.envelope == null || condition.envelope.intersects(f.envelope))
+        {
+          return filter(f)
+        }
+        return false
+      }
+      return (result != null)
+    }
+    return result
+  }
+
+//////////////////////////////////////////////////////////////////////////
+// Serialization
+//////////////////////////////////////////////////////////////////////////
+
+  override Str toStr()
+  {
+    str := provider.context.curId +","+ provider.schema.name + "," + provider.indexDeep
+    return str
+  }
+
+  static new fromStr(Str s)
+  {
+    t := s.split(',')
+    fset := PointGridFeatureSet(DataProvider.makeByTable(Context(t[0]), t[1], t[2].toInt)){}
+    return fset
+  }
+}

chunmap/database/fan/ShpToDb.fan

   QuartTreeIndex? index
   GridIndex? grid
   Schema metadataSchema := DataProvider.makeMetadataSchema
+  Bool makeGridIndex := false
 
   Void open(Schema table)
   {
     buf.flip
     values.add(buf)
 
-    values.add(index.key(old.geometry.envelope))
-
+    //optimize for point
+    if (old.geometry.geometryType == GeometryType.point)
+    {
+      p := (old.geometry as GeoPoint).point
+      values.add(grid.pointAt(p))
+    }
+    else
+    {
+      values.add(index.key(old.geometry.envelope))
+    }
     nr := Record(ns, values)
     return nr
   }
         echo("created $ns.name")
 
         //create Grid Index table
-        gridIndexSchema = makeGridIndexSchema(ns.name + "_GridIndex")
-        if (c.tableExists(gridIndexSchema))
+        if (makeGridIndex)
         {
-          c.dropTable(gridIndexSchema)
+          gridIndexSchema = makeGridIndexSchema(ns.name + "_GridIndex")
+          if (c.tableExists(gridIndexSchema))
+          {
+            c.dropTable(gridIndexSchema)
+          }
+          c.createTable(gridIndexSchema)
         }
-        c.createTable(gridIndexSchema)
       }
       nf := changeRecord(ns, f)
       c.insert(nf)
 
       //insert Grid index record
-      Str uuid := nf.get(ns.find("UUID").index)
-      keys := grid.geomKeys(f.geometry)
-      Int size := keys.size
-      keys.each |key|
+      if (makeGridIndex)
       {
-        r := Record(gridIndexSchema)
-        r.set(0, uuid)
-        r.set(1, key)
-        r.set(2, size)
-        c.insert(r)
-        echo(".")
+        Str uuid := nf.get(ns.find("UUID").index)
+        keys := grid.geomKeys(f.geometry)
+        Int size := keys.size
+        keys.each |key|
+        {
+          r := Record(gridIndexSchema)
+          r.set(0, uuid)
+          r.set(1, key)
+          r.set(2, size)
+          c.insert(r)
+          //echo(".")
+        }
+        echo("$f.id $uuid")
       }
-      echo("$f.id $uuid")
     }
 
     //build metadata
     if (c.tableExists(metadataSchema))
     {
-      c.dropTable(metadataSchema)
+      //c.dropTable(metadataSchema)
     }
-    c.createTable(metadataSchema)
+    else
+    {
+      c.createTable(metadataSchema)
+    }
     setMataValue("minX", layer0.envelope.minX.toStr)
     setMataValue("minY", layer0.envelope.minY.toStr)
     setMataValue("maxX", layer0.envelope.maxX.toStr)
 
   private Void setMataValue(Str key, Str value)
   {
+    c.deleteById(metadataSchema, key)
     Record obj := metadataSchema.newInstance
     obj.set(0, key)
     obj.set(1, value)

chunmap/model/fan/index/Grid.fan

   **
   ** get tile coord by position
   **
-  private Tile getTile(Point p, Int z, Bool isMax)
+  Tile getTile(Point p, Int z, Bool isMax)
   {
     num := 2f.pow(z.toFloat).toInt
     x := ((p.x - minX)  * num) / width

chunmap/model/fan/index/GridIndex.fan

   }
 
   **
+  ** tile key of the point at
+  **
+  Str pointAt(Point p)
+  {
+    grid.getTile(p, deep, false).toKey
+  }
+
+  **
   ** find all keys that intersects env
   **
   Str[] findKeys(Envelope env)

example/DatabaseTest.fan

 
 using fwt
 using gfx
-using gfx2
-using gfx2Imp
+using fgfxFwt
 
 using slanActor
 using slanData
     conn := SqlConn.open(uri, null, null)
     Actor.locals[Context.id] = conn
     c := Context()
-    fset := GridDataFeatureSet(GridDataProvider.makeByTable(c, "cntry02", 3)){}
+    fset := QuartTreeFeatureSet(DataProvider.makeByTable(c, "cntry02", 3)){}
+    //fset := PointGridFeatureSet(DataProvider.makeByTable(c, "city1")){}
     return VectorLayer.makeFeatureSet(fset)
   }
 
   Void main()
   {
+    FwtToolkitEnv.init
+
     map := MapCanvas()
     map.ctrl.layers.add(makeLayer)
     //map.ctrl.fullView