ここ数日は、ブロックデータに挑戦していましたが、ブロックデータクラスや回転、
倍率処理・・・どれもややこし過ぎです。ブロックデータクラスの内容がいまいち理解
できていないので、基本的なところで間違っている可能性もありますが、
とりあえず回転、倍率処理を見送り、なんとか表示できるようになりました(^^;
そこで前回のソリッド描画と斜め楕円の描画も追加してコードをまとめてみました。
※斜め楕円の描画は、旧FDelphi 16番会議室「玉石混淆みんなで作るSample蔵」
斜め楕円の描画(裏目小僧さん、凛さん)を使わせて頂きました。
※ELVがブロック図形となっています。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, ComCtrls, Clipbrd, jwwunit, jwwDraw;
type
TForm1 = class(TForm)
TreeView1: TTreeView;
Panel1: TPanel;
PaintBox1: TPaintBox;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormMouseWheelDown(Sender: TObject; Shift: TShiftState;
MousePos: TPoint; var Handled: Boolean);
procedure FormMouseWheelUp(Sender: TObject; Shift: TShiftState;
MousePos: TPoint; var Handled: Boolean);
procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure PaintBox1Paint(Sender: TObject);
procedure FormResize(Sender: TObject);
procedure TreeView1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses
Commctrl, ShlObj;
// 初期設定
procedure TForm1.FormCreate(Sender: TObject);
var
FileName: String;
WindowStyles: Integer;
begin
// TreeViewにCheckBoxを表示させます。
WindowStyles := GetWindowLong(TreeView1.Handle, GWL_STYLE);
SetWindowLong(TreeView1.Handle, GWL_STYLE, WindowStyles or TVS_CHECKBOXES);
JWWBlockList := TJWWBlockList.Create;
FileName := 'c:\jww\Aマンション平面例.jww';
JwwDataLoadFromFile(FileName);
SetLayerName(TreeView1);
JWWDataDraw(PaintBox1);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
JWWBlockList.Free;
end;
procedure TForm1.FormResize(Sender: TObject);
begin
JWWDataDraw(PaintBox1);
end;
procedure TForm1.FormMouseWheelDown(Sender: TObject; Shift: TShiftState;
MousePos: TPoint; var Handled: Boolean);
begin
if ((MousePos.X > 0) and (MousePos.X < PaintBox1.Width)) and
((MousePos.Y > 0) and (MousePos.Y < PaintBox1.Height)) then
begin
Handled := True; // TreeView1とPaintBox1を独立してスクロール処理させるために必要
ZoomUp(PaintBox1.Canvas);
end;
end;
procedure TForm1.FormMouseWheelUp(Sender: TObject; Shift: TShiftState;
MousePos: TPoint; var Handled: Boolean);
begin
if ((MousePos.x > PaintBox1.Left) and (MousePos.x < PaintBox1.Left + PaintBox1.Width)) and
((MousePos.y > PaintBox1.Top) and (MousePos.y < PaintBox1.Top + PaintBox1.Height))
then
begin
Handled := True; // TreeView1とPaintBox1を独立してスクロール処理させるために必要
ZoomDown(PaintBox1.Canvas);
end;
end;
procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if not CanDraw then Exit;
if (ssLeft in Shift) or (ssRight in Shift) then
begin
DraggingNow := True;
RubberBandShow := False;
DragStartPoint := Point(X,Y);
DragEndPoint := Point(0,0);
if (ssLeft in Shift) then DragEndPoint.X := 1;
if (ssRight in Shift) then DragEndPoint.Y := 1;
end;
end;
procedure TForm1.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if DraggingNow then
begin
if RubberBandShow then
RubberBand(PaintBox1.Canvas, DragStartPoint, DragEndPoint);
if (ssLeft in Shift) and (ssRight in Shift) then
begin
DragEndPoint := Point(X,Y);
RubberBand(PaintBox1.Canvas, DragStartPoint, DragEndPoint);
RubberBandShow := True;
end
else
begin
RubberBandShow := False;
if (ssLeft in Shift) then DragEndPoint.X := 1;
if (ssRight in Shift) then DragEndPoint.Y := 1;
end;
end
end;
procedure TForm1.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
function GetDragModeKind: Integer;
begin
if (Abs(DragStartPoint.X - X) <= 5) and (Abs(DragStartPoint.Y - Y) <= 5) then
Result := 0 // 移動
else
begin
if (DragStartPoint.X <= X) then
Result := 1 // 拡大
else
Result := 2; // 縮小
end;
end;
var
x1, y1, x2, y2: Double;
cx, cy: Double;
dx, dy: Double;
bx, by: Double;
P1, P2: Double;
begin
if (not RubberBandShow) and ((DragEndPoint.X = 0) or (DragEndPoint.Y = 0)) then
begin
DraggingNow := False;
Exit;
end;
if DraggingNow then
begin
DraggingNow := False;
if RubberBandShow then
RubberBand(PaintBox1.Canvas, DragStartPoint, DragEndPoint);
DragModeKind := GetDragModeKind;
x1 := ViewArea.Left + (DragStartPoint.X / mm_dot); // ドラッグ開始位置の左上X座標
y1 := ViewArea.Bottom - (DragStartPoint.Y / mm_dot); // ドラッグ開始位置の左下Y座標
x2 := ViewArea.Left + (X / mm_dot); // ドラッグ終了位置の左上X座標
y2 := ViewArea.Bottom - (Y / mm_dot); // ドラッグ終了位置の左下Y座標
dx := Abs(ViewArea.Right - ViewArea.Left); // ビューの幅
dy := Abs(ViewArea.Bottom - ViewArea.Top ); // ビューの高さ
bx := Abs(x1 - x2); // 長方形の大きさ X
by := Abs(y1 - y2); // 長方形の大きさ Y
cx := (x1 + x2) / 2.0; // 長方形の中央の座標 X
cy := (y1 + y2) / 2.0; // 長方形の中央の座標 Y
case (DragModeKind) of
0: begin
// 移動
cx := (ViewArea.Left + ViewArea.Right ) / 2.0; // 現在のビューの中心座標 X
cy := (ViewArea.Top + ViewArea.Bottom) / 2.0; // 現在のビューの中心座標 Y
dx := x2 - cx; // 移動量
dy := y2 - cy; // 移動量
ViewArea.Left := ViewArea.Left + dx; // 移動計算
ViewArea.Top := ViewArea.Top + dy; // 移動計算
ViewArea.Right := ViewArea.Right + dx; // 移動計算
ViewArea.Bottom := ViewArea.Bottom + dy; // 移動計算
end;
1: begin
// 拡大
if (bx < 0.000001) then bx:=0.000001;
if (by < 0.000001) then by:=0.000001;
P1 := dx / bx;
P2 := dy / by;
if (P1 < P2) then
mm_dot := mm_dot * P1
else
mm_dot := mm_dot * P2;
ViewArea.Left := cx - ((ImageSize.Width / 2.0) / mm_dot);
ViewArea.Top := cy - ((ImageSize.Height / 2.0) / mm_dot);
ViewArea.Right := cx + ((ImageSize.Width / 2.0) / mm_dot);
ViewArea.Bottom := cy + ((ImageSize.Height / 2.0) / mm_dot);
end;
2: begin
// 縮小
P1 := bx / dx;
P2 := by / dy;
if (P1 > P2) then
mm_dot := mm_dot * P1
else
mm_dot := mm_dot * P2;
ViewArea.Left := cx - ((ImageSize.Width / 2.0) / mm_dot);
ViewArea.Top := cy - ((ImageSize.Height / 2.0) / mm_dot);
ViewArea.Right := cx + ((ImageSize.Width / 2.0) / mm_dot);
ViewArea.Bottom := cy + ((ImageSize.Height / 2.0) / mm_dot);
end;
end;
DrawData(PaintBox1.Canvas);
end
end;
procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
DrawData(PaintBox1.Canvas);
end;
// TreeViewのチェックボックス処理
procedure TForm1.TreeView1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
HitTest: TTVHitTestInfo;
Node: TTreeNode;
I, J, K: Integer;
begin
// クリックした位置のノードを取得します。
Node := TreeView1.GetNodeAt(X, Y);
if Node = nil then Exit;
HitTest.pt.x := X;
HitTest.pt.y := Y;
TreeView_HitTest(TreeView1.Handle, HitTest);
if (HitTest.flags = TVHT_ONITEMSTATEICON) then
begin
if TreeView_GetCheckState(TreeView1.Handle, Node.ItemId) > 0 then
K := 1
else
K := 0;
if Node.Level = 0 then
begin
I := Node.AbsoluteIndex mod 16;
JWWHd.GLay[I].m_anGLay := K;
end
else
begin
I := Node.Parent.AbsoluteIndex mod 16;
J := Node.Index;
JWWHd.GLay[I].m_nLay[J].m_aanLay := K;
end;
PaintBox1.Invalidate;
end;
end;
end.
描画のユニットです。
unit jwwDraw;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, ComCtrls, jwwunit, Math;
type
TPointEx = packed record
X: Double;
Y: Double;
end;
TRectEx = packed record
case Integer of
0: (Left, Top, Right, Bottom: Double);
1: (TopLeft, BottomRight: TPointEx);
end;
TSize = packed record
Height: Integer;
Width: Integer;
end;
TSizeEx = packed record
Height: Double;
Width: Double;
end;
var
OriginPoint: TPoint; // 原点
ImageSize: TSize; // 画面ドットサイズ
PaperSize: TSizeEx; // 用紙サイズ
mm_dot: Double; // mm_dot比
ViewArea: TRectEx; // ビューエリア
DragStartPoint: TPoint; // ドラッグ開始点
DragEndPoint: TPoint; // ドラッグ終了点
DragModeKind : Integer; // ドラッグモード 0:移動 1:拡大 2:縮小
DraggingNow : Boolean; // ドラッグ中かどうかのフラグ
RubberBandShow : Boolean; // ラバーバンド表示フラグ
CanDraw: Boolean; // 描画可能かどうかのフラグ
function PointEx(X, Y: Double): TPointEx; // PointEx型を作成します。
procedure JWWDataDraw(APaintBox: TPaintBox);
procedure DrawData(ACanvas: TCanvas); // 図面の描画
procedure SetPaperSize(Size: Integer); // 用紙サイズの設定
procedure ZoomUp(ACanvas: TCanvas); // 拡大
procedure ZoomDown(ACanvas: TCanvas); // 縮小
procedure RubberBand(ACanvas: TCanvas; P1, P2: TPoint); // ラバーバンドの描画
procedure SetLayerName(ATreeView: TTreeView); // レイヤー名及び表示/非表示の設定
procedure JwwDataLoadFromFile(FileName: String);
implementation
uses
Commctrl, ShlObj;
const
TVIS_CHECKED = $2000;
procedure JwwDataLoadFromFile(FileName: String);
begin
DraggingNow := False;
RubberBandShow := False;
jwwRead(FileName);
SetPaperSize(JWWHd.m_nZumen);
CanDraw := True;
mm_dot := 0;
end;
function PointEx(X, Y: Double): TPointEx;
begin
Result.X := X;
Result.Y := Y;
end;
// ラバーバンド長方形描画
procedure RubberBand(ACanvas: TCanvas; P1, P2: TPoint);
begin
ACanvas.Pen.Mode := pmXor;
ACanvas.Pen.Color := clAqua;
ACanvas.Pen.Width := 0;
ACanvas.Pen.Style := psSolid;
ACanvas.Brush.Style := bsClear;
ACanvas.Rectangle(P1.X, P1.Y, P2.X, P2.Y);
end;
// 用紙サイズの設定
procedure SetPaperSize(Size: Integer);
begin
case Size of
0: begin // A0
PaperSize.Width :=1189;
PaperSize.Height := 841;
end;
1: begin // A1
PaperSize.Width := 841;
PaperSize.Height := 594;
end;
2: begin // A2
PaperSize.Width := 594;
PaperSize.Height := 420;
end;
3: begin // A3
PaperSize.Width := 420;
PaperSize.Height := 297;
end;
4: begin // A4
PaperSize.Width := 297;
PaperSize.Height := 210;
end;
else
PaperSize.Width :=1189;
PaperSize.Height := 841;
end;
end;
// JWWデータを描画します。
procedure JWWDataDraw(APaintBox: TPaintBox);
procedure Calc_mm_dot;
var
P1, P2: Double;
begin
ImageSize.Width := APaintBox.Width;
ImageSize.Height := APaintBox.Height;
P1 := ImageSize.Width / PaperSize.Width;
P2 := ImageSize.Height / PaperSize.Height;
if mm_dot = 0 then
begin
if (P1 < P2) then
mm_dot := P1
else
mm_dot := P2;
end;
end;
procedure Calc_ViewArea;
begin
ViewArea.Left := - (ImageSize.Width / 2.0) / mm_dot;
ViewArea.Top := - (ImageSize.Height / 2.0) / mm_dot;
ViewArea.Right := (ImageSize.Width / 2.0) / mm_dot;
ViewArea.Bottom := (ImageSize.Height / 2.0) / mm_dot;
end;
begin
if not CanDraw then Exit;
Calc_mm_dot;
Calc_ViewArea;
APaintBox.Invalidate;
end;
// CADデータの描画
procedure DrawData(ACanvas: TCanvas);
// 画面の消去
procedure CLS;
begin
ACanvas.Pen.Mode := pmCopy;
ACanvas.Pen.Color := clWhite;
ACanvas.Pen.Style := psSolid;
ACanvas.Pen.Width := 1;
ACanvas.Brush.Color := clWhite;
ACanvas.Brush.Style := bsSolid;
ACanvas.Rectangle(0, 0, ImageSize.Width, ImageSize.Height);
end;
// 用紙枠の描画
procedure Draw_Paper_Frame;
var
ARect: TRect;
begin
// 原点の計算
OriginPoint.X := Round( (0.0 - ViewArea.Left ) * mm_dot);
OriginPoint.Y := Round(-(0.0 - ViewArea.Bottom) * mm_dot);
// 用紙枠の描画
ARect.Left := Round( (-PaperSize.Width / 2 - ViewArea.Left ) * mm_dot);
ARect.Top := Round(-(-PaperSize.Height/ 2 - ViewArea.Bottom) * mm_dot);
ARect.Right := Round( ( PaperSize.Width / 2 - ViewArea.Left ) * mm_dot);
ARect.Bottom := Round(-( PaperSize.Height/ 2 - ViewArea.Bottom) * mm_dot);
ACanvas.Pen.Color := clBlue;
ACanvas.Brush.Style := bsClear;
ACanvas.Rectangle(ARect);
end;
// 座標を変換
procedure Change_mm_dot_Point(PEx: TPointEx; var P: TPoint);
begin
P.x := Round( PEx.x * mm_dot + OriginPoint.X );
P.y := Round(-PEx.y * mm_dot + OriginPoint.Y );
end;
// 線及び円弧の線種・線色の設定
procedure LineSetting(Root: CData);
begin
ACanvas.Pen.Width := 0;
case Root.m_nPenStyle of
1: ACanvas.Pen.Style := psSolid;
2,3,4,9: ACanvas.Pen.Style := psDot;
5,6,7,8: ACanvas.Pen.Style := psDashDot;
end;
case Root.m_nPenColor of
1: ACanvas.Pen.Color := RGB(0,192,192);
2: ACanvas.Pen.Color := clBlack;
3: ACanvas.Pen.Color := RGB(0,192,0);
4: ACanvas.Pen.Color := RGB(192,192,0);
5: ACanvas.Pen.Color := RGB(192,0,192);
6: ACanvas.Pen.Color := RGB(0,0,255);
7: ACanvas.Pen.Color := RGB(0,128,128);
8: ACanvas.Pen.Color := RGB(255,0,128);
9: ACanvas.Pen.Color := RGB(255,128,255);
end;
end;
// フォントの設定
function FontSetting(ACDataMoji: CDataMoji): Boolean;
var
I: Integer;
begin
Result := True;
ACanvas.Font.Name := ACDataMoji.m_strFontName;
ACanvas.Font.Height := Round(ACDataMoji.m_dSizeY * mm_dot);
if ACanvas.Font.Height = 0 then
begin
Result := False;
Exit;
end;
// フォントのスタイルの設定
I := ACDataMoji.m_nMojiShu;
if I >= 30000 then // ボールド + 斜体文字
begin
ACanvas.Font.Style := [fsBold,fsItalic];
I := I - 30000
end
else if I >= 20000 then // ボールド
begin
ACanvas.Font.Style := [fsBold];
I := I -20000
end
else if I >= 10000 then // 斜体文字
begin
ACanvas.Font.Style := [fsItalic];
I := I -10000;
end
else
ACanvas.Font.Style := [];
// フォントの色の設定
case JWWHd.m_Moji[I].m_anMojiCol of
1: ACanvas.Font.Color := RGB(0,192,192);
2: ACanvas.Font.Color := clBlack;
3: ACanvas.Font.Color := RGB(0,192,0);
4: ACanvas.Font.Color := RGB(192,192,0);
5: ACanvas.Font.Color := RGB(192,0,192);
6: ACanvas.Font.Color := RGB(0,0,255);
7: ACanvas.Font.Color := RGB(0,128,128);
8: ACanvas.Font.Color := RGB(255,0,128);
9: ACanvas.Font.Color := RGB(255,128,255);
10: ACanvas.Font.Color := clBlack; // 不明
end;
end;
// レイヤーの表示/非表示
function LayerCheck(Root: CData): Boolean;
var
I, J: Integer;
F1, F2: Boolean;
begin
I := Root.m_nGLayer;
J := Root.m_nLayer;
F1 := JWWHd.GLay[I].m_anGLay <> 0;
F2 := JWWHd.GLay[I].m_nLay[J].m_aanLay <> 0;
Result := F1 and F2;
end;
// 補助線かどうか
function IsSupportLine(Root: CData): Boolean;
begin
Result := (Root.m_nPenStyle = 9);
end;
// 線の描画
procedure DrawSen(Sen: CDataSen);
var
P1, P2: TPoint;
begin
if (not IsSupportLine(Sen.Root)) and LayerCheck(Sen.Root) then
begin
Change_mm_dot_Point(PointEx(Sen.m_start_x, Sen.m_start_y), P1);
Change_mm_dot_Point(PointEx(Sen.m_end_x , Sen.m_end_y ), P2);
LineSetting(Sen.Root);
ACanvas.MoveTo(P1.X, P1.Y);
ACanvas.LineTo(P2.X, P2.Y);
end;
end;
{ 旧FDelphi 玉石混淆みんなで作るSample蔵「斜め楕円の描画 」 }
// 凛さん、裏目小僧さんのコード
procedure Ellipse2(Center: TPoint; LongRadius, ShortRadius, Angle,
angleFrom, angleTo: Extended);
function rot(x,y: Extended; rad: Extended):TPointEx;//rad:radian
var
ss, cc: Extended;
begin
ss := sin(rad);
cc := cos(rad);
Result.x := cc*x-ss*y;
Result.y := ss*x+cc*y;
end;
procedure drawDeclinedEllipsePP(aFrom, aTo: Extended);
var
I: Integer;
bufP: array[0..3] of TPointEx;
thePoints:array[0..3] of TPoint;
s,c,xc,yc,fa: Extended;
begin
fa := aTo-aFrom;
s := sin(fa);
c := cos(fa);
xc := cos(fa/2);
yc := sin(fa/2);
bufP[0].x := 1;
bufP[0].y := 0;
bufP[1].x := 1;
bufP[1].y := -4*c*(1+c-2*xc)/s/3+4*(2*yc-s)/3;
bufP[2].x := (-4-c+8*xc)/3;
bufP[2].y := 4*c*(1+c-2*xc)/s/3+s;
bufP[3].x := c;
bufP[3].y := s;
for I:= 0 to 3 do
begin
bufP[I]:=rot(BufP[I].x,bufP[I].y,aFrom);
bufP[I]:=rot(LongRadius*BufP[I].x,shortRadius*BufP[I].y,angle);
thePoints[I].x:=round(bufP[I].x + Center.X);
thePoints[I].y:=round(bufP[I].y + Center.Y);
end;
PolyBezier(ACanvas.Handle, thePoints, 4);
end;
const
Err=0.001;
var
sep, I: Integer;
division: Extended;
begin
division := PI/3;
sep := Trunc((AngleTo-AngleFrom)/division);
for I := 0 to sep-1 do
drawDeclinedEllipsePP(angleFrom+ I*division, angleFrom+(I+1)*division);
if (AngleTo-AngleFrom)-(sep*division) > Err then
drawDeclinedEllipsePP(angleFrom+sep*division, angleTo);
end;
// 円弧の描画
procedure DrawEnko(Enko: CDataEnko; IsSolid: Boolean=False);
var
Center: TPointEx;
x1, y1, Hankei: Double;
LongRadius, ShortRadius: Double;
Hajime, Owari, Inclination: Double;
PEx1, PEx2: TPointEx;
P1, P2, P3,P4: TPoint;
begin
Hajime := Enko.m_radKaishiKaku + Enko.m_radKatamukiKaku;
Owari := Enko.m_radKaishiKaku + Enko.m_radEnkoKaku +
Enko.m_radKatamukiKaku;
if (not IsSupportLine(Enko.Root)) and LayerCheck(Enko.Root) then
begin
x1 := Enko.m_start_x;
y1 := Enko.m_start_y;
Center.X := X1;
Center.Y := Y1;
Hankei := Enko.m_dHankei;
if Enko.m_radKatamukiKaku < 0 then
begin
PEx1.X := X1-Hankei * Enko.m_dHenpeiRitsu;
PEx1.Y := Y1-Hankei;
PEx2.X := X1+Hankei * Enko.m_dHenpeiRitsu;
PEx2.Y := Y1+Hankei;
end
else
begin
PEx1.X := X1-Hankei;
PEx1.Y := Y1-Hankei*Enko.m_dHenpeiRitsu;
PEx2.X := X1+Hankei;
PEx2.Y := Y1+Hankei*Enko.m_dHenpeiRitsu;
end;
// 円弧の設定
LineSetting(Enko.Root);
// mm→dot変換
Change_mm_dot_Point(PEx1, P1);
Change_mm_dot_Point(PEx2, P2);
// ソリッドかどうか
if IsSolid then
ACanvas.Brush.Style := bsSolid
else
ACanvas.Brush.Style := bsClear;
// 円弧の描画
if Enko.m_bZenEnFlg = 1 then // 円・楕円の場合
begin
begin
if Enko.m_radKatamukiKaku = 0 then
begin
// 斜め描画しない
// 円(楕円)・全円(全楕円)ソリッド
ACanvas.Ellipse(P1.X,P1.Y,P2.X,P2.Y);
end
else
begin
// 斜め描画する
Change_mm_dot_Point(Center, P3);
if Enko.m_radKatamukiKaku < 0 then
Inclination := (PI /2) - Enko.m_radKatamukiKaku
else
Inclination := - Enko.m_radKatamukiKaku;
LongRadius := (P2.X-P1.X) div 2;
ShortRadius := (P2.Y-P1.Y) div 2;
Hajime := DegToRad(0);
Owari := DegToRad(360);
Ellipse2(P3, LongRadius, ShortRadius, Inclination, Hajime, Owari);
end;
end;
end
else
begin
// 楕円弧の場合
if Enko.m_dHenpeiRitsu <> 1.0 then
begin
Change_mm_dot_Point(Center, P3);
if Enko.m_radKatamukiKaku < 0 then
Inclination := (PI /2) - Enko.m_radKatamukiKaku
else
Inclination := -Enko.m_radKatamukiKaku;
LongRadius := (P2.X-P1.X) div 2;
ShortRadius := (P2.Y-P1.Y) div 2;
Hajime := (Inclination+Enko.m_radKatamukiKaku+Enko.m_radKaishiKaku);
Owari := (Inclination+Enko.m_radKatamukiKaku+Enko.m_radKaishiKaku +
Enko.m_radEnkoKaku);
Ellipse2(P3, LongRadius, ShortRadius, Inclination, Hajime, Owari);
end
else
begin
// 円弧
P3.X := Round( ((x1+Hankei*Cos(Hajime)))*MM_dot+OriginPoint.X);
P3.Y := Round(-((y1+Hankei*Sin(Hajime)))*MM_dot+OriginPoint.Y);
P4.X := Round( ((x1+Hankei*Cos(Owari )))*MM_dot+OriginPoint.X);
P4.Y := Round(-((y1+Hankei*Sin(Owari )))*MM_dot+OriginPoint.Y);
if (P3.X <> P4.X) or (P3.Y <> P4.Y) then
begin
if (Enko.m_radEnkoKaku < 0) then
SetArcDirection(ACanvas.Handle, AD_CLOCKWISE) // 時計回り
else
SetArcDirection(ACanvas.Handle, AD_COUNTERCLOCKWISE); // 反時計回り
if Enko.m_bZenEnFlg = 0 then
ACanvas.Arc(P1.X,P1.Y,P2.X,P2.Y,P3.X,P3.Y,P4.X,P4.Y) // 円弧
else if Enko.m_bZenEnFlg = 2 then
ACanvas.Chord(P1.X,P1.Y,P2.X,P2.Y,P3.X,P3.Y,P4.X,P4.Y) // 弓形ソリッド
else if Enko.m_bZenEnFlg = 3 then
ACanvas.Pie(P1.X,P1.Y,P2.X,P2.Y,P3.X,P3.Y,P4.X,P4.Y); // 扇形ソリッド
end;
end;
end;
end;
end;
// ソリッド図形の描画
procedure DrawSolid(Solid: CDataSolid);
var
poly: array[0..3] of TPoint;
Enko: CDataEnko;
begin
if LayerCheck(Solid.Root) then
begin
if Solid.Root.m_nPenStyle > 100 then
begin
if Solid.Root.m_nPenStyle = 101 then
begin
//円のソリッド
Enko.Root := Solid.Root;
Enko.m_start_x := Solid.m_start_x;
Enko.m_start_y := Solid.m_start_y;
Enko.m_dHankei := Solid.m_end_x;
Enko.m_radKaishiKaku := Solid.m_DPoint2_y;
Enko.m_radEnkoKaku := Solid.m_DPoint3_x;
Enko.m_radKatamukiKaku := Solid.m_DPoint2_x;
Enko.m_dHenpeiRitsu := Solid.m_end_y;
ACanvas.Pen.Color := Solid.m_Color;
ACanvas.Brush.Color := ACanvas.Pen.Color;
if Solid.m_DPoint3_y = 100 then
Enko.m_bZenEnFlg := 1 // 全円ソリッド
else if Solid.m_DPoint3_y = 5 then
Enko.m_bZenEnFlg := 2 // 弓形ソリッド ※2は適当
else if Solid.m_DPoint3_y = 0 then
Enko.m_bZenEnFlg := 3 // 扇形ソリッド ※3は適当
else if Solid.m_DPoint3_y = -1 then
Enko.m_bZenEnFlg := 4 // 外側円弧ソリッド・・・どんな処理?
else
Enko.m_bZenEnFlg := 10; // 処理しない ※10は適当
if Enko.m_bZenEnFlg < 10 then
DrawEnko(Enko, True);
end
else if Solid.Root.m_nPenStyle = 101 then
begin
//円環ソリッド・・・どんな処理?
end
else if Solid.Root.m_nPenStyle = 111 then
begin
//円周ソリッド・・・どんな処理?
end;
end
else
begin
/// 線のソリッド
// mm→dot変換
Change_mm_dot_Point(PointEx(Solid.m_start_x , Solid.m_start_y ), Poly[0]);
Change_mm_dot_Point(PointEx(Solid.m_end_x , Solid.m_end_y ), Poly[1]);
Change_mm_dot_Point(PointEx(Solid.m_DPoint2_x, Solid.m_DPoint2_y), Poly[2]);
Change_mm_dot_Point(PointEx(Solid.m_DPoint3_x, Solid.m_DPoint3_y), Poly[3]);
ACanvas.Pen.Color := Solid.m_Color;
ACanvas.Brush.Color := ACanvas.Pen.Color;
ACanvas.Polygon(poly);
end;
end;
end;
// 文字の描画
procedure DrawMoji(Moji: CDataMoji);
var
S: String;
LF: TLogFont;
P1, P2: TPoint;
begin
if LayerCheck(Moji.Root) then
begin
S := Moji.m_string;
// mm→dot変換
Change_mm_dot_Point(PointEx(Moji.m_start_x, Moji.m_start_y), P1);
Change_mm_dot_Point(PointEx(Moji.m_end_x , Moji.m_end_y ), P2);
// フォントの設定
if FontSetting(Moji) then
begin
// 文字の描画
GetObject(ACanvas.Font.Handle, SizeOf(LF), @LF);
SetTextAlign(ACanvas.Handle,TA_LEFT or TA_BOTTOM);
LF.lfEscapement := Round(Moji.m_degKakudo*10);
ACanvas.Font.Handle := CreateFontIndirect(LF);
ACanvas.TextOut(P1.X, P1.Y, S);
end;
end;
end;
// ブロック図形の描画---回転や倍率は未対応です。
// いまいち理解できていないので、間違った処理かも??
var
x1, y1: Double;
procedure DrawBlock(CDB: CDataBlock);
var
I,J: Integer;
Sen1: CDataSen;
Enko1: CDataEnko;
Moji1: CDataMoji;
Solid1: CDataSolid;
begin
I := CDB.m_n_Number;
x1 := CDB.m_DPKijunTen_x+x1;
y1 := CDB.m_DPKijunTen_y+y1;
for J := JWWBlockList.BlockList[I].Count-1 downto 0 do
begin
case JWWBlockList.DataType[I,J] of
Sen: begin
Sen1 := JWWBlockList.DataSen[I,J];
Sen1.m_start_x := Sen1.m_start_x+x1;
Sen1.m_start_y := Sen1.m_start_y+y1;
Sen1.m_end_x := Sen1.m_end_x +x1;
Sen1.m_end_y := Sen1.m_end_y +y1;
DrawSen(Sen1);
end;
Enko: begin
Enko1 := JWWBlockList.DataEnko[I,J];
Enko1.m_start_x := Enko1.m_start_x+x1;
Enko1.m_start_y := Enko1.m_start_y+y1;
DrawEnko(Enko1);
end;
Moji: begin
Moji1 := JWWBlockList.DataMoji[I,J];
Moji1.m_start_x := Moji1.m_start_x+x1;
Moji1.m_start_y := Moji1.m_start_y+y1;
DrawMoji(Moji1);
end;
Solid: begin
Solid1 := JWWBlockList.DataSolid[I,J];
Solid1.m_start_x := Solid1.m_start_x+x1;
Solid1.m_start_y := Solid1.m_start_y+y1;
Solid1.m_end_x := Solid1.m_end_x+x1;
Solid1.m_end_y := Solid1.m_end_y+y1;
Solid1.m_DPoint2_x := Solid1.m_DPoint2_x+x1;
Solid1.m_DPoint2_y := Solid1.m_DPoint2_y+y1;
Solid1.m_DPoint3_x := Solid1.m_DPoint3_x+x1;
Solid1.m_DPoint3_y := Solid1.m_DPoint3_y+y1;
DrawSolid(Solid1);
end;
Block: begin
DrawBlock(JWWBlockList.DataBlock[I,J]);
end;
end;
end;
end;
var
I: Integer;
begin
// 画面の消去
CLS;
// 用紙枠の描画
Draw_Paper_Frame;
// 線の描画
for I := Low(JWWSen) to High(JWWSen) do
DrawSen(JWWSen[I]);
// 円弧の描画
for I := Low(JWWEnko) to High(JWWEnko) do
DrawEnko(JWWEnko[I]);
// 文字の描画
for I := Low(JWWMoji) to High(JWWMoji) do
DrawMoji(JWWMoji[I]);
// ソリッド図形
for I := Low(JWWSolid) to High(JWWSolid) do
DrawSolid(JWWSolid[I]);
// ブロックデータの描画
for I:= Low(JWWBlock) to High(JWWBlock) do
begin
x1:= 0; y1 := 0;
DrawBlock(JWWBlock[I]);
end;
end;
// ビュー中央の座標、ビューの幅、高さを取得
procedure GetViewInfo(var View_CenterPoint: TPointEx;
var View_Width, View_Height: Double);
begin
View_CenterPoint.X := (ViewArea.Left + ViewArea.Right) / 2.0;
View_CenterPoint.Y := (ViewArea.Top + ViewArea.Bottom) / 2.0;
View_Width := Abs(ViewArea.Right - ViewArea.Left);
View_Height := Abs(ViewArea.Bottom - ViewArea.Top);
end;
// 用紙枠の描画サイズ
procedure GetPaperFrameDrawSize(var ARect: TRect;
AView_x1, AView_y1, Amm_dot: Double);
begin
ARect.Left := Round( (-PaperSize.Width /2.0 - AView_x1) * Amm_dot);
ARect.Bottom := Round(-(-PaperSize.Height/2.0 - AView_y1) * Amm_dot);
ARect.Right := Round( ( PaperSize.Width /2.0 - AView_x1) * Amm_dot);
ARect.Top := Round(-( PaperSize.Height/2.0 - AView_y1) * Amm_dot);
end;
// 拡大
procedure ZoomUp(ACanvas: TCanvas);
var
View_Width, View_Height: Double;
View_CenterPoint: TPointEx;
// 一定以上大きくさせない。
function LargeCheck: Boolean;
const
Max = 80000;
var
Check_mm_dot, Check_view_x1, Check_view_y1: Double;
ARect: TRect;
begin
Result := False;
//2倍に拡大
Check_mm_dot := mm_dot * 2.0;
Check_view_x1 := View_CenterPoint.x - (View_Width / 4.0);
Check_view_y1 := View_CenterPoint.y + (View_Height / 4.0);
// 用紙枠の描画サイズ
GetPaperFrameDrawSize(ARect,Check_view_x1,Check_view_y1,Check_mm_dot);
if (ARect.Right-ARect.Left > Max) or (ARect.Bottom- ARect.Top >Max) then Exit;
Result := True;
end;
begin
// ビュー中央の座標、ビューの幅、高さを取得
GetViewInfo(View_CenterPoint, View_Width, View_Height);
// 一定以上拡大させない。
if not LargeCheck then Exit;
//2倍に拡大
mm_dot := mm_dot * 2.0;
ViewArea.Left := View_CenterPoint.X - (View_Width /4.0);
ViewArea.Top := View_CenterPoint.Y - (View_Height/4.0);
ViewArea.Right := View_CenterPoint.X + (View_Width /4.0);
ViewArea.Bottom := View_CenterPoint.Y + (View_Height/4.0);
DrawData(ACanvas);
end;
// 縮小
procedure ZoomDown(ACanvas: TCanvas);
var
View_Width, View_Height: Double;
View_CenterPoint: TPointEx;
// 一定以上縮小させない。
function SmallCheck: Boolean;
const
Min = 10;
var
Check_mm_dot, Check_view_x1, Check_view_y1: Double;
ARect: TRect;
begin
Result := False;
// 1/2倍に縮小
Check_mm_dot := mm_dot * 0.5;
Check_view_x1 := View_CenterPoint.X - View_Width;
Check_view_y1 := View_CenterPoint.Y + View_Height;
// 用紙枠の描画サイズ
GetPaperFrameDrawSize(ARect,Check_view_x1,Check_view_y1,Check_mm_dot);
if (ARect.Right-ARect.Left < Min) or (ARect.Bottom-ARect.Top <Min) then Exit;
Result := True;
end;
begin
// ビュー中央の座標、ビューの幅、高さを取得
GetViewInfo(View_CenterPoint, View_Width, View_Height);
// 一定以上縮小させない。
if not SmallCheck then Exit;
// 1/2倍に縮小
mm_dot := mm_dot * 0.5;
ViewArea.Left := View_CenterPoint.X - View_Width;
ViewArea.Top := View_CenterPoint.Y - View_Height;
ViewArea.Right := View_CenterPoint.X + View_Width;
ViewArea.Bottom := View_CenterPoint.Y + View_Height;
DrawData(ACanvas);
end;
// レイヤー名及び表示/非表示の設定
procedure SetLayerName(ATreeView: TTreeView);
// ノードのチェックボックス設定
procedure NodeCheckBox(Node: TTreeNode; F: Boolean);
var
TvItem: TTVItem;
begin
TvItem.hItem := Node.ItemId;
TvItem.stateMask := TVIS_STATEIMAGEMASK;
TvItem.mask := TVIF_HANDLE or TVIF_STATE;
if F then
TvItem.state := TVIS_CHECKED
else
TvItem.state := TVIS_CHECKED shr 1;
TreeView_SetItem(ATreeView.Handle, TvItem);
end;
// 太字設定
procedure SetBold(Node: TTreeNode);
var
TvItem: TTVItem;
begin
TvItem.hItem := Node.ItemId;
TvItem.stateMask := TVIS_BOLD;
TvItem.mask := TVIF_HANDLE or TVIF_STATE;
TvItem.state := TVIS_BOLD;
TreeView_SetItem(ATreeView.Handle, TvItem);
end;
var
I, J, K, SNo, ENo: Integer;
NodeA, NodeB: TTreeNode;
LayerNo, Scale, LayerName: String;
F: Boolean;
begin
ATreeView.Items.BeginUpdate;
try
ATreeView.Items.Clear;
// レイヤーグループの設定
for I := Low(JWWHd.m_aStrGLayName) to High(JWWHd.m_aStrGLayName) do
begin
// レイヤーグループ番号
LayerNo := '[' + IntToHex(I, 1) +'] ';
// 縮尺
if JWWHd.GLay[I].m_adScale < 1 then
Scale := IntToStr(Round(1 / JWWHd.GLay[I].m_adScale)) + '/1'
else
Scale := '1/'+ IntToStr(Trunc(JWWHd.GLay[I].m_adScale));
// レイヤーグループ名
LayerName := ' ' + JWWHd.m_aStrGLayName[I];
// ノードの追加及び表示/非表示の設定
NodeA := ATreeView.Items.Add(nil, LayerNo + Scale + LayerName);
F := JWWHd.GLay[I].m_anGLay <> 0;
NodeCheckBox(NodeA, F);
SetBold(NodeA);
// レイヤーの設定
SNo := I * 16; // 読み取り開始番号
ENo := SNo + 15; // 読み取り終了番号
for J := SNo to ENo do
begin
K := J - SNo;
LayerNo := '[' + IntToHex(K, 1) +'] '; // レイヤーグループ番号
LayerName := ' ' + JWWHd.m_aStrLayName[J]; // レイヤー名
// ノードの追加及び表示/非表示の設定
NodeB := ATreeView.Items.AddChild(NodeA, LayerNo + LayerName);
F := JWWHd.GLay[I].m_nLay[K].m_aanLay <> 0;
NodeCheckBox(NodeB, F);
end;
end;
finally
ATreeView.Items.EndUpdate;
end;
end;
end.
Peter's Room
jww data read & save unit Ver1.31β
http://www5b.biglobe.ne.jp/~peter/
AFsoft WebSite
CAD作ろ!
http://afsoft.jp/