@maptalks/traffic 0.87.2 → 0.88.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/maptalks.traffic.es.js +2 -2
- package/dist/maptalks.traffic.js +2 -2
- package/package.json +53 -53
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @maptalks/traffic v0.
|
|
2
|
+
* @maptalks/traffic v0.88.0
|
|
3
3
|
* LICENSE : UNLICENSED
|
|
4
4
|
* (c) 2016-2023 maptalks.org
|
|
5
5
|
*/
|
|
@@ -978,4 +978,4 @@ class b {
|
|
|
978
978
|
|
|
979
979
|
export { b as TrafficScene };
|
|
980
980
|
|
|
981
|
-
"undefined" != typeof console && console.log("@maptalks/traffic v0.
|
|
981
|
+
"undefined" != typeof console && console.log("@maptalks/traffic v0.88.0");
|
package/dist/maptalks.traffic.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @maptalks/traffic v0.
|
|
2
|
+
* @maptalks/traffic v0.88.0
|
|
3
3
|
* LICENSE : UNLICENSED
|
|
4
4
|
* (c) 2016-2023 maptalks.org
|
|
5
5
|
*/
|
|
6
|
-
!function(t,i){"object"==typeof exports&&"undefined"!=typeof module?i(exports,require("maptalks"),require("@maptalks/gl-layers"),require("turf")):"function"==typeof define&&define.amd?define(["exports","maptalks","@maptalks/gl-layers","turf"],i):i((t="undefined"!=typeof globalThis?globalThis:t||self).maptalks=t.maptalks||{},t.maptalks,t.maptalks,t.turf)}(this,(function(t,i,s,n){"use strict";function e(t){if(t&&t.t)return t;var i=Object.create(null);return t&&Object.keys(t).forEach((function(s){if("default"!==s){var n=Object.getOwnPropertyDescriptor(t,s);Object.defineProperty(i,s,n.get?n:{enumerable:!0,get:function(){return t[s]}})}})),i.default=t,Object.freeze(i)}var r=e(i),h=e(n);let o=0;function u(t,i,s){return null==i||s?(t.length!==+t.length&&(t=function(t){const i=function(t){if(!function(t){return t===Object(t)}(t))return[];const i=[];for(const s in t)g(t,s)&&i.push(s);return i}(t),s=i.length,n=new Array(s);for(let e=0;e<s;e++)n[e]=t[i[e]];return n}(t)),t[a(t.length-1)]):function(t){let i,s=0;const n=[];return d(t,t=>{i=i(s++),n[s-1]=n[i],n[i]=t}),n}(t).slice(0,Math.max(0,i))}function l(t){const i=++o+"";return t?t+i:i}function c(t,i){let s;if(nativeBind&&t.bind===nativeBind)return nativeBind.apply(t,slice.call(arguments,1));const n=slice.call(arguments,2);return s=function(){if(!(this instanceof s))return t.apply(i,n.concat(slice.call(arguments)));ctor.prototype=t.prototype;const e=new ctor;ctor.prototype=null;const r=t.apply(e,n.concat(slice.call(arguments)));return Object(r)===r?r:e}}function a(t,i){return i||(i=t,t=0),t+Math.floor(Math.random()*(i-t+1))}function f(t){return d(slice.call(arguments,1),(function(i){if(i)for(const s in i)t[s]=i[s]})),t}function d(t,i,s){if(null==t)return t;if(nativeForEach&&t.forEach===nativeForEach)t.forEach(i,s);else if(t.length===+t.length){for(let n=0,e=t.length;n<e;n++)if(i.call(s,t[n],n,t)===breaker)return null}else{const n=n(t);for(let e=0,r=n.length;e<r;e++)if(i.call(s,t[n[e]],n[e],t)===breaker)return null}return t}function g(t,i){return hasOwnProperty.call(t,i)}class w{constructor(t,i){let s,n,e;if(this.factory=t,this.objects={},null!=i&&null!=i.objects)for(s in e=i.objects,e)n=e[s],this.objects[s]=this.factory.copy(n)}get length(){return Object.keys(this.objects).length}toJSON(){return this.objects}get(t){return this.objects[t]}put(t){return this.objects[t.id]=t}pop(t){let i;const s=null!=(i=t.id)?i:t,n=this.objects[s];return"function"==typeof n.release&&n.release(),delete this.objects[s],n}all(){return this.objects}clear(){return this.objects={}}}class p{constructor(t,i){this.x=t||0,this.y=i||0}get length(){return Math.sqrt(this.x*this.x+this.y*this.y)}get direction(){return Math.atan2(this.y,this.x)}get normalized(){return new p(this.x/this.length,this.y/this.length)}add(t){return new p(this.x+t.x,this.y+t.y)}subtract(t){return new p(this.x-t.x,this.y-t.y)}mult(t){return new p(this.x*t,this.y*t)}divide(t){return new p(this.x/t,this.y/t)}}class m{constructor(t,i){this.source=t,this.target=i}get vector(){return this.target.subtract(this.source)}get length(){return this.vector.length}get direction(){return this.vector.direction}get center(){return this.getPoint(.5)}split(t,i){let s,n,e,r,h,o;const u=i?function(){h=[];for(let i=r=t-1;r<=0?i<=0:i>=0;r<=0?i++:i--)h.push(i);return h}.apply(this):function(){o=[];for(let i=0,s=t-1;0<=s?i<=s:i>=s;0<=s?i++:i--)o.push(i);return o}.apply(this),l=[];for(n=0,e=u.length;n<e;n++)s=u[n],l.push(this.subsegment(s/t,(s+1)/t));return l}getPoint(t){return this.source.add(this.vector.mult(t))}subsegment(t,i){const s=this.vector,n=this.source.add(s.mult(t)),e=this.source.add(s.mult(i));return new m(n,e)}}class v{constructor(t,i,s,n){this.x=t||0,this.y=i||0,this.width=s||0,this.height=n||0}copy(t){return new v(t.x,t.y,t.width,t.height)}toJSON(){return f({},this)}area(){return this.width*this.height}left(t){return null!=t&&(this.x=t),this.x}right(t){return null!=t&&(this.x=t-this.width),this.x+this.width}top(t){return null!=t&&(this.y=t),this.y}bottom(t){return null!=t&&(this.y=t-this.height),this.y+this.height}center(t){return null!=t&&(this.x=t.x-this.width/2,this.y=t.y-this.height/2),new p(this.x+this.width/2,this.y+this.heigh/2)}containsPoint(t){let i,s;return this.left()<=(i=t.x)&&i<=this.right()&&this.top()<=(s=t.y)&&s<=this.bottom()}containsRect(t){return this.left()<=t.left()&&t.right()<=this.right()&&this.top()<=t.top()&&t.bottom()<=this.bottom()}getVertices(){return[new p(this.left(),this.top()),new p(this.right(),this.top()),new p(this.right(),this.bottom()),new p(this.left(),this.bottom())]}getSide(t){const i=this.getVertices();return new m(i[t],i[(t+1)%4])}getSectorId(t){const i=t.subtract(this.center());if(i.y<=0&&Math.abs(i.x)<=Math.abs(i.y))return 0;if(i.x>=0&&Math.abs(i.x)>=Math.abs(i.y))return 1;if(i.y>=0&&Math.abs(i.x)<=Math.abs(i.y))return 2;if(i.x<=0&&Math.abs(i.x)>=Math.abs(i.y))return 3;throw new Error("algorithm error")}getSector(t){return this.getSide(this.getSectorId(t))}}class M{constructor(t){this.intersection=t,this.time=0,this.flipMultiplier=.4*Math.random()-.2+1,this.stateNum=0,this.lightsFlipInterval=20,this.states=[["L","","L",""],["FR","","FR",""],["","L","","L"],["","FR","","FR"]]}get flipInterval(){return this.flipMultiplier*this.lightsFlipInterval}get state(){let t=this.states[this.stateNum%this.states.length];this.intersection.roads.length<=2&&(t=["LFR","LFR","LFR","LFR"]);const i=[];for(let s=0,n=t.length;s<n;s++){const n=t[s];i.push(this.decode(n))}return i}decode(t){const i=[0,0,0],s=[].indexOf||function(t){for(let i=0,s=this.length;i<s;i++)if(i in this&&this[i]===t)return i;return-1};return s.call(t,"L")>=0&&(i[0]=1),s.call(t,"F")>=0&&(i[1]=1),s.call(t,"R")>=0&&(i[2]=1),i}flip(){return this.stateNum+=1}onTick(t){return this.time+=t,this.time>this.flipInterval?(this.flip(),this.time-=this.flipInterval):null}}class b{constructor(t){this.rect=t,this.id=l("intersection"),this.roads=[],this.inRoads=[],this.controlSignals=new M(this)}copy(t){t.rect=v.copy(t.rect);const i=Object.create(b.prototype);return f(i,t),i.roads=[],i.inRoads=[],i.controlSignals=new M(i),i}toJSON(){return{id:this.id,rect:this.rect}}update(){let t,i,s,n,e;const r=this.roads;for(i=0,n=r.length;i<n;i++)t=r[i],t.update();const h=this.inRoads,o=[];for(s=0,e=h.length;s<e;s++)t=h[s],o.push(t.update());return o}}class y{constructor(t,i,s){this.car=t,this.position=s,this.id=l("laneposition"),this.free=!0,this.tmpLane=i}get lane(){return this.tmpLane}set lane(t){this.release(),this.tmpLane=t}get relativePosition(){return this.position/this.lane.length}get nextCarDistance(){let t,i;const s=this.getNext();return s?(i=s.position-s.car.length/2,t=this.position+this.car.length/2,{car:s.car,distance:i-t}):{car:null,distance:1/0}}acquire(){let t;return null!=(null!=(t=this.lane)?t.addCarPosition:void 0)?(this.free=!1,this.lane.addCarPosition(this)):null}release(){let t;return!this.free&&(null!=(t=this.lane)?t.removeCar:void 0)?(this.free=!0,this.lane.removeCar(this)):null}getNext(){return this.lane&&!this.free?this.lane.getNext(this):null}}class L{constructor(t,i,s,n){this.A=t,this.B=i,this.O=s,this.Q=n,this.AB=new m(this.A,this.B),this.AO=new m(this.A,this.O),this.OQ=new m(this.O,this.Q),this.QB=new m(this.Q,this.B),this.len=null}get length(){let t,i,s,n,e;if(null==this.len)for(s=10,n=null,this.len=0,t=e=0;e<=10;t=++e)i=this.getPoint(t/10),n&&(this.len+=i.subtract(n).length),n=i;return this.len}getPoint(t){const i=this.AO.getPoint(t),s=this.OQ.getPoint(t),n=this.QB.getPoint(t),e=new m(i,s).getPoint(t),r=new m(s,n).getPoint(t);return new m(e,r).getPoint(t)}getDirection(t){const i=this.AO.getPoint(t),s=this.OQ.getPoint(t),n=this.QB.getPoint(t),e=new m(i,s).getPoint(t),r=new m(s,n).getPoint(t);return new m(e,r).direction}}class x{constructor(t,i,s){this.car=t,this.current=new y(this.car,i,s||0),this.current.acquire(),this.next=new y(this.car),this.temp=new y(this.car),this.isChangingLanes=!1}get lane(){return this.temp.lane||this.current.lane}get absolutePosition(){return null!=this.temp.lane?this.temp.position:this.current.position}get relativePosition(){return this.absolutePosition/this.lane.length}get direction(){return this.lane.getDirection(this.relativePosition)}get coords(){return this.lane.getPoint(this.relativePosition)}get nextCarDistance(){const t=this.current.nextCarDistance,i=this.next.nextCarDistance;return t.distance<i.distance?t:i}get distanceToStopLine(){return this.canEnterIntersection()?1/0:this.getDistanceToIntersection()}get nextIntersection(){return this.current.lane.road.target}get previousIntersection(){return this.current.lane.road.source}isValidTurn(){const t=this.car.nextLane,i=this.current.lane,s=i.getTurnDirection(t);if(3===s)throw Error("no U-turns are allowed");if(0===s&&!i.isLeftmost)throw Error("no left turns from this lane");if(2===s&&!i.isRightmost)throw Error("no right turns from this lane");return!0}canEnterIntersection(){const t=this.car.nextLane,i=this.current.lane;if(!t)return!0;const s=this.nextIntersection,n=i.getTurnDirection(t),e=i.road.targetSideId;return s.controlSignals.state[e][n]}getDistanceToIntersection(){const t=this.current.lane.length-this.car.length/2-this.current.position;return this.isChangingLanes?1/0:Math.max(t,0)}timeToMakeTurn(t){return null==t&&(t=0),this.getDistanceToIntersection()<=t}moveForward(t){let i,s;t=Math.max(t,0),this.current.position+=t,this.next.position+=t,this.temp.position+=t,this.timeToMakeTurn()&&this.canEnterIntersection()&&this.isValidTurn()&&this.i(this.car.popNextLane(),0);const n=this.temp.position/(null!=(i=this.temp.lane)?i.length:void 0),e=2*this.car.length;return this.isChangingLanes&&this.temp.position>e&&!this.current.free&&this.current.release(),this.isChangingLanes&&this.next.free&&this.temp.position+e>(null!=(s=this.temp.lane)?s.length:void 0)&&this.next.acquire(),this.isChangingLanes&&n>=1&&this.s(),!this.current.lane||this.isChangingLanes||this.car.nextLane?null:this.car.pickNextLane()}changeLane(t){if(this.isChangingLanes)throw Error("already changing lane");if(null==t)throw Error("no next lane");if(t===this.lane)throw Error("next lane == current lane");if(this.lane.road!==t.road)throw Error("not neighbouring lanes");const i=this.current.position+3*this.car.length;return this.i(t,i)}h(){const t=this.current.lane.getPoint(this.current.relativePosition),i=this.next.lane.getPoint(this.next.relativePosition),s=i.subtract(t).length,n=this.current.lane.middleLine.vector.normalized.mult(.3*s),e=t.add(n),r=this.next.lane.middleLine.vector.normalized.mult(.3*s),h=i.subtract(r);return new L(t,i,e,h)}o(){return this.h()}i(t,i){if(this.isChangingLanes)throw Error("already changing lane");if(null==t)return 0;this.isChangingLanes=!0,this.next.lane=t,this.next.position=i;const s=this.o();return this.temp.lane=s,this.temp.position=0,this.next.position-=this.temp.lane.length}s(){if(!this.isChangingLanes)throw Error("no lane changing is going on");return this.isChangingLanes=!1,this.current.lane=this.next.lane,this.current.position=this.next.position||0,this.current.acquire(),this.next.lane=null,this.next.position=NaN,this.temp.lane=null,this.temp.position=NaN,this.current.lane}release(){let t,i,s;return null!=(t=this.current)&&t.release(),null!=(i=this.next)&&i.release(),null!=(s=this.temp)?s.release():void 0}}const C=[];class E{constructor(t,i){this.type=a(C.length-1),this.id=l("car"),this.color=(300+240*Math.random()|0)%360,this.tmpSpeed=0,this.width=2,this.length=2,this.maxSpeed=30,this.s0=2,this.timeHeadway=1.5,this.maxAcceleration=1,this.maxDeceleration=3,this.trajectory=new x(this,t,i),this.alive=!0,this.preferedLane=null}get coords(){return this.trajectory.coords}get speed(){return this.tmpSpeed}set speed(t){t<0&&(t=0),t>this.maxSpeed&&(t=this.maxSpeed),this.tmpSpeed=t}get direction(){return this.trajectory.direction}release(){return this.trajectory.release()}getAcceleration(){let t;const i=this.trajectory.nextCarDistance,s=Math.max(i.distance,0),n=this.maxAcceleration,e=this.maxDeceleration,r=this.speed-(null!=(t=i.car)?t.speed:void 0)||0,h=Math.pow(this.speed/this.maxSpeed,4),o=this.s0,u=this.speed*this.timeHeadway,l=o+u+this.speed*r/(2*Math.sqrt(n*e)),c=Math.pow(l/s,2),a=1+u+Math.pow(this.speed,2)/(2*e),f=1-h-c-Math.pow(a/this.trajectory.distanceToStopLine,2);return this.maxAcceleration*f}move(t){const i=this.getAcceleration();if(this.speed+=i*t,!this.trajectory.isChangingLanes&&this.nextLane){const t=this.trajectory.current.lane,i=t.getTurnDirection(this.nextLane),s=function(){switch(i){case 0:return t.leftmostAdjacent;case 2:return t.rightmostAdjacent;default:return t}}();s!==t&&this.trajectory.changeLane(s)}const s=this.speed*t+.5*i*Math.pow(t,2);return this.trajectory.nextCarDistance.distance<s&&console.log("bad IDM"),this.trajectory.timeToMakeTurn(s)&&null==this.nextLane?(this.alive=!1,this.alive):this.trajectory.moveForward(s)}pickNextRoad(){const t=this.trajectory.nextIntersection,i=this.trajectory.current.lane,s=t.roads.filter((function(t){return t.target!==i.road.source}));if(0===s.length)return null;return u(s)}pickNextLane(){if(this.nextLane)throw Error("next lane is already chosen");this.nextLane=null;const t=this.pickNextRoad();if(!t)return null;const i=this.trajectory.current.lane.road.getTurnDirection(t),s=function(){switch(i){case 0:return t.lanesNumber-1;case 1:return a(0,t.lanesNumber-1);case 2:return 0}return null}();return this.nextLane=t.lanes[s],this.nextLane}popNextLane(){const t=this.nextLane;return this.nextLane=null,this.preferedLane=null,t}}class O{constructor(t,i,s){this.sourceSegment=t,this.targetSegment=i,this.road=s,this.leftAdjacent=null,this.rightAdjacent=null,this.leftmostAdjacent=null,this.rightmostAdjacent=null,this.carsPositions={},this.update()}get sourceSideId(){return this.road.sourceSideId}get targetSideId(){return this.road.targetSideId}get isRightmost(){return this===this.rightmostAdjacent}get isLeftmost(){return this===this.leftmostAdjacent}get leftBorder(){return new m(this.sourceSegment.source,this.targetSegment.target)}get rightBorder(){return new m(this.sourceSegment.target,this.targetSegment.source)}toJSON(){const t=f({},this);return delete t.carsPositions,t}update(){return this.middleLine=new m(this.sourceSegment.center,this.targetSegment.center),this.length=this.middleLine.length,this.direction=this.middleLine.direction}getTurnDirection(t){return t?this.road.getTurnDirection(t.road):1}getDirection(){return this.direction}getPoint(t){return this.middleLine.getPoint(t)}addCarPosition(t){if(t.id in this.carsPositions)throw Error("car is already here");return this.carsPositions[t.id]=t}removeCar(t){if(!(t.id in this.carsPositions))throw Error("removing unknown car");return delete this.carsPositions[t.id]}getNext(t){if(t.lane!==this)throw Error("car is on other lane");let i=null,s=1/0;const n=this.carsPositions;for(const e in n){const r=n[e],h=r.position-t.position;!r.free&&0<h&&h<s&&(s=h,i=r)}return i}}class R{constructor(t,i,s){this.source=t,this.target=i,this.id=l("road"),this.lanes=[],this.gridSize=s||32,this.lanesNumber=null,this.update()}get length(){return this.targetSide.target.subtract(this.sourceSide.source).length}get leftmostLane(){return this.lanes[this.lanesNumber-1]}get rightmostLane(){return this.lanes[0]}copy(t){const i=Object.create(R.prototype);return f.extend(i,t),null==i.lanes&&(i.lanes=[]),i}toJSON(){return{id:this.id,source:this.source.id,target:this.target.id}}getTurnDirection(t){if(this.target!==t.source)throw Error("invalid roads");const i=this.targetSideId;return(t.sourceSideId-i-1+8)%4}update(){let t,i,s,n,e,r;if(!this.source||!this.target)throw Error("incomplete road");this.sourceSideId=this.source.rect.getSectorId(this.target.rect.center()),this.sourceSide=this.source.rect.getSide(this.sourceSideId).subsegment(.5,1),this.targetSideId=this.target.rect.getSectorId(this.source.rect.center()),this.targetSide=this.target.rect.getSide(this.targetSideId).subsegment(0,.5),this.lanesNumber=0|Math.min(this.sourceSide.length,this.targetSide.length),this.lanesNumber=Math.max(2,this.lanesNumber/this.gridSize|0);const h=this.sourceSide.split(this.lanesNumber,!0),o=this.targetSide.split(this.lanesNumber);if(null==this.lanes||this.lanes.length<this.lanesNumber)for(null==this.lanes&&(this.lanes=[]),t=s=0,e=this.lanesNumber-1;0<=e?s<=e:s>=e;t=0<=e?++s:--s)null==(i=this.lanes)[t]&&(i[t]=new O(h[t],o[t],this));const u=[];for(t=n=0,r=this.lanesNumber-1;0<=r?n<=r:n>=r;t=0<=r?++n:--n)this.lanes[t].sourceSegment=h[t],this.lanes[t].targetSegment=o[t],this.lanes[t].leftAdjacent=this.lanes[t+1],this.lanes[t].rightAdjacent=this.lanes[t-1],this.lanes[t].leftmostAdjacent=this.lanes[this.lanesNumber-1],this.lanes[t].rightmostAdjacent=this.lanes[0],u.push(this.lanes[t].update());return u}}class N{constructor(t){this.toRemove=[],this.options=t||{},this.carsNumber=this.options.carsNumber||10,this.gridSize=this.options.gridSize||32,this.u=0,this.l=0,this.g=5,this.carsList={},this.p=new s.GLTFLayer("traffic"),this.m="stop",this.v=[],this.M={},this.set()}run(){this.m="running",this.L()}stop(){this.m="stop"}remove(){this.C&&cancelAnimationFrame(this.C),this.p.remove(),delete this.map}setSymbols(t){this.v=t;for(let t=0;t<this.v.length;t++){const i=this.v[t];this.M[i.url]=new s.MultiGLTFMarker([],{symbol:i}).addTo(this.p)}}L(){if("running"!==this.m)return;const t=Date.now();this.l=t;const i=Date.now();let s,n=i-this.u||0;n>100&&(n=100),this.u=i,this.onTick(this.g*n/1e3);let e=this.toRemove.length;for(;e--;)this.R(this.toRemove[e]);this.clearTmpRemove();const r=this.cars.all();for(s in r)this.N(r[s],s);this.C=window.requestAnimationFrame(this.L.bind(this))}I(){for(const t in this.M)this.M[t].removeData();for(const t in this.carsList){const i=this.carsList[t],s=i.url;this.M[s].addData(i)}}N(t){const i=t.id.substring(3);if(this.carsList[i]){if(!t)return;const s=t.coords,n=t.direction,e=this.map,h=e.pointAtResToCoordinate(new r.Point(s.x/this.gridSize,s.y/this.gridSize),e.getGLRes()),o=n/Math.PI*180+90;this.carsList[i].coordinates=h,this.carsList[i].rotation=[0,0,o];const u=this.S(i),l=this.carsList[i].url;u>-1?this.M[l].updateData(u,this.carsList[i]):this.M[l].addData(this.carsList[i])}else{const t=this.v[Math.floor(Math.random()*this.v.length)];this.carsList[i]={coordinates:null,direction:null,url:t.url},this.showHideCar(this.carsList[i],"show")}}showHideCar(t,i,s){const n=this;r.animation.Animation.animate({"symbol":{transparent:1}},{duration:1e3,easing:"out"},(function(e){if("running"===e.state.playState){let r=0;"show"===i?(r=e.styles.symbol.transparent,t.color=[1,1,1,r]):"hide"===i&&(r=1-e.styles.symbol.transparent,t.color=[1,1,1,r],r<.01&&setTimeout((function(){const t=n.S(s);if(!n.carsList[s])return;const i=n.carsList[s].url;t>-1&&n.M[i].removeData(t),delete n.carsList[s]}),100))}})).play()}S(t){const i=this.carsList[t];if(!i)return-1;const s=i.url;return this.M[s].getAllData().indexOf(this.carsList[t])}R(t){const i=t.substring(3);null!=this.carsList[i]&&this.showHideCar(this.carsList[i],"hide",i)}get instantSpeed(){const t=function(t,i,s){const n=[];return null==t?n:nativeMap&&t.map===nativeMap?t.map(i,s):(d(t,(t,e,r)=>{n.push(i.call(s,t,e,r))}),n)}(this.cars.all(),t=>t.speed);return 0===t.length?0:function(t,i,s,n){let e=arguments.length>2;return null==t&&(t=[]),nativeReduce&&t.reduce===nativeReduce?(n&&(i=c(i,n)),e?t.reduce(i,s):t.reduce(i)):(d(t,(t,r,h)=>{e?s=i.call(n,s,t,r,h):(s=t,e=!0)}),s)}(t,(function(t,i){return t+i}))/t.length}get map(){const t=this.T;return t?t.getMap():null}addTo(t){this.T=t,this.p.addTo(t)}set(t){return null==t&&(t={}),this.intersections=new w(b,t.intersections),this.roads=new w(R,t.roads),this.cars=new w(E,t.cars),this.carsNumber=0}save(){const t=f({},this);return delete t.cars,window.localStorage.world=JSON.stringify(t)}setCarNumber(t){this.carsNumber=t}getCarNumber(){return this.carsNumber}load(){let t,i,s,n;if(t=window.localStorage.world,t=t&&JSON.parse(t),null==t)return null;this.clear(),this.carsNumber=t.carsNumber||0;const e=t.intersections;for(i in e)s=e[i],this.addIntersection(b.copy(s));const r=t.roads,h=[];for(i in r)n=r[i],n=(new R).copy(n),n.source=this.getIntersection(n.source),n.target=this.getIntersection(n.target),h.push(this.addRoad(n));return h}intersectSegment(t,i){for(let s=0;s<i.length-1;s++){const n=[i[s],i[s+1]],e=h.lineString(n),r=h.lineIntersect(t,e);if(r.features.length)return{intersectIndex:s,coord:r.features[0].geometry.coordinates}}return null}intersection(t,i,s,n,e,r){const o=h.lineString(t);for(let t=i+1;t<n.length;t++){const h=n[t],u=this.intersectSegment(o,h);if(!u)continue;const l={};l[i]={pre:s},l[t]={pre:u.intersectIndex+r[t]};const c={inLines:l,coordinate:this.map.coordinateToPointAtRes({x:u.coord[0],y:u.coord[1]},this.map.getGLRes())};e.push(c)}}generateTraffic(t){if(!this.map)return;const i={};let s=0;for(let n=0;n<t.length;n++)i[n]=s,s+=t[n].length;const n=[];let e=0;for(let s=0;s<t.length;s++){const r=t[s];for(let h=0;h<r.length-1;h++){const o=[r[h],r[h+1]];this.intersection(o,s,e+h,t,n,i)}e+=r.length}const r=[];let h=0;const o=this.map;for(let i=0;i<t.length;i++){const s=t[i];for(let t=0;t<s.length;t++){const n=o.coordinateToPointAtRes({x:s[t][0],y:s[t][1]},o.getGLRes()),e={};0===t?e[i]={pre:null}:(s.length,e[i]={pre:t-1+h});const u={inLines:e,coordinate:n};r.push(u)}h+=s.length}for(let t=0;t<r.length;t++){const i=r[t];this.comparePrePoint(i,t,n)}const u=this.gridSize,l=[];for(let t=0;t<r.length;t++){const i=r[t],s=i.coordinate.x,n=i.coordinate.y,e=new v(s*u-.5,n*u-.5,1,1),h=new b(e);h.connectRoads=i.roads,l.push(h),this.addIntersection(h)}const c=[];for(let t=0;t<n.length;t++){const i=n[t],s=i.coordinate.x,e=i.coordinate.y,r=new v(s*u-.5,e*u-.5,1,1),h=new b(r);h.connectRoads=i.roads,c.push(h),this.addIntersection(h)}for(let t=0;t<l.length;t++){const i=l[t],s=i.connectRoads;if(s)for(let t=0;t<s.length;t++){const n=s[t];if(null!=n.pre){let t=null;const s=n.type;"line"===s?t=l[n.pre]:"line-interact"===s&&(t=c[n.pre]),this.addRoad(new R(i,t)),this.addRoad(new R(t,i))}}}for(let t=0;t<c.length;t++){const i=c[t],s=i.connectRoads;if(s)for(let t=0;t<s.length;t++){const n=s[t];if(null!=n.pre){let t=null;const s=n.type;"line"===s?t=l[n.pre]:"line-interact"===s&&(t=c[n.pre]),this.addRoad(new R(i,t)),this.addRoad(new R(t,i))}}}}comparePrePoint(t,i,s){const n=this.getPre(t);if(n){const{pre:e,lineIndex:r}=n;for(let n=0;n<s.length;n++){const h=s[n];h.inLines[r]&&h.inLines[r].pre===e&&(t.roads=[{pre:n,type:"line-interact"}],h.roads?h.roads.push({pre:i-1,type:"line"}):h.roads=[{pre:i-1,type:"line"}])}t.roads||(t.roads=[{pre:i-1,type:"line"}])}}getPre(t){for(const i in t.inLines)if(null!==t.inLines[i].pre)return{pre:t.inLines[i].pre,lineIndex:i};return null}clear(){return this.set({})}onTick(t){let i,s,n;if(t>1)throw Error("delta > 1");this.refreshCars();const e=this.intersections.all();for(s in e)n=e[s],n.controlSignals.onTick(t);const r=this.cars.all(),h=[];for(s in r)i=r[s],i.move(t),i.alive?h.push(void 0):h.push(this.removeCar(i));return h}refreshCars(){return this.cars.length<this.carsNumber&&this.addRandomCar(),this.cars.length>this.carsNumber?this.removeRandomCar():null}addRoad(t){return this.roads.put(t),t.source.roads.push(t),t.target.inRoads.push(t),t.update()}getRoad(t){return this.roads.get(t)}addCar(t){return this.cars.put(t)}getCar(t){return this.cars.get(t)}removeCar(t){return this.toRemove.push(t.id),this.cars.pop(t)}clearTmpRemove(){this.toRemove=[]}addIntersection(t){return this.intersections.put(t)}getIntersection(t){return this.intersections.get(t)}addRandomCar(){let t;const i=u(this.roads.all());return null!=i&&(t=u(i.lanes),null!=t)?this.addCar(new E(t)):null}removeRandomCar(){const t=u(this.cars.all());return null!=t?this.removeCar(t):null}}"undefined"!=typeof window&&window.maptalks&&(window.maptalks.TrafficScene=N),t.TrafficScene=N,Object.defineProperty(t,"t",{value:!0}),"undefined"!=typeof console&&console.log("@maptalks/traffic v0.87.2")}));
|
|
6
|
+
!function(t,i){"object"==typeof exports&&"undefined"!=typeof module?i(exports,require("maptalks"),require("@maptalks/gl-layers"),require("turf")):"function"==typeof define&&define.amd?define(["exports","maptalks","@maptalks/gl-layers","turf"],i):i((t="undefined"!=typeof globalThis?globalThis:t||self).maptalks=t.maptalks||{},t.maptalks,t.maptalks,t.turf)}(this,(function(t,i,s,n){"use strict";function e(t){if(t&&t.t)return t;var i=Object.create(null);return t&&Object.keys(t).forEach((function(s){if("default"!==s){var n=Object.getOwnPropertyDescriptor(t,s);Object.defineProperty(i,s,n.get?n:{enumerable:!0,get:function(){return t[s]}})}})),i.default=t,Object.freeze(i)}var r=e(i),h=e(n);let o=0;function u(t,i,s){return null==i||s?(t.length!==+t.length&&(t=function(t){const i=function(t){if(!function(t){return t===Object(t)}(t))return[];const i=[];for(const s in t)g(t,s)&&i.push(s);return i}(t),s=i.length,n=new Array(s);for(let e=0;e<s;e++)n[e]=t[i[e]];return n}(t)),t[a(t.length-1)]):function(t){let i,s=0;const n=[];return d(t,t=>{i=i(s++),n[s-1]=n[i],n[i]=t}),n}(t).slice(0,Math.max(0,i))}function l(t){const i=++o+"";return t?t+i:i}function c(t,i){let s;if(nativeBind&&t.bind===nativeBind)return nativeBind.apply(t,slice.call(arguments,1));const n=slice.call(arguments,2);return s=function(){if(!(this instanceof s))return t.apply(i,n.concat(slice.call(arguments)));ctor.prototype=t.prototype;const e=new ctor;ctor.prototype=null;const r=t.apply(e,n.concat(slice.call(arguments)));return Object(r)===r?r:e}}function a(t,i){return i||(i=t,t=0),t+Math.floor(Math.random()*(i-t+1))}function f(t){return d(slice.call(arguments,1),(function(i){if(i)for(const s in i)t[s]=i[s]})),t}function d(t,i,s){if(null==t)return t;if(nativeForEach&&t.forEach===nativeForEach)t.forEach(i,s);else if(t.length===+t.length){for(let n=0,e=t.length;n<e;n++)if(i.call(s,t[n],n,t)===breaker)return null}else{const n=n(t);for(let e=0,r=n.length;e<r;e++)if(i.call(s,t[n[e]],n[e],t)===breaker)return null}return t}function g(t,i){return hasOwnProperty.call(t,i)}class w{constructor(t,i){let s,n,e;if(this.factory=t,this.objects={},null!=i&&null!=i.objects)for(s in e=i.objects,e)n=e[s],this.objects[s]=this.factory.copy(n)}get length(){return Object.keys(this.objects).length}toJSON(){return this.objects}get(t){return this.objects[t]}put(t){return this.objects[t.id]=t}pop(t){let i;const s=null!=(i=t.id)?i:t,n=this.objects[s];return"function"==typeof n.release&&n.release(),delete this.objects[s],n}all(){return this.objects}clear(){return this.objects={}}}class p{constructor(t,i){this.x=t||0,this.y=i||0}get length(){return Math.sqrt(this.x*this.x+this.y*this.y)}get direction(){return Math.atan2(this.y,this.x)}get normalized(){return new p(this.x/this.length,this.y/this.length)}add(t){return new p(this.x+t.x,this.y+t.y)}subtract(t){return new p(this.x-t.x,this.y-t.y)}mult(t){return new p(this.x*t,this.y*t)}divide(t){return new p(this.x/t,this.y/t)}}class m{constructor(t,i){this.source=t,this.target=i}get vector(){return this.target.subtract(this.source)}get length(){return this.vector.length}get direction(){return this.vector.direction}get center(){return this.getPoint(.5)}split(t,i){let s,n,e,r,h,o;const u=i?function(){h=[];for(let i=r=t-1;r<=0?i<=0:i>=0;r<=0?i++:i--)h.push(i);return h}.apply(this):function(){o=[];for(let i=0,s=t-1;0<=s?i<=s:i>=s;0<=s?i++:i--)o.push(i);return o}.apply(this),l=[];for(n=0,e=u.length;n<e;n++)s=u[n],l.push(this.subsegment(s/t,(s+1)/t));return l}getPoint(t){return this.source.add(this.vector.mult(t))}subsegment(t,i){const s=this.vector,n=this.source.add(s.mult(t)),e=this.source.add(s.mult(i));return new m(n,e)}}class v{constructor(t,i,s,n){this.x=t||0,this.y=i||0,this.width=s||0,this.height=n||0}copy(t){return new v(t.x,t.y,t.width,t.height)}toJSON(){return f({},this)}area(){return this.width*this.height}left(t){return null!=t&&(this.x=t),this.x}right(t){return null!=t&&(this.x=t-this.width),this.x+this.width}top(t){return null!=t&&(this.y=t),this.y}bottom(t){return null!=t&&(this.y=t-this.height),this.y+this.height}center(t){return null!=t&&(this.x=t.x-this.width/2,this.y=t.y-this.height/2),new p(this.x+this.width/2,this.y+this.heigh/2)}containsPoint(t){let i,s;return this.left()<=(i=t.x)&&i<=this.right()&&this.top()<=(s=t.y)&&s<=this.bottom()}containsRect(t){return this.left()<=t.left()&&t.right()<=this.right()&&this.top()<=t.top()&&t.bottom()<=this.bottom()}getVertices(){return[new p(this.left(),this.top()),new p(this.right(),this.top()),new p(this.right(),this.bottom()),new p(this.left(),this.bottom())]}getSide(t){const i=this.getVertices();return new m(i[t],i[(t+1)%4])}getSectorId(t){const i=t.subtract(this.center());if(i.y<=0&&Math.abs(i.x)<=Math.abs(i.y))return 0;if(i.x>=0&&Math.abs(i.x)>=Math.abs(i.y))return 1;if(i.y>=0&&Math.abs(i.x)<=Math.abs(i.y))return 2;if(i.x<=0&&Math.abs(i.x)>=Math.abs(i.y))return 3;throw new Error("algorithm error")}getSector(t){return this.getSide(this.getSectorId(t))}}class M{constructor(t){this.intersection=t,this.time=0,this.flipMultiplier=.4*Math.random()-.2+1,this.stateNum=0,this.lightsFlipInterval=20,this.states=[["L","","L",""],["FR","","FR",""],["","L","","L"],["","FR","","FR"]]}get flipInterval(){return this.flipMultiplier*this.lightsFlipInterval}get state(){let t=this.states[this.stateNum%this.states.length];this.intersection.roads.length<=2&&(t=["LFR","LFR","LFR","LFR"]);const i=[];for(let s=0,n=t.length;s<n;s++){const n=t[s];i.push(this.decode(n))}return i}decode(t){const i=[0,0,0],s=[].indexOf||function(t){for(let i=0,s=this.length;i<s;i++)if(i in this&&this[i]===t)return i;return-1};return s.call(t,"L")>=0&&(i[0]=1),s.call(t,"F")>=0&&(i[1]=1),s.call(t,"R")>=0&&(i[2]=1),i}flip(){return this.stateNum+=1}onTick(t){return this.time+=t,this.time>this.flipInterval?(this.flip(),this.time-=this.flipInterval):null}}class b{constructor(t){this.rect=t,this.id=l("intersection"),this.roads=[],this.inRoads=[],this.controlSignals=new M(this)}copy(t){t.rect=v.copy(t.rect);const i=Object.create(b.prototype);return f(i,t),i.roads=[],i.inRoads=[],i.controlSignals=new M(i),i}toJSON(){return{id:this.id,rect:this.rect}}update(){let t,i,s,n,e;const r=this.roads;for(i=0,n=r.length;i<n;i++)t=r[i],t.update();const h=this.inRoads,o=[];for(s=0,e=h.length;s<e;s++)t=h[s],o.push(t.update());return o}}class y{constructor(t,i,s){this.car=t,this.position=s,this.id=l("laneposition"),this.free=!0,this.tmpLane=i}get lane(){return this.tmpLane}set lane(t){this.release(),this.tmpLane=t}get relativePosition(){return this.position/this.lane.length}get nextCarDistance(){let t,i;const s=this.getNext();return s?(i=s.position-s.car.length/2,t=this.position+this.car.length/2,{car:s.car,distance:i-t}):{car:null,distance:1/0}}acquire(){let t;return null!=(null!=(t=this.lane)?t.addCarPosition:void 0)?(this.free=!1,this.lane.addCarPosition(this)):null}release(){let t;return!this.free&&(null!=(t=this.lane)?t.removeCar:void 0)?(this.free=!0,this.lane.removeCar(this)):null}getNext(){return this.lane&&!this.free?this.lane.getNext(this):null}}class L{constructor(t,i,s,n){this.A=t,this.B=i,this.O=s,this.Q=n,this.AB=new m(this.A,this.B),this.AO=new m(this.A,this.O),this.OQ=new m(this.O,this.Q),this.QB=new m(this.Q,this.B),this.len=null}get length(){let t,i,s,n,e;if(null==this.len)for(s=10,n=null,this.len=0,t=e=0;e<=10;t=++e)i=this.getPoint(t/10),n&&(this.len+=i.subtract(n).length),n=i;return this.len}getPoint(t){const i=this.AO.getPoint(t),s=this.OQ.getPoint(t),n=this.QB.getPoint(t),e=new m(i,s).getPoint(t),r=new m(s,n).getPoint(t);return new m(e,r).getPoint(t)}getDirection(t){const i=this.AO.getPoint(t),s=this.OQ.getPoint(t),n=this.QB.getPoint(t),e=new m(i,s).getPoint(t),r=new m(s,n).getPoint(t);return new m(e,r).direction}}class x{constructor(t,i,s){this.car=t,this.current=new y(this.car,i,s||0),this.current.acquire(),this.next=new y(this.car),this.temp=new y(this.car),this.isChangingLanes=!1}get lane(){return this.temp.lane||this.current.lane}get absolutePosition(){return null!=this.temp.lane?this.temp.position:this.current.position}get relativePosition(){return this.absolutePosition/this.lane.length}get direction(){return this.lane.getDirection(this.relativePosition)}get coords(){return this.lane.getPoint(this.relativePosition)}get nextCarDistance(){const t=this.current.nextCarDistance,i=this.next.nextCarDistance;return t.distance<i.distance?t:i}get distanceToStopLine(){return this.canEnterIntersection()?1/0:this.getDistanceToIntersection()}get nextIntersection(){return this.current.lane.road.target}get previousIntersection(){return this.current.lane.road.source}isValidTurn(){const t=this.car.nextLane,i=this.current.lane,s=i.getTurnDirection(t);if(3===s)throw Error("no U-turns are allowed");if(0===s&&!i.isLeftmost)throw Error("no left turns from this lane");if(2===s&&!i.isRightmost)throw Error("no right turns from this lane");return!0}canEnterIntersection(){const t=this.car.nextLane,i=this.current.lane;if(!t)return!0;const s=this.nextIntersection,n=i.getTurnDirection(t),e=i.road.targetSideId;return s.controlSignals.state[e][n]}getDistanceToIntersection(){const t=this.current.lane.length-this.car.length/2-this.current.position;return this.isChangingLanes?1/0:Math.max(t,0)}timeToMakeTurn(t){return null==t&&(t=0),this.getDistanceToIntersection()<=t}moveForward(t){let i,s;t=Math.max(t,0),this.current.position+=t,this.next.position+=t,this.temp.position+=t,this.timeToMakeTurn()&&this.canEnterIntersection()&&this.isValidTurn()&&this.i(this.car.popNextLane(),0);const n=this.temp.position/(null!=(i=this.temp.lane)?i.length:void 0),e=2*this.car.length;return this.isChangingLanes&&this.temp.position>e&&!this.current.free&&this.current.release(),this.isChangingLanes&&this.next.free&&this.temp.position+e>(null!=(s=this.temp.lane)?s.length:void 0)&&this.next.acquire(),this.isChangingLanes&&n>=1&&this.s(),!this.current.lane||this.isChangingLanes||this.car.nextLane?null:this.car.pickNextLane()}changeLane(t){if(this.isChangingLanes)throw Error("already changing lane");if(null==t)throw Error("no next lane");if(t===this.lane)throw Error("next lane == current lane");if(this.lane.road!==t.road)throw Error("not neighbouring lanes");const i=this.current.position+3*this.car.length;return this.i(t,i)}h(){const t=this.current.lane.getPoint(this.current.relativePosition),i=this.next.lane.getPoint(this.next.relativePosition),s=i.subtract(t).length,n=this.current.lane.middleLine.vector.normalized.mult(.3*s),e=t.add(n),r=this.next.lane.middleLine.vector.normalized.mult(.3*s),h=i.subtract(r);return new L(t,i,e,h)}o(){return this.h()}i(t,i){if(this.isChangingLanes)throw Error("already changing lane");if(null==t)return 0;this.isChangingLanes=!0,this.next.lane=t,this.next.position=i;const s=this.o();return this.temp.lane=s,this.temp.position=0,this.next.position-=this.temp.lane.length}s(){if(!this.isChangingLanes)throw Error("no lane changing is going on");return this.isChangingLanes=!1,this.current.lane=this.next.lane,this.current.position=this.next.position||0,this.current.acquire(),this.next.lane=null,this.next.position=NaN,this.temp.lane=null,this.temp.position=NaN,this.current.lane}release(){let t,i,s;return null!=(t=this.current)&&t.release(),null!=(i=this.next)&&i.release(),null!=(s=this.temp)?s.release():void 0}}const C=[];class E{constructor(t,i){this.type=a(C.length-1),this.id=l("car"),this.color=(300+240*Math.random()|0)%360,this.tmpSpeed=0,this.width=2,this.length=2,this.maxSpeed=30,this.s0=2,this.timeHeadway=1.5,this.maxAcceleration=1,this.maxDeceleration=3,this.trajectory=new x(this,t,i),this.alive=!0,this.preferedLane=null}get coords(){return this.trajectory.coords}get speed(){return this.tmpSpeed}set speed(t){t<0&&(t=0),t>this.maxSpeed&&(t=this.maxSpeed),this.tmpSpeed=t}get direction(){return this.trajectory.direction}release(){return this.trajectory.release()}getAcceleration(){let t;const i=this.trajectory.nextCarDistance,s=Math.max(i.distance,0),n=this.maxAcceleration,e=this.maxDeceleration,r=this.speed-(null!=(t=i.car)?t.speed:void 0)||0,h=Math.pow(this.speed/this.maxSpeed,4),o=this.s0,u=this.speed*this.timeHeadway,l=o+u+this.speed*r/(2*Math.sqrt(n*e)),c=Math.pow(l/s,2),a=1+u+Math.pow(this.speed,2)/(2*e),f=1-h-c-Math.pow(a/this.trajectory.distanceToStopLine,2);return this.maxAcceleration*f}move(t){const i=this.getAcceleration();if(this.speed+=i*t,!this.trajectory.isChangingLanes&&this.nextLane){const t=this.trajectory.current.lane,i=t.getTurnDirection(this.nextLane),s=function(){switch(i){case 0:return t.leftmostAdjacent;case 2:return t.rightmostAdjacent;default:return t}}();s!==t&&this.trajectory.changeLane(s)}const s=this.speed*t+.5*i*Math.pow(t,2);return this.trajectory.nextCarDistance.distance<s&&console.log("bad IDM"),this.trajectory.timeToMakeTurn(s)&&null==this.nextLane?(this.alive=!1,this.alive):this.trajectory.moveForward(s)}pickNextRoad(){const t=this.trajectory.nextIntersection,i=this.trajectory.current.lane,s=t.roads.filter((function(t){return t.target!==i.road.source}));if(0===s.length)return null;return u(s)}pickNextLane(){if(this.nextLane)throw Error("next lane is already chosen");this.nextLane=null;const t=this.pickNextRoad();if(!t)return null;const i=this.trajectory.current.lane.road.getTurnDirection(t),s=function(){switch(i){case 0:return t.lanesNumber-1;case 1:return a(0,t.lanesNumber-1);case 2:return 0}return null}();return this.nextLane=t.lanes[s],this.nextLane}popNextLane(){const t=this.nextLane;return this.nextLane=null,this.preferedLane=null,t}}class O{constructor(t,i,s){this.sourceSegment=t,this.targetSegment=i,this.road=s,this.leftAdjacent=null,this.rightAdjacent=null,this.leftmostAdjacent=null,this.rightmostAdjacent=null,this.carsPositions={},this.update()}get sourceSideId(){return this.road.sourceSideId}get targetSideId(){return this.road.targetSideId}get isRightmost(){return this===this.rightmostAdjacent}get isLeftmost(){return this===this.leftmostAdjacent}get leftBorder(){return new m(this.sourceSegment.source,this.targetSegment.target)}get rightBorder(){return new m(this.sourceSegment.target,this.targetSegment.source)}toJSON(){const t=f({},this);return delete t.carsPositions,t}update(){return this.middleLine=new m(this.sourceSegment.center,this.targetSegment.center),this.length=this.middleLine.length,this.direction=this.middleLine.direction}getTurnDirection(t){return t?this.road.getTurnDirection(t.road):1}getDirection(){return this.direction}getPoint(t){return this.middleLine.getPoint(t)}addCarPosition(t){if(t.id in this.carsPositions)throw Error("car is already here");return this.carsPositions[t.id]=t}removeCar(t){if(!(t.id in this.carsPositions))throw Error("removing unknown car");return delete this.carsPositions[t.id]}getNext(t){if(t.lane!==this)throw Error("car is on other lane");let i=null,s=1/0;const n=this.carsPositions;for(const e in n){const r=n[e],h=r.position-t.position;!r.free&&0<h&&h<s&&(s=h,i=r)}return i}}class R{constructor(t,i,s){this.source=t,this.target=i,this.id=l("road"),this.lanes=[],this.gridSize=s||32,this.lanesNumber=null,this.update()}get length(){return this.targetSide.target.subtract(this.sourceSide.source).length}get leftmostLane(){return this.lanes[this.lanesNumber-1]}get rightmostLane(){return this.lanes[0]}copy(t){const i=Object.create(R.prototype);return f.extend(i,t),null==i.lanes&&(i.lanes=[]),i}toJSON(){return{id:this.id,source:this.source.id,target:this.target.id}}getTurnDirection(t){if(this.target!==t.source)throw Error("invalid roads");const i=this.targetSideId;return(t.sourceSideId-i-1+8)%4}update(){let t,i,s,n,e,r;if(!this.source||!this.target)throw Error("incomplete road");this.sourceSideId=this.source.rect.getSectorId(this.target.rect.center()),this.sourceSide=this.source.rect.getSide(this.sourceSideId).subsegment(.5,1),this.targetSideId=this.target.rect.getSectorId(this.source.rect.center()),this.targetSide=this.target.rect.getSide(this.targetSideId).subsegment(0,.5),this.lanesNumber=0|Math.min(this.sourceSide.length,this.targetSide.length),this.lanesNumber=Math.max(2,this.lanesNumber/this.gridSize|0);const h=this.sourceSide.split(this.lanesNumber,!0),o=this.targetSide.split(this.lanesNumber);if(null==this.lanes||this.lanes.length<this.lanesNumber)for(null==this.lanes&&(this.lanes=[]),t=s=0,e=this.lanesNumber-1;0<=e?s<=e:s>=e;t=0<=e?++s:--s)null==(i=this.lanes)[t]&&(i[t]=new O(h[t],o[t],this));const u=[];for(t=n=0,r=this.lanesNumber-1;0<=r?n<=r:n>=r;t=0<=r?++n:--n)this.lanes[t].sourceSegment=h[t],this.lanes[t].targetSegment=o[t],this.lanes[t].leftAdjacent=this.lanes[t+1],this.lanes[t].rightAdjacent=this.lanes[t-1],this.lanes[t].leftmostAdjacent=this.lanes[this.lanesNumber-1],this.lanes[t].rightmostAdjacent=this.lanes[0],u.push(this.lanes[t].update());return u}}class N{constructor(t){this.toRemove=[],this.options=t||{},this.carsNumber=this.options.carsNumber||10,this.gridSize=this.options.gridSize||32,this.u=0,this.l=0,this.g=5,this.carsList={},this.p=new s.GLTFLayer("traffic"),this.m="stop",this.v=[],this.M={},this.set()}run(){this.m="running",this.L()}stop(){this.m="stop"}remove(){this.C&&cancelAnimationFrame(this.C),this.p.remove(),delete this.map}setSymbols(t){this.v=t;for(let t=0;t<this.v.length;t++){const i=this.v[t];this.M[i.url]=new s.MultiGLTFMarker([],{symbol:i}).addTo(this.p)}}L(){if("running"!==this.m)return;const t=Date.now();this.l=t;const i=Date.now();let s,n=i-this.u||0;n>100&&(n=100),this.u=i,this.onTick(this.g*n/1e3);let e=this.toRemove.length;for(;e--;)this.R(this.toRemove[e]);this.clearTmpRemove();const r=this.cars.all();for(s in r)this.N(r[s],s);this.C=window.requestAnimationFrame(this.L.bind(this))}I(){for(const t in this.M)this.M[t].removeData();for(const t in this.carsList){const i=this.carsList[t],s=i.url;this.M[s].addData(i)}}N(t){const i=t.id.substring(3);if(this.carsList[i]){if(!t)return;const s=t.coords,n=t.direction,e=this.map,h=e.pointAtResToCoordinate(new r.Point(s.x/this.gridSize,s.y/this.gridSize),e.getGLRes()),o=n/Math.PI*180+90;this.carsList[i].coordinates=h,this.carsList[i].rotation=[0,0,o];const u=this.S(i),l=this.carsList[i].url;u>-1?this.M[l].updateData(u,this.carsList[i]):this.M[l].addData(this.carsList[i])}else{const t=this.v[Math.floor(Math.random()*this.v.length)];this.carsList[i]={coordinates:null,direction:null,url:t.url},this.showHideCar(this.carsList[i],"show")}}showHideCar(t,i,s){const n=this;r.animation.Animation.animate({"symbol":{transparent:1}},{duration:1e3,easing:"out"},(function(e){if("running"===e.state.playState){let r=0;"show"===i?(r=e.styles.symbol.transparent,t.color=[1,1,1,r]):"hide"===i&&(r=1-e.styles.symbol.transparent,t.color=[1,1,1,r],r<.01&&setTimeout((function(){const t=n.S(s);if(!n.carsList[s])return;const i=n.carsList[s].url;t>-1&&n.M[i].removeData(t),delete n.carsList[s]}),100))}})).play()}S(t){const i=this.carsList[t];if(!i)return-1;const s=i.url;return this.M[s].getAllData().indexOf(this.carsList[t])}R(t){const i=t.substring(3);null!=this.carsList[i]&&this.showHideCar(this.carsList[i],"hide",i)}get instantSpeed(){const t=function(t,i,s){const n=[];return null==t?n:nativeMap&&t.map===nativeMap?t.map(i,s):(d(t,(t,e,r)=>{n.push(i.call(s,t,e,r))}),n)}(this.cars.all(),t=>t.speed);return 0===t.length?0:function(t,i,s,n){let e=arguments.length>2;return null==t&&(t=[]),nativeReduce&&t.reduce===nativeReduce?(n&&(i=c(i,n)),e?t.reduce(i,s):t.reduce(i)):(d(t,(t,r,h)=>{e?s=i.call(n,s,t,r,h):(s=t,e=!0)}),s)}(t,(function(t,i){return t+i}))/t.length}get map(){const t=this.T;return t?t.getMap():null}addTo(t){this.T=t,this.p.addTo(t)}set(t){return null==t&&(t={}),this.intersections=new w(b,t.intersections),this.roads=new w(R,t.roads),this.cars=new w(E,t.cars),this.carsNumber=0}save(){const t=f({},this);return delete t.cars,window.localStorage.world=JSON.stringify(t)}setCarNumber(t){this.carsNumber=t}getCarNumber(){return this.carsNumber}load(){let t,i,s,n;if(t=window.localStorage.world,t=t&&JSON.parse(t),null==t)return null;this.clear(),this.carsNumber=t.carsNumber||0;const e=t.intersections;for(i in e)s=e[i],this.addIntersection(b.copy(s));const r=t.roads,h=[];for(i in r)n=r[i],n=(new R).copy(n),n.source=this.getIntersection(n.source),n.target=this.getIntersection(n.target),h.push(this.addRoad(n));return h}intersectSegment(t,i){for(let s=0;s<i.length-1;s++){const n=[i[s],i[s+1]],e=h.lineString(n),r=h.lineIntersect(t,e);if(r.features.length)return{intersectIndex:s,coord:r.features[0].geometry.coordinates}}return null}intersection(t,i,s,n,e,r){const o=h.lineString(t);for(let t=i+1;t<n.length;t++){const h=n[t],u=this.intersectSegment(o,h);if(!u)continue;const l={};l[i]={pre:s},l[t]={pre:u.intersectIndex+r[t]};const c={inLines:l,coordinate:this.map.coordinateToPointAtRes({x:u.coord[0],y:u.coord[1]},this.map.getGLRes())};e.push(c)}}generateTraffic(t){if(!this.map)return;const i={};let s=0;for(let n=0;n<t.length;n++)i[n]=s,s+=t[n].length;const n=[];let e=0;for(let s=0;s<t.length;s++){const r=t[s];for(let h=0;h<r.length-1;h++){const o=[r[h],r[h+1]];this.intersection(o,s,e+h,t,n,i)}e+=r.length}const r=[];let h=0;const o=this.map;for(let i=0;i<t.length;i++){const s=t[i];for(let t=0;t<s.length;t++){const n=o.coordinateToPointAtRes({x:s[t][0],y:s[t][1]},o.getGLRes()),e={};0===t?e[i]={pre:null}:(s.length,e[i]={pre:t-1+h});const u={inLines:e,coordinate:n};r.push(u)}h+=s.length}for(let t=0;t<r.length;t++){const i=r[t];this.comparePrePoint(i,t,n)}const u=this.gridSize,l=[];for(let t=0;t<r.length;t++){const i=r[t],s=i.coordinate.x,n=i.coordinate.y,e=new v(s*u-.5,n*u-.5,1,1),h=new b(e);h.connectRoads=i.roads,l.push(h),this.addIntersection(h)}const c=[];for(let t=0;t<n.length;t++){const i=n[t],s=i.coordinate.x,e=i.coordinate.y,r=new v(s*u-.5,e*u-.5,1,1),h=new b(r);h.connectRoads=i.roads,c.push(h),this.addIntersection(h)}for(let t=0;t<l.length;t++){const i=l[t],s=i.connectRoads;if(s)for(let t=0;t<s.length;t++){const n=s[t];if(null!=n.pre){let t=null;const s=n.type;"line"===s?t=l[n.pre]:"line-interact"===s&&(t=c[n.pre]),this.addRoad(new R(i,t)),this.addRoad(new R(t,i))}}}for(let t=0;t<c.length;t++){const i=c[t],s=i.connectRoads;if(s)for(let t=0;t<s.length;t++){const n=s[t];if(null!=n.pre){let t=null;const s=n.type;"line"===s?t=l[n.pre]:"line-interact"===s&&(t=c[n.pre]),this.addRoad(new R(i,t)),this.addRoad(new R(t,i))}}}}comparePrePoint(t,i,s){const n=this.getPre(t);if(n){const{pre:e,lineIndex:r}=n;for(let n=0;n<s.length;n++){const h=s[n];h.inLines[r]&&h.inLines[r].pre===e&&(t.roads=[{pre:n,type:"line-interact"}],h.roads?h.roads.push({pre:i-1,type:"line"}):h.roads=[{pre:i-1,type:"line"}])}t.roads||(t.roads=[{pre:i-1,type:"line"}])}}getPre(t){for(const i in t.inLines)if(null!==t.inLines[i].pre)return{pre:t.inLines[i].pre,lineIndex:i};return null}clear(){return this.set({})}onTick(t){let i,s,n;if(t>1)throw Error("delta > 1");this.refreshCars();const e=this.intersections.all();for(s in e)n=e[s],n.controlSignals.onTick(t);const r=this.cars.all(),h=[];for(s in r)i=r[s],i.move(t),i.alive?h.push(void 0):h.push(this.removeCar(i));return h}refreshCars(){return this.cars.length<this.carsNumber&&this.addRandomCar(),this.cars.length>this.carsNumber?this.removeRandomCar():null}addRoad(t){return this.roads.put(t),t.source.roads.push(t),t.target.inRoads.push(t),t.update()}getRoad(t){return this.roads.get(t)}addCar(t){return this.cars.put(t)}getCar(t){return this.cars.get(t)}removeCar(t){return this.toRemove.push(t.id),this.cars.pop(t)}clearTmpRemove(){this.toRemove=[]}addIntersection(t){return this.intersections.put(t)}getIntersection(t){return this.intersections.get(t)}addRandomCar(){let t;const i=u(this.roads.all());return null!=i&&(t=u(i.lanes),null!=t)?this.addCar(new E(t)):null}removeRandomCar(){const t=u(this.cars.all());return null!=t?this.removeCar(t):null}}"undefined"!=typeof window&&window.maptalks&&(window.maptalks.TrafficScene=N),t.TrafficScene=N,Object.defineProperty(t,"t",{value:!0}),"undefined"!=typeof console&&console.log("@maptalks/traffic v0.88.0")}));
|
package/package.json
CHANGED
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@maptalks/traffic",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "a tool to render traffic effect",
|
|
5
|
-
"license": "UNLICENSED",
|
|
6
|
-
"repository": {
|
|
7
|
-
"type": "git",
|
|
8
|
-
"url": "https://github.com/liubgithub/traffic.git"
|
|
9
|
-
},
|
|
10
|
-
"main": "dist/maptalks.traffic.js",
|
|
11
|
-
"module": "dist/maptalks.traffic.es.js",
|
|
12
|
-
"unpkg": "dist/maptalks.traffic.js",
|
|
13
|
-
"jsdelivr": "dist/maptalks.traffic.js",
|
|
14
|
-
"files": [
|
|
15
|
-
"dist/maptalks.traffic.js",
|
|
16
|
-
"dist/maptalks.traffic.es.js"
|
|
17
|
-
],
|
|
18
|
-
"scripts": {
|
|
19
|
-
"dev": "rollup -w -c rollup.config.js",
|
|
20
|
-
"build": "rollup --environment BUILD:production -c rollup.config.js",
|
|
21
|
-
"build-dev": "rollup -c rollup.config.js",
|
|
22
|
-
"pretest": "npm run lint && npm run build",
|
|
23
|
-
"test": "karma start --single-run",
|
|
24
|
-
"tdd": "karma start --no-single-run",
|
|
25
|
-
"preversion": "npm run lint",
|
|
26
|
-
"version": "npm run build",
|
|
27
|
-
"lint": "eslint src/**/*.js",
|
|
28
|
-
"prepare": "npm run build"
|
|
29
|
-
},
|
|
30
|
-
"devDependencies": {
|
|
31
|
-
"@babel/eslint-parser": "^7.15.0",
|
|
32
|
-
"@babel/preset-env": "^7.15.0",
|
|
33
|
-
"@maptalks/gl-layers": "0.23.0",
|
|
34
|
-
"@rollup/plugin-commonjs": "^20.0.0",
|
|
35
|
-
"@rollup/plugin-json": "^4.1.0",
|
|
36
|
-
"@rollup/plugin-node-resolve": "^13.0.4",
|
|
37
|
-
"@rollup/plugin-replace": "4.0.0",
|
|
38
|
-
"eslint": "^7.32.0",
|
|
39
|
-
"eslint-plugin-mocha": "^9.0.0",
|
|
40
|
-
"expect.js": "^0.3.1",
|
|
41
|
-
"karma": "^6.4.1",
|
|
42
|
-
"karma-chrome-launcher": "^3.1.1",
|
|
43
|
-
"karma-expect": "^1.1.3",
|
|
44
|
-
"karma-mocha": "^2.0.1",
|
|
45
|
-
"karma-mocha-reporter": "^2.2.5",
|
|
46
|
-
"maptalks": "^1.0.0-rc.23",
|
|
47
|
-
"mocha": "^9.0.3",
|
|
48
|
-
"rollup": "^2.56.2",
|
|
49
|
-
"rollup-plugin-terser": "^5.3.1",
|
|
50
|
-
"turf": "3.0.14"
|
|
51
|
-
},
|
|
52
|
-
"gitHead": "
|
|
53
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@maptalks/traffic",
|
|
3
|
+
"version": "0.88.0",
|
|
4
|
+
"description": "a tool to render traffic effect",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/liubgithub/traffic.git"
|
|
9
|
+
},
|
|
10
|
+
"main": "dist/maptalks.traffic.js",
|
|
11
|
+
"module": "dist/maptalks.traffic.es.js",
|
|
12
|
+
"unpkg": "dist/maptalks.traffic.js",
|
|
13
|
+
"jsdelivr": "dist/maptalks.traffic.js",
|
|
14
|
+
"files": [
|
|
15
|
+
"dist/maptalks.traffic.js",
|
|
16
|
+
"dist/maptalks.traffic.es.js"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"dev": "rollup -w -c rollup.config.js",
|
|
20
|
+
"build": "rollup --environment BUILD:production -c rollup.config.js",
|
|
21
|
+
"build-dev": "rollup -c rollup.config.js",
|
|
22
|
+
"pretest": "npm run lint && npm run build",
|
|
23
|
+
"test": "karma start --single-run",
|
|
24
|
+
"tdd": "karma start --no-single-run",
|
|
25
|
+
"preversion": "npm run lint",
|
|
26
|
+
"version": "npm run build",
|
|
27
|
+
"lint": "eslint src/**/*.js",
|
|
28
|
+
"prepare": "npm run build"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@babel/eslint-parser": "^7.15.0",
|
|
32
|
+
"@babel/preset-env": "^7.15.0",
|
|
33
|
+
"@maptalks/gl-layers": "0.23.0",
|
|
34
|
+
"@rollup/plugin-commonjs": "^20.0.0",
|
|
35
|
+
"@rollup/plugin-json": "^4.1.0",
|
|
36
|
+
"@rollup/plugin-node-resolve": "^13.0.4",
|
|
37
|
+
"@rollup/plugin-replace": "4.0.0",
|
|
38
|
+
"eslint": "^7.32.0",
|
|
39
|
+
"eslint-plugin-mocha": "^9.0.0",
|
|
40
|
+
"expect.js": "^0.3.1",
|
|
41
|
+
"karma": "^6.4.1",
|
|
42
|
+
"karma-chrome-launcher": "^3.1.1",
|
|
43
|
+
"karma-expect": "^1.1.3",
|
|
44
|
+
"karma-mocha": "^2.0.1",
|
|
45
|
+
"karma-mocha-reporter": "^2.2.5",
|
|
46
|
+
"maptalks": "^1.0.0-rc.23",
|
|
47
|
+
"mocha": "^9.0.3",
|
|
48
|
+
"rollup": "^2.56.2",
|
|
49
|
+
"rollup-plugin-terser": "^5.3.1",
|
|
50
|
+
"turf": "3.0.14"
|
|
51
|
+
},
|
|
52
|
+
"gitHead": "6f5a25b63de64fd796dd5771651c10fee504253e"
|
|
53
|
+
}
|