logo
Разработка web–системы имитационного моделирования

Заключение

В ходе работы были рассмотрены возможности современных систем имитационного моделирования и актуальность внедрения веб-ориентированных интерфейсов для систем имитационного моделирования в современной жизни. Разработано веб-приложение, визуализирующее структуру имитационной модели и принцип ее работы в динамике. Разработка велась на языке PHP и JavaScript, с использованием библиотек Tween, Arbor, Graphics, jQuery и элемента HTML5 Canvas. В качестве примеров были визуализированы модели из таких областей применения, как: производство, системы массового обслуживания, социальная динамика, городской транспорт.

Список использованных источников

1 Имитационное моделирование. Теория и практика [Электронный ресурс]. URL: http://immod.gpss.ru/static/materialy_konferencii.html (дата обращения: 5.05.2014).

2 Инструмент многоподходного имитационного моделирования AnyLogic [Электронный ресурс]. URL:http:// http://www.anylogic.ru (дата обращения: 5.05.2014).

3 Cоветов, Б.Я. Моделирование систем. Практикум, 5-е издание / Б.Я. Советов, С.А. Яковлев. - Высшая школа, 2003. - 293 с.

4 Карпов, Ю. Г.Имитационное моделирование систем. Введение в моделирование с AnyLogic 5 / Ю.Г. Карпов. - СПб: БХВ-Петербург, 2006. - 400 с.

5 Замятина, О.М. Система имитационного моделирования Arena 7.0. Basic Process Panel / О.М. Замятина, Н.Г. Саночкина. - Томск: ТПУ, 2005. - 24 с.

6 Задорожный, В.Н. Мультиагентное моделирование микромира / В.Н. Задорожный, Е.Б. Юдин. - Омск: ОмГТУ, 2009. - 179 с.

7 Ганеева, М.И. Построение агентных моделей в системе моделирования SIMBIGRAPH / М.И. Ганеева, Д.А. Огнев, Е.А. Пендер. - Омск: ОмГТУ, 2011. - 105 с.

8 Forio [Электронный ресурс]. URL: http://www.forio.com (дата обращения: 11.05.2014).

9 JSON - Википедия [Электронный ресурс]. URL: http://ru.wikipedia.org/wiki/JSON (дата обращения: 11.05.2014).

10 Русская документация по jQuery [Электронный ресурс]. URL: http://jquery-docs.ru (дата обращения: 11.05.2014).

11 Arbor.js [Электронный ресурс]. URL: http://arborjs.org (дата обращения: 11.05.2014).

12 Oсновы HTML5: Часть 4. Завершающий штрих - Canvas [Электронный ресурс]. URL: http://www.ibm.com/developerworks/ru/library/wa-html5fundamentals4 (дата обращения: 11.05.2014).

13 Tween J.S. [Электронный ресурс]. URL: http://www.createjs.com/#!/TweenJS (дата обращения: 11.05.2014).

14 Что такое requestAnimationFrame()? [Электронный ресурс]. URL: http://html5.by/blog/what-is-requestanimationframe (дата обращения: 11.05.2014).

15 Имитационное моделирование систем массового обслуживания на языке GPSS [Электронный ресурс]. URL: http://gpss.h11.ru/norenkov.php#c11 (дата обращения: 11.05.2014).

16 Сочнев А.Н. Имитационное моделирование движения маршрутных автобусов // Современные научные исследования и инновации. - Май 2012. - № 5 [Электронный ресурс]. URL: http://web.snauka.ru/issues/2012/05/12603 (дата обращения: 11.05.2014).

17 Pedestrian dynamics [Электронный ресурс]. URL: http://www.runthemodel.com/models/pedestrian_dynamics (дата обращения: 11.05.2014).

Приложение А

