【仿真建模-anylogic】动态生成ConveyorCustomStation

2024-06-19 02:04

本文主要是介绍【仿真建模-anylogic】动态生成ConveyorCustomStation,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Author:赵志乾
Date:2024-06-18
Declaration:All Right Reserved!!!

0. 背景

        直接使用Anylogic组件开发的模型无法动态改变运输网布局;目前需求是要将运输网布局配置化;运输网配置化的前提是将其标准化为仅包含辊道、自定义站点两种元素的网络;之后依据配置文件动态构建运输网;最后将自定义Agent逻辑关联到自定义站点实现流程串通;本次示例仅包含运输网中的辊道和自定义站点的动态生成以及组装过程;

1. 常用函数

函数功能
ConveyorCustomStation()构造函数
addVertex(double x, double y)添加点以构建2D图形,注意点:需要至少三个点,且连起的图形不得自身有交叉;通常会将CustomStation的图形隐藏,而将其内部自定义逻辑封装成Agent,用Agent的presentation替补CustomStation本身的图形;
addConnection(ConveyorPath conveyor, PathType type)将CustomStation与conveyor连接起来
onEnter(T agent)根据需要定义子类覆写该方法;当所运输物料进入CustomStation时,会自动执行该方法;

2. 数据结构定义

{"points": [{"code": "", // 点编码"name": "", // 点名称"x": 0.0, // 点坐标"y": 0.0,"z": 0.0}],"conveyors": [{"code": "", // 辊道编码"name": "", // 辊道名称"pointCodes": [] // 辊道从起点至终点所经历的位置点编码列表}],"customStations": [{"code": "",     // 自定义站点编码"name": "",     // 自定义站点名称"inConveyorCodes": [], // 传入站点的辊道"outConveyorCodes": [] // 传出站点的辊道}]
}

3. 代码实现

// ************************数据对象定义****************************
public class PointDefinition implements Serializable {private String code;private String name;private Double x;private Double y;private Double z;// setter、getter
}public class ConveyorDefinition implements Serializable {private String code;private String name;// setter、getter
}public class LayoutDefinition implements Serializable {private List<PointDefinition> points;private List<ConveyorDefinition> conveyors;private List<CustomStationDefinition> customStations;// setter、getter
}public class CustomStationDefinition implements Serializable {private String code;private String name;private List<String> inConveyorCodes;private List<String> outConveyorCodes;// setter、getter
}//******************************子类*******************************
public class CustomStation<T extends Agent> extends ConveyorCustomStation<T> {// 持有站点定义,便于onEnter中依据站点不同做不同处理CustomStationDefinition customStationDefinition;public CustomStation(CustomStationDefinition customStationDefinition) {super();this.customStationDefinition = customStationDefinition;}public void onEnter(T agent ) {// 自定义逻辑}
}//**************************动态生成过程******************************
// step1: 转map,方便后续使用
Map<String,PointDefinition> codeToPointDefinitionMap = layoutDefinition.getPoints().stream().collect(Collectors.toMap(PointDefinition::getCode, Function.identity(), (a,b)->b));
Map<String,ConveyorDefinition> codeToConveyorDefinitionMap = layoutDefinition.getConveyors().stream().collect(Collectors.toMap(ConveyorDefinition::getCode, Function.identity(), (a,b)->b));
Map<ConveyorDefinition,ConveyorPath> definitionToConveyorMap = new HashMap<>();// step2: 定义网络对象
ConveyorNetwork conveyorNetwork = new ConveyorNetwork(this,"conveyorNetwork");// step3: 向网络添加conveyor
for(ConveyorDefinition conveyorDefinition : layoutDefinition.getConveyors()){ConveyorPath conveyor = new ConveyorPath();// 每个conveyor由若干段组成for(int index=0; index<conveyorDefinition.getPointCodes().size()-1; index++){PointDefinition startPoint = codeToPointDefinitionMap.get(conveyorDefinition.getPointCodes().get(index));PointDefinition endPoint = codeToPointDefinitionMap.get(conveyorDefinition.getPointCodes().get(index+1));double startX = scale.pixelsPerUnit(METER)*startPoint.getX();double startY = scale.pixelsPerUnit(METER)*startPoint.getY();double startZ = scale.pixelsPerUnit(METER)*startPoint.getZ();double endX = scale.pixelsPerUnit(METER)*endPoint.getX();double endY = scale.pixelsPerUnit(METER)*endPoint.getY();double endZ = scale.pixelsPerUnit(METER)*endPoint.getZ();MarkupSegmentLine segment = new MarkupSegmentLine(startX, startY, startZ, endX, endY, endZ);conveyor.addSegment(segment);}definitionToConveyorMap.put(conveyorDefinition, conveyor);conveyorNetwork.add(conveyor);
}// step4: 自定义站点添加
for(CustomStationDefinition customStationDefinition : layoutDefinition.getCustomStations()){// step4.1: 站点创建CustomStation<Agent> customStation = new CustomStation(customStationDefinition);List<PointDefinition> points = new ArrayList<>();// step4.2: 站点与辊道关联,并绘制站点图形 for(String conveyorCode : customStationDefinition.getInConveyorCodes()){customStation.addConnection(definitionToConveyorMap.get(codeToConveyorDefinitionMap.get(conveyorCode)), PathEndType.END);ConveyorDefinition conveyorDefinition = codeToConveyorDefinitionMap.get(conveyorCode);PointDefinition pointDefinition = codeToPointDefinitionMap.get(conveyorDefinition.getPointCodes().get(conveyorDefinition.getPointCodes().size()-1));points.add(pointDefinition);customStation.addVertex(scale.pixelsPerUnit(METER)*pointDefinition.getX(), scale.pixelsPerUnit(METER)*pointDefinition.getY());}for(String conveyorCode : customStationDefinition.getOutConveyorCodes()){customStation.addConnection(definitionToConveyorMap.get(codeToConveyorDefinitionMap.get(conveyorCode)), PathEndType.BEGIN);ConveyorDefinition conveyorDefinition = codeToConveyorDefinitionMap.get(conveyorCode);PointDefinition pointDefinition = codeToPointDefinitionMap.get(conveyorDefinition.getPointCodes().get(0));points.add(pointDefinition);customStation.addVertex(scale.pixelsPerUnit(METER)*pointDefinition.getX(), scale.pixelsPerUnit(METER)*pointDefinition.getY());}// step4.3: 站点图形补充int conveyorNum = customStationDefinition.getInConveyorCodes().size()+customStationDefinition.getOutConveyorCodes().size();if(conveyorNum==0){error("不允许无连接辊道的ConveyorCustomStation");}else if(conveyorNum==1){// 已有一个点,需要额外补充两个点customStation.addVertex(scale.pixelsPerUnit(METER)*(points.get(points.size()-1).getX()+0.1), scale.pixelsPerUnit(METER)*(points.get(points.size()-1).getY()+0.2));customStation.addVertex(scale.pixelsPerUnit(METER)*(points.get(points.size()-1).getX()+0.1), scale.pixelsPerUnit(METER)*(points.get(points.size()-1).getY()+0.4));}else if(conveyorNum==2){// 已有一个点,需要额外补充一个点,借助两点的法线寻找第三点double x1 = scale.pixelsPerUnit(METER)*points.get(0).getX();double y1 = scale.pixelsPerUnit(METER)*points.get(0).getY();double x2 = scale.pixelsPerUnit(METER)*points.get(points.size()-1).getX();double y2 = scale.pixelsPerUnit(METER)*points.get(points.size()-1).getY();double kAB;  if (x2 - x1 == 0) { kAB = Double.POSITIVE_INFINITY;} else {  kAB = (y2 - y1) / (x2 - x1);  }  double kPerp;  if (kAB == Double.POSITIVE_INFINITY || kAB == Double.NEGATIVE_INFINITY || kAB == 0) {  kPerp = kAB == 0 ? Double.POSITIVE_INFINITY : 0;  } else {  kPerp = -1 / kAB;  }  double xC = x1 + 0.5;  double yC;  if (kPerp == Double.POSITIVE_INFINITY || kPerp == Double.NEGATIVE_INFINITY) {  yC = y1;  } else {  yC = y1 + kPerp * (xC - x1);  }  customStation.addVertex(xC,yC);}conveyorNetwork.add(customStation);
}// step5: 将生成的网络添加到演示中
Level customLevel = new Level(this,"customLevel",SHAPE_DRAW_2D3D,0);
customLevel.add(conveyorNetwork);
customLevel.initialize();
presentation.add(customLevel);

这篇关于【仿真建模-anylogic】动态生成ConveyorCustomStation的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1073699

相关文章

MybatisGenerator文件生成不出对应文件的问题

《MybatisGenerator文件生成不出对应文件的问题》本文介绍了使用MybatisGenerator生成文件时遇到的问题及解决方法,主要步骤包括检查目标表是否存在、是否能连接到数据库、配置生成... 目录MyBATisGenerator 文件生成不出对应文件先在项目结构里引入“targetProje

Python使用qrcode库实现生成二维码的操作指南

《Python使用qrcode库实现生成二维码的操作指南》二维码是一种广泛使用的二维条码,因其高效的数据存储能力和易于扫描的特点,广泛应用于支付、身份验证、营销推广等领域,Pythonqrcode库是... 目录一、安装 python qrcode 库二、基本使用方法1. 生成简单二维码2. 生成带 Log

VUE动态绑定class类的三种常用方式及适用场景详解

《VUE动态绑定class类的三种常用方式及适用场景详解》文章介绍了在实际开发中动态绑定class的三种常见情况及其解决方案,包括根据不同的返回值渲染不同的class样式、给模块添加基础样式以及根据设... 目录前言1.动态选择class样式(对象添加:情景一)2.动态添加一个class样式(字符串添加:情

Python使用Pandas库将Excel数据叠加生成新DataFrame的操作指南

《Python使用Pandas库将Excel数据叠加生成新DataFrame的操作指南》在日常数据处理工作中,我们经常需要将不同Excel文档中的数据整合到一个新的DataFrame中,以便进行进一步... 目录一、准备工作二、读取Excel文件三、数据叠加四、处理重复数据(可选)五、保存新DataFram

SpringBoot生成和操作PDF的代码详解

《SpringBoot生成和操作PDF的代码详解》本文主要介绍了在SpringBoot项目下,通过代码和操作步骤,详细的介绍了如何操作PDF,希望可以帮助到准备通过JAVA操作PDF的你,项目框架用的... 目录本文简介PDF文件简介代码实现PDF操作基于PDF模板生成,并下载完全基于代码生成,并保存合并P

SpringCloud配置动态更新原理解析

《SpringCloud配置动态更新原理解析》在微服务架构的浩瀚星海中,服务配置的动态更新如同魔法一般,能够让应用在不重启的情况下,实时响应配置的变更,SpringCloud作为微服务架构中的佼佼者,... 目录一、SpringBoot、Cloud配置的读取二、SpringCloud配置动态刷新三、更新@R

详解Java中如何使用JFreeChart生成甘特图

《详解Java中如何使用JFreeChart生成甘特图》甘特图是一种流行的项目管理工具,用于显示项目的进度和任务分配,在Java开发中,JFreeChart是一个强大的开源图表库,能够生成各种类型的图... 目录引言一、JFreeChart简介二、准备工作三、创建甘特图1. 定义数据集2. 创建甘特图3.

如何用Python绘制简易动态圣诞树

《如何用Python绘制简易动态圣诞树》这篇文章主要给大家介绍了关于如何用Python绘制简易动态圣诞树,文中讲解了如何通过编写代码来实现特定的效果,包括代码的编写技巧和效果的展示,需要的朋友可以参考... 目录代码:效果:总结 代码:import randomimport timefrom math

Java中JSON字符串反序列化(动态泛型)

《Java中JSON字符串反序列化(动态泛型)》文章讨论了在定时任务中使用反射调用目标对象时处理动态参数的问题,通过将方法参数存储为JSON字符串并进行反序列化,可以实现动态调用,然而,这种方式容易导... 需求:定时任务扫描,反射调用目标对象,但是,方法的传参不是固定的。方案一:将方法参数存成jsON字

.NET利用C#字节流动态操作Excel文件

《.NET利用C#字节流动态操作Excel文件》在.NET开发中,通过字节流动态操作Excel文件提供了一种高效且灵活的方式处理数据,本文将演示如何在.NET平台使用C#通过字节流创建,读取,编辑及保... 目录用C#创建并保存Excel工作簿为字节流用C#通过字节流直接读取Excel文件数据用C#通过字节