C# 卡车装车示例

Posted 多见多闻

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C# 卡车装车示例相关的知识,希望对你有一定的参考价值。

1. 创建一个货物类,包含长、宽、高、重量、颜色、标签等属性,并定义一个列表用于存储所有货物对象。

public class Cargo 
    public float length;
    public float width;
    public float height;
    public float weight;
    public Color color;
    public string label;

    public Cargo(float l, float w, float h, float m, Color c, string lbl) 
        length = l;
        width = w;
        height = h;
        weight = m;
        color = c;
        label = lbl;
    


List<Cargo> cargoes = new List<Cargo>();

2. 在UI界面中添加输入框和按钮,让用户输入货物参数和算法选择。

float length = float.Parse(lengthInput.text);
float width = float.Parse(widthInput.text);
float height = float.Parse(heightInput.text);
float weight = float.Parse(weightInput.text);
string label = labelInput.text;
Color color = colorPicker.color;

// 添加新货物到列表中
Cargo newCargo = new Cargo(length, width, height, weight, color, label);
cargoes.Add(newCargo);

// 计算最优摆放方案,使用选择的算法
if (algorithmDropdown.value == 0) 
    // 贪心算法
 else if (algorithmDropdown.value == 1) 
    // 回溯算法
 else if (algorithmDropdown.value == 2) 
    // 遗传算法

3. 实现贪心算法来计算最优摆放方案,并在场景中绘制货物。

// 定义贪心算法函数
public void GreedyAlgorithm() 
    float maxWidth = 20f;
    float maxHeight = 10f;
    float maxLength = 50f;

    // 按照重量从大到小排序
    cargoes.Sort((a, b) => b.weight.CompareTo(a.weight));

    // 计算总体积和总重量,同时记录每个货物的位置和旋转角度
    Vector3 pos = Vector3.zero;
    Quaternion rot = Quaternion.identity;
    float totalWeight = 0f;
    float totalVolume = 0f;
    foreach (Cargo cargo in cargoes) 
        if (cargo.length <= maxLength && cargo.width <= maxWidth && cargo.height <= maxHeight) 
            // 判断是否可以放入卡车
            if (totalWeight + cargo.weight <= maxWeight && totalVolume + cargo.length * cargo.width * cargo.height <= maxVolume) 
                totalWeight += cargo.weight;
                totalVolume += cargo.length * cargo.width * cargo.height;

                // 计算当前货物的位置和旋转角度
                cargo.transform.position = pos;
                cargo.transform.rotation = rot;
                cargo.gameObject.SetActive(true);

                // 更新下一个货物的位置和旋转角度
                Vector3 nextPos = pos + new Vector3(cargo.length / 2f, cargo.height / 2f, -cargo.width / 2f);
                if (nextPos.y > maxHeight) 
                    nextPos.y = 0f;
                    nextPos.x += maxLength;
                
                pos = nextPos;
            
        
    


// 在场景中创建货物对象,设置位置和旋转角度,并添加到列表中
Cargo cargo1 = Instantiate(cargoPrefab).GetComponent<Cargo>();
cargo1.length = 5f;
cargo1.width = 2f;
cargo1.height = 3f;
cargo1.weight = 10f;
cargo1.color = Color.red;
cargo1.label = "Box 1";
cargo1.gameObject.SetActive(false);
cargoes.Add(cargo1);

// 绘制卡车模型,并计算最优摆放方案
CreateTruck();
GreedyAlgorithm();

4. 实现拖放事件和数据显示组件。

public class Cargo : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler 
    public void OnBeginDrag(PointerEventData eventData) 
        // 开始拖动货物时,记录初始位置和旋转角度
        startPos = transform.position;
        startRot = transform.rotation;

5. 实现摆放到卡车功能,并在UI界面中添加“装载”按钮。

public class Cargo : MonoBehaviour 
    public void LoadToTruck() 
        // 将货物设置为静态,禁止再次拖放
        GetComponent<Rigidbody>().isKinematic = true;

        // 设置货物父节点为卡车对象
        transform.SetParent(truck.transform);

        // 将货物加入已装载货物列表中
        loadedCargoes.Add(this);
    


