Matlab 2012a 面向对象(1):二维点,地理点和地理线的类设计和实现

Point2D
x
y
obj = Point2D(x,y)
GeoPoint
name
obj = GeoPoint(name,x,y)
new_obj = NewByDeg(obj,name,deg,len)
h = plot(obj,style)
disp(obj)
GeoLine
name
head
tail
deg
len
space
num
items
obj = GeoLine(name,head,tail,deg,len,space,num)
obj = get_deg(obj)
obj = get_len(obj)
obj = get_space(obj)
obj = get_tail(obj)
obj = get_items(obj,n,d)
obj = remove_items(obj)
h = plot(obj,style)
h = plot_items(obj,style)
disp(obj)
disp_items(obj)

0 面向对象语法简述

Matlab的面向对象编程逻辑更为清晰,当面向过程的程序较为复杂时,最好将其改写为面向对象的。这样能大大增强代码可读性,逻辑性也好理解。

Matlab的面向对象跟C++大体一致,但还是有一点小的不同,初学起来可能会有些坑。这里稍微讲一下。

类的写法:

classdef ClassName

    properties
    end
    
    % 受保护 继承序列可访问
    properties (Access = protected)
    end
    
    % 常数不可更改
    properties (Constant)
    end
    
    % 通过计算得到的
    properties (Dependent)
    end
    
    methods
        % 构造函数
        function newobj = GeoPL(name,type,x0,y0,x1,y1)
        end
    end

    methods (Access = protected)
    end
    
end

其中,类也写为两个区域,1个是属性区,1个是方法区。属性区什么限制也不加就是公有的,可以继承,加了protected就是保护性继承,加了depedent就是依赖,需要用get函数建立约束。

值得注意的是,get函数是自动执行的,我感觉不太好使,因此放弃了这种写法。

此外,貌似类文件只能单独写成文件,而且类名和文件名必须相同,还不能在类文件里写别的事儿,或者把类写到script中,不知道是不是这样?

类写完之后,放到同一个文件夹下,或者设置工作路径,否则就可能无法调用

1 二维点

二维点是单纯的几何点,只有x和y两个属性,可以通过构造函数定义。

classdef Point2D
    %POINT2D 二维点
    %   Detailed explanation goes here
    
    properties
        x
        y
    end
    
    methods
        % 构造函数
        function obj = Point2D(x,y)
            if (nargin==0)
                obj.x = nan;
                obj.y = nan;
            elseif (nargin==1)
                obj.x = nan;
                obj.y = nan;
            elseif (nargin==2)
                obj.x = x;
                obj.y = y;
            end
        end
    end
end

2 地理点

地理点是继承于二维点,有x和y两个属性和nam属性,可以通过构造函数定义。同时也考虑了用角度和长度来延伸定义。注意:这里的角度和长度并不是地理点对象的属性,而是外部获取的。

classdef GeoPoint < Point2D
    %GEOPIONT 点对象
    %   Detailed explanation goes here
    
    properties
        name
    end
    
    methods
        % 构造函数
        function obj = GeoPoint(name,x,y)
            if (nargin==0)
                name = '';
                x = nan;
                y = nan;
            elseif (nargin==1)
                x = nan;
                y = nan;
            elseif (nargin==2)
                x = nan;
                y = nan;
            end
            obj = obj@Point2D(x,y);
            obj.name = name;
        end
        
        % 角度,距离新建点对象
        function new_obj = NewByDeg(obj,name,deg,len)
            new_obj = GeoPoint(name);
            new_obj.x = obj.x+len*cosd(deg);
            new_obj.y = obj.y+len*sind(deg);
        end

        % 重载绘图函数
        function h = plot(obj,style)
            x = obj.x;
            y = obj.y;
            if(nargin==1)
                h = plot(x,y,'o');
            elseif(nargin==2)
                h = plot(x,y,style);
            end
        end
        
        % 重载信息打印
        function disp(obj)
            fprintf('%s, x=%.2f, y=%.2f\n',obj.name,obj.x,obj.y);
        end
    end
end

在方法中,实现了plot和disp的重载,方便查看信息。

3 地理线

地理线的概念要复杂一些,包括名称,起始点,终止点,角度,长度,点距,点数,元素数组。

其中元素数组占用空间开销稍大,一般情况下可空着。前面几个属性也是相互咬合的关系,在新建对象是,要考虑到约束关系。

