Forráskód Böngészése

feat 技术调研验证

lihao1 3 éve
szülő
commit
587ad09245
37 módosított fájl, 1354 hozzáadás és 219 törlés
  1. 7 0
      build.gradle
  2. 7 7
      cadengine/build.gradle
  3. 84 6
      cadengine/src/main/java/cn/sagacloud/android/cadengine/FloorScene.kt
  4. 4 0
      cadengine/src/main/java/cn/sagacloud/android/cadengine/items/BaseMapItem.kt
  5. 20 6
      cadengine/src/main/java/cn/sagacloud/android/cadengine/items/DoorItem.kt
  6. 17 50
      cadengine/src/main/java/cn/sagacloud/android/cadengine/items/EquipItem.kt
  7. 49 0
      cadengine/src/main/java/cn/sagacloud/android/cadengine/items/GestureItem.kt
  8. 144 0
      cadengine/src/main/java/cn/sagacloud/android/cadengine/items/GridItem.kt
  9. 27 13
      cadengine/src/main/java/cn/sagacloud/android/cadengine/items/PipeLineItem.kt
  10. 92 0
      cadengine/src/main/java/cn/sagacloud/android/cadengine/items/PipeNodeItem.kt
  11. 34 4
      cadengine/src/main/java/cn/sagacloud/android/cadengine/items/PointItem.kt
  12. 15 4
      cadengine/src/main/java/cn/sagacloud/android/cadengine/items/QrcodeItem.kt
  13. 13 4
      cadengine/src/main/java/cn/sagacloud/android/cadengine/items/TunableSpaceItem.kt
  14. 3 1
      cadengine/src/main/java/cn/sagacloud/android/cadengine/items/WallItem.kt
  15. 25 0
      cadengine/src/main/java/cn/sagacloud/android/cadengine/types/Grid.kt
  16. 5 2
      cadengine/src/main/java/cn/sagacloud/android/cadengine/types/PipeLine.kt
  17. BIN
      cadengine/src/main/res/drawable/centertack_img.png
  18. 17 9
      demo/build.gradle
  19. BIN
      demo/libs/tbs_sdk_thirdapp_v4.3.0.67_43967_sharewithdownloadwithfile_withoutGame_obfs_20200923_120452.jar
  20. 2 1
      demo/src/main/AndroidManifest.xml
  21. 24 2
      demo/src/main/java/com/sybotan/android/demo/DemoApp.kt
  22. 371 23
      demo/src/main/java/com/sybotan/android/demo/activities/GraphyActivity.kt
  23. 5 5
      demo/src/main/java/com/sybotan/android/demo/activities/MainActivity.kt
  24. 12 1
      demo/src/main/java/com/sybotan/android/demo/activities/PocActivity.kt
  25. 1 2
      demo/src/main/java/com/sybotan/android/demo/activities/WebViewActivity.kt
  26. 36 0
      demo/src/main/java/com/sybotan/android/demo/tools/AssetsUtil.java
  27. 130 0
      demo/src/main/java/com/sybotan/android/demo/tools/NetworkManager.java
  28. 1 1
      demo/src/main/java/com/sybotan/android/demo/viewmodel/GraphyVM.kt
  29. 24 5
      demo/src/main/res/layout/activity_graphy.xml
  30. 6 0
      demo/src/main/res/values/strings.xml
  31. 6 6
      settings.gradle
  32. 98 36
      sybotan-android-graphy/src/main/java/com/sybotan/android/graphy/SGraphyItem.kt
  33. 20 7
      sybotan-android-graphy/src/main/java/com/sybotan/android/graphy/SGraphyScene.kt
  34. 49 19
      sybotan-android-graphy/src/main/java/com/sybotan/android/graphy/SGraphyView.kt
  35. 3 1
      sybotan-android-graphy/src/main/java/com/sybotan/android/graphy/items/SGraphyRectItem.kt
  36. 2 2
      sybotan-android-views/build.gradle
  37. 1 2
      sybotan-android-works/build.gradle

+ 7 - 0
build.gradle