public void LoadCargoesToTruck() 
    foreach (Cargo cargo in selectedCargoes) 
        cargo.LoadToTruck();
    

    // 计算已装载货物的总重量和总体积
    float totalWeight = 0f;
    float totalVolume = 0f;
    foreach (Cargo cargo in loadedCargoes) 
        totalWeight += cargo.weight;
        totalVolume += cargo.length * cargo.width * cargo.height;
    

    // 显示已装载货物的总重量和总体积
    weightText.text = "Total weight: " + totalWeight.ToString("F2");
    volumeText.text = "Total volume: " + totalVolume.ToString("F2");

6. 实现场景旋转、放大、拖动功能,并使用Unity自带的Camera类实现视角控制。

public class CameraController : MonoBehaviour 
    public float moveSpeed = 10f;
    public float rotateSpeed = 100f;
    public float zoomSpeed = 10f;

    private Camera camera;

    void Start() 
        camera = GetComponent<Camera>();
    

    void Update() 
        // 控制场景移动
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");
        float depth = Input.GetAxis("Depth");
        transform.position += transform.right * horizontal * moveSpeed * Time.deltaTime;
        transform.position += transform.up * vertical * moveSpeed * Time.deltaTime;
        transform.position += transform.forward * depth * moveSpeed * Time.deltaTime;

        // 控制场景旋转
        float rotateHorizontal = Input.GetAxis("Mouse X");
        float rotateVertical = Input.GetAxis("Mouse Y");
        transform.Rotate(Vector3.up, rotateHorizontal * rotateSpeed * Time.deltaTime, Space.World);
        transform.Rotate(Vector3.left, rotateVertical * rotateSpeed * Time.deltaTime, Space.World);

        // 控制摄像机缩放
        float zoom = Input.GetAxis("Mouse ScrollWheel");
        camera.fieldOfView -= zoom * zoomSpeed;
        camera.fieldOfView = Mathf.Clamp(camera.fieldOfView, 1f, 100f);
    

7. 在UI界面中添加“保存场景”按钮,并使用Unity自带的JsonUtility类将货物列表保存到本地文件。

public void SaveScene() 
    // 将货物列表转换为JSON格式字符串
    string json = JsonUtility.ToJson(cargoes);

    // 将JSON字符串写入本地文件
    string filePath = Application.dataPath + "/cargoes.json";
    File.WriteAllText(filePath, json);

8. 在UI界面中添加“加载场景”按钮,并使用Unity自带的JsonUtility类从本地文件中读取货物列表。

public void LoadScene() 
    // 从本地文件读取JSON字符串
    string filePath = Application.dataPath + "/cargoes.json";
    string json = File.ReadAllText(filePath);

    // 将JSON字符串转换为货物对象列表
    cargoes = JsonUtility.FromJson<List<Cargo>>(json);

    // 在场景中创建每个货物对象,并设置其位置和旋转角度
    foreach (Cargo cargo in cargoes) 
        Cargo newCargo = Instantiate(cargoPrefab).GetComponent<Cargo>();
        newCargo.length = cargo.length;
        newCargo.width = cargo.width;
        newCargo.height = cargo.height;
        newCargo.weight = cargo.weight;
        newCargo.color = cargo.color;
        newCargo.label = cargo.label;
        newCargo.transform.position = cargo.position;
        newCargo.transform.rotation = cargo.rotation;
    

9. 在货物类中添加序列化属性,以便将货物对象保存到本地文件。

[System.Serializable]
public class Cargo 
    public float length;
    public float width;
    public float height;
    public float weight;
    public Color color;
    public string label;

    // 序列化货物位置和旋转角度
    public Vector3 position;
    public Quaternion rotation;

    public Cargo(float l, float w, float h, float m, Color c, string lbl) 
        length = l;
        width = w;
        height = h;
        weight = m;
        color = c;
        label = lbl;
    

10. 在货物类中添加Equals方法和GetHashCode方法,以便将相同属性的货物对象视为相等。

public override bool Equals(object obj) 
    if (obj == null) return false;
    Cargo other = obj as Cargo;
    if (other == null) return false;
    return length == other.length && width == other.width && height == other.height && weight == other.weight && color.Equals(other.color) && label.Equals(other.label);