{

nodes:{

1:{color:yellow,shape:dot,label:source1},

2:{color:yellow,shape:dot,label:source2},

3:{color:orange,shape:dot,label:queue1},

4:{color:orange,shape:dot,label:queue2},

5:{color:brown,shape:dot,label:kas1},

6:{color:brown,shape:dot,label:kas2},

7:{color:grey,shape:dot,label:sink}

},

edges:{

1:{ 3:{directed:1}},

2:{4:{directed:1}},

3:{5:{directed:1}},

4:{6:{directed:1}},

6:{7:{directed:1}},

5:{7:{directed:1}}

}

Приложение Б

{stream:{

1:{color:green,speed:3000},

3:{color:green,speed:3000, delay:0},

5:{color:green,speed:3000, delay:5000},

7:{}

},

stream:{

2:{color:yelow, speed:3000},

4:{color:yelow, speed:3000, delay:0},

6:{color:yelow, speed:3000, delay:4500},

7:{}

},

stream:{

1:{color:blue,speed:3000},

3:{color:blue,speed:3000, delay:2000},

5:{color:blue,speed:3000, delay:5000},

7:{}

},

stream:{

2:{color:#99ff66, speed:3000},

4:{color:#99ff66, speed:3000, delay:1000},

6:{color:#99ff66, speed:3000, delay:4000},

7:{}

},

stream:{

1:{color:brown,speed:3000},

3:{color:brown,speed:3000, delay:5000},

5:{color:brown,speed:3000, delay:5000},

7:{}

},

stream:{

2:{color:#66ccff, speed:3000},

4:{color:#66ccff, speed:3000, delay:2000},

6:{color:#66ccff, speed:3000, delay:5000},

7:{}

},

stream:{

1:{color:red,speed:3000},

3:{color:red,speed:3000, delay:7000},

5:{color:red,speed:3000, delay:5000},

7:{}

},

stream:{

2:{color:orange, speed:3000},

4:{color:orange, speed:3000, delay:4000},

6:{color:orange, speed:3000, delay:4000},

7:{}

}

Приложение В

init.json

{

nodes:{

1:{color:yellow,shape:dot,label:source1},

2:{color:yellow,shape:dot,label:source2},

3:{color:grey,shape:rect,label:A1},

4:{color:grey,shape:rect,label:A2},

5:{color:grey,shape:rect,label:A3}

},

edges:{

1:{ 3:{directed:1}},

2:{3:{directed:1}},

3:{4:{directed:1}},

4:{5:{}},

3:{5:{}}

}

redraw.json

{period: {speed:3000}

stream:{

1:{color:green,speed:1000},

3:{color:blue,speed:1000, delay:22000},

4:{color:brown,speed:1000, delay:11000},

5:{color:yellow,speed:1000, delay:8000},

3:{color:orange,speed:1000, delay:13000},

5:{color:black,speed:1000, delay:15000}

4:{}

},

stream:{

2:{color:green,speed:1000},

3:{color:#33ffcc,speed:1000, delay:22000},

4:{color:#9933ff,speed:1000, delay:11000},

5:{color:#66ff66,speed:1000, delay:8000},

3:{color:red,speed:1000, delay:13000},

5:{color:#990000,speed:1000, delay:15000}

4:{}

}

Приложение Г

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

<title>Network diagram</title>

<style>

#canv {

width:100%;

height:100%;

}

#but1{

background: #3399ff;

padding: 7px 30px;

font-size:13px;

font-weight: bold;

color:#fff;

text-align: center;

border:solid 1px #73c8f0;

border-radius: 5px;}

</style>

</head>

<body onload="Start()">

<script src="js/jquery.min.js"></script>

<script src="js/arbor.js"></script>

<script src="js/graphics.js" ></script>

<script src="js/tween.min.js"></script>

<script src="js/RequestAnimationFrame.js"></script>

<script>

var ma = <?

//удалим содержимое директории upload/

$handle = opendir (upload/);

while(false !== ($file = readdir ($handle)))

if($file != "." && $file != "..") unlink (upload/.$file);

closedir ($handle);

$fileElementName = $_FILES[myfile];

$i = 0;

$j = 0;

$files_count = sizeof($fileElementName["name"]);

$mas = array();

for ($i = 0; $i < $files_count; $i++) {

$b= $fileElementName["tmp_name"][$i];

if (substr($fileElementName["type"][$i],0,5) == "image"){

$mas[$j] = $fileElementName["name"][$i];

$j++;

}

move_uploaded_file($fileElementName[tmp_name][$i], "upload/". $fileElementName[name][$i]);

}

echo json_encode($mas);

?>;

var a = <?$p=file_get_contents("upload/init.json"); echo $p; ?>;

var b = <?$p=file_get_contents("upload/redraw.json"); echo json_encode($p); ?>;

var mas = new Array();

var i = 0;

$.each(ma,function(name, value){ mas[i]= String(value);i++;});

var ar = new Array();

for (var q=0;q<mas.length;q++){

ar[q] = new Image();

ar[q].src=upload/+mas[q];

}

var nodeBoxes = {};

function findArrVal(arr,value) {

for (var ind=0;ind<arr.length;ind++){

if (arr[ind].substr(0,arr[ind].length-4) == value) {return ind;}

}

function Renderer(canvas)

{

var canvas = $(canvas).get(0);

var ctx = canvas.getContext("2d");

var gfx = arbor.Graphics(canvas);

var particleSystem = null;

var that = {

init:function(system){

//начальная инициализация

particleSystem = system;

particleSystem.screenSize(canvas.width, canvas.height);

particleSystem.screenPadding(80);

that.initMouseHandling();

},

redraw:function(){

//действия при перересовке

gfx.clear();

particleSystem.eachNode(//теперь каждую вершину

function(node, pt){//получаем вершину и точку где она

var label = node.data.label||""

var w = ctx.measureText(""+label).width + 10

if (!(""+label).match(/^[ ]*$/)){

pt.x = Math.floor(pt.x)

pt.y = Math.floor(pt.y)

}else{

label = null

}

if (node.data.color==none) {ctx.fillStyle = #333333} else {ctx.fillStyle=node.data.color}

if (node.data.shape==image){

ctx.drawImage(ar[findArrVal(mas,node.data.label)],pt.x, pt.y,50,50);

if (label){

ctx.font = "12px Helvetica"

ctx.textAlign = "center"

ctx.fillStyle = "black"

ctx.fillText(label||"", pt.x+11, pt.y-5)

nodeBoxes[node.name] = [pt.x, pt.y, w,w]

}

else if (node.data.shape==dot){

if (node.data.color==none) {ctx.fillStyle = #333333} else {ctx.fillStyle=node.data.color}

gfx.oval(pt.x-10, pt.y-10, 20,20, {fill:ctx.fillStyle})

nodeBoxes[node.name] = [pt.x-10, pt.y-10, w,w]

ctx.fillStyle = "black"

if (label) {ctx.fillText(label||"", pt.x, pt.y-12);}

}else{

if (node.data.color==none) {ctx.fillStyle = #333333} else {ctx.fillStyle=node.data.color}

gfx.rect(pt.x-w/2, pt.y-10, w,20, 4, {fill:ctx.fillStyle})

nodeBoxes[node.name] = [pt.x-w/2, pt.y-11, w, 22]

ctx.fillStyle = "black"

if (label) {ctx.fillText(label||"", pt.x, pt.y-12);}

}

});

particleSystem.eachEdge(//отрисуем каждую грань

function(edge, pt1, pt2){//будем работать с гранями и точками её начала и конца

var weight = !isNaN(edge.data.weight) ? parseFloat(weight): 1;

var color = !isNaN(edge.data.color) ? parseString(edge.data.color): "rgba(100,0,50,.5)";

var tail = intersect_line_box(pt1, pt2, nodeBoxes[edge.source.name]);

var head = intersect_line_box(tail, pt2, nodeBoxes[edge.target.name]);

ctx.strokeStyle = "rgba(100,0,50,.8)";//грани будут чёрным цветом с некой прозрачностью

ctx.lineWidth = 1;//толщиной в один пиксель

ctx.beginPath();//начинаем рисовать

ctx.moveTo(tail.x, tail.y)

ctx.lineTo(head.x, head.y)

ctx.stroke()

ctx.restore()

// draw an arrowhead if this is a -> style edge

if (edge.data.directed){

ctx.save()

// move to the head position of the edge we just drew

var wt = 1

var arrowLength = 6 + wt

var arrowWidth = 2 + wt

ctx.fillStyle = color

ctx.translate(head.x, head.y);

ctx.rotate(Math.atan2(head.y - tail.y, head.x - tail.x));

// delete some of the edge thats already there (so the point isnt hidden)

ctx.clearRect(-arrowLength/2,-wt/2, arrowLength/2,wt)

// draw the chevron

ctx.beginPath();

ctx.moveTo(-arrowLength, arrowWidth);

ctx.lineTo(0, 0);

ctx.lineTo(-arrowLength, -arrowWidth);

ctx.lineTo(-arrowLength * 0.8, -0);

ctx.closePath();

ctx.fill();

ctx.restore()

}

initMouseHandling:function(){//события с мышью

var dragged = null;//вершина которую перемещают

var handler = {

clicked:function(e){//нажали

var pos = $(canvas).offset();//получаем позицию canvas

_mouseP = arbor.Point(e.pageX-pos.left, e.pageY-pos.top); //и позицию нажатия кнопки относительно canvas

dragged = particleSystem.nearest(_mouseP);//определяем ближайшую вершину к нажатию

if (dragged && dragged.node !== null){

dragged.node.fixed = true;//фиксируем её

}

$(canvas).bind(mousemove, handler.dragged);//слушаем события перемещения мыши

$(window).bind(mouseup, handler.dropped);//и отпускания кнопки

return false;

},

dragged:function(e){//перетаскиваем вершину

var pos = $(canvas).offset();

var s = arbor.Point(e.pageX-pos.left, e.pageY-pos.top);

if (dragged && dragged.node !== null){

var p = particleSystem.fromScreen(s);

dragged.node.p = p;//тянем вершину за нажатой мышью

}

return false;

},

dropped:function(e){//отпустили

if (dragged===null || dragged.node===undefined) return;//если не перемещали, то уходим

if (dragged.node !== null) dragged.node.fixed = false;//если перемещали - отпускаем

dragged = null; //очищаем

$(canvas).unbind(mousemove, handler.dragged); //перестаём слушать события

$(window).unbind(mouseup, handler.dropped);

_mouseP = null;

return false;

}

// слушаем события нажатия мыши

$(canvas).mousedown(handler.clicked);

},

// helpers for figuring out where to draw arrows (thanks springy.js)

var intersect_line_line = function(p1, p2, p3, p4)

{

var denom = ((p4.y - p3.y)*(p2.x - p1.x) - (p4.x - p3.x)*(p2.y - p1.y));

if (denom === 0) return false // lines are parallel

var ua = ((p4.x - p3.x)*(p1.y - p3.y) - (p4.y - p3.y)*(p1.x - p3.x)) / denom;

var ub = ((p2.x - p1.x)*(p1.y - p3.y) - (p2.y - p1.y)*(p1.x - p3.x)) / denom;

if (ua < 0 || ua > 1 || ub < 0 || ub > 1) return false

return arbor.Point(p1.x + ua * (p2.x - p1.x), p1.y + ua * (p2.y - p1.y));

}

var intersect_line_box = function(p1, p2, boxTuple)

{

var p3 = {x:boxTuple[0], y:boxTuple[1]},

w = 20//boxTuple[2],

h = 20//boxTuple[3]

var tl = {x: p3.x, y: p3.y};

var tr = {x: p3.x + w, y: p3.y};

var bl = {x: p3.x, y: p3.y + h};

var br = {x: p3.x + w, y: p3.y + h};

return intersect_line_line(p1, p2, tl, tr) ||

intersect_line_line(p1, p2, tr, br) ||

intersect_line_line(p1, p2, br, bl) ||

intersect_line_line(p1, p2, bl, tl) ||

false

}

return that;

}

function Start(){

var sys = arbor.ParticleSystem(1,000, 600,0.9);

sys.parameters({gravity:true});

sys.parameters({dt:0.5});

sys.renderer = Renderer("#canv");//начинаем рисовать в выбраной области

sys.graft(a);

};

function redraw(){

var nm = b.split(;);

for (var i=0; i<nm.length;i++){nm[i]=JSON.parse(nm[i]);}

init(nm);

animate();

}

function init(mas) {

var x0=nodeBoxes[mas[0].name][0],

y0=nodeBoxes[mas[0].name][1];

var xx = new Array();

var yy = new Array();

for (var i=1; i<mas.length-1; i++){

xx[i-1] = nodeBoxes[mas[i].name][0]

yy[i-1] = nodeBoxes[mas[i].name][1]

}

var canvas = $("#canv").get(0);

var context = canvas.getContext( 2d );

context.lineWidth = 2;

context.strokeStyle = "#00ff00";

var obj = { x: x0, y: y0,old: { x: x0, y: y0}};

mtween = new TWEEN.Tween( obj ).to( { x: xx, y: yy }, 9000);

mtween.interpolation(TWEEN.Interpolation.Linear);

mtween.easing( TWEEN.Easing.Linear.None );

mtween.delay( 10 );

mtween.onComplete(function(){mtween.stop()});

mtween.onUpdate( function() {

context.beginPath();

context.moveTo( this.old.x, this.old.y );

context.lineTo( this.x, this.y );

context.closePath();

context.stroke();

this.old.x = this.x;

this.old.y = this.y;

}).start();

}

function animate() {

requestAnimationFrame( animate );

TWEEN.update();

}

</script>

<canvas id="canv" width="1260" height="600"></canvas>

<div>

<input type="button" id="but1" value="reload" style="position:absolute;bottom:50px;left:50px;" onclick="test()"></input>

<a href="http://site/index.html"><input type="button" id="but1" value="Home" style="position:absolute;bottom:50px;right:50px;"></input></a>

</div> </body></html>