classdef GeoLine
    %GEOLINE Summary of this class goes here
    %   Detailed explanation goes here
    
    properties
        name
        head
        tail
        deg
        len
        space
        num
        items
    end
    
    methods
        % 构造函数
        function obj = GeoLine(name,head,tail,deg,len,space,num)
            if (nargin==0)
                obj.name = '';
                obj.head = GeoPoint;
                obj.tail = GeoPoint;
                obj.deg = nan;
                obj.len = nan;
                obj.space = nan;
                obj.num = nan;
            elseif (nargin==1)
                obj.name = name;
                obj.head = GeoPoint;
                obj.tail = GeoPoint;
                obj.deg = nan;
                obj.len = nan;
                obj.space = nan;
                obj.num = nan;
            elseif (nargin==3)
                obj.name = name;
                obj.head = head;
                obj.tail = GeoPoint;
                obj.deg = nan;
                obj.len = nan;
                obj.space = nan;
                obj.num = nan;
            elseif (nargin==4)
                obj.name = name;
                obj.head = head;
                obj.tail = tail;
                obj.deg = deg;
                obj.len = nan;
                obj.space = nan;
                obj.num = nan;
            elseif (nargin==5)
                obj.name = name;
                obj.head = head;
                obj.tail = tail;
                obj.deg = deg;
                obj.len = len;
                obj.space = nan;
                obj.num = nan;
            elseif (nargin==6)
                obj.name = name;
                obj.head = head;
                obj.tail = tail;
                obj.deg = deg;
                obj.len = len;
                obj.space = space;
                obj.num = nan;
            elseif (nargin==7)
                obj.name = name;
                obj.head = head;
                obj.tail = tail;
                obj.deg = deg;
                obj.len = len;
                obj.space = space;
                obj.num = num;
            end
        end
        
        % 从首尾点计算角度
        function obj = get_deg(obj)
            x0 = obj.head.x;
            y0 = obj.head.y;
            x1 = obj.tail.x;
            y1 = obj.tail.y;
            dx = x1-x0;
            dy = y1-y0;
            obj.deg = rad2deg(atan2(dy,dx));
        end

        % 从首尾点计算长度
        function obj = get_len(obj)
            x0 = obj.head.x;
            y0 = obj.head.y;
            x1 = obj.tail.x;
            y1 = obj.tail.y;
            dx = x1-x0;
            dy = y1-y0;
            obj.len = sqrt(dx^2+dy^2);
        end

        % 从长度和点数计算点距
        function obj = get_space(obj)
            obj.space = obj.len/(obj.num-1);
        end        
        
        % 从起点和角度、长度计算终点
        function obj = get_tail(obj)
            obj.tail = GeoPoint;
            x0 = obj.head.x;
            y0 = obj.head.y;
            obj.tail.x = x0+obj.len*cosd(obj.deg);
            obj.tail.y = y0+obj.len*sind(obj.deg);
        end
        
        % 计算测线元素
        function obj = get_items(obj,n,d)
            if (nargin==1)
                n = 1;  % 重新编号
                d = 1;  % 默认编号间隔
            elseif (nargin==2)
                d = 1;               
            end
            Items(obj.num) = GeoPoint;
            Items(1) = obj.head;
            Items(1).name = [obj.name,'-',num2str(n)];
            Items(obj.num) = obj.tail;
            Items(obj.num).name = [obj.name,'-',num2str(n+(obj.num-1)*d)];
            if(obj.num<3)
                return;
            end
            for i = 2:obj.num-1
                Items(i).name = [obj.name,'-',num2str(n+(i-1)*d)];
                Items(i).x = obj.head.x+(i-1)*obj.space*cosd(obj.deg);
                Items(i).y = obj.head.y+(i-1)*obj.space*sind(obj.deg);                
            end
            obj.items = Items;
        end
        
        function obj = remove_items(obj)
            if(isempty(obj.items))
                return;
            else
                obj.items = [];
            end
        end
        
        % 重载绘图函数
        function h = plot(obj,style)
            x(1) = obj.head.x;
            y(1) = obj.head.y;
            x(2) = obj.tail.x;
            y(2) = obj.tail.y;
            if(nargin==1)
                h = plot(x,y,'o');
            elseif(nargin==2)
                h = plot(x,y,style);
            end
        end

        % 元素绘图函数
        function h = plot_items(obj,style)
            x = zeros(obj.num,1);
            y = zeros(obj.num,1);
            for i = 1:obj.num
                x(i) = obj.items(i).x;
                y(i) = obj.items(i).y;
            end
            if(nargin==1)
                h = plot(x,y,'o');
            elseif(nargin==2)
                h = plot(x,y,style);
            end
        end        
        
        % 重载信息打印
        function disp(obj)
            fprintf('%s, O=(%.2f,%.2f), End=(%.2f,%.2f),θ=%.2f ,L=%.2f, Δ=%.2f, N=%d \n',...
                obj.name,obj.head.x,obj.head.y,obj.tail.x,...
                obj.tail.y,obj.deg,obj.len,obj.space,obj.num);
        end

        % 元素信息打印
        function disp_items(obj)
            for i = 1:obj.num
                disp(obj.items(i));
            end
        end
    end
end

这里实现了地理线的角度、长度、点距、元素的计算,以及可视化重载。地理线的首尾点,元素等用到了地理点对象。

4 应用

下面做一个简单的应用:

clc;clear;
% clear classes;

% 定义首尾两点
p1 = GeoPoint('P1',0,0);
p2 = p1.NewByDeg('P2',-100,4);

%
h1 = plot(p1,'s');
hold on;
h2 = plot(p2,'*');

% 从首尾点确定测线
np = 50;
L1 = GeoLine('L1',p1,p2,[],[],[],np);
L1.disp();

% 计算角度
L1 = L1.get_deg();
L1.disp();

% 计算长度
L1 = L1.get_len();
L1.disp();

% 计算点距
L1 = L1.get_space();
L1.disp();

% 计算元素
L1 = L1.get_items();
disp_items(L1);

% 绘制
h3 = plot(L1,'k-o');
h4 = plot_items(L1);
axis equal;

% 去除元素
L1 = L1.remove_items();
L1 = L1.get_items(100,2);

效果如下:
在这里插入图片描述
可用流程图简单讲解下:

Created with Raphaël 2.3.0 开始 用坐标定义p1 用角度,长度定义p2 绘制p1和p2 用p1、p2定义L1,同时指定点数 计算L1角度 计算L1点距 计算L1元素 绘制地理线和元素 删除元素 结束

后续,将继续考虑新建地理对象类,其中包含点和线,同时实现链表式管理。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Intimes

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值