public override int GetHashCode() 
    return length.GetHashCode() ^ width.GetHashCode() ^ height.GetHashCode() ^ weight.GetHashCode() ^ color.GetHashCode() ^ label.GetHashCode();

11. 在摆放算法中实现相同货物尽量放置在一起的要求,并使用字典记录已放置的货物类型和数量。

// 定义贪心算法函数
public void GreedyAlgorithm() 
    float maxWidth = 20f;
    float maxHeight = 10f;
    float maxLength = 50f;

    // 按照重量从大到小排序
    cargoes.Sort((a, b) => b.weight.CompareTo(a.weight));

    // 计算总体积和总重量,同时记录每个货物的位置和旋转角度
    Vector3 pos = Vector3.zero;
    Quaternion rot = Quaternion.identity;
    float totalWeight = 0f;
    float totalVolume = 0f;
    Dictionary<Cargo, int> cargoCount = new Dictionary<Cargo, int>();
    foreach (Cargo cargo in cargoes) 
        if (cargo.length <= maxLength && cargo.width <= maxWidth && cargo.height <= maxHeight) 
            // 判断是否可以放入卡车
            if (totalWeight + cargo.weight <= maxWeight && totalVolume + cargo.length * cargo.width * cargo.height <= maxVolume) 
                // 判断是否需要新建一层
                if (pos.y + cargo.height / 2f > maxHeight) 
                    pos.y = 0f;
                    pos.x += maxLength;
                

                // 判断是否与上一个货物相同
                bool sameCargo = false;
                foreach (KeyValuePair<Cargo, int> item in cargoCount) 
                    if (item.Key.Equals(cargo)) 
                        sameCargo = true;
                        pos.z += item.Key.length / 2f + cargo.length / 2f;
                        break;
                    
                
                if (!sameCargo) 
                    cargoCount[cargo] = 1;
                 else 
                    cargoCount[cargo]++;
                

                // 更新当前货物的位置和旋转角度
                cargo.transform.position = pos;
                cargo.transform.rotation = rot;
                cargo.gameObject.SetActive(true);

                // 更新下一个货物的位置和旋转角度
                pos += new Vector3(0f, cargo.height / 2f, cargo.width / 2f);
                totalWeight += cargo.weight;
                totalVolume += cargo.length * cargo.width * cargo.height;
            
        
    

12. 在摆放算法中实现最大化利用空间要求,根据卡车尺寸计算每层最大可用空间,并动态调整货物高度来最大化利用空间。

// 定义贪心算法函数
public void GreedyAlgorithm() 
    float maxWidth = 20f;
    float maxHeight = 10f;
    float maxLength = 50f;

    // 按照重量从大到小排序
    cargoes.Sort((a, b) => b.weight.CompareTo(a.weight));

    // 计算总体积和总重量,同时记录每个货物的位置和旋转角度
    Vector3 pos = Vector3.zero;
    Quaternion rot = Quaternion.identity;
    float totalWeight = 0f;
    float totalVolume = 0f;
    Dictionary<Cargo, int> cargoCount = new Dictionary<Cargo, int>();
    foreach (Cargo cargo in cargoes) 
        if (cargo.length <= maxLength && cargo.width <= maxWidth && cargo.height <= maxHeight) 
            // 判断是否可以放入卡车
            if (totalWeight + cargo.weight <= maxWeight && totalVolume + cargo.length * cargo.width * cargo.height <= maxVolume) 
                // 判断是否需要新建一层
                if (pos.y + cargo.height / 2f > maxHeight) 
                    pos.y = 0f;
                    pos.x += maxLength;
                

                // 判断是否与上一个货物相同
                bool sameCargo = false;
                foreach (KeyValuePair<Cargo, int> item in cargoCount) 
                    if (item.Key.Equals(cargo)) 
                        sameCargo = true;
                        pos.z += item.Key.length / 2f + cargo.length / 2f;
                        break;
                    
                
                if (!sameCargo) 
                    cargoCount[cargo] = 1;
                 else 
                    cargoCount[cargo]++;
                

                // 动态调整货物高度来最大化利用空间
                float availableHeight = maxHeight - pos.y;
                if (availableHeight < cargo.height) 
                    cargo.transform.localScale *= availableHeight / cargo.height;
                    cargo.height = availableHeight;
                

                // 更新当前货物的位置和旋转角度
                cargo.transform.position = pos;
                cargo.transform.rotation = rot;
                cargo.gameObject.SetActive(true);

                // 更新下一个货物的位置和旋转角度
                pos += new Vector3(0f, cargo.height / 2f, cargo.width / 2f);
                totalWeight += cargo.weight;
                totalVolume += cargo.length * cargo.width * cargo.height;
            
        
    