@@ -54,6 +54,13 @@ allprojects {
 
         jcenter()
         google()
+        maven {
+            url 'http://nexus.arashivision.com:9999/repository/maven-public/'
+            credentials {
+                username = 'deployment'
+                password = 'test123'
+            }
+        }
 
     }
     tasks.withType(Javadoc) {

+ 7 - 7
cadengine/build.gradle

@@ -87,15 +87,15 @@ dependencies {
 //    implementation group: "cn.sagacloud", name: "sybotan-android-graphy", version: SYBOTAN_ANDROID_VERSION
 //    implementation group: "cn.sagacloud", name: "sybotan-android-database", version: SYBOTAN_ANDROID_VERSION
     implementation group: 'cn.sagacloud', name: 'saga-kotlin-base', version: SAGA_KOTLIN_VERSION
-    implementation group: 'cn.sagacloud', name: 'saga-kotlin-database', version: SAGA_KOTLIN_VERSION
-//    implementation project(':sybotan-android-base')
-//    implementation project(':sybotan-android-database')
-//    implementation project(':sybotan-android-graphy')
+//    implementation group: 'cn.sagacloud', name: 'saga-kotlin-database', version: SAGA_KOTLIN_VERSION
+    implementation project(':sybotan-android-base')
+    implementation project(':sybotan-android-database')
+    implementation project(':sybotan-android-graphy')
 
     // Sybotan依赖
-    implementation group: 'cn.sagacloud', name: 'saga-kotlin-database', version: SAGA_KOTLIN_VERSION
-    implementation group: 'cn.sagacloud', name: 'sybotan-android-base', version: SYBOTAN_ANDROID_VERSION
-    implementation group: 'cn.sagacloud', name: 'sybotan-android-graphy', version: SYBOTAN_ANDROID_VERSION
+//    implementation group: 'cn.sagacloud', name: 'saga-kotlin-database', version: SAGA_KOTLIN_VERSION
+//    implementation group: 'cn.sagacloud', name: 'sybotan-android-base', version: SYBOTAN_ANDROID_VERSION
+//    implementation group: 'cn.sagacloud', name: 'sybotan-android-graphy', version: SYBOTAN_ANDROID_VERSION
     //noinspection GradleDependency
     implementation 'org.greenrobot:eventbus:3.0.0'
     implementation 'com.google.code.gson:gson:2.8.1'

+ 84 - 6
cadengine/src/main/java/cn/sagacloud/android/cadengine/FloorScene.kt

@@ -2,16 +2,16 @@ package cn.sagacloud.android.cadengine
 
 import android.graphics.Color
 import android.graphics.PointF
+import android.text.TextUtils
 import android.util.Log
+import cn.sagacloud.android.cadengine.items.*
 import cn.sagacloud.android.cadengine.types.*
 import com.sybotan.android.graphy.SGraphyScene
+import com.sybotan.android.graphy.SMotionEvent
+import com.sybotan.android.graphy.events.SGraphyViewMoveEvent
 import com.sybotan.base.extensions.toJson
 import com.sybotan.base.utils.SHttpUtil
 import com.sybotan.base.utils.SJsonUtil
-import android.text.TextUtils
-import cn.sagacloud.android.cadengine.items.*
-import com.sybotan.android.graphy.SMotionEvent
-import com.sybotan.android.graphy.events.SGraphyViewMoveEvent
 import org.greenrobot.eventbus.Subscribe
 import org.greenrobot.eventbus.ThreadMode
 
@@ -151,6 +151,7 @@ open class FloorScene : SGraphyScene() {
 
     /** 管道 */
     val pipeItemList = ArrayList<PipeLineItem>()
+    val pipeNodeList = ArrayList<PipeNodeItem>()
 
     /** 有任务的空间 list   */
     var tunableSpaceList = ArrayList<TunableSpaceItem>()
@@ -427,20 +428,24 @@ open class FloorScene : SGraphyScene() {
                     if (hasChose) {
                         if (space.calculateArea() < choseSpace!!.calculateArea()) {
                             space.outPaint.color = Color.rgb(0xbd, 0xe8, 0xfe)
+                            space.outPaint.strokeWidth = 500f
                             space.paint.color = Opt.spaceChoseColor
                             mapType = "space"
                             choseSpace = space
                             hasChose = true
+
                         }
                     } else {
                         space.outPaint.color = Color.rgb(0xbd, 0xe8, 0xfe)
                         space.paint.color = Opt.spaceChoseColor
+                        space.outPaint.strokeWidth = 500f
                         mapType = "space"
                         choseSpace = space
                         hasChose = true
                     }
                 } else {
                     space.paint.color = Opt.spaceColor
+                    space.outPaint.strokeWidth = 50f
                     space.outPaint.color = Color.rgb(0xff, 0xff, 0xff)
                 }
             }
@@ -491,7 +496,7 @@ open class FloorScene : SGraphyScene() {
             pointf.x = e.x
             pointf.y = -e.y
             pipeLineList.add(pointf)
-            pipe.points!!.add(pipeLineList)
+            pipe.points!!.addAll(pipeLineList)
             var item = PipeLineItem(pipe, null)
             item!!.isVisible = true
             item!!.zOrder = 100000f
@@ -523,9 +528,81 @@ open class FloorScene : SGraphyScene() {
             if (eqItem != null) {
                 removeItem(eqItem!!)
             }
+
+            var dist = 500.00
+            for (index in 0..choseSpace!!.mPoints.size - 1) {
+
+
+                val point1 = choseSpace!!.mPoints.get(index)
+                var point2 = PointF()
+                if (index == choseSpace!!.mPoints.size - 1) {
+                    point2 = choseSpace!!.mPoints.get(0)
+                } else {
+                    point2 = choseSpace!!.mPoints.get(index + 1)
+                }
+
+
+                val l1 = Math.sqrt(Math.pow(Math.abs(point1.x - point2.x).toDouble(), 2.0) + Math.pow(Math.abs(point1.y - point2.y).toDouble(), 2.0)).toFloat()
+                val l2 = Math.sqrt(Math.pow(Math.abs(point1.x - e.x).toDouble(), 2.0) + Math.pow(Math.abs(point1.y + e.y).toDouble(), 2.0)).toFloat()
+                val l3 = Math.sqrt(Math.pow(Math.abs(point2.x - e.x).toDouble(), 2.0) + Math.pow(Math.abs(point2.y + e.y).toDouble(), 2.0)).toFloat()
+                val halfP = (l1 + l2 + l3) / 2
+                val s = Math.sqrt(halfP * (halfP - l1) * (halfP - l2) * (halfP - l3).toDouble())
+                val h = 2 * s / l1
+                if (h < dist) {
+                    dist = h
+                    var k1: Float
+                    if (point1.x - point2.x == 0f) {
+                        k1 = 0f
+                    } else {
+                        k1 = (point1.y - point2.y) / (point1.x - point2.x)
+                    }
+
+                    val b1 = point1.y - k1 * point1.x
+
+                    var k2: Float
+                    if (k1 == 0f) {
+                        k2 = 0f
+                    } else {
+                        k2 = -1 / k1
+                    }
+
+                    val b2 = e.y - k2 * e.x
+
+                    val x1 = (b2 - b1) / (k1 - k2)
+                    val y1 = k2 * (e.x) + b2
+
+                    if (point1.x - point2.x == 0f) {
+                        point.mX = point1.x
+                        if (Math.abs(k1) == 0f) {
+                            point.mY = e.y
+                        } else {
+                            if (point1.y - point2.y == 0f) {
+                                point.mY = -point1.y
+                            } else {
+                                point.mY = y1
+                            }
+                        }
+
+                    } else {
+                        if (Math.abs(k1) == 0f) {
+                            point.mX = e.x
+                        } else {
+                            point.mX = x1
+                        }
+                        if (point1.y - point2.y == 0f) {
+                            point.mY = -point1.y
+                        } else {
+                            point.mY = y1
+                        }
+                    }
+
+                }
+
+            }
+
             eqItem = EquipItem(point, null, defaultPointScale)
             eqItem!!.isVisible = true
-            eqItem!!.zOrder = 100000f
+            eqItem!!.zOrder = 10000012f
             addItem(eqItem!!)
         }
 
@@ -535,6 +612,7 @@ open class FloorScene : SGraphyScene() {
         return super.onSingleTapUp(e)
     }
 
+
     interface OnSingleTopUp {
         fun onSingUp(x: Float, y: Float)
     }

+ 4 - 0
cadengine/src/main/java/cn/sagacloud/android/cadengine/items/BaseMapItem.kt

@@ -5,6 +5,8 @@ import android.content.Context
 import android.graphics.*
 import cn.sagacloud.android.cadengine.R
 import com.sybotan.android.graphy.SGraphyItem
+import com.sybotan.android.graphy.enums.SGraphyItemFlag
+import java.util.*
 
 
 /**
@@ -20,6 +22,8 @@ class BaseMapItem(context: Context, parent: SGraphyItem? = null) :
     init {
         mPaint.alpha = 0X80
         mBitmap = BitmapFactory.decodeResource(context.resources, R.drawable.pipecadcolor)
+        flags = EnumSet.of(SGraphyItemFlag.ItemIsMovable)
+        val contains = flags.contains(SGraphyItemFlag.ItemIsMovable)
     }
 
     /**

+ 20 - 6
cadengine/src/main/java/cn/sagacloud/android/cadengine/items/DoorItem.kt

@@ -4,6 +4,8 @@ import android.graphics.*
 import cn.sagacloud.android.cadengine.types.Door
 import cn.sagacloud.android.cadengine.Opt
 import com.sybotan.android.graphy.SGraphyItem
+import com.sybotan.android.graphy.enums.SGraphyItemFlag
+import java.util.*
 import kotlin.math.atan2
 import kotlin.math.sqrt
 import kotlin.math.abs
@@ -13,13 +15,16 @@ class DoorItem(private val data: Door, parent: SGraphyItem? = null) : SGraphyIte
     /** 画笔 */
     private val paint1 = Paint()
     private val paint2 = Paint()
+
     /** 门长度 */
     private var d = 0f
 
     /** 角度  */
     private var angle = 0f
+
     /** 旋转点 */
     private var p = PointF(0f, 0f)
+
     /** 旋转起始角度 */
     private var startAng = 0f
 
@@ -27,7 +32,7 @@ class DoorItem(private val data: Door, parent: SGraphyItem? = null) : SGraphyIte
      * 构造
      */
     init {
-
+        flags = EnumSet.of(SGraphyItemFlag.ItemIsSelectable, SGraphyItemFlag.ItemIsFocusable)
         try {
             paint1.style = Paint.Style.STROKE
             paint1.color = Opt.doorColor
@@ -48,11 +53,11 @@ class DoorItem(private val data: Door, parent: SGraphyItem? = null) : SGraphyIte
                 val fo = atan2(-data.faceDirection!!.y, data.faceDirection!!.x)
                 // 门朝向角度
                 angle =
-                    if (data.faceDirection!!.x > 0) {
-                        fo
-                    } else {
-                        fo + Math.PI.toFloat()
-                    }
+                        if (data.faceDirection!!.x > 0) {
+                            fo
+                        } else {
+                            fo + Math.PI.toFloat()
+                        }
 
 ////                val dir = data.faceDirection!!.x * (data.handDirection!!.y - data.faceDirection!!.y) - data.faceDirection!!.y * (data.handDirection!!.x - data.faceDirection!!.x)
 ////                if (dir < 0) {
@@ -95,6 +100,10 @@ class DoorItem(private val data: Door, parent: SGraphyItem? = null) : SGraphyIte
         }
     } // Constructor
 
+    override fun boundingRect(): RectF {
+        return RectF(data.outLine!![0][0].x, data.outLine!![0][0].y, data.outLine!![0][1].x, data.outLine!![0][1].y)
+    }
+
     /**
      * Item绘制操作
      *
@@ -106,6 +115,11 @@ class DoorItem(private val data: Door, parent: SGraphyItem? = null) : SGraphyIte
 //        canvas.rotate(angle * 180f / Math.PI.toFloat())
 //
 //        canvas.drawLine(0f, 0f, d, 0f, paint1)
+        paint1.color = if (this.focus) {
+            Color.RED
+        } else {
+            Opt.doorColor
+        }
         canvas.drawLine(data.outLine!![0][0].x, -data.outLine!![0][0].y, data.outLine!![0][1].x, -data.outLine!![0][1].y, paint1)
 //        canvas.drawArc(-d, -d, d, d, startAng, 90f, false, paint2)
         super.onDraw(canvas)

+ 17 - 50
cadengine/src/main/java/cn/sagacloud/android/cadengine/items/EquipItem.kt

@@ -5,8 +5,14 @@ import android.graphics.Canvas
 import android.graphics.Color
 import android.graphics.Paint
 import android.graphics.drawable.BitmapDrawable
+import android.util.Log
+import android.view.GestureDetector
+import android.view.MotionEvent
 import cn.sagacloud.android.cadengine.types.Point
 import com.sybotan.android.graphy.SGraphyItem
+import com.sybotan.android.graphy.SMotionEvent
+import com.sybotan.android.graphy.enums.SGraphyItemFlag
+import java.util.*
 
 
 /**
@@ -14,55 +20,14 @@ import com.sybotan.android.graphy.SGraphyItem
  * Date: 2021/6/4
  */
 class EquipItem(val data: Point, parent: SGraphyItem? = null, defaultScale: Float) :
-    SGraphyItem(parent) {
+        SGraphyItem(parent) {
     /** 新建 画笔 */
     val mPaint_inner = Paint()
     val mPaint_center = Paint()
-    val mPaint_outer = Paint()
-
-    /** 按时 画笔 */
-    val not_overTime_inner = Paint()
-    val not_overTime_outer = Paint()
-
-    /** 逾期 画笔 */
-    val overTime_inner = Paint()
-    val overTime_outer = Paint()
-
-    /** 承接查验复核中 */
-    val checkReviewing_inner = Paint()
-    val checkReviewing_outer = Paint()
     var mDefaultScale = 0f
-    //var defaultScale = 1.0f
-    //var mScale = 1f
 
     init {
         mDefaultScale = defaultScale;
-        /** 按时 */
-        not_overTime_inner.color = Color.parseColor("#ffffff")
-        not_overTime_inner.isAntiAlias = true
-        not_overTime_inner.style = Paint.Style.FILL
-
-        not_overTime_outer.color = Color.parseColor("#04df97")//绿色
-        not_overTime_outer.isAntiAlias = true
-        not_overTime_outer.style = Paint.Style.FILL
-
-        /** 逾期 */
-        overTime_inner.color = Color.parseColor("#ffffff")
-        overTime_inner.isAntiAlias = true
-        overTime_inner.style = Paint.Style.FILL
-
-        overTime_outer.color = Color.parseColor("#ff3b33")//红色
-        overTime_outer.isAntiAlias = true
-        overTime_outer.style = Paint.Style.FILL
-
-        /** 承接查验复核中 */
-        checkReviewing_inner.color = Color.parseColor("#ffffff")
-        checkReviewing_inner.isAntiAlias = true
-        checkReviewing_inner.style = Paint.Style.FILL
-
-        checkReviewing_outer.color = Color.parseColor("#F7B500")//黄色
-        checkReviewing_outer.isAntiAlias = true
-        checkReviewing_outer.style = Paint.Style.FILL
 
         /** 新建 */
         //内圈
@@ -70,13 +35,15 @@ class EquipItem(val data: Point, parent: SGraphyItem? = null, defaultScale: Floa
         mPaint_inner.isAntiAlias = true
         mPaint_inner.style = Paint.Style.FILL
         //中圈
-        mPaint_center.color = Color.parseColor("#ffffff")
+        mPaint_center.color = Color.parseColor("#ff00ff")
         mPaint_center.isAntiAlias = true
         mPaint_center.style = Paint.Style.FILL
-        //外圈
-        mPaint_outer.color = Color.parseColor("#260c90eb")
-        mPaint_outer.isAntiAlias = true
-        mPaint_outer.style = Paint.Style.FILL
+        flags = EnumSet.of(SGraphyItemFlag.ItemIsMovable, SGraphyItemFlag.ItemIsSelectable, SGraphyItemFlag.ItemIsFocusable)
+    }
+
+    override fun onSingleTapUp(e: SMotionEvent): Boolean {
+        Log.e("TAG", "x=" + e.viewX.toString() + ",y=" + e.viewY.toString())
+        return super.onSingleTapUp(e)
     }
 
     /**
@@ -85,11 +52,11 @@ class EquipItem(val data: Point, parent: SGraphyItem? = null, defaultScale: Floa
      * @param   canvas          画布
      * @param   rect            绘制区域
      */
+
     override fun onDraw(canvas: Canvas) {
         data.scalePoint = mDefaultScale / scene!!.view!!.scale
-//        canvas.drawCircle(data.mX, data.mY, 2400f * data.scalePoint, mPaint_outer)
-        canvas.drawCircle(data.mX, data.mY, 500f * data.scalePoint, mPaint_center)
-        canvas.drawCircle(data.mX, data.mY, 1500f * data.scalePoint, mPaint_inner)
+        canvas.drawCircle(data.mX, data.mY, 500f, mPaint_center)
+//        canvas.drawCircle(data.mX, -data.mY, 1500f, mPaint_inner)
         super.onDraw(canvas)
     } // Function onDraw()
 

+ 49 - 0
cadengine/src/main/java/cn/sagacloud/android/cadengine/items/GestureItem.kt

@@ -0,0 +1,49 @@
+package cn.sagacloud.android.cadengine.items
+
+import android.graphics.*
+import android.view.MotionEvent
+import cn.sagacloud.android.cadengine.types.Door
+import com.sybotan.android.graphy.SGraphyItem
+import java.util.*
+
+
+class GestureItem(parent: SGraphyItem? = null) : SGraphyItem(parent) {
+    /** 画笔 */
+    private val paint = Paint()
+    private val path = Path()
+
+    /**
+     * 构造
+     */
+    init {
+
+//        this.mContext = context;
+        paint.setAntiAlias(true)
+        paint.setStyle(Paint.Style.STROKE)
+        paint.setStrokeWidth(5f)
+        paint.setColor(Color.BLACK)
+    } // Constructor
+
+    override fun onActionMove(event: MotionEvent) {
+        super.onActionMove(event)
+
+    }
+
+    override fun onActionUp() {
+        super.onActionUp()
+    }
+
+
+
+    /**
+     * Item绘制操作
+     *
+     * @param   canvas          画布
+     * @param   rect            绘制区域
+     */
+    override fun onDraw(canvas: Canvas) {
+        // 通过画布绘制多点形成的图形
+        canvas.drawPath(path, paint)
+        super.onDraw(canvas)
+    } // Function onDraw()
+} // Class DoorItem

+ 144 - 0
cadengine/src/main/java/cn/sagacloud/android/cadengine/items/GridItem.kt

@@ -0,0 +1,144 @@
+package cn.sagacloud.android.cadengine.items
+
+import android.annotation.SuppressLint
+import android.graphics.*
+import android.text.TextPaint
+import cn.sagacloud.android.cadengine.Opt
+import cn.sagacloud.android.cadengine.types.Grid
+import com.sybotan.android.graphy.SGraphyItem
+import com.sybotan.android.graphy.SGraphyView
+
+
+/**
+ * 墙item
+ *
+ * @author  郝建龙
+ */
+class GridItem(private val data: Grid, parent: SGraphyItem? = null, view: SGraphyView) : SGraphyItem(parent) {
+    /** 画笔 */
+    private val paint = Paint()
+
+    /** 画笔 */
+    private val paintText = TextPaint()
+
+    /** 墙轮廓 */
+    private val pathList = ArrayList<Path>()
+
+    /** X坐标最小值  */
+    private var minX = 0f
+
+    /** X坐标最大值  */
+    private var maxX = 0f
+
+    /** Y坐标最小值  */
+    private var minY = 0f
+
+    /** Y坐标最大值  */
+    private var maxY = 0f
+    lateinit var view: SGraphyView
+
+    /**
+     * 构造
+     */
+    init {
+        try {
+            this.view = view
+            val path = Path()
+            path.moveTo(data.location!!.points!![0].x, -data.location!!.points!![0].y)
+            path.lineTo(data.location!!.points!![1].x, -data.location!!.points!![1].y)
+            pathList.add(path)
+
+            paintText.style = Paint.Style.FILL
+            paintText.flags = Paint.ANTI_ALIAS_FLAG
+            paintText.color = Opt.textColor
+            paintText.textSize = 1500f
+            val font: Typeface = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD)
+            paintText.setTypeface(font)
+
+//            if (data.outLine != null && data.outLine!!.size > 0 && data.outLine!![0].size > 0) {
+//                minX = data.outLine!![0][0].x
+//                maxX = data.outLine!![0][0].x
+//                minY = data.outLine!![0][0].y
+//                maxY = data.outLine!![0][0].y
+//
+//                for (line in data.outLine!!) {
+//                    if (line.size < 1) {
+//                        continue
+//                    }
+//
+//                    val path = Path()
+//                    path.moveTo(line[0].x, -line[0].y)
+//                    for (p in line) {
+//                        if (p.x < minX) {
+//                            minX = p.x
+//                        }
+//                        if (p.x > maxX) {
+//                            maxX = p.x
+//                        }
+//                        if (-p.y < minY) {
+//                            minY = -p.y
+//                        }
+//                        if (-p.y > maxY) {
+//                            maxY = -p.y
+//                        }
+//                        path.lineTo(p.x, -p.y)
+//                    }
+//                    path.close()
+//                    pathList.add(path)
+//                }
+//            }
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+    } // Constructor
+
+    /**
+     * Item对象边界区域
+     *
+     * @return  边界区域
+     */
+    override fun boundingRect(): RectF {
+        return RectF(minX, minY, maxX, maxY)
+    } // Function boundingRect()
+
+    /**
+     * Item绘制操作
+     *
+     * @param   canvas          画布
+     * @param   rect            绘制区域
+     */
+    @SuppressLint("DrawAllocation")
+    override fun onDraw(canvas: Canvas) {
+        paint.style = Paint.Style.STROKE
+        paint.strokeJoin = Paint.Join.ROUND
+        paint.isAntiAlias = true
+        paint.pathEffect = DashPathEffect(floatArrayOf(800f, 600f), 0f)
+        for (path in pathList) {
+            canvas.drawPath(path, paint)
+        }
+
+
+        var k = (data.location!!.points!![0].y - data.location!!.points!![1].y) / (data.location!!.points!![0].x - data.location!!.points!![1].x)
+        if (data.location!!.points!![0].x - data.location!!.points!![1].x == 0f) {
+            k = 1f
+        }
+        val b = data.location!!.points!![0].y - k * data.location!!.points!![0].x
+        val mapFromScene = view.mapToScene(0f, 0f)
+        var y = 0f
+        var x = 0f
+        if (k >= 1 || k <= -1) {
+            y = mapFromScene.y + 2000
+            if (mapFromScene.y < -data.location!!.points!![0].y) {
+                y = -data.location!!.points!![0].y
+            }
+            x = data.location!!.points!![0].x
+        } else {
+            x = mapFromScene.x
+            if (mapFromScene.x < data.location!!.points!![0].x) {
+                x = data.location!!.points!![0].x
+            }
+            y = -(k * mapFromScene.x + b)
+        }
+        canvas.drawText(data.name!!, x, y, paintText)
+    } // Function onDraw()
+} // Class WallItem

+ 27 - 13
cadengine/src/main/java/cn/sagacloud/android/cadengine/items/PipeLineItem.kt

@@ -5,6 +5,9 @@ import cn.sagacloud.android.cadengine.Opt
 import cn.sagacloud.android.cadengine.types.PipeLine
 import cn.sagacloud.android.cadengine.types.Point
 import com.sybotan.android.graphy.SGraphyItem
+import com.sybotan.android.graphy.enums.SGraphyItemFlag
+import java.util.*
+import kotlin.collections.ArrayList
 
 /**
  * Created by lihao.
@@ -25,21 +28,32 @@ class PipeLineItem(val data: PipeLine, parent: SGraphyItem? = null) : SGraphyIte
 
     var mPoints = ArrayList<PointF>()
 
+    /** X坐标最小值  */
+    private var minX = 0f
+
+    /** X坐标最大值  */
+    private var maxX = 0f
+
+    /** Y坐标最小值  */
+    private var minY = 0f
+
+    /** Y坐标最大值  */
+    private var maxY = 0f
+
     init {
         try {
             zOrder = 1f
 
-
+            minX = data.points!![0].x
+            maxX = data.points!![0].x
+            minY = data.points!![0].y
+            maxY = data.points!![0].y
+            val path = Path()
+            path.moveTo(data.points!![0].x, -data.points!![0].y)
             for (line in data.points!!) {
-                if (line.size < 1) {
-                    continue
-                }
 
-                val path = Path()
-                path.moveTo(line[0].x, -line[0].y)
-                for (p in line) {
-                    path.lineTo(p.x, -p.y)
-                }
+                path.lineTo(line.x, -line.y)
+
                 if (pipePath == null) {
                     pipePath = path;
                 } else {
@@ -50,7 +64,6 @@ class PipeLineItem(val data: PipeLine, parent: SGraphyItem? = null) : SGraphyIte
         } catch (e: Exception) {
             e.printStackTrace()
         }
-
         outPaint.style = Paint.Style.STROKE
         outPaint.strokeJoin = Paint.Join.ROUND
         outPaint.isAntiAlias = true
@@ -79,9 +92,10 @@ class PipeLineItem(val data: PipeLine, parent: SGraphyItem? = null) : SGraphyIte
 
             canvas.drawPath(pipePath!!, outPaint)
             val size = data.points!!.size - 1
-            val get = data.points!!.get(size).get(data.points!!.get(size).size - 1)
-            canvas.drawCircle(data.points!!.get(0).get(0).x, -data.points!!.get(0).get(0).y, 160f, mPaint_inner)
-            canvas.drawCircle(get.x, -get.y, 160f, mPaint_inner)
+//            val get = data.points!!.get(size).get(data.points!!.get(size).size - 1)
+//            val get1 = data.points!!.get(0).get(0)
+//            canvas.drawCircle(get1.x, -get1.y, 160f, mPaint_inner)
+//            canvas.drawCircle(get.x, -get.y, 160f, mPaint_inner)
         }
     } // Function onDraw()
 }

+ 92 - 0
cadengine/src/main/java/cn/sagacloud/android/cadengine/items/PipeNodeItem.kt

@@ -0,0 +1,92 @@
+package cn.sagacloud.android.cadengine.items
+
+import android.graphics.*
+import cn.sagacloud.android.cadengine.Opt
+import cn.sagacloud.android.cadengine.types.PipeLine
+import cn.sagacloud.android.cadengine.types.Point
+import com.sybotan.android.graphy.SGraphyItem
+import com.sybotan.android.graphy.SMotionEvent
+import com.sybotan.android.graphy.enums.SGraphyItemFlag
+import java.util.*
+import kotlin.collections.ArrayList
+
+/**
+ * Created by lihao.
+ * Date: 2021/6/7
+ */
+class PipeNodeItem(val data: PointF, parent: SGraphyItem? = null) : SGraphyItem(parent) {
+    /** 画笔 */
+    val paint = Paint()
+    val mPaint_inner = Paint()
+
+    val outPaint = Paint()
+
+    var x: Float = 0f
+    var y: Float = 0f
+    lateinit var onScroll: OnScroll
+
+    init {
+        try {
+            flags = EnumSet.of(SGraphyItemFlag.ItemIsMovable, SGraphyItemFlag.ItemIsSelectable, SGraphyItemFlag.ItemIsFocusable)
+
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+        outPaint.style = Paint.Style.STROKE
+        outPaint.strokeJoin = Paint.Join.ROUND
+        outPaint.isAntiAlias = true
+        outPaint.color = Color.rgb(0x66, 0x66, 0xff)
+        outPaint.strokeWidth = 150f
+        x = data.x
+        y = data.y
+
+        //内圈
+        mPaint_inner.color = Color.RED
+        mPaint_inner.isAntiAlias = true
+        mPaint_inner.style = Paint.Style.FILL
+    } // Constructor
+
+    override fun boundingRect(): RectF {
+        return RectF(data.x - 200f, -data.y - 200f, data.x + 200f, -data.y + 200f)
+    }
+
+    override fun onScroll(e1: SMotionEvent, e2: SMotionEvent, distanceX: Float, distanceY: Float): Boolean {
+        val fx = pos.x - distanceX * scale.x
+        val fy = pos.y - distanceY * scale.y
+        x = data.x + fx
+        y = data.y - fy
+        moveTo(pos.x - distanceX * scale.x, pos.y - distanceY * scale.y)
+        onScroll.onScroll(data.x + fx, data.y + fy)
+        return true
+
+
+//        moveTo(pos.x - distanceX * scale.x, pos.y - distanceY * scale.y)
+
+//        onScroll.onScroll(data.x + pos.x - distanceX * scale.x, data.y - pos.y - distanceY * scale.y)
+//        onScroll.onScroll(data.x, data.y)
+
+
+
+//        return super.onScroll(e1, e2, distanceX, distanceY)
+    }
+
+    interface OnScroll {
+        fun onScroll(x: Float, y: Float)
+    }
+
+    fun setOnScrollListener(onScroll: OnScroll) {
+        this.onScroll = onScroll
+    }
+
+
+    /**
+     * Item绘制操作
+     *
+     * @param   canvas          画布
+     * @param   rect            绘制区域
+     */
+    override fun onDraw(canvas: Canvas) {
+        canvas.drawCircle(data.x, -data.y, 400f, mPaint_inner)
+    } // Function onDraw()
+
+}

+ 34 - 4
cadengine/src/main/java/cn/sagacloud/android/cadengine/items/PointItem.kt

@@ -4,15 +4,23 @@ package cn.sagacloud.android.cadengine.items
 import android.graphics.Canvas
 import android.graphics.Color
 import android.graphics.Paint
+import android.graphics.RectF
+import android.util.Log
+import android.view.MotionEvent
 import cn.sagacloud.android.cadengine.types.Point
 import com.sybotan.android.graphy.SGraphyItem
+import com.sybotan.android.graphy.SMotionEvent
+import com.sybotan.android.graphy.enums.SGraphyItemFlag
+import java.util.*
 
 /**
  * Created by lihao.
  * Date: 2021/6/4
  */
 class PointItem(val data: Point, parent: SGraphyItem? = null, defaultScale: Float) :
-    SGraphyItem(parent) {
+        SGraphyItem(parent) {
+    private lateinit var actionMove: ActionMove
+
     /** 新建 画笔 */
     val mPaint_inner = Paint()
     val mPaint_center = Paint()
@@ -34,6 +42,7 @@ class PointItem(val data: Point, parent: SGraphyItem? = null, defaultScale: Floa
     //var mScale = 1f
 
     init {
+        flags = EnumSet.of(SGraphyItemFlag.ItemIsMovable, SGraphyItemFlag.ItemIsSelectable, SGraphyItemFlag.ItemIsFocusable)
         mDefaultScale = defaultScale;
         /** 按时 */
         not_overTime_inner.color = Color.parseColor("#ffffff")
@@ -77,6 +86,15 @@ class PointItem(val data: Point, parent: SGraphyItem? = null, defaultScale: Floa
         mPaint_outer.style = Paint.Style.FILL
     }
 
+    override fun boundingRect(): RectF {
+        return RectF(data.mX - 500f, data.mY - 500f, data.mX + 500f, data.mY + 500f)
+    }
+
+    override fun onSingleTapUp(e: SMotionEvent): Boolean {
+        Log.e("TAG", "x=" + e.viewX.toString() + ",y=" + e.viewY.toString())
+        return super.onSingleTapUp(e)
+    }
+
     /**
      * Item绘制操作
      *
@@ -85,10 +103,22 @@ class PointItem(val data: Point, parent: SGraphyItem? = null, defaultScale: Floa
      */
     override fun onDraw(canvas: Canvas) {
         data.scalePoint = mDefaultScale / scene!!.view!!.scale
-        canvas.drawCircle(data.mX, data.mY, 2500f * data.scalePoint, mPaint_outer)
-        canvas.drawCircle(data.mX, data.mY, 1200f * data.scalePoint, mPaint_center)
-        canvas.drawCircle(data.mX, data.mY, 600f * data.scalePoint, mPaint_inner)
+        canvas.drawCircle(data.mX, data.mY, 500f, mPaint_outer)
+        canvas.drawCircle(data.mX, data.mY, 200f, mPaint_center)
+        canvas.drawCircle(data.mX, data.mY, 100f, mPaint_inner)
         super.onDraw(canvas)
     } // Function onDraw()
 
+    override fun onActionMove(event: MotionEvent) {
+        super.onActionMove(event)
+    }
+
+    interface ActionMove {
+        fun onActionMove(event: MotionEvent)
+    }
+
+    fun setOnActionMove(actionMove: ActionMove) {
+        this.actionMove=actionMove
+    }
+
 }

+ 15 - 4
cadengine/src/main/java/cn/sagacloud/android/cadengine/items/QrcodeItem.kt

@@ -4,15 +4,18 @@ package cn.sagacloud.android.cadengine.items
 import android.graphics.Canvas
 import android.graphics.Color
 import android.graphics.Paint
+import android.graphics.RectF
 import cn.sagacloud.android.cadengine.types.Point
 import com.sybotan.android.graphy.SGraphyItem
+import com.sybotan.android.graphy.enums.SGraphyItemFlag
+import java.util.*
 
 /**
  * Created by lihao.
  * Date: 2021/6/4
  */
 class QrcodeItem(val data: Point, parent: SGraphyItem? = null, defaultScale: Float) :
-    SGraphyItem(parent) {
+        SGraphyItem(parent) {
     /** 新建 画笔 */
     val mPaint_inner = Paint()
     val mPaint_center = Paint()
@@ -35,6 +38,7 @@ class QrcodeItem(val data: Point, parent: SGraphyItem? = null, defaultScale: Flo
 
     init {
         mDefaultScale = defaultScale;
+        flags = EnumSet.of(SGraphyItemFlag.ItemIsMovable, SGraphyItemFlag.ItemIsSelectable, SGraphyItemFlag.ItemIsFocusable)
         /** 按时 */
         not_overTime_inner.color = Color.parseColor("#ffffff")
         not_overTime_inner.isAntiAlias = true
@@ -77,6 +81,10 @@ class QrcodeItem(val data: Point, parent: SGraphyItem? = null, defaultScale: Flo
         mPaint_outer.style = Paint.Style.FILL
     }
 
+    override fun boundingRect(): RectF {
+        return RectF(data.mX - 250f, data.mY - 250f, data.mX + 250f, data.mY + 250f)
+    }
+
     /**
      * Item绘制操作
      *
@@ -85,9 +93,12 @@ class QrcodeItem(val data: Point, parent: SGraphyItem? = null, defaultScale: Flo
      */
     override fun onDraw(canvas: Canvas) {
         data.scalePoint = mDefaultScale / scene!!.view!!.scale
-//        canvas.drawCircle(data.mX, data.mY, 2400f * data.scalePoint, mPaint_outer)
-//        canvas.drawCircle(data.mX, data.mY, 1200f * data.scalePoint, mPaint_center)
-        canvas.drawCircle(data.mX, data.mY, 1500f * data.scalePoint, mPaint_inner)
+        mPaint_inner.color = if (this.isSelected) {
+            Color.RED
+        } else {
+            Color.BLUE
+        }
+        canvas.drawCircle(data.mX, data.mY, 500f, mPaint_inner)
         super.onDraw(canvas)
     } // Function onDraw()
 

+ 13 - 4
cadengine/src/main/java/cn/sagacloud/android/cadengine/items/TunableSpaceItem.kt

@@ -23,16 +23,16 @@ class TunableSpaceItem(val data: TunableSpace, parent: SGraphyItem? = null) : SG
     /** 空间轮廓线坐标list  */
     //private val pointArr = ArrayList<ArrayList<PointF>>()
     /** X坐标最小值  */
-    private var minX = 0f
+    public var minX = 0f
 
     /** X坐标最大值  */
-    private var maxX = 0f
+    public var maxX = 0f
 
     /** Y坐标最小值  */
-    private var minY = 0f
+    public var minY = 0f
 
     /** Y坐标最大值  */
-    private var maxY = 0f
+    public var maxY = 0f
 
     var mPoints = ArrayList<PointF>()
 
@@ -182,6 +182,15 @@ class TunableSpaceItem(val data: TunableSpace, parent: SGraphyItem? = null) : SG
         return RectF(minX, minY, maxX, maxY)
     } // Function boundingRect()
 
+    /**
+     * Item对象边界区域+2m
+     *
+     * @return SRect
+     */
+    fun boundingLargeRect(): RectF {
+        return RectF(minX - 2000, minY - 2000, maxX + 2000, maxY + 2000)
+    } // Function boundingRect()
+
 
     /**
      * Item绘制操作

+ 3 - 1
cadengine/src/main/java/cn/sagacloud/android/cadengine/items/WallItem.kt

@@ -4,6 +4,8 @@ import android.graphics.*
 import cn.sagacloud.android.cadengine.Opt
 import cn.sagacloud.android.cadengine.types.Wall
 import com.sybotan.android.graphy.SGraphyItem
+import java.util.*
+import kotlin.collections.ArrayList
 
 /**
  * 墙item
@@ -81,7 +83,7 @@ class WallItem(private val data: Wall, parent: SGraphyItem? = null) : SGraphyIte
      * @param   canvas          画布
      * @param   rect            绘制区域
      */
-    override fun onDraw(canvas : Canvas) {
+    override fun onDraw(canvas: Canvas) {
         paint.style = Paint.Style.FILL
         paint.color = Opt.wallColor
         for (path in pathList) {

+ 25 - 0
cadengine/src/main/java/cn/sagacloud/android/cadengine/types/Grid.kt

@@ -0,0 +1,25 @@
+package cn.sagacloud.android.cadengine.types
+
+import android.graphics.PointF
+
+/**
+ * Created by lihao.
+ * Date: 8/12/21
+ * 轴网
+ */
+class Grid {
+    /** 层id */
+    var levelId: String? = null
+    /** 位置  */
+    var location: Place? = null
+    /** 模型id(外键)    */
+    var modelId: String? = null
+    /** 名称  */
+    var name: String? = null
+    /** 轮廓线  */
+    var outLine: ArrayList<ArrayList<PointF>>? = null
+    /** 对应Revit模型id */
+    var sourceId: String? = null
+    /** 厚度  */
+    var width: String? = null
+} // Calss Wall

+ 5 - 2
cadengine/src/main/java/cn/sagacloud/android/cadengine/types/PipeLine.kt

@@ -1,14 +1,17 @@
 package cn.sagacloud.android.cadengine.types
 
 import android.graphics.PointF
+import android.os.Parcelable
+import java.io.Serializable
 
 /**
  * Created by lihao.
  * Date: 2021/6/7
  */
-class PipeLine {
+class PipeLine : Serializable {
     /** 定位点 */
-    var points: ArrayList<ArrayList<PointF>>? = ArrayList()
+    var points: ArrayList<PointF>? = ArrayList()
+
     /** 类型 */
     var type: String? = null
 }

BIN
cadengine/src/main/res/drawable/centertack_img.png


+ 17 - 9
demo/build.gradle

@@ -78,6 +78,7 @@ dependencies {
     implementation fileTree(dir: 'libs', include: ['*.jar'])
     implementation 'com.android.support.constraint:constraint-layout:1.1.2'
     implementation files('libs/zbardecoder.jar')
+    implementation files('libs/tbs_sdk_thirdapp_v4.3.0.67_43967_sharewithdownloadwithfile_withoutGame_obfs_20200923_120452.jar')
     testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: JUNIT_VERSION
     androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.2', {
         exclude group: 'com.android.support', module: 'support-annotations'
@@ -147,17 +148,17 @@ dependencies {
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     // Sybotan依赖
     implementation group: 'cn.sagacloud', name: 'saga-kotlin-base', version: SAGA_KOTLIN_VERSION
-//    implementation project(':sybotan-android-base')
-//    implementation project(':sybotan-android-database')
-//    implementation project(':sybotan-android-devices')
-//    implementation project(':sybotan-android-views')
-//    implementation project(':sybotan-android-graphy')
-//    implementation project(':sybotan-android-works')
+    implementation project(':sybotan-android-base')
+    implementation project(':sybotan-android-database')
+    implementation project(':sybotan-android-devices')
+    implementation project(':sybotan-android-views')
+    implementation project(':sybotan-android-graphy')
+    implementation project(':sybotan-android-works')
     implementation project(':cadengine')
     // Sybotan依赖
-    implementation group: 'cn.sagacloud', name: 'saga-kotlin-database', version: SAGA_KOTLIN_VERSION
-    implementation group: 'cn.sagacloud', name: 'sybotan-android-base', version: SYBOTAN_ANDROID_VERSION
-    implementation group: 'cn.sagacloud', name: 'sybotan-android-graphy', version: SYBOTAN_ANDROID_VERSION
+//    implementation group: 'cn.sagacloud', name: 'saga-kotlin-database', version: SAGA_KOTLIN_VERSION
+//    implementation group: 'cn.sagacloud', name: 'sybotan-android-base', version: SYBOTAN_ANDROID_VERSION
+//    implementation group: 'cn.sagacloud', name: 'sybotan-android-graphy', version: SYBOTAN_ANDROID_VERSION
     implementation 'androidx.multidex:multidex:2.0.0'
     implementation 'io.reactivex.rxjava2:rxjava:2.1.1'
     implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
@@ -168,4 +169,11 @@ dependencies {
     implementation 'com.squareup.retrofit2:retrofit:2.9.0'
     implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
     implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'
+
+    implementation 'com.arashivision.sdk:sdkcamera:1.3.10'
+    implementation 'com.arashivision.sdk:sdkmedia:1.3.10'
+    implementation 'com.lzy.net:okgo:3.0.4'
+    implementation 'com.afollestad.material-dialogs:core:0.9.6.0'
+//    implementation 'com.yanzhenjie.permission:x:2.0.1'
+//    implementation 'me.rosuh:AndroidFilePicker:0.6.7-x'
 }

BIN
demo/libs/tbs_sdk_thirdapp_v4.3.0.67_43967_sharewithdownloadwithfile_withoutGame_obfs_20200923_120452.jar


+ 2 - 1
demo/src/main/AndroidManifest.xml

@@ -3,6 +3,8 @@
           xmlns:tools="http://schemas.android.com/tools"
           package="com.sybotan.android.demo">
 
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
     <uses-permission android:name="android.permission.INTERNET"/>
     <uses-permission android:name="android.permission.BLUETOOTH"/> <!-- SD卡中创建与删除文件权限 -->
     <uses-permission
@@ -15,7 +17,6 @@
     <uses-feature android:name="android.hardware.camera"/>
     <uses-feature android:name="android.hardware.camera.autofocus"/>
 
-    <uses-permission android:name="android.permission.CAMERA"/>
 
     <application
             android:name=".DemoApp"

+ 24 - 2
demo/src/main/java/com/sybotan/android/demo/DemoApp.kt

@@ -27,17 +27,27 @@ import android.annotation.SuppressLint
 import android.app.Application
 import android.content.Context
 import android.util.Log
+import com.arashivision.sdkcamera.InstaCameraSDK
+import com.arashivision.sdkmedia.InstaMediaSDK
+import com.sybotan.android.demo.tools.AssetsUtil
+import java.io.File
+
 
 class DemoApp : Application() {
 
 
     companion object {
         private val TAG = DemoApp::class.java.name
+        var sInstance: DemoApp? = null
         var mContext: Context? = null
 
         fun getContext(): DemoApp? {
             return mContext as DemoApp
         }
+        fun getInstance(): DemoApp? {
+            return sInstance
+        }
+        val COPY_DIR: String = getInstance()?.cacheDir.toString() + "/hdr_source"
     }
 
     /**
@@ -46,11 +56,23 @@ class DemoApp : Application() {
     @SuppressLint("MissingSuperCall")
     override fun onCreate() {
         super.onCreate()
+        sInstance = this
         Log.d(TAG, "DemoApp starting...")
         mContext = applicationContext
-        return
-    } // Function onCreate()
 
+        // Init SDK
+        InstaCameraSDK.init(this)
+        InstaMediaSDK.init(this)
 
+        // Copy sample pictures from assets to local
+        copyHdrSourceFromAssets()
+        return
+    } // Function onCreate()
 
+    private fun copyHdrSourceFromAssets() {
+        val dir: File = File(COPY_DIR)
+        if (!dir.exists()) {
+            AssetsUtil.copyFilesFromAssets(this, "hdr_source", dir.absolutePath)
+        }
+    }
 } // Class DemoApp

+ 371 - 23
demo/src/main/java/com/sybotan/android/demo/activities/GraphyActivity.kt

@@ -23,26 +23,37 @@
 
 package com.sybotan.android.demo.activities
 
+import android.annotation.SuppressLint
 import android.content.Intent
 import android.graphics.Color
 import android.graphics.PointF
 import android.os.Bundle
+import android.os.Environment
 import android.support.v7.widget.GridLayoutManager
 import android.support.v7.widget.LinearLayoutManager
 import android.util.Log
 import android.view.Gravity
+import android.view.MotionEvent
 import android.view.View
+import android.webkit.WebSettings
+import android.webkit.WebView
+import android.webkit.WebViewClient
 import android.widget.TextView
 import android.widget.Toast
 import cn.sagacloud.android.cadengine.FloorScene
+import cn.sagacloud.android.cadengine.Lasso
 import cn.sagacloud.android.cadengine.Opt
 import cn.sagacloud.android.cadengine.items.*
-import cn.sagacloud.android.cadengine.types.PipeLine
-import cn.sagacloud.android.cadengine.types.Point
-import cn.sagacloud.android.cadengine.types.Space
-import cn.sagacloud.android.cadengine.types.TunableSpace
+import cn.sagacloud.android.cadengine.types.*
 import cn.sagacloud.cadengine.HttpDownloadMap
+import com.afollestad.materialdialogs.MaterialDialog
+import com.arashivision.sdkcamera.camera.InstaCameraManager
+import com.arashivision.sdkcamera.camera.callback.ICameraChangedCallback
+import com.arashivision.sdkcamera.camera.callback.ICaptureStatusListener
 import com.google.gson.Gson
+import com.lzy.okgo.OkGo
+import com.lzy.okgo.callback.FileCallback
+import com.lzy.okgo.model.Response
 import com.sybotan.android.demo.R
 import com.sybotan.android.demo.activities.poc.DeviceActivity
 import com.sybotan.android.demo.activities.poc.RelationActivity
@@ -50,6 +61,7 @@ import com.sybotan.android.demo.adapter.PipeAdapter
 import com.sybotan.android.demo.bean.result.*
 import com.sybotan.android.demo.retrofit.BaseViewModelInterface
 import com.sybotan.android.demo.tools.DensityUtils
+import com.sybotan.android.demo.tools.NetworkManager
 import com.sybotan.android.demo.viewmodel.GraphyVM
 import com.sybotan.android.graphy.events.SGraphyViewMoveEvent
 import com.zbar.lib.CaptureActivity
@@ -59,10 +71,15 @@ import org.greenrobot.eventbus.Subscribe
 import org.jetbrains.anko.doAsync
 import org.jetbrains.anko.textColor
 import org.jetbrains.anko.uiThread
+import java.io.*
+import java.text.SimpleDateFormat
+import java.util.*
+import java.util.concurrent.atomic.AtomicInteger
+import kotlin.collections.ArrayList
 
 
 @Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
-class GraphyActivity : BaseActivity() {
+class GraphyActivity : BaseActivity(), ICaptureStatusListener, ICameraChangedCallback {
     companion object {
         private val TAG = GraphyActivity::class.java.name
 
@@ -79,6 +96,8 @@ class GraphyActivity : BaseActivity() {
         var isAddBaseMap: Boolean = false
     }
 
+    private lateinit var spacePipeModel: java.util.ArrayList<SpacePipeModel>
+
     /** viewModel */
     lateinit var graphyVM: GraphyVM
 
@@ -130,13 +149,20 @@ class GraphyActivity : BaseActivity() {
         EventBus.getDefault().register(this)
         /** 初始化数据 */
         initData()
-
+        InstaCameraManager.getInstance().registerCameraChangedCallback(this)
         graphyView.scene = scene
 
+        val rect1 = scene.addRectItem(10f, 10f, 400f, 300f)
+        rect1.moveTo(53587.82f, 28717.135f)
+        rect1.zOrder = 1000009f
+
         /** 开启异步 */
         doAsync {
             val downloadGZIPMap = HttpDownloadMap.downloadGZIPMap(floorMap)
-            downloadGZIPMap?.let { scene.loadData(it) }
+            downloadGZIPMap?.let {
+                scene.loadData(it)
+                eagleView.scene = scene
+            }
             /** 主线程处理ui */
             uiThread {
                 /** 适应屏幕大小 */
@@ -152,6 +178,7 @@ class GraphyActivity : BaseActivity() {
 //                    scene.addItem(mapItem)
                     mapItem = BaseMapItem(this@GraphyActivity, null)
                 }
+                eagleView.fitSceneToView()
 
                 Log.e("viewH", graphyView.measuredHeight.toString())
             }
@@ -163,11 +190,72 @@ class GraphyActivity : BaseActivity() {
         /** 网络请求回调处理 */
         initViewModel()
 
-
+        initGrid()
         return
     } // Function onCreate()
 
     /**
+     * 模拟轴网
+     */
+    private fun initGrid() {
+        val grid1 = Grid()
+        val place1 = Place()
+        place1.points = ArrayList<PointF>()
+        val point1 = PointF()
+        point1.x = 53587.82f
+        point1.y = 28717.135f
+        place1.points!!.add(point1)
+        val point2 = PointF()
+        point2.x = 53587.82f
+        point2.y = -36885.92f
+        place1.points!!.add(point2)
+        grid1.location = place1
+        grid1.name = "A"
+
+
+        val grid3 = Grid()
+        val place3 = Place()
+        place3.points = ArrayList<PointF>()
+        val point5 = PointF()
+        point5.x = 44587.82f
+        point5.y = 28717.135f
+        place3.points!!.add(point5)
+        val point6 = PointF()
+        point6.x = 44587.82f
+        point6.y = -36885.92f
+        place3.points!!.add(point6)
+        grid3.location = place3
+        grid3.name = "B"
+
+        val grid2 = Grid()
+        val place2 = Place()
+        place2.points = ArrayList<PointF>()
+        val point3 = PointF()
+        point3.x = -16887.006f
+        point3.y = 7738.7656f
+        place2.points!!.add(point3)
+        val point4 = PointF()
+        point4.x = 152855.56f
+        point4.y = 9129.109f
+        place2.points!!.add(point4)
+        grid2.location = place2
+        grid2.name = "X"
+
+        val gridItem1 = GridItem(grid1, null, graphyView)
+        gridItem1.zOrder = 1000009f
+        val gridItem2 = GridItem(grid2, null, graphyView)
+        gridItem2.zOrder = 1000009f
+        val gridItem3 = GridItem(grid3, null, graphyView)
+        gridItem3.zOrder = 1000009f
+
+        scene.addItem(gridItem1)
+        scene.addItem(gridItem2)
+        scene.addItem(gridItem3)
+
+    }
+
+
+    /**
      * 初始化数据
      */
     private fun initData() {
@@ -194,21 +282,45 @@ class GraphyActivity : BaseActivity() {
         return false
     }
 
+    class MyWebViewClient : WebViewClient() {
+        //兼容低版本
+        override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
+            view.loadUrl(url)
+            return true
+        }
+
+        override fun onPageFinished(view: WebView, url: String) {
+            super.onPageFinished(view, url)
+        }
+    }
+
     /**
      * 图形点击事件
      * */
     private fun initSingleTopUp() {
         scene.setOnSingleTopUp(object : FloorScene.OnSingleTopUp {
+            @SuppressLint("SetJavaScriptEnabled")
             override fun onSingUp(x: Float, y: Float) {
+                //设置
+                val settings: WebSettings = webview.getSettings()
+                settings.javaScriptEnabled = true
+                settings.defaultTextEncodingName = "utf-8"
+                settings.builtInZoomControls = true
+                settings.loadsImagesAutomatically = true
+                settings.layoutAlgorithm = WebSettings.LayoutAlgorithm.SINGLE_COLUMN
+                webview.webViewClient = MyWebViewClient()
+                webview.loadUrl("http://60.205.177.43:8000/APP/#/")
                 if (isFastDoubleClick()) {
                     if (isAddBaseMap) {
                         scene.removeItem(mapItem)
                         isAddBaseMap = false
+                        webview.visibility = View.GONE
                     } else {
                         mapItem.zOrder = 1000000f
                         mapItem.isVisible = true
                         scene.addItem(mapItem)
                         isAddBaseMap = true
+                        webview.visibility = View.VISIBLE
                     }
                 }
                 if ("pipe".equals(scene.type)) {
@@ -216,6 +328,14 @@ class GraphyActivity : BaseActivity() {
                 }
                 //选中空间完毕界面逻辑
                 if (scene.mapType.equals("space")) {
+                    /** 4、平面图空间自动放缩定位并聚焦到某一具体空间 */
+//                    val w = graphyView.width.toFloat()
+//                    val h = graphyView.height.toFloat()
+//                    val rect = scene.choseSpace!!.boundingRect()
+//                    graphyView.setCenterPoint(PointF(rect.centerX(), rect.centerY()),
+//                            min(w / rect.width(), h / rect.height()) * 0.8f)
+
+
                     if ("space".equals(from)) {
                         quesDetail.visibility = View.GONE
                         if (!scene.choseSpace!!.data.jobStatus.equals("03")) {
@@ -306,10 +426,26 @@ class GraphyActivity : BaseActivity() {
         })
     }
 
+    private fun checkSdCardEnabled(): Boolean {
+        if (!InstaCameraManager.getInstance().isSdCardEnabled()) {
+            Toast.makeText(this, "No SD card inserted or Not enough free space", Toast.LENGTH_SHORT).show()
+            return false
+        }
+        return true
+    }
+
+
     /**
      * 页面全部监听事件
      */
     private fun initListener() {
+        /** 普通拍照 */
+        quesIma.setOnClickListener {
+            InstaCameraManager.getInstance().openCamera(InstaCameraManager.CONNECT_TYPE_WIFI)
+            if (checkSdCardEnabled()) {
+                InstaCameraManager.getInstance().startNormalCapture(false)
+            }
+        }
         /** nfc点击监听 */
         nfc.setOnClickListener { Toast.makeText(this, "正在开发中,敬请期待", Toast.LENGTH_SHORT).show() }
 
@@ -540,17 +676,43 @@ class GraphyActivity : BaseActivity() {
                     }
                     scene.pointItemList.clear()
                     var list = params as ArrayList<ProblemsModel>
+                    val mPoints = ArrayList<PointF>()
+                    val point1 = PointF()
+                    point1.set(scene.choseSpace!!.minX - 1000, scene.choseSpace!!.maxY + 1000)
+                    val point2 = PointF()
+                    point2.set(scene.choseSpace!!.maxX + 1000, scene.choseSpace!!.maxY + 1000)
+                    val point3 = PointF()
+                    point3.set(scene.choseSpace!!.minX - 1000, scene.choseSpace!!.minY - 1000)
+                    val point4 = PointF()
+                    point4.set(scene.choseSpace!!.maxX + 1000, scene.choseSpace!!.minY - 1000)
+                    mPoints.add(point1)
+                    mPoints.add(point2)
+                    mPoints.add(point4)
+                    mPoints.add(point3)
+
                     for (model in list) {
-                        val point = Point()
                         var position = gson.fromJson(model.position, Position::class.java)
-                        point.mX = position.x.toFloat()
-                        point.mY = position.y.toFloat()
-                        point.id = model.id
-                        var item = PointItem(point, null, scene.defaultPointScale)
-                        item.isVisible = true
-                        item.zOrder = 100000f
-                        scene.pointItemList.add(item)
-                        scene.addItem(item)
+                        val polygonContainsPoint = Lasso.isPolygonContainsPoint(
+                                mPoints,
+                                android.graphics.Point(position.x.toFloat().toInt(), position.y.toFloat().toInt())
+                        )
+                        if (polygonContainsPoint) {
+                            val point = Point()
+                            point.mX = position.x.toFloat()
+                            point.mY = position.y.toFloat()
+                            point.id = model.id
+                            var item = PointItem(point, null, scene.defaultPointScale)
+                            item.isVisible = true
+                            item.zOrder = 10000001f
+                            scene.pointItemList.add(item)
+                            scene.addItem(item)
+                            item.setOnActionMove(object : PointItem.ActionMove {
+                                override fun onActionMove(event: MotionEvent) {
+                                    eagleView.setCenterPoint(PointF(event.x, event.y), graphyView.scale * 10f)
+                                }
+
+                            })
+                        }
                     }
                 }
 
@@ -719,25 +881,96 @@ class GraphyActivity : BaseActivity() {
             scene.removeItem(item)
         }
         scene.pipeItemList.clear()
-
-        for (model in spacePipeModel) {
+        this.spacePipeModel = spacePipeModel
+        for (model in this.spacePipeModel) {
             if (!model.children.isEmpty() && !model.isCheck) {
                 for (child in model.children) {
                     val pipe = PipeLine()
-                    var points: ArrayList<ArrayList<PointF>> = ArrayList()
-                    points.add(child.position)
-                    pipe.points!!.addAll(points)
+
+                    pipe.points!!.addAll(child.position)
+
                     val pipeItem = PipeLineItem(pipe, null)
                     pipeItem.isVisible = true
                     pipeItem.zOrder = 100000f
                     scene.pipeItemList.add(pipeItem)
                     scene.addItem(pipeItem)
 
+                    for (point in child.position) {
+                        val pipeNodeItem = PipeNodeItem(point, null)
+                        pipeNodeItem.isVisible = true
+                        pipeNodeItem.zOrder = 100000f
+                        scene.addItem(pipeNodeItem)
+                        scene.pipeNodeList.add(pipeNodeItem)
+                        pipeNodeItem.setOnScrollListener(object : PipeNodeItem.OnScroll {
+                            override fun onScroll(x: Float, y: Float) {
+                                for (item in scene.pipeItemList) {
+                                    scene.removeItem(item)
+                                }
+
+                                val newData = PipeLine()
+                                for (node in scene.pipeNodeList) {
+                                    val po = PointF()
+                                    po.x = node.x
+                                    po.y = node.y
+                                    newData.points!!.add(po)
+                                }
+                                val pipeItem2 = PipeLineItem(newData, null)
+                                pipeItem2.isVisible = true
+                                pipeItem2.zOrder = 100000f
+                                scene.pipeItemList.add(pipeItem2)
+                                scene.addItem(pipeItem2)
+
+//                                for (pointItem1 in scene.pipeItemList) {
+//                                    for (pointList1 in pointItem1.data.points!!) {
+//                                        for (point1 in pointList1) {
+//                                            if (point1.x == pipeNodeItem.x && point1.y == pipeNodeItem.y) {
+//                                                point1.x = x
+//                                                point1.y = y
+//                                                pipeNodeItem.x = x
+//                                                pipeNodeItem.y = y
+
+//                                                scene.removeItem(pointItem1)
+//
+//                                                val newData: PipeLine = deepClone(pointItem1.data) as PipeLine
+//                                                for (pl in newData.points!!) {
+//                                                    for (p in pl) {
+//                                                        if (p.x == pipeNodeItem.x && p.y == pipeNodeItem.y) {
+//                                                            p.x = x
+//                                                            p.y = y
+//                                                        }
+//                                                    }
+//                                                }
+//                                                val pipeItem2 = PipeLineItem(newData, null)
+//                                                pipeItem2.isVisible = true
+//                                                pipeItem2.zOrder = 100000f
+//                                                scene.pipeItemList.add(pipeItem2)
+//                                                scene.addItem(pipeItem2)
+//                                            }
+//                                        }
+//                                    }
+//                                }
+                            }
+                        })
+                    }
+
+
                 }
             }
         }
     }
 
+    @Throws(Exception::class)
+    fun deepClone(data: PipeLine): Any? {
+        // 序列化
+        val bos = ByteArrayOutputStream()
+        val oos = ObjectOutputStream(bos)
+        oos.writeObject(data)
+        // 反序列化
+        val bis = ByteArrayInputStream(bos.toByteArray())
+        val ois = ObjectInputStream(bis)
+        return ois.readObject()
+    }
+
     /**
      * 刷新地图上设备
      */
@@ -759,7 +992,7 @@ class GraphyActivity : BaseActivity() {
 
                     var item = EquipItem(point, null, scene.defaultPointScale)
                     item.isVisible = true
-                    item.zOrder = 100000f
+                    item.zOrder = 10000012f
                     scene.equipList.add(item)
                     scene.addItem(item)
                 }
@@ -820,6 +1053,9 @@ class GraphyActivity : BaseActivity() {
                         "\ny轴:${point.data.mY}" +
                         "\n点击下方“问题已解决”按钮后可关闭该问题点。"
         )
+        quesTv.setOnClickListener {
+//            Toast.makeText(this@GraphyActivity, InstaCameraManager.getInstance(). + "======", Toast.LENGTH_LONG).show()
+        }
 
         /** 问题已解决按钮 */
         quesSubmit.setOnClickListener {
@@ -882,5 +1118,117 @@ class GraphyActivity : BaseActivity() {
         }
     }
 
+    override fun onCaptureFinish(p0: Array<out String>?) {
+        val time = SimpleDateFormat("HH:mm:ss").format(Date(System.currentTimeMillis()))
+        quesTv.text = quesTv.text.toString() + "\n$time:拍照完成"
+        downloadFilesAndPlay(p0)
+    }
+
+    override fun onCaptureStarting() {
+        val time = SimpleDateFormat("HH:mm:ss").format(Date(System.currentTimeMillis()))
+        quesTv.text = "$time:准备拍照"
+    }
+
+    override fun onCaptureWorking() {
+        val time = SimpleDateFormat("HH:mm:ss").format(Date(System.currentTimeMillis()))
+        quesTv.text = quesTv.text.toString() + "\n$time:拍照中"
+    }
+
+    override fun onCaptureStopping() {
+        val time = SimpleDateFormat("HH:mm:ss").format(Date(System.currentTimeMillis()))
+        quesTv.text = quesTv.text.toString() + "\n$time:拍照中断"
+    }
+
+    override fun onCameraConnectError() {
+        super.onCameraConnectError()
+        Toast.makeText(this, "相机连接失败", Toast.LENGTH_SHORT).show()
+    }
+
+    override fun onCameraSDCardStateChanged(enabled: Boolean) {
+        super.onCameraSDCardStateChanged(enabled)
+        if (enabled) {
+            Toast.makeText(this, "SD卡可用", Toast.LENGTH_SHORT).show()
+            // Capture Status Callback
+            InstaCameraManager.getInstance().setCaptureStatusListener(this)
+        } else {
+            Toast.makeText(this, "SD卡异常", Toast.LENGTH_SHORT).show()
+        }
+    }
+
+    override fun onCameraStatusChanged(enabled: Boolean) {
+        super.onCameraStatusChanged(enabled)
+        if (enabled) {
+            Toast.makeText(this, "相机已连接", Toast.LENGTH_SHORT).show()
+        } else {
+            NetworkManager.getInstance().clearBindProcess()
+            Toast.makeText(this, "相机连接断开", Toast.LENGTH_SHORT).show()
+        }
+    }
+
+    private fun downloadFilesAndPlay(urls: Array<out String>?) {
+        if (urls == null || urls.size == 0) {
+            return
+        }
+        val localFolder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString() + "/SDK_DEMO_CAPTURE"
+        val fileNames = arrayOfNulls<String>(urls.size)
+        val localPaths = arrayOfNulls<String>(urls.size)
+        var needDownload = false
+        val dir = File(localFolder)
+        if (!dir.exists()) {
+            dir.mkdirs()
+        }
+        for (i in localPaths.indices) {
+            fileNames[i] = urls[i].substring(urls[i].lastIndexOf("/") + 1)
+            localPaths[i] = localFolder + "/" + fileNames[i]
+            if (!File(localPaths[i]).exists()) {
+                needDownload = true
+            }
+        }
+        if (!needDownload) {
+            val time = SimpleDateFormat("HH:mm:ss").format(Date(System.currentTimeMillis()))
+            quesTv.text = quesTv.text.toString() + "\n$time:文件已存在"
+//            PlayAndExportActivity.launchActivity(this@CaptureActivity, localPaths)
+            return
+        }
+        val dialog: MaterialDialog = MaterialDialog.Builder(this)
+                .title(R.string.osc_dialog_title_downloading)
+                .content(getString(R.string.osc_dialog_msg_downloading, urls.size, 0, 0))
+                .cancelable(false)
+                .canceledOnTouchOutside(false)
+                .show()
+        val successfulCount = AtomicInteger(0)
+        val errorCount = AtomicInteger(0)
+        for (i in localPaths.indices) {
+            val url = urls[i]
+            OkGo.get<File>(url).execute(object : FileCallback(localFolder, fileNames[i]) {
+                override fun onError(response: Response<File?>?) {
+                    super.onError(response)
+                    errorCount.incrementAndGet()
+                    checkDownloadCount()
+                }
+
+                override fun onSuccess(response: Response<File?>?) {
+                    successfulCount.incrementAndGet()
+                    checkDownloadCount()
+                }
+
+                private fun checkDownloadCount() {
+                    dialog.setContent(getString(R.string.osc_dialog_msg_downloading, urls.size, successfulCount.toInt(), errorCount.toInt()))
+                    if (successfulCount.toInt() + errorCount.toInt() >= urls.size) {
+//                                PlayAndExportActivity.launchActivity(this@CaptureActivity, localPaths)
+                        val time = SimpleDateFormat("HH:mm:ss").format(Date(System.currentTimeMillis()))
+                        quesTv.text = quesTv.text.toString() + "\n$time:下载完成"
+                        dialog.dismiss()
+                    }
+                }
+            })
+        }
+    }
+
+    override fun onDestroy() {
+        super.onDestroy()
+        InstaCameraManager.getInstance().unregisterCameraChangedCallback(this)
+    }
+
 
 } // Class GraphyActivity

+ 5 - 5
demo/src/main/java/com/sybotan/android/demo/activities/MainActivity.kt

@@ -32,7 +32,7 @@ import com.sybotan.android.demo.R
 import kotlinx.android.synthetic.main.activity_main.*
 import org.jetbrains.anko.startActivity
 
-class MainActivity : SBaseActivity() {
+class MainActivity : BaseActivity() {
 
     companion object {
         private val TAG = MainActivity::class.java.name
@@ -52,10 +52,10 @@ class MainActivity : SBaseActivity() {
         //immersive()
 
         /** 申请权限 */
-        requestPermission(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE,
-                Manifest.permission.CAMERA,
-                Manifest.permission.WRITE_EXTERNAL_STORAGE,
-                Manifest.permission.INTERNET))
+//        requestPermission(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE,
+//                Manifest.permission.CAMERA,
+//                Manifest.permission.WRITE_EXTERNAL_STORAGE,
+//                Manifest.permission.INTERNET))
 
         qrcode.setOnClickListener {
 //            startActivity<SQrCodeActivity>()

+ 12 - 1
demo/src/main/java/com/sybotan/android/demo/activities/PocActivity.kt

@@ -1,19 +1,24 @@
 package com.sybotan.android.demo.activities
 
+import android.Manifest
 import android.os.Bundle
 import android.support.constraint.ConstraintLayout
+import android.support.v4.app.ActivityCompat
 import android.support.v7.app.AppCompatActivity
 import com.sybotan.android.demo.R
 import com.sybotan.android.demo.activities.poc.SceneActivity
 import com.sybotan.android.demo.activities.poc.SpaceActivity
+import com.zbar.lib.CaptureActivity
 import org.jetbrains.anko.startActivity
 
 class PocActivity : AppCompatActivity() {
     private val tag = "PocActivity"
+    private val REQUEST_EXTERNAL_STORAGE = 1 // 不可改
+
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         setContentView(R.layout.activity_poc)
-
+        checkStoragePermission()
         val spaceCL = findViewById<ConstraintLayout>(R.id.spaceCL)
         spaceCL.setOnClickListener {
             startActivity<SpaceActivity>()
@@ -24,4 +29,10 @@ class PocActivity : AppCompatActivity() {
             startActivity<SceneActivity>()
         }
     }
+
+    private fun checkStoragePermission() {
+        ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE,
+                Manifest.permission.WRITE_EXTERNAL_STORAGE),
+                REQUEST_EXTERNAL_STORAGE)
+    }
 }

+ 1 - 2
demo/src/main/java/com/sybotan/android/demo/activities/WebViewActivity.kt

@@ -23,7 +23,6 @@
 
 package com.sybotan.android.demo.activities
 
-import android.support.v7.app.AppCompatActivity
 import android.os.Bundle
 import com.sybotan.android.demo.R
 //import com.sybotan.android.devices.printer.SLPrinter
@@ -34,7 +33,7 @@ import kotlinx.android.synthetic.main.activity_web_view.*
  *
  * @author  庞利祥(sybotan@126.com)
  */
-class WebViewActivity : AppCompatActivity() {
+class WebViewActivity : BaseActivity() {
 
     /**
      * 创建Activity时的回调函数

+ 36 - 0
demo/src/main/java/com/sybotan/android/demo/tools/AssetsUtil.java

@@ -0,0 +1,36 @@
+package com.sybotan.android.demo.tools;
+
+import android.content.Context;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+
+public class AssetsUtil {
+
+    public static void copyFilesFromAssets(Context context, String assetsPath, String savePath) {
+        try {
+            String[] fileNames = context.getAssets().list(assetsPath);
+            if (fileNames.length > 0) {
+                File file = new File(savePath);
+                file.mkdirs();
+                for (String fileName : fileNames) {
+                    copyFilesFromAssets(context, assetsPath + "/" + fileName, savePath + "/" + fileName);
+                }
+            } else {
+                InputStream is = context.getAssets().open(assetsPath);
+                FileOutputStream fos = new FileOutputStream(new File(savePath));
+                byte[] buffer = new byte[1024];
+                int byteCount = 0;
+                while ((byteCount = is.read(buffer)) != -1) {
+                    fos.write(buffer, 0, byteCount);
+                }
+                fos.flush();
+                is.close();
+                fos.close();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}

+ 130 - 0
demo/src/main/java/com/sybotan/android/demo/tools/NetworkManager.java

@@ -0,0 +1,130 @@
+package com.sybotan.android.demo.tools;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
+import android.net.NetworkRequest;
+import android.os.Build;
+import android.widget.Toast;
+
+import com.arashivision.sdkcamera.camera.InstaCameraManager;
+import com.sybotan.android.demo.DemoApp;
+import com.sybotan.android.demo.R;
+
+public class NetworkManager {
+
+    private static class NetworkHolder {
+        private static final NetworkManager instance = new NetworkManager();
+    }
+
+    private NetworkManager() {
+    }
+
+    public static NetworkManager getInstance() {
+        return NetworkHolder.instance;
+    }
+
+    private long mMobileNetId = -1;
+
+    private ConnectivityManager.NetworkCallback mNetworkCallback = null;
+
+    // 绑定移动网络
+    // Bind Mobile Network
+    public void exchangeNetToMobile() {
+        if (isBindingMobileNetwork()) {
+            return;
+        }
+
+        ConnectivityManager connManager = (ConnectivityManager) DemoApp.Companion.getInstance().getSystemService(Context.CONNECTIVITY_SERVICE);
+        Network[] networks = connManager.getAllNetworks();
+        for (Network network : networks) {
+            NetworkInfo networkInfo = connManager.getNetworkInfo(network);
+            if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
+                // 需将WIFI的网络ID设置给相机
+                // Need to set network Id of current wifi to camera
+                InstaCameraManager.getInstance().setNetIdToCamera(getNetworkId(network));
+            }
+        }
+
+        NetworkRequest request = new NetworkRequest.Builder()
+                .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+                .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+                .build();
+        mNetworkCallback = new ConnectivityManager.NetworkCallback() {
+            @Override
+            public void onAvailable(Network network) {
+                super.onAvailable(network);
+                boolean bindSuccessful;
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+                    connManager.bindProcessToNetwork(null);
+                    bindSuccessful = connManager.bindProcessToNetwork(network);
+                } else {
+                    ConnectivityManager.setProcessDefaultNetwork(null);
+                    bindSuccessful = ConnectivityManager.setProcessDefaultNetwork(network);
+                }
+                // 记录绑定的移动网络ID
+                // Record the bound mobile network ID
+                mMobileNetId = getNetworkId(network);
+                if (bindSuccessful) {
+                    Toast.makeText(DemoApp.Companion.getInstance(), R.string.live_toast_bind_mobile_network_successful, Toast.LENGTH_SHORT).show();
+                } else {
+                    Toast.makeText(DemoApp.Companion.getInstance(), R.string.live_toast_bind_mobile_network_failed, Toast.LENGTH_SHORT).show();
+                }
+            }
+
+            @Override
+            public void onLost(Network network) {
+                super.onLost(network);
+                // 移动网络突然不可用,需临时解除绑定等待网络再次恢复
+                // The mobile network is suddenly unavailable, need to temporarily unbind and wait for the network to recover again
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+                    connManager.bindProcessToNetwork(null);
+                } else {
+                    ConnectivityManager.setProcessDefaultNetwork(null);
+                }
+                Toast.makeText(DemoApp.Companion.getInstance(), R.string.live_toast_unbind_mobile_network_when_lost, Toast.LENGTH_SHORT).show();
+            }
+        };
+        connManager.requestNetwork(request, mNetworkCallback);
+    }
+
+    private long getNetworkId(Network network) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            return network.getNetworkHandle();
+        }
+        return Long.parseLong(network.toString());
+    }
+
+    // 解除网络绑定
+    // Unbind Mobile Network
+    public void clearBindProcess() {
+        ConnectivityManager connManager = (ConnectivityManager) DemoApp.Companion.getInstance().getSystemService(Context.CONNECTIVITY_SERVICE);
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            connManager.bindProcessToNetwork(null);
+        } else {
+            ConnectivityManager.setProcessDefaultNetwork(null);
+        }
+        if (mNetworkCallback != null) {
+            // 注销callback,彻底解除绑定
+            // Unregister Callback, Unbind completely
+            connManager.unregisterNetworkCallback(mNetworkCallback);
+            Toast.makeText(DemoApp.Companion.getInstance(), R.string.live_toast_unbind_mobile_network, Toast.LENGTH_SHORT).show();
+        }
+        mNetworkCallback = null;
+        mMobileNetId = -1;
+        // 重置相机网络
+        // Reset Camera Net Id
+        InstaCameraManager.getInstance().setNetIdToCamera(-1);
+    }
+
+    public long getMobileNetId() {
+        return mMobileNetId;
+    }
+
+    public boolean isBindingMobileNetwork() {
+        return mNetworkCallback != null;
+    }
+
+}

+ 1 - 1
demo/src/main/java/com/sybotan/android/demo/viewmodel/GraphyVM.kt

@@ -75,7 +75,7 @@ class GraphyVM(b: BaseViewModelInterface?, activity: BaseActivity?, //建筑id
     fun getProblem(choseSpace: TunableSpaceItem?) {
         val bean = ReqProblems()
         bean.floorId = floorId
-        bean.spaceId = choseSpace!!.data.id
+//        bean.spaceId = choseSpace!!.data.id
         val observable = RetrofitFactory.getInstance().problems(getRequestBody(bean))
         sendRequest(observable, object : BaseObserver<List<ProblemsModel>>(mActivity, this) {
             override fun onSuccess(models: List<ProblemsModel>) {

+ 24 - 5
demo/src/main/res/layout/activity_graphy.xml

@@ -44,12 +44,31 @@
             android:layout_marginRight="20dp" />
     </ScrollView>
 
-    <com.sybotan.android.graphy.SGraphyView
-        android:id="@+id/graphyView"
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1">
+
+        <com.sybotan.android.graphy.SGraphyView
+            android:id="@+id/graphyView"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_marginBottom="5dp" />
+
+        <com.sybotan.android.graphy.SGraphyView
+            android:visibility="gone"
+            android:id="@+id/eagleView"
+            android:layout_width="120dp"
+            android:layout_height="120dp" />
+    </RelativeLayout>
+
+    <WebView
+        android:id="@+id/webview"
         android:layout_width="match_parent"
         android:layout_height="0dp"
         android:layout_marginBottom="5dp"
-        android:layout_weight="1" />
+        android:layout_weight="1"
+        android:visibility="gone" />
 
     <RelativeLayout
         android:layout_width="match_parent"
@@ -190,14 +209,14 @@
                 android:layout_marginTop="20dp"
                 android:layout_marginRight="20dp"
                 android:layout_toRightOf="@+id/quesIma"
-                android:text="这是一段描述问题的文本,左侧是问题现场拍照图片。\nx轴、y轴坐标。\n点击下方“问题已解决”按钮后可关闭该问题点。"
+                android:text=""
                 android:textColor="@color/grey_900" />
 
             <TextView
                 android:id="@+id/quesSubmit"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_below="@+id/quesTv"
+                android:layout_below="@+id/quesIma"
                 android:layout_centerHorizontal="true"
                 android:layout_gravity="center_horizontal"
                 android:layout_marginLeft="50dp"

+ 6 - 0
demo/src/main/res/values/strings.xml

@@ -31,4 +31,10 @@
         \n请点击”设置”->在应用程序中找到”popon”->权限管理->%2$s->”允许”即可
     </string>
     <string name="camera">摄像头(相机)</string>
+    <string name="live_toast_bind_mobile_network_successful">绑定移动网络成功</string>
+    <string name="live_toast_bind_mobile_network_failed">绑定移动网络失败</string>
+    <string name="live_toast_unbind_mobile_network">解除绑定移动网络</string>
+    <string name="live_toast_unbind_mobile_network_when_lost">移动网络丢失,临时解绑</string>
+    <string name="osc_dialog_title_downloading">下载远程文件</string>
+    <string name="osc_dialog_msg_downloading">"总数 %1$d, 成功 %2$d, 失败 %3$d</string>
 </resources>

+ 6 - 6
settings.gradle

@@ -22,11 +22,11 @@
  */
 rootProject.name = 'saga-android'
 
-//include ':sybotan-android-base'
-//include ':sybotan-android-database'
-//include ':sybotan-android-devices'
-//include ':sybotan-android-graphy'
-//include ':sybotan-android-views'
-//include ':sybotan-android-works'
+include ':sybotan-android-base'
+include ':sybotan-android-database'
+include ':sybotan-android-devices'
+include ':sybotan-android-graphy'
+include ':sybotan-android-views'
+include ':sybotan-android-works'
 include ':cadengine'
 include ':demo'

+ 98 - 36
sybotan-android-graphy/src/main/java/com/sybotan/android/graphy/SGraphyItem.kt

@@ -28,9 +28,10 @@ import android.graphics.Matrix
 import android.graphics.PointF
 import android.graphics.RectF
 import android.util.Log
+import android.view.MotionEvent
 import com.sybotan.android.graphy.enums.SGraphyItemFlag
 import com.sybotan.android.graphy.listeners.SGraphyItemPosListener
-import com.sybotan.android.graphy.utils.MatrixTools
+import com.sybotan.android.graphy.utils.MatrixUtil
 import com.sybotan.base.extensions.toJson
 import org.jetbrains.anko.doAsync
 import java.util.*
@@ -41,17 +42,19 @@ import java.util.*
  * @author  庞利祥(sybotan@126.com)
  */
 open class SGraphyItem(parent: SGraphyItem? = null) {
-
     /**
      * 类对象
      */
     companion object {
         private val TAG = SGraphyItem::class.java.name
+
         /** 当前移动Item */
         private var currentMoveItem: SGraphyItem? = null
+
         /** 当前焦点Item */
         private var currentFocusItem: SGraphyItem? = null
 
+
         /**
          * MotionEvent转子对象MotionEvent
          *
@@ -61,17 +64,28 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
          */
         fun toChildMotionEvent(child: SGraphyItem, e: SMotionEvent): SMotionEvent {
             val ce = SMotionEvent(e)
-            ce.matrix.postTranslate(child.pos.x, child.pos.y);
-            ce.matrix.postScale(child.scale.x, child.scale.y);
-            ce.matrix.postRotate(child.rotate,0f, 0f);
+//            ce.matrix.postTranslate(child.pos.x, child.pos.y);
+//            ce.matrix.postScale(child.scale.x, child.scale.y);
+//            ce.matrix.postRotate(child.rotate,0f, 0f);
+            ce.matrix.preTranslate(child.pos.x, child.pos.y);
+            ce.matrix.preScale(child.scale.x, child.scale.y);
+            ce.matrix.preRotate(child.rotate, 0f, 0f);
+
             // 不跟随缩放
             if (!child.isTransform) {
-                ce.matrix.postScale(child._inverseScale, child._inverseScale);
+                val src = kotlin.floatArrayOf(0f, 1f, 2f, 3f, 4f, 5f, 6f, 7f, 8f)
+//                ce.matrix.postScale(child._inverseScaleX, child._inverseScaleY);
+                ce.matrix.getValues(src)
+                val matrix = Matrix()
+                matrix.preTranslate(src[2], src[5])
+                matrix.preScale(child.scale.x, child.scale.y)
+                matrix.preRotate(child.rotate)
+                ce.matrix = matrix
             }
 //            se.setLocation((e.x - child.pos.x) / child.scale.x, (e.y - child.pos.y) / child.scale.y)
             val matrixMat = Matrix()
             ce.matrix.invert(matrixMat)
-            val matrixTransform = MatrixTools.matrixTransform(matrixMat, e.viewX, e.viewY)
+            val matrixTransform = MatrixUtil.matrixTransform(matrixMat, e.viewX, e.viewY)
             ce.x = matrixTransform.x
             ce.y = matrixTransform.y
             return ce
@@ -79,7 +93,7 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
     } // companion object
 
     /** 父节点 */
-    var parent:SGraphyItem? = parent
+    var parent: SGraphyItem? = parent
         set(value) {
             if (field == value) {   // 如果值没变化
                 return
@@ -99,7 +113,7 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
         }
 
     /** 子节点列表 */
-    val children =  ArrayList<SGraphyItem>()
+    val children = ArrayList<SGraphyItem>()
 
     /** item所属场景 */
     var scene: SGraphyScene? = null
@@ -121,6 +135,7 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
             invalidate()
             posListener?.onMoveTo(field.x, field.y)
         }
+
     /** item位置变更监听器 */
     var posListener: SGraphyItemPosListener? = null
 
@@ -136,14 +151,20 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
             }
             invalidate()
         }
+
     /** 缩放比例 */
     var scale = PointF(1f, 1f)
+
     /** 旋转 */
     var rotate = 0.0f
+
     /** 是否进行变形 */
-   var isTransform = true;
+    var isTransform = true;
+
     /** 放缩反比例 */
-    var _inverseScale = 1f;
+    var _inverseScaleX = 1f;
+    var _inverseScaleY = 1f;
+
     /** item标志 */
     var flags: EnumSet<SGraphyItemFlag> = EnumSet.noneOf(SGraphyItemFlag::class.java)
 
@@ -250,8 +271,7 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
      *
      * @param   pos         新的位置
      */
-    fun moveTo(pos: PointF)
-    {
+    fun moveTo(pos: PointF) {
         this.pos = pos
         return
     } // Function move()
@@ -262,8 +282,7 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
      * @param   x           新位置的x坐标
      * @param   y           新位置的y坐标
      */
-    fun moveTo(x: Float, y: Float)
-    {
+    fun moveTo(x: Float, y: Float) {
         pos = PointF(x, y)
         return
     } // Function move()
@@ -282,7 +301,7 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
         val m = this.scene2itemMattrix()
         val matrix = Matrix()
         m.invert(matrix)
-       return MatrixTools.matrixTransform(matrix,x,y)
+        return MatrixUtil.matrixTransform(matrix, x, y)
     } // Function mapFromScene()
 
     /**
@@ -309,7 +328,7 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
             return PointF(x, y)
         }
         val m = this.scene2itemMattrix()
-        return return MatrixTools.matrixTransform(m,x,y)
+        return return MatrixUtil.matrixTransform(m, x, y)
 //        return parent!!.mapToScene(x * scale.x + pos.x, y * scale.y + pos.y)
     } // Function mapToScene()
 
@@ -348,6 +367,7 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
      * @return  true包含;false不包含。
      */
     open fun contains(x: Float, y: Float): Boolean {
+        Log.e("boundingRect", boundingRect().contains(x, y).toString())
         return boundingRect().contains(x, y)
     } // Function ()
 
@@ -370,12 +390,14 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
      * @param   canvas      画布对象
      * @param   rect        更新区域
      */
-    open fun onPaint(canvas : Canvas, rect: RectF) {
+    open fun onPaint(canvas: Canvas, rect: RectF) {
         canvas.save()
+//        val mat1 = SJsonUtil.fromJson(canvas.matrix.toJson(), Matrix::class.java)
         this.onDraw(canvas)
+//        canvas.matrix = mat1
         canvas.restore()
         val src = kotlin.floatArrayOf(0f, 1f, 2f, 3f, 4f, 5f, 6f, 7f, 8f)
-        for (i in 1 .. children.size) {        // 倒序依次取item列中的所有item。将所有item的边界做并交处理。
+        for (i in 1..children.size) {        // 倒序依次取item列中的所有item。将所有item的边界做并交处理。
             val item = children[children.size - i]
             if (!item.isVisible) {      // 如果对象不可见
                 continue
@@ -383,16 +405,28 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
             try {
                 // 保存画布状态
                 canvas.save()
+//                val mat = SJsonUtil.fromJson(canvas.matrix.toJson(), Matrix::class.java)
                 // item位移到指定位置绘制
                 canvas.translate(item.pos.x, item.pos.y)
-                canvas.scale(item.scale.x,item.scale.y)
+                canvas.scale(item.scale.x, item.scale.y)
                 canvas.rotate(item.rotate)
 
                 if (!item.isTransform) {
-                    val matrix = canvas.matrix
-                    matrix.getValues(src)
-                    item._inverseScale = 1.0f/src[0]
-                    canvas.scale(item._inverseScale,item._inverseScale)
+                    canvas.matrix.getValues(src)
+                    val matrix = Matrix()
+                    matrix.preTranslate(src[2], src[5])
+                    matrix.preScale(item.scale.x, item.scale.y)
+                    matrix.preRotate(item.rotate)
+                    canvas.matrix = matrix
+//                    matrix.getValues(src)
+//                    item._inverseScaleX = 1.0f/src[0]
+//                    item._inverseScaleY = 1.0f/src[4]
+//                    canvas.scale(item._inverseScaleX,item._inverseScaleY)
+
+//                    matrix.preTranslate(src[2], src[5])
+//                    matrix.preTranslate(item.scale.x,item.scale.y)
+//                    matrix.preRotate(item.rotate)
+//                    canvas.matrix = matrix
                 }
                 // 设置绘制区域
                 // canvas.clipRect(item.boundingRect())
@@ -400,6 +434,7 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
                 item.onPaint(canvas, rect)
                 // 恢复画布状态
                 canvas.restore()
+//                canvas.matrix = mat;
             } catch (e: Exception) {
                 e.printStackTrace()
             }
@@ -412,7 +447,7 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
      *
      * @param painter    绘制对象
      */
-    open fun onDraw(canvas : Canvas) {
+    open fun onDraw(canvas: Canvas) {
 
     }
 
@@ -467,21 +502,34 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
     open fun onSingleTapUp(e: SMotionEvent): Boolean {
         Log.d(TAG, "onSingleTapUp: releaseItem")
         releaseItem()
-        Log.e("手势scene",e.toJson())
         for (item in children) {
             if (!item.isVisible) {      // 如果对象不可见
+                Log.e("手势3scene", e.toJson())
                 continue
             }
             val ce = toChildMotionEvent(item, e)
+            Log.e("手势view", "${scene?.view?.scale}")
+            Log.e("手势e", "${e.x}, ${e.y}")
+            Log.e("手势ce", "${ce.x}, ${ce.y}")
+            Log.e("手势1scene", (item.contains(ce.x, ce.y)).toString())
             if (item.contains(ce.x, ce.y)                                   // 如果点在子项目上
                     && item.onSingleTapUp(ce)) {                            // 且子项目处理了事件
+                Log.e("手势4scene", e.toJson())
                 return true
             }
         }
-
+        Log.e("手势2scene", e.toJson())
         return false
     } // Function onSingleTapUp()
 
+    open fun onActionUp() {
+        releaseItem()
+    }
+
+    open fun onActionMove(event: MotionEvent) {
+
+    }
+
     /**
      * 用户点击触发
      *
@@ -565,6 +613,7 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
         return false
     } // Function onScroll()
 
+
     /**
      * 用户按下触摸屏、快速移动后松开。即滑动操作。
      *
@@ -574,7 +623,7 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
      * @param   velocityY   Y轴上的移动速度,像素/秒
      * @return  如果事件被处理返回 true , 否则返回 false 。
      */
-     open fun onFling(e1: SMotionEvent, e2: SMotionEvent, velocityX: Float, velocityY: Float): Boolean {
+    open fun onFling(e1: SMotionEvent, e2: SMotionEvent, velocityX: Float, velocityY: Float): Boolean {
         Log.d(TAG, "onFling: releaseItem")
         releaseItem()
 
@@ -613,6 +662,7 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
      */
     private fun releaseItem() {
         isSelected = false
+        currentMoveItem = null
         scene!!.grabItem = null
         return
     } // Function grabItem
@@ -622,16 +672,28 @@ open class SGraphyItem(parent: SGraphyItem? = null) {
      *
      * @return 转换矩阵
      */
-    fun scene2itemMattrix() : Matrix{
-        val m = Matrix()
+    fun scene2itemMattrix(): Matrix {
+        var m = Matrix()
         val list = this.itemPath()
-        for ( item in list) {
-            m.postTranslate(item.pos.x, item.pos.y);
-            m.postScale(item.scale.x, item.scale.y);
-            m.postRotate(item.rotate)
+        for (item in list) {
+//            m.postTranslate(item.pos.x, item.pos.y);
+//            m.postScale(item.scale.x, item.scale.y);
+//            m.postRotate(item.rotate)
+            m.preTranslate(item.pos.x, item.pos.y);
+            m.preScale(item.scale.x, item.scale.y);
+            m.preRotate(item.rotate)
+
             // 如果不进行变形处理,则取消 painter 的变型操作
-            if (!item.isTransform){
-                m.postScale(item._inverseScale, item._inverseScale);
+            if (!item.isTransform) {
+//                m.postScale(item._inverseScaleX, item._inverseScaleY);
+                /****************************************** 待确认 ************************************************/
+                val src = kotlin.floatArrayOf(0f, 1f, 2f, 3f, 4f, 5f, 6f, 7f, 8f)
+                m.getValues(src)
+                val matrix = Matrix()
+                matrix.preTranslate(src[2], src[5])
+                matrix.preScale(item.scale.x, item.scale.y)
+                matrix.preRotate(item.rotate)
+                m = matrix
             }
         }
         return m

+ 20 - 7
sybotan-android-graphy/src/main/java/com/sybotan/android/graphy/SGraphyScene.kt

@@ -25,13 +25,14 @@ package com.sybotan.android.graphy
 
 import android.graphics.*
 import android.util.Log
+import android.view.MotionEvent
 import com.sybotan.android.base.extensions.adjusted
 import com.sybotan.android.graphy.data.SLineF
 import com.sybotan.android.graphy.enums.SGraphyItemFlag
 import com.sybotan.android.graphy.items.SGraphyImageItem
 import com.sybotan.android.graphy.items.SGraphyLineItem
 import com.sybotan.android.graphy.items.SGraphyRectItem
-import com.sybotan.android.graphy.utils.MatrixTools
+import com.sybotan.android.graphy.utils.MatrixUtil
 import com.sybotan.base.extensions.toJson
 
 /**
@@ -186,7 +187,7 @@ open class SGraphyScene {
     fun worldRect(): RectF {
         val rect = RectF()
 
-        for (item in rootNode.children) {        // 依次取item列中的所有item。将所有item的边界做并处理。
+        for (item in rootNode.children) {        // 依次取item列中的所有item。将所有item的边界做并处理。
             rect.union(item.boundingRect().adjusted(item.pos))
         }
 
@@ -302,6 +303,14 @@ open class SGraphyScene {
         return rootNode.onFling(e1, e2, velocityX, velocityY)
     } // Function onFling()
 
+
+    fun onActionUp(event: MotionEvent) {
+        rootNode.onActionUp()
+    }
+    fun onActionMove(event: MotionEvent) {
+        rootNode.onActionMove(event)
+    }
+
     /**
      * 转换场景事件坐标到指定Item坐标事件
      *
@@ -313,14 +322,18 @@ open class SGraphyScene {
         val se = SMotionEvent(e)
         se.matrix = Matrix()
         if (this.view != null ){
-            se.matrix.postTranslate(this.view!!.pos.x, this.view!!.pos.y);
-            se.matrix.postScale(this.view!!.scale, this.view!!.scale)
-            se.matrix.postRotate(this.view!!.rotate)
+//            se.matrix.postTranslate(this.view!!.pos.x, this.view!!.pos.y);
+//            se.matrix.postScale(this.view!!.scale, this.view!!.scale)
+//            se.matrix.postRotate(this.view!!.rotate)
+            se.matrix.preTranslate(this.view!!.pos.x, this.view!!.pos.y);
+            se.matrix.preScale(this.view!!.scale, this.view!!.scale)
+            se.matrix.preRotate(this.view!!.rotate)
+
         }
-        se.matrix.postConcat(item.scene2itemMattrix())
+        se.matrix.preConcat(item.scene2itemMattrix())
         val matrix = Matrix()
         se.matrix.invert(matrix)
-        val matrixTransform = MatrixTools.matrixTransform(matrix, se.viewX, se.viewY)
+        val matrixTransform = MatrixUtil.matrixTransform(matrix, se.viewX, se.viewY)
         se.x = matrixTransform.x
         se.y = matrixTransform.y
 //        val p = item.mapFromScene(e.x, e.y)

+ 49 - 19
sybotan-android-graphy/src/main/java/com/sybotan/android/graphy/SGraphyView.kt

@@ -28,11 +28,10 @@ import android.graphics.*
 import android.util.AttributeSet
 import android.util.Log
 import android.view.*
-import android.view.MotionEvent
 import com.sybotan.android.graphy.enums.SGraphyViewTouchState
 import com.sybotan.android.graphy.events.SGraphyViewMoveEvent
 import com.sybotan.android.graphy.events.SGraphyViewZoomEvent
-import com.sybotan.android.graphy.utils.MatrixTools
+import com.sybotan.android.graphy.utils.MatrixUtil
 import com.sybotan.base.extensions.toJson
 import org.greenrobot.eventbus.EventBus
 import kotlin.math.max
@@ -76,10 +75,6 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
             field = value
             moveRange()
         }
-    /** 默认缩放比例,用于指定最小缩放比例*/
-    var defaultScale = 0.0000001f
-    /**点的基数缩放比 */
-    var defaultPointScale = 0.01785718f
     /** 最小缩放比例 */
     var minScale = 0.0000001f
         set(value) {
@@ -129,6 +124,12 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
         initView()
     } // init
 
+    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
+        Log.e("w",widthMeasureSpec.toString())
+        Log.e("h",heightMeasureSpec.toString())
+    }
+
     /**
      * 适配视图到视图
      */
@@ -137,12 +138,25 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
         if (null == scene) {
             return
         }
+//        val w = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
+//        val h = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
+//        this.measure(width, height)
+//        val h: Int = this.getMeasuredHeight()
+//        val w: Int = this.getMeasuredWidth()
+
+        this.post {
+            val w = width.toFloat()
+            val h = height.toFloat()
+
+            val rect = scene!!.worldRect()
+            setCenterPoint( PointF(rect.centerX(), rect.centerY()),
+                    min(w / rect.width(), h / rect.height()) * fitrate)
+//            Log.e("w",w.toString())
+//            Log.e("h",h.toString())
+//            Log.e("rect1",rect.toJson())
+//            Log.e("min",(min(w / rect.width(), h / rect.height())).toJson())
+        }
 
-        val w = width.toFloat()
-        val h = height.toFloat()
-        val rect = scene!!.worldRect()
-        setCenterPoint( PointF(rect.centerX(), rect.centerY()),
-                min(w / rect.width(), h / rect.height()) * fitrate)
     } // Function FitView()
 
     /**
@@ -292,6 +306,7 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
                     true
                 }
                 MotionEvent.ACTION_MOVE -> {
+                    scene?.onActionMove(event)
                     if (SGraphyViewTouchState.ZoomState == touchState && canZoom) { // 两点绽放操作
                         viewZoom(event)
                         true
@@ -299,6 +314,10 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
                         gesture.onTouchEvent(event)
                     }
                 }
+                MotionEvent.ACTION_UP -> {
+                    scene?.onActionUp(event)
+                    gesture.onTouchEvent(event)
+                }
                 else -> {
                     gesture.onTouchEvent(event)
                 }
@@ -553,19 +572,30 @@ open class SGraphyView(context: Context, attrs: AttributeSet? = null)
         val src1 = kotlin.floatArrayOf(0f, 1f, 2f, 3f, 4f, 5f, 6f, 7f, 8f)
         val src2 = kotlin.floatArrayOf(0f, 1f, 2f, 3f, 4f, 5f, 6f, 7f, 8f)
         val se = SMotionEvent(e)
-        se.matrix.postTranslate(pos.x,pos.y)
-        se.matrix.postScale(this.scale, this.scale);
-        se.matrix.postRotate(this.rotate)
-        se.matrix.getValues(src1)
-        Log.e("src1= ",src1.toJson())
+//        se.matrix.postTranslate(pos.x,pos.y)
+//        se.matrix.postScale(this.scale, this.scale);
+//        se.matrix.postRotate(this.rotate)
+
+        se.matrix.preTranslate(pos.x,pos.y)
+        se.matrix.preScale(this.scale, this.scale);
+        se.matrix.preRotate(this.rotate)
+
 
         val matrixMat = Matrix()
         se.matrix.invert(matrixMat)
+
+        se.matrix.getValues(src1)
+        Log.e("src1= ",src1.toJson())
         matrixMat.getValues(src2)
         Log.e("src2= ",src2.toJson())
-        val matrixTransform = MatrixTools.matrixTransform(matrixMat, e.x, e.y)
-        se.x = matrixTransform.x
-        se.y = matrixTransform.y
+
+        val mp = MatrixUtil.matrixTransform(matrixMat, e.x, e.y)
+        se.x = mp.x
+        se.y = mp.y
+//        Log.e("ex = ",e.x.toString())
+//        Log.e("ey = ",e.y.toString())
+//        Log.e("sex = ",se.x .toString())
+//        Log.e("sey = ",se.y.toString())
 //        se.setLocation((e.x - pos.x) / scale, (e.y - pos.y) / scale)
         return se
     } // Function toSceneMotionEvent()

+ 3 - 1
sybotan-android-graphy/src/main/java/com/sybotan/android/graphy/items/SGraphyRectItem.kt

@@ -56,8 +56,10 @@ open class SGraphyRectItem(rect: RectF, parent: SGraphyItem? = null) : SGraphyIt
 
     init {
         pen.color = Color.RED
-        flags = EnumSet.of(SGraphyItemFlag.ItemIsMovable)
+        flags = EnumSet.of(SGraphyItemFlag.ItemIsMovable,SGraphyItemFlag.ItemIsSelectable,SGraphyItemFlag.ItemIsFocusable)
         isVisible = true
+        this.rect = rect
+
     } // init()
 
     /**

+ 2 - 2
sybotan-android-views/build.gradle

@@ -101,8 +101,8 @@ dependencies {
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     // SAGA依赖
     implementation group: 'cn.sagacloud', name: 'saga-kotlin-base', version: SAGA_KOTLIN_VERSION
-//    implementation project(':sybotan-android-base')
-    implementation group: 'cn.sagacloud', name: 'sybotan-android-base', version: SYBOTAN_ANDROID_VERSION
+    implementation project(':sybotan-android-base')
+
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

+ 1 - 2
sybotan-android-works/build.gradle

@@ -101,9 +101,8 @@ dependencies {
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     // SAGA依赖
     implementation group: 'cn.sagacloud', name: 'saga-kotlin-base', version: SAGA_KOTLIN_VERSION
-//    implementation project(':sybotan-android-base')
+    implementation project(':sybotan-android-base')
     implementation project(':sybotan-android-views')
-    implementation group: 'cn.sagacloud', name: 'sybotan-android-base', version: SYBOTAN_ANDROID_VERSION
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////