图形的面积计算(200分)

  • 主题发起人 主题发起人 lxj
  • 开始时间 开始时间
L

lxj

Unregistered / Unconfirmed
GUEST, unregistred user!
不规则图形(二维)的面积计算。
1、如何判别该图形是否封闭;
2、当封闭时如何计算面积;
3、不用微积分方法可以吗;
4、微积分方式如何计算,由技巧吗?
 
呵呵,图形学都快忘光了。
 
说点想法,也许是瞎说。很外行的作法。

选定两点,确认P1在图形内部,P2在外部。
以P1为源FloodFill(dc,P1.x,P1.y,color);
如果P2的颜色变了,说明是不封闭的。

if 封闭 then
逐行扫过,记下颜色为color的象素个数n。
然后与一个单位正方形(含m个象素,面积为s)一比就出来了。 即 n*s/m

如果精度要求高,图形可以画大些。
 
呵呵,不封闭 哪有内部外部,

我不懂,应该是图形学方面的知识吧
 
总得有个大体近似封闭的形状吧?如果没有,还求什么面积。:-)
 
function CreateRgnFromBmp(B: TBitmap; var RgnData: PRgnData): integer;
const
max = 10000;
var
j, i, i1: integer;
C: TFBColor;
FB: TFBitmap;
Rts: array [0..max] of TRect;
Count: integer;
begin
Result := 0;
If B.Empty Then Exit;
Count := 0;
FB := TFBitmap.Create(B.Handle);
for j := 0 to B.Height-1 do
begin
i := 0;
while i < B.Width do
begin
C := FB.Pixels[j, i];
If C.R + C.G + C.B = 0 Then
begin
i1 := i;
C := FB.Pixels[j, i1];
while C.R + C.G + C.B = 0 do
begin
{ Inc(i1);
C := FB.Pixels[j, i1];
If i1 >= B.Width Then Break;} // modify kang
Inc(i1);
If i1 >= B.Width Then Break;
C := FB.Pixels[j, i1];
end;
Rts[Count] := Rect(i, j, i1, j+1);
Inc(Count);
i := i1;
Continue;
end;
Inc(i);
end;
end;
FB.Free;
// Make Region data
Result := Count*SizeOf(TRect);
GetMem(Rgndata, SizeOf(TRgnDataHeader)+Result);
FillChar(Rgndata^, SizeOf(TRgnDataHeader)+Result, 0);
RgnData^.rdh.dwSize := SizeOf(TRgnDataHeader);
RgnData^.rdh.iType := RDH_RECTANGLES;
RgnData^.rdh.nCount := Count;
RgnData^.rdh.nRgnSize := 0;
RgnData^.rdh.rcBound := Rect(0, 0, B.Width, B.Height);
// Update New Region
Move(Rts, RgnData^.Buffer, Result);
Result := SizeOf(TRgnDataHeader)+Count*SizeOf(TRect);
end;

这是epForm的Source,此函数根据一个图形求出边界.
可能有帮助.
 
如果是不规则图形(没有解析式),就与微积分没关系(不
过借用积分的定义来逐线扫描倒也是一个方法)。
判断是否是封闭图形很简单,只要沿边缘线搜一圈即可,
但应当处理交叉的情况。
计算面积更简单:
对于点阵图像,找到边缘(可和判断封闭性同时进行)后,
数一下内部的点数即可。
对于矢量图像,理解成多边形,分成若干个三角形分别计算相加。
三角形的面积可用行列式求,保留符号,以免在“负”的三角形上出错
 
其实,图形面积计算的关键是找到好的算法判断给定点是不是在图形内部,
虽然说图形学原理很简单,但是具体实现上还是有许多技巧的。好的技巧实现
可以非常显著的加快速度。
 
[答]
const MaxPointNum = 65535;
type
PXY = ^TXY;
TXY = record // 点的数据结构
x, y: single;
end;
XYArray = array[0..MaxPointNum] of TXY;
PXYArray = ^XYArray; // 线/面的数据结构

// 积分方法求多边形/面状图形的面积
// 多边形坐标在 xys 中,点数在 nn 中
function AreaOfPolygon(xys: PXYArray; nn: integer):single;
var ii:integer;
ss: single;
begin
ss := 0;
for ii := 0 to nn-2 do
ss := ss + (xys^[ii].y+xys^[ii+1].y) * (xys^[ii].x-xys^[ii+1].x) / 2;
result := abs(ss);
end;

// 判别点(x,y)是否落在多边形内
// 多边形坐标在 xys 中,点数在 nn 中
function isPtInRegion(x, y: single; xys: PXYArray; nn: integer): boolean;
var ii, ncross : integer;
yt, x0, y0, x1, y1, x2, y2 : single;
begin
ncross := 0;
x0 := x; y0 := y;
for ii := 0 to nn-2 do begin
x1 := xys^[ii].X; y1 := xys^[ii].Y;
x2 := xys^[ii+1].X; y2 := xys^[ii+1].Y;
if((x0>=x1) and (x0<x2)) or ((x0>=x2) and (x0<x1)) then begin
yt := y1 + (x0-x1)*(y2-y1)/(x2-x1);
if yt < y0 then inc( ncross );
end;
end;
if ((ncross>0) and ((ncross mod 2) = 1)) then Result := True
else Result := FALSE;
end;
 
如果是位图

我看不仅只是求面积,你得做
边缘提取
模式识别(区分哪个图形要计算面积)
然后取面积就简单了。


如果可以量化到只有黑白两色的实心图形(黑色:图形 白色:空白),并且不用识别
,问题就简单了:
1)把位图等分为n*m个小块,n,m决定你的误差
2)判断每个小块的中间是否为黑色,把有黑色的
小块数加起来*小块的面积即可
3)精度不够就增加n,m。

 
多人接受答案了。
 

Similar threads

D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
D
回复
0
查看
911
DelphiTeacher的专栏
D
D
回复
0
查看
868
DelphiTeacher的专栏
D
后退
顶部