已知点矩阵的三个顶点坐标、行列数和行列的间距,计算得出剩余所有点的坐标

news/2025/2/22 16:55:49

已知点矩阵的三个顶点坐标、行列数和行列的间距,计算得出剩余所有点的坐标

  • 计算矩阵中每个点的坐标
    • 代码实现
    • 案例图
    • 调用验证

计算矩阵中每个点的坐标

给定左上角、左下角和右上角三个点的坐标,以及矩阵的行数、列数、行间距和列间距,我们可以计算出所有点的坐标。
在项目中有一个运动装置,只可按照x或y方向移动。目标是在96孔板的96个孔,而这些孔是排列整齐有序的,那么我们就可通过该方案计算出剩余的点,来简化示教人员的工作。

代码实现

public class PlateWellPoint
{
    public double X { get; }
    public double Y { get; }
    public int RowIndex { get; set; }
    public int ColumnIndex { get; set; }

    public PlateWellPoint(double x, double y)
    {
        X = x;
        Y = y;
    }

    public override string ToString()
    {
        return $"R{RowIndex}C{ColumnIndex}({X:F2}, {Y:F2})";
    }
}
public class PlatePointMatrixGenerator
{
    public static List<PlateWellPoint> GeneratePoints(PlateWellPoint topLeft, PlateWellPoint bottomLeft, PlateWellPoint topRight, int rows, int cols, double rowSpacing, double colSpacing)
    {
        // 计算右下角点坐标
        PlateWellPoint bottomRight = CalculateBottomRightPoint(topLeft, bottomLeft, topRight);
        // 验证输入的四个点是否形成矩形
        if (!IsRectangle(topLeft, bottomLeft, topRight, bottomRight))
        {
            Console.WriteLine("警告:输入的三个点无法形成矩形,计算结果可能不准确。");
        }
        // 计算矩阵中所有点的坐标
        List<PlateWellPoint> allPoints = CalculateAllPoints(topLeft, topRight, bottomLeft, rows, cols);
        // 输出所有点的坐标
        Console.WriteLine("\n矩阵中所有点的坐标:");
        int index = 0;
        for (int r = 0; r < rows; r++)
        {
            for (int c = 0; c < cols; c++)
            {
                Console.WriteLine($"点[{r},{c}]: {allPoints[index]}");
                index++;
            }
        }

        // 验证间距
        VerifySpacing(allPoints, rows, cols, rowSpacing, colSpacing);
        return allPoints;
    }
    // 计算右下角的点坐标
    static PlateWellPoint CalculateBottomRightPoint(PlateWellPoint topLeft, PlateWellPoint bottomLeft, PlateWellPoint topRight)
    {
        // 右下角的坐标可以通过向量加法计算
        // 从左上角到右上角的位移 + 从左上角到左下角的位移 = 从左上角到右下角的位移
        double bottomRightX = topLeft.X + (topRight.X - topLeft.X) + (bottomLeft.X - topLeft.X);
        double bottomRightY = topLeft.Y + (topRight.Y - topLeft.Y) + (bottomLeft.Y - topLeft.Y);

        return new PlateWellPoint(bottomRightX, bottomRightY);
    }
    // 检查四个点是否构成矩形
    static bool IsRectangle(PlateWellPoint topLeft, PlateWellPoint bottomLeft, PlateWellPoint topRight, PlateWellPoint bottomRight)
    {
        // 计算对角线长度是否相等
        double diagonal1 = Math.Sqrt(Math.Pow(topLeft.X - bottomRight.X, 2) + Math.Pow(topLeft.Y - bottomRight.Y, 2));
        double diagonal2 = Math.Sqrt(Math.Pow(topRight.X - bottomLeft.X, 2) + Math.Pow(topRight.Y - bottomLeft.Y, 2));

        // 对角线长度应该近似相等
        return Math.Abs(diagonal1 - diagonal2) < 0.001;
    }
    // 计算矩阵中所有点的坐标
    static List<PlateWellPoint> CalculateAllPoints(PlateWellPoint topLeft, PlateWellPoint topRight, PlateWellPoint bottomLeft, int rows, int cols)
    {
        List<PlateWellPoint> points = new List<PlateWellPoint>();

        // 计算行方向和列方向的单位向量
        double rowVectorX = (bottomLeft.X - topLeft.X) / (rows - 1);
        double rowVectorY = (bottomLeft.Y - topLeft.Y) / (rows - 1);

        double colVectorX = (topRight.X - topLeft.X) / (cols - 1);
        double colVectorY = (topRight.Y - topLeft.Y) / (cols - 1);

        // 计算每个点的坐标
        for (int r = 0; r < rows; r++)
        {
            for (int c = 0; c < cols; c++)
            {
                double x = topLeft.X + r * rowVectorX + c * colVectorX;
                double y = topLeft.Y + r * rowVectorY + c * colVectorY;
                points.Add(new PlateWellPoint(x, y) { RowIndex = r, ColumnIndex = c });
            }
        }

        return points;
    }
    // 验证计算的点是否符合给定的行间距和列间距
    static void VerifySpacing(List<PlateWellPoint> points, int rows, int cols, double expectedRowSpacing, double expectedColSpacing)
    {
        double totalRowSpacingError = 0;
        int rowSpacingCount = 0;
        double totalColSpacingError = 0;
        int colSpacingCount = 0;

        // 检查行间距
        for (int r = 0; r < rows - 1; r++)
        {
            for (int c = 0; c < cols; c++)
            {
                int idx1 = r * cols + c;
                int idx2 = ((r + 1) * cols) + c;

                double distance = Math.Sqrt(Math.Pow(points[idx1].X - points[idx2].X, 2) + Math.Pow(points[idx1].Y - points[idx2].Y, 2));
                totalRowSpacingError += Math.Abs(distance - expectedRowSpacing);
                rowSpacingCount++;
            }
        }

        // 检查列间距
        for (int r = 0; r < rows; r++)
        {
            for (int c = 0; c < cols - 1; c++)
            {
                int idx1 = r * cols + c;
                int idx2 = r * cols + c + 1;

                double distance = Math.Sqrt(Math.Pow(points[idx1].X - points[idx2].X, 2) + Math.Pow(points[idx1].Y - points[idx2].Y, 2));
                totalColSpacingError += Math.Abs(distance - expectedColSpacing);
                colSpacingCount++;
            }
        }

        // 打印平均误差
        if (rowSpacingCount > 0)
        {
            double avgRowError = totalRowSpacingError / rowSpacingCount;
            Console.WriteLine($"\n行间距平均误差: {avgRowError:F4} mm");
        }

        if (colSpacingCount > 0)
        {
            double avgColError = totalColSpacingError / colSpacingCount;
            Console.WriteLine($"列间距平均误差: {avgColError:F4} mm");
        }
    }
}