13. 在UI界面中添加“清空场景”按钮,并在点击后移除所有已放置的货物,并重置数据显示。

public void ClearScene() 
    foreach (Cargo cargo in loadedCargoes) 
        Destroy(cargo.gameObject);
    
    loadedCargoes.Clear();
    weightText.text = "Total weight: ";
    volumeText.text = "Total volume: ";

14. 在UI界面中添加“退出应用程序”按钮,并在点击后退出应用程序。

public void QuitApplication() 
    Application.Quit();

15. 在UI界面中添加“选择算法”下拉框,并在其中添加各种摆放算法选项。

public Dropdown algorithmDropdown;

void Start() 
    // 在下拉框中添加选项
    List<string> algorithms = new List<string>()  "Greedy Algorithm", "Genetic Algorithm", "Simulated Annealing" ;
    algorithmDropdown.AddOptions(algorithms);

16. 在UI界面中添加“摆放货物”按钮,并在点击后根据选定的算法进行货物摆放。

public void LoadCargoes() 
    // 移除之前的货物
    ClearScene();

    // 根据选定的算法进行货物摆放
    switch (algorithmDropdown.value) 
        case 0:
            GreedyAlgorithm();
            break;
        case 1:
            GeneticAlgorithm();
            break;
        case 2:
            SimulatedAnnealing();
            break;
    

    // 更新数据显示
    weightText.text = "Total weight: " + loadedWeight.ToString("F2") + " tons";
    volumeText.text = "Total volume: " + loadedVolume.ToString("F2") + " cubic meters";

17. 在UI界面中添加“摆放到卡车”按钮,并在点击后将货物摆放到卡车上。

public void PlaceCargoes() 
    // 将货物摆放到卡车上
    foreach (Cargo cargo in loadedCargoes) 
        cargo.transform.SetParent(truck.transform);
    

18. 在UI界面中添加“拖动场景”按钮,并在点击后启用场景拖放功能。

public void EnableDrag() 
    dragManager.enabled = true;

19. 在UI界面中添加“缩放场景”选框,并在选中后开启场景缩放功能。

public Toggle zoomToggle;

void Update() 
    // 如果选中了缩放场景选框,则开启场景缩放功能
    if (zoomToggle.isOn) 
        float zoom = Input.GetAxis("Mouse ScrollWheel");
        Camera.main.transform.position += Camera.main.transform.forward * zoom * zoomSpeed;
    

20. 在UI界面中添加“显示/隐藏方案”选框,并在选中后显示或隐藏货物摆放方案。

public Toggle planToggle;

void Update() 
    // 如果选中了显示/隐藏方案选框,则显示或隐藏货物摆放方案
    foreach (Cargo cargo in loadedCargoes) 
        cargo.plan.SetActive(planToggle.isOn);
    

21. 在货物类中添加plan属性,并在创建货物时同时创建其对应的货物摆放方案。

public GameObject planPrefab;
public GameObject plan  get; private set; 

void Awake() 
    plan = Instantiate(planPrefab, transform.position, transform.rotation, transform);
    plan.SetActive(false);

22. 在卡车类中添加bounds属性,表示卡车所占用的空间范围,并在添加货物时更新该属性。

public Bounds bounds  get; private set; 

void Awake() 
    bounds = new Bounds(transform.position, new Vector3(maxLength, maxHeight, maxWidth));


public bool AddCargo(Cargo cargo) 
    // 判断是否可以放入卡车
    if (loadedWeight + cargo.weight <= maxWeight && loadedVolume + cargo.length * cargo.width * cargo.height <= maxVolume) 
        // 判断是否与上一个货物相同
        bool sameCargo = false;
        foreach (KeyValuePair<Cargo, int> item in cargoCount) 
            if (item.Key.Equals(cargo)) 
                sameCargo = true;
                pos.z += item.Key.length / 2f + cargo.length / 2f;
                break;
            
        
        if (!sameCargo) 
            cargoCount[cargo] = 1;
         else 
            cargoCount[cargo]++;
        

        // 更新当前货物的位置和旋转角度
        cargo.transform.position = pos;
        cargo.transform.rotation = rot;
        cargo.gameObject.SetActive(true);

        // 更新卡车的属性和下一个货物的位置和旋转角度
        loadedCargoes.Add(cargo);
        loadedWeight += cargo.weight;
        loadedVolume += cargo.length * cargo.width * cargo.height;
        bounds.Encapsulate(new Bounds(cargo.transform.position, new Vector3(cargo.length, cargo.height, cargo.width)));
        pos += new Vector3(0f, cargo.height / 2f, cargo.width / 2f);
        return true;
     else 
        return false;
    

23. 在UI界面中添加“拖动货物”选框,并在选中后启用货物拖放功能。

public Toggle cargoDragToggle;

void Update() 
    // 如果选中了拖动货物选框,则启用货物拖放功能
    if (cargoDragToggle.isOn) 
        foreach (Cargo cargo in loadedCargoes) 
            cargo.gameObject.AddComponent<DragManager>();
        
    

 

在 Anylogic 中,我如何为向多个客户交付订单的卡车建模

【中文标题】在 Anylogic 中,我如何为向多个客户交付订单的卡车建模【英文标题】:In Anylogic How can I model truck that deliver orders to multiple clients 【发布时间】:2021-10-21 00:26:03 【问题描述】:

我正在根据 AnyLogic 提供的产品交付示例创建一个模型。在我自己的模型中,我希望一辆卡车在一次旅行中交付多个订单,而不是一次。我的流程图如下所示。在这里,一个订单通过 enter 块进入,并且在批处理块中累积了几个订单。每个订单都有一个指定的目的地。如何对卡车进行建模,使其结合两个订单并首先移动到最近的交货地点,然后是第二个等?

主要问题是我不知道每个订单中访问参数“交货位置”的代码。

enter image description here enter image description here

附加信息:

生成订单代理并将交货地点存储在名为“client”的参数中 批处理块将(比如说 2 个)订单组合成订单类型的批处理(高级设置设置为代理人数) 服务块从资源包中拉出一辆卡车,并使用 send(batch.unit) 将这批订单发送给卡车代理 卡车代理将订单/订单(?)存储在一个名为“订单”的变量中 然后,moveTo 函数应该将订单传递到第一个目的地

移动到第一个、第二个等目的地的代码是什么?

【问题讨论】:

我已经删除了你的 [batch-file] 标签。每个标签都有一个描述,说明它们的用途。 [batch-file] 标签用于基于文本的脚本,这些脚本使用.bat.cmd 文件扩展名,并且在MS-DOS、OS/2 或Microsoft Windows 上运行。如果您认为有必要,请随意添加另一个标签,但请考虑是否有必要将您的问题引导给适当的受众。使用不适当的标签不仅不太可能帮助您获得解决方案,而且可能会吸引反对票或关闭票。 【参考方案1】:

这是您可能不知道的概念部分,它应该可以帮助您朝着正确的方向前进:

您可以将“for 循环”作为流程的一部分。在下面,您会看到一个示例,其中代理一直开车到某个地方,直到没有包裹为止。

显然,模块的详细信息取决于您的型号,但在每个模块中,如果您的卡车代理类型中有卡车订单(显然这是必需的),您就可以访问卡车的订单。

【讨论】:

以上是关于C# 卡车装车示例的主要内容,如果未能解决你的问题,请参考以下文章

在 Anylogic 中,我如何为向多个客户交付订单的卡车建模

制作卡车和按钮以提高速度,通过 jQuery 使用 html/js 改变方向

增城改装车 l 雪佛兰Impala 在告诉你什么叫趴

2021 中青杯 A题:汽车组装车间流水线物料配送问题 赛题思路

POJ 2923 Relocation 装车问题 状态压缩DP+01背包

5系(F10/18)SACHS CSS避震台湾装车