DrivingRoute.kt 7.81 KB
package cn.feewee.amap3d.map_view.route

import android.content.Context
import android.graphics.Color
import android.widget.Toast
import cn.feewee.amap3d.*
import cn.feewee.amap3d.R
import com.amap.api.maps.AMap
import com.amap.api.maps.model.*
import com.amap.api.services.core.AMapException
import com.amap.api.services.route.*
import com.facebook.react.bridge.ReadableArray

class DrivingRoute(context: Context) : RouteOverlay(context) {
    private var drivePath: DrivePathV2? = null
    private var throughPointList: List<LatLng> = emptyList()
    private var isColorfulline = true
    private var throughPointMarkerList: ArrayList<Marker> = ArrayList()
    private var throughPointMarkerVisible = true
    private var mPolylineOptions: PolylineOptions? = null
    private var mPolylineOptionsColor: PolylineOptions? = null

    init {
        try {
            mRouteSearch = RouteSearchV2(context)
        } catch (e: AMapException) {
            e.printStackTrace()
        }
    }

    fun setThroughPointList(throughPoints: List<LatLng>) {
        if (throughPoints.size > 6) {
            throughPointList = throughPoints.take(6)
            return
        }
        throughPointList = throughPoints
    }

    fun setIsColorfulline(iscolorfulline: Boolean) {
        isColorfulline = iscolorfulline
    }

    fun setThroughPointMarkerVisible(visible: Boolean) {
        try {
            throughPointMarkerVisible = visible
            if (this.throughPointMarkerList.isNotEmpty()) {
                for (i in this.throughPointMarkerList.indices) {
                    this.throughPointMarkerList[i].isVisible = visible
                }
            }
        } catch (e: Throwable) {
            e.printStackTrace()
        }
    }

    override fun add(map: AMap) {
        this.map = map
        searchRouteResult()
    }

    override fun remove() {
        removeMarkerFromMap()
        removeLineFromMap()
        try {
            if (throughPointMarkerList.size > 0) {
                for (i in throughPointMarkerList.indices) {
                    throughPointMarkerList[i].remove()
                }
                throughPointMarkerList.clear()
            }
        } catch (e: Throwable) {
            e.printStackTrace()
        }
    }

    private fun addToMap() {
        initPolylineOptions()
        if (getRouteWidth() == 0f || drivePath == null) {
            return
        }

        val mLatLngsOfPath = ArrayList<LatLng>()
        val tmcs = ArrayList<TMC>()
        val drivePaths = drivePath?.steps

        for (step in drivePaths!!) {
            val latlonPoints = step.polyline
            val tmclist = step.tmCs
            tmcs.addAll(tmclist)
            addDrivingStationMarkers(step, latlonPoints[0].convertToLatLng())
            for (latlonpoint in latlonPoints) {
                mPolylineOptions?.add(latlonpoint.convertToLatLng())
                mLatLngsOfPath.add(latlonpoint.convertToLatLng())
            }
        }
        addStartAndEndMarker()
        addThroughPointMarker()
        if (isColorfulline && tmcs.size > 0) {
            colorWayUpdate(tmcs)
            addPolyLine(mPolylineOptionsColor)
        } else {
            addPolyLine(mPolylineOptions)
        }
    }

    /**
     * 初始化线段属性
     */
    private fun initPolylineOptions() {
        mPolylineOptions = PolylineOptions()
            .color(getRoadColor())
            .setCustomTexture(getRoadLine())
            .width(getRouteWidth())
    }

    /**
     * 根据不同的路段拥堵情况展示不同的颜色
     *
     * @param tmcSection
     */
    private fun colorWayUpdate(tmcSection: List<TMC>) {
        var segmentTrafficStatus: TMC
        mPolylineOptionsColor = PolylineOptions().width(getRouteWidth())
        mPolylineOptionsColor?.add(tmcSection[0].polyline[0].convertToLatLng())

        val colorList: MutableList<Int> = ArrayList()
        colorList.add(getRoadColor())
        for (i in tmcSection.indices) {
            segmentTrafficStatus = tmcSection[i]
            val color: Int = getColor(segmentTrafficStatus.status)
            val mployline = segmentTrafficStatus.polyline
            for (j in 1 until mployline.size) {
                mPolylineOptionsColor?.add(mployline[j].convertToLatLng())
                colorList.add(color)
            }
        }
        colorList.add(getRoadColor())
        mPolylineOptionsColor?.colorValues(colorList)
    }

    private fun getColor(status: String): Int {
        return when (status) {
            "畅通" -> {
                Color.GREEN
            }
            "缓行" -> {
                Color.YELLOW
            }
            "拥堵" -> {
                Color.RED
            }
            "严重拥堵" -> {
                Color.parseColor("#990033")
            }
            else -> {
                Color.parseColor("#537edc")
            }
        }
    }

    /**
     * @param driveStep
     * @param latLng
     */
    private fun addDrivingStationMarkers(driveStep: DriveStepV2, latLng: LatLng) {
        addStationMarker(
            MarkerOptions()
                .position(latLng)
                .title("\u65B9\u5411:" + driveStep.instruction + "\n\u9053\u8DEF:" + driveStep.road)
                .snippet(driveStep.instruction).visible(nodeIconVisible)
                .anchor(0.5f, 0.5f).icon(getDriveBit())
        )
    }

    /**
     * 添加途经点marker
     */
    private fun addThroughPointMarker() {
        if (throughPointList.isNotEmpty()) {
            for (i in throughPointList.indices) {
                val latLonPoint = throughPointList[i]
                throughPointMarkerList.add(
                    map.addMarker(
                        MarkerOptions()
                            .position(latLonPoint)
                            .visible(throughPointMarkerVisible)
                            .icon(getThroughBit())
                            .title("\u9014\u7ECF\u70B9")
                    )
                )
            }
        }
    }

    override fun searchRouteResult() {
        if (mRouteSearch == null) {
            return
        }
        val fromAndTo = createFromAndTo() ?: return
        try {
            showProgressDialog()
            val driveRouteResult = mRouteSearch!!.calculateDriveRoute(
                RouteSearchV2.DriveRouteQuery(
                    fromAndTo,
                    RouteSearchV2.DrivingStrategy.DEFAULT,
                    throughPointList.map { r -> r.convertToLatLonPoint() },
                    null,
                    null
                )
            )
            onDriveRouteSearched(driveRouteResult)
        } catch (e: AMapException) {
            dissmissProgressDialog()
            showerror(context, e.errorCode)
        }

    }

    private fun onDriveRouteSearched(result: DriveRouteResultV2) {
        dissmissProgressDialog()
        map.clear()
        if (result.paths != null) {
            if (result.paths.size > 0) {
                drivePath = result.paths[0] ?: return
                remove()
                addToMap()
                zoomToSpan()

            } else if (result.paths == null) {
                show(context, R.string.no_result)
            }
        } else {
            show(context, R.string.no_result)
        }
    }


    fun searchRoute(args: ReadableArray?) {
        val start = args?.getMap(0)?.toLatLonPoint()
        val end = args?.getMap(1)?.toLatLonPoint()
        val through = args?.getArray(2)?.toLatLngList()
        if (start == null) {
            Toast.makeText(context, "起点不能为空", Toast.LENGTH_LONG).show()
            return
        }
        if (end == null) {
            Toast.makeText(context, "终点不能为空", Toast.LENGTH_LONG).show()
            return
        }
        setStartPoint(start)
        setEndPoint(end)
        if (through?.isNotEmpty() == true) {
            setThroughPointList(through)
        }
        searchRouteResult()
    }

}