案例图

<a class=矩阵模拟图" />

调用验证

var leftTop = new PlateWellPoint(2, 2);
var rightTop = new PlateWellPoint(6, 6);
var leftButtom = new PlateWellPoint(4, 0);
int rowCount = 3;
int columnCount = 5;
var points = PlatePointMatrixGenerator.GeneratePoints(leftTop, leftButtom, rightTop, rowCount, columnCount, 1, 1);

运行结果
在这里插入图片描述
注意:行列序号从0开始的。

从上述结果中随便选一个点,在案例图中找到进行坐标验证
例如:取索引为13的点,是R2C3即第三行第四列,在案例图中核对坐标是否为x:7,y:3。
从案例图中任选一个坐标点,在上述结果中查找,是否为指定的行和列。


http://www.niftyadmin.cn/n/5862547.html

相关文章

MATLAB在投资组合优化中的应用:从基础理论到实践

引言 投资组合优化是现代金融理论中的核心问题之一&#xff0c;旨在通过合理配置资产&#xff0c;实现风险与收益的最佳平衡。MATLAB凭借其强大的数学计算能力和丰富的金融工具箱&#xff0c;成为投资组合优化的理想工具。本文将详细介绍如何使用MATLAB进行投资组合优化&#…

网页五子棋——对战后端

目录 GameHandler 创建请求响应对象 处理连接成功 玩家下线处理 处理落子请求 handleTextMessage putChess 落子 胜负判定 构造落子响应并返回 更新玩家分数 修改客户端代码 对战模块测试 在本篇文章中&#xff0c;我们继续实现对战模块的后端逻辑 GameHandler…

计算机视觉基础|卷积神经网络:从数学原理到可视化实战

一、引言 在当今人工智能飞速发展的时代&#xff0c;卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;简称 CNN&#xff09;无疑在诸多领域发挥着关键作用&#xff0c;尤其在计算机视觉领域&#xff0c;如人脸识别、图像分类、目标检测等任务中&#xff0c;…

【SpringBoot教程】SpringBoot整合Caffeine本地缓存及Spring Cache注解的使用

&#x1f64b;大家好&#xff01;我是毛毛张! &#x1f308;个人首页&#xff1a; 神马都会亿点点的毛毛张 毛毛张今天要介绍的是本地缓存之王&#xff01;Caffeine&#xff01;SpringBoot整合Caffeine本地缓存及Spring Cache注解的使用 文章目录 1.Caffeine本地缓存1.1 本地…

Dify怎么创建数据交易的智能体

Dify怎么创建数据交易的智能体 Dify是一个低代码AI应用开发平台,能帮助你快速创建智能体。以下是使用Dify创建一个数据定价智能体的大致步骤和示例: 1. 注册与登录 首先,访问Dify官网(https://dify.ai/ ),完成注册并登录到你的账号。 2. 创建新项目 登录后,点击创建…

Jupyter里面的manim编程学习

1.Jupyterlab的使用 因为我之前一直都是使用的vscode进行manim编程的&#xff0c;但是今天看的这个教程使用的是Jupyter&#xff0c;我也很是好奇这个manim在Jupyter这样的交互式下面会生成怎么样的效果&#xff0c;所以今天尝试了jupyter&#xff0c;并且对于两个进行比较和说…

鸿蒙NEXT应用App测试-通用测试

注意&#xff1a;大家记得学完通用测试记得再学鸿蒙专项测试 https://blog.csdn.net/weixin_51166786/article/details/145768653 注意&#xff1a;博主有个鸿蒙专栏&#xff0c;里面从上到下有关于鸿蒙next的教学文档&#xff0c;大家感兴趣可以学习下 如果大家觉得博主文章…

SWAT| 水文 | SWAT模型(四):气象数据库制备(附Python代码)

Tips&#xff1a; 本期向大家分享SWAT模型的气象数据库的制备方法。最终要制作5项气象数据&#xff0c;分别是日降水量、最高/最低气温、太阳辐射、相对湿度、平均风速&#xff0c;每项气象数据要有①站点文件和②站点气象数据文件&#xff0c;都用txt文本文件来储存。…