📄 gr32_vectormaps.pas
字号:
SetSize(Width, Height);
BlockRead(MeshFile, FVectors[0], Width * Height * SizeOf(TFixedVector));
ConvertVertices;
end;
finally
CloseFile(MeshFile);
end
else Exception.Create('File not found!');
end;
procedure TVectorMap.Merge(DstLeft, DstTop: Integer; Src: TVectorMap; SrcRect: TRect);
var
I,J,P: Integer;
DstRect: TRect;
Progression: TFixedVector;
ProgressionX, ProgressionY: TFixed;
CombineCallback: TVectorCombineEvent;
DstPtr : PFixedPointArray;
SrcPtr : PFixedPoint;
begin
if Src.Empty then Exception.Create('Src is empty!');
if Empty then Exception.Create('Base is empty!');
IntersectRect( SrcRect, Src.BoundsRect, SrcRect);
DstRect.Left := DstLeft;
DstRect.Top := DstTop;
DstRect.Right := DstLeft + (SrcRect.Right - SrcRect.Left);
DstRect.Bottom := DstTop + (SrcRect.Bottom - SrcRect.Top);
IntersectRect(DstRect, BoundsRect, DstRect);
if IsRectEmpty(DstRect) then Exit;
P := SrcRect.Top * Src.Width;
Progression.Y := - FixedOne;
case Src.FVectorCombineMode of
vcmAdd:
begin
for I := DstRect.Top to DstRect.Bottom do
begin
DstPtr := @GetVectors[I * Width];
SrcPtr := @Src.GetVectors[SrcRect.Left + P];
for J := DstRect.Left to DstRect.Right do
begin
Inc(SrcPtr^.X, DstPtr[J].X);
Inc(SrcPtr^.Y, DstPtr[J].Y);
Inc(SrcPtr);
end;
Inc(P, Src.Width);
end;
end;
vcmReplace:
begin
for I := DstRect.Top to DstRect.Bottom do
begin
DstPtr := @GetVectors[I * Width];
SrcPtr := @Src.GetVectors[SrcRect.Left + P];
for J := DstRect.Left to DstRect.Right do
begin
SrcPtr^.X := DstPtr[J].X;
SrcPtr^.Y := DstPtr[J].Y;
Inc(SrcPtr);
end;
Inc(P, Src.Width);
end;
end;
else
CombineCallback := Src.FOnVectorCombine;
ProgressionX := Fixed(2 / (DstRect.Right - DstRect.Left - 1));
ProgressionY := Fixed(2 / (DstRect.Bottom - DstRect.Top - 1));
for I := DstRect.Top to DstRect.Bottom do
begin
Progression.X := - FixedOne;
DstPtr := @GetVectors[I * Width];
SrcPtr := @Src.GetVectors[SrcRect.Left + P];
for J := DstRect.Left to DstRect.Right do
begin
CombineCallback(SrcPtr^, Progression, DstPtr[J]);
Inc(SrcPtr);
Inc(Progression.X, ProgressionX);
end;
Inc(P, Src.Width);
Inc(Progression.Y, ProgressionY);
end;
end;
end;
procedure TVectorMap.SaveToFile(const FileName: string);
procedure ConvertVerticesX;
var
I: Integer;
begin
for I := 0 to Length(FVectors) - 1 do
FVectors[I] := FixedPoint(TFloatVector(FVectors[I])); //Not a mistake!
end;
procedure ConvertVerticesF;
var
I: Integer;
begin
for I := 0 to Length(FVectors) - 1 do
TFloatVector(FVectors[I]) := FloatPoint(FVectors[I]); //Not a mistake!
end;
var
Header: TPSLiquifyMeshHeader;
MeshFile: File;
Pad: Cardinal;
begin
try
AssignFile(MeshFile, FileName);
Rewrite(MeshFile, 1);
with Header do
begin
Pad0 := $02000000;
Ident := MeshIdent;
Pad1 := $00000002;
Width := Self.Width;
Height := Self.Height;
end;
BlockWrite(MeshFile, Header, SizeOf(TPSLiquifyMeshHeader));
with Header do
begin
ConvertVerticesF;
BlockWrite(MeshFile, FVectors[0], Length(FVectors) * SizeOf(TFixedVector));
ConvertVerticesX;
end;
if Odd(Length(FVectors) * SizeOf(TFixedVector) - 1) then
begin
Pad := $00000000;
BlockWrite(MeshFile, Pad, 4);
BlockWrite(MeshFile, Pad, 4);
end;
finally
CloseFile(MeshFile);
end;
end;
procedure TVectorMap.SetFloatVector(X, Y: Integer; const Point: TFloatVector);
begin
FVectors[X + Y * Width] := FixedPoint(Point);
end;
procedure TVectorMap.SetFloatVectorF(X, Y: Single; const Point: TFloatVector);
begin
SetFixedVectorX(Fixed(X), Fixed(Y), FixedPoint(Point));
end;
procedure TVectorMap.SetFloatVectorFS(X, Y: Single; const Point: TFloatVector);
begin
SetFixedVectorXS(Fixed(X), Fixed(Y), FixedPoint(Point));
end;
procedure TVectorMap.SetFloatVectorS(X, Y: Integer; const Point: TFloatVector);
begin
if (X >= 0) and (X < Width) and
(Y >= 0) and (Y < Height) then
FVectors[X + Y * Width] := FixedPoint(Point);
end;
procedure TVectorMap.SetFixedVector(X, Y: Integer; const Point: TFixedVector);
begin
FVectors[X + Y * Width] := Point;
end;
procedure TVectorMap.SetFixedVectorS(X, Y: Integer; const Point: TFixedVector);
begin
if (X >= 0) and (X < Width) and
(Y >= 0) and (Y < Height) then
FVectors[X + Y * Width] := Point;
end;
procedure TVectorMap.SetFixedVectorX(X, Y: TFixed; const Point: TFixedVector);
var
flrx, flry, celx, cely: Integer;
P: PFixedPoint;
begin
flrx := TFixedRec(X).Frac;
celx := flrx xor $FFFF;
flry := TFixedRec(Y).Frac;
cely := flry xor $FFFF;
P := @FVectors[TFixedRec(X).Int + TFixedRec(Y).Int * Width];
CombineVectorsMem(Point, P^, FixedMul(celx, cely)); Inc(P);
CombineVectorsMem(Point, P^, FixedMul(flrx, cely)); Inc(P, Width);
CombineVectorsMem(Point, P^, FixedMul(flrx, flry)); Dec(P);
CombineVectorsMem(Point, P^, FixedMul(celx, flry));
end;
procedure TVectorMap.SetFixedVectorXS(X, Y: TFixed; const Point: TFixedVector);
var
flrx, flry, celx, cely: Integer;
P: PFixedPoint;
begin
if (X < -$10000) or (Y < -$10000) then Exit;
flrx := TFixedRec(X).Frac;
X := TFixedRec(X).Int;
flry := TFixedRec(Y).Frac;
Y := TFixedRec(Y).Int;
if (X >= Width) or (Y >= Height) then Exit;
celx := flrx xor $FFFF;
cely := flry xor $FFFF;
P := @FVectors[X + Y * Width];
if (X >= 0) and (Y >= 0)then
begin
CombineVectorsMem(Point, P^, FixedMul(celx, cely) ); Inc(P);
CombineVectorsMem(Point, P^, FixedMul(flrx, cely) ); Inc(P, Width);
CombineVectorsMem(Point, P^, FixedMul(flrx, flry) ); Dec(P);
CombineVectorsMem(Point, P^, FixedMul(celx, flry) );
end
else
begin
if (X >= 0) and (Y >= 0) then CombineVectorsMem(Point, P^, FixedMul(celx, cely)); Inc(P);
if (X < Width - 1) and (Y >= 0) then CombineVectorsMem(Point, P^, FixedMul(flrx, cely)); Inc(P, Width);
if (X < Width - 1) and (Y < Height - 1) then CombineVectorsMem(Point, P^, FixedMul(flrx, flry)); Dec(P);
if (X >= 0) and (Y < Height - 1) then CombineVectorsMem(Point, P^, FixedMul(celx, flry));
end;
end;
procedure TVectorMap.SetVectorCombineMode(const Value: TVectorCombineMode);
begin
if FVectorCombineMode <> Value then
begin
FVectorCombineMode := Value;
Changed;
end;
end;
function TVectorMap.GetTrimmedBounds: TRect;
var
J: Integer;
VectorPtr : PFixedVector;
label
TopDone, BottomDone, LeftDone, RightDone;
begin
with Result do
begin
//Find Top
Top := 0;
VectorPtr := @Vectors[Top];
repeat
if Int64(VectorPtr^) <> 0 then goto TopDone;
Inc(VectorPtr);
Inc(Top);
until Top = Width * Height;
TopDone: Top := Top div Width;
//Find Bottom
Bottom := Width * Height - 1;
VectorPtr := @Vectors[Bottom];
repeat
if Int64(VectorPtr^) <> 0 then goto BottomDone;
Dec(VectorPtr);
Dec(Bottom);
until Bottom < 0;
BottomDone: Bottom := Bottom div Width - 1;
//Find Left
Left := 0;
repeat
J := Top;
repeat
if Int64(FixedVector[Left, J]) <> 0 then goto LeftDone;
Inc(J);
until J >= Bottom;
Inc(Left)
until Left >= Width;
LeftDone:
//Find Right
Right := Width - 1;
repeat
J := Bottom;
repeat
if Int64(FixedVector[Right, J]) <> 0 then goto RightDone;
Dec(J);
until J <= Top;
Dec(Right)
until Right <= Left;
end;
RightDone:
if IsRectEmpty(Result) then
Result := Rect(0,0,0,0);
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -