{------------------------------------------------------------------------------} { Unit Name: kCutter Purpose : Unit for simulating Cutter Author : Vesa Lappalainen Date : 20.2.1998 Changed : 29.10.2000/vl - blades Min,Max,Org are absolute measurements inside the cutter relative to cutters Origo ToDo : Creates two TBlade component. } {------------------------------------------------------------------------------} unit kCutter; interface uses Dialogs,Graphics,Classes,Controls,ExtCtrls,kavesimu; type TCutter = class; TBlade = class; TBladeMessage = ( blmsgDone, blmsgHome, blmsgOverDone,blmsgOverHome,blmsgStartCut,blmsgGoHome,blmsgPutHome ); TBladeLine = ( blOnline, blUpperLeft, blUpperRight ); TBladeEvent = procedure (blade:TBlade; msg:TBladeMessage) of object; TBlade = class(TPersistent) // Blade can be only inside TCutter private FAutoCut : boolean; FMin : double; // Relative to parent Origo FMax : double; FOrg : double; FHole : double; FTimeWork : double; // In sec. FTimeRet : double; FDirection : integer; // -1 = down, 1 = up, 0 = no move FBlade : TaSimuObject; FOwner : TCutter; FTimer : TTimer; FSpeed : double; FDs : double; // Following are relative to Cutter Origo FRelPosY : double; FGoal : double; // Temp value that is changed after getting to home FOnBlade : TBladeEvent; FFast: boolean; FInterval : integer; procedure SetFast(const Value: boolean); procedure SetRelPosY(const Value: double); procedure CalcRel; virtual; protected public function IsHome:boolean; virtual; constructor Create(AOwner:TCutter); virtual; destructor Destroy; override; procedure SetHole(value:double); virtual; function GetBrush : TBrush; virtual; procedure SetBrush(value:TBrush); virtual; function GetPen : TPen; virtual; procedure SetPen(value:TPen); virtual; function GetVisible : Boolean; virtual; procedure SetVisible(value:Boolean); virtual; // procedure Assign(value:TPersistent); override; property Blade : TaSimuObject read FBlade; procedure OnTimerWork(Sender: TObject); procedure OnTimerHome(Sender: TObject); procedure StartCut; virtual; procedure GoHome; virtual; procedure PutHome; virtual; procedure Stop; virtual; property Owner : TCutter read FOwner; function GetInterval : Integer; virtual; procedure SetInterval(value:Integer); virtual; property Fast : boolean read FFast write SetFast; published property Max : double read FMax write FMax nodefault; property Min : double read FMin write FMin nodefault; property Org : double read FOrg write FOrg nodefault; property TimeWork : double read FTimeWork write FTimeWork; property TimeRet : double read FTimeRet write FTimeRet; property Direction : integer read FDirection write FDirection default -1; property Hole : double read FHole write SetHole nodefault; property Brush : TBrush read GetBrush write SetBrush; property Pen : TPen read GetPen write SetPen; property OnBlade : TBladeEvent read FOnBlade write FOnBlade; property RelPosY : double read FRelPosY write SetRelPosY; property AutoCut : boolean read FAutoCut write FAutoCut default false; property Interval : Integer read GetInterval write SetInterval default 100; property Visible : boolean read GetVisible write SetVisible default True; end; TCutter = class(TaSimuObject) private FBladeUpper : TBlade; FBladeLower : TBlade; FBladeLine : TBladeLine; protected procedure SetParent(AParent:TWinControl); override; function GetFast: boolean; virtual; procedure SetFast(const Value: boolean); virtual; public constructor Create(AOwner:TComponent); override; destructor Destroy; override; procedure DoScale(force:boolean); override; procedure CheckBlades; virtual; procedure Paint; override; function GetOnBladeUpper : TBladeEvent; virtual; procedure SetOnBladeUpper(value:TBladeEvent); virtual; function GetOnBladeLower : TBladeEvent; virtual; procedure SetOnBladeLower(value:TBladeEvent); virtual; function GetVisible : boolean; override; procedure SetVisible(value:boolean); override; procedure SetBladeLine(value:TBladeLine); virtual; function GetOnMouseDown : TMouseEvent; virtual; procedure SetOnMouseDown(value:TMouseEvent); virtual; procedure PutHome; virtual; procedure StartCut; virtual; procedure GoHome; virtual; procedure Stop; virtual; published property BladeUpper : TBlade read FBladeUpper write FBladeUpper; property BladeLower : TBlade read FBladeLower write FBladeLower; property OnBladeUpper : TBladeEvent read GetOnBladeUpper write SetOnBladeUpper; property OnBladeLower : TBladeEvent read GetOnBladeLower write SetOnBladeLower; property Visible : boolean read GetVisible write SetVisible default True; property BladeLine : TBladeLine read FBladeLine write SetBladeLine default blOnline; property OnMouseDown : TMouseEvent read GetOnMouseDown write SetOnMouseDown; property Fast : boolean read GetFast write SetFast; end; procedure Register; {------------------------------------------------------------------------------} implementation {------------------------------------------------------------------------------} procedure Register; begin RegisterComponents('Kave2000', [TCutter]); end; //----------------------------------------------------------------------------- procedure TCutter.DoScale(force:boolean); // override; begin inherited; CheckBlades; end; //----------------------------------------------------------------------------- procedure TCutter.CheckBlades; // virtual; begin if ( not assigned(BladeUpper) ) or ( not Assigned(BladeLower) ) then exit; with BladeUpper.Blade.Box do begin DoInform := false; case BladeLine of blOnline: begin dp.x := Self.Box.dp.x; Origo.x := Self.Box.Origo.x; end; blUpperLeft : begin dp.x := Self.Box.Origo.x; Origo.x := dp.x; end; blUpperRight : begin dp.x := Self.Box.dp.x - Self.Box.Origo.x; Origo.x := 0; end; end; Origo.y := 0; dp.y := Self.Box.dp.y - Self.Box.Origo.y - BladeUpper.Hole; p.x := Self.Box.p.x; BladeUpper.CalcRel; BladeUpper.RelPosY := BladeUpper.RelPosY; DoInform := true; end; with BladeLower.Blade.Box do begin DoInform := false; case BladeLine of blOnline: begin dp.x := Self.Box.dp.x; Origo.x := Self.Box.Origo.x; end; blUpperLeft : begin dp.x := Self.Box.dp.x - Self.Box.Origo.x; Origo.x := 0; end; blUpperRight : begin dp.x := Self.Box.Origo.x; Origo.x := dp.x; end; end; dp.y := Self.Box.Origo.y + BladeLower.Hole; Origo.y := dp.y; p.x := Self.Box.p.x; BladeLower.RelPosY := BladeLower.RelPosY; BladeLower.CalcRel; DoInform := true; end; end; //----------------------------------------------------------------------------- constructor TCutter.Create(AOwner:TComponent); // override; begin inherited; Brush.Style := bsClear; Pen.Style := psDot; FBladeUpper := TBlade.Create(self); FBladeLower := TBlade.Create(self); ControlVisible(false); FBladeLower.Direction := 0; FBladeLower.Hole := 0; FBladeLower.Min := -0.2; FBladeUpper.Max := 0.2; FBladeUpper.Hole := 0.1; FBladeLine := blOnline; CheckBlades; end; //----------------------------------------------------------------------------- destructor TCutter.Destroy; // override; begin // if ( Assigned(LowerBlade ) ) then LowerBlade.Free; FBladeLower := nil; // if ( Assigned(BladeUpper ) ) then BladeUpper.Free; FBladeUpper := nil; inherited; end; //----------------------------------------------------------------------------- procedure TCutter.SetBladeLine(value:TBladeLine); // virtual; begin FBladeLine := value; CheckBlades; PutHome; end; //----------------------------------------------------------------------------- procedure TCutter.SetParent(AParent:TWinControl); // override; begin inherited; if ( Assigned(BladeLower ) ) then BladeUpper.Blade.Parent := AParent; if ( Assigned(BladeUpper ) ) then BladeLower.Blade.Parent := AParent; BringToFront; end; //----------------------------------------------------------------------------- procedure TCutter.SetOnBladeUpper(value:TBladeEvent); // virtual; begin BladeUpper.OnBlade := value; end; //----------------------------------------------------------------------------- function TCutter.GetOnBladeUpper : TBladeEvent; // virtual; begin Result := BladeUpper.OnBlade; end; //----------------------------------------------------------------------------- procedure TCutter.SetOnBladeLower(value:TBladeEvent); // virtual; begin BladeLower.OnBlade := value; end; //----------------------------------------------------------------------------- function TCutter.GetOnBladeLower : TBladeEvent; // virtual; begin Result := BladeLower.OnBlade; end; //----------------------------------------------------------------------------- procedure TCutter.Paint; // override; begin inherited; end; //----------------------------------------------------------------------------- procedure TCutter.SetVisible(value:boolean); // virtual; begin if ( value = Visible ) then exit; Link.SetLinkVisible(value); BladeUpper.Visible := value; BladeLower.Visible := value; ControlVisible(false); end; //----------------------------------------------------------------------------- function TCutter.GetVisible : boolean; // virtual; begin Result := BladeUpper.Visible; end; //----------------------------------------------------------------------------- procedure TCutter.SetOnMouseDown(value:TMouseEvent); // virtual; begin inherited OnMouseDown := value; BladeUpper.Blade.OnMouseDown := value; BladeLower.Blade.OnMouseDown := value; end; //----------------------------------------------------------------------------- function TCutter.GetOnMouseDown : TMouseEvent; // virtual; begin Result := inherited OnMouseDown; end; //----------------------------------------------------------------------------- constructor TBlade.Create(AOwner:TCutter); // virtual; begin inherited Create; FOwner := AOwner; FBlade := taSimuObject.Create(FOwner); FMin := 0; FMax := 0; FOrg := 0; FTimeRet := 1; FTimeWork := 1; FHole := 0; FDirection := -1; FTimer := TTimer.Create(FOwner); FTimer.Enabled := false; Fast := false; Interval := 100; end; //----------------------------------------------------------------------------- procedure TBlade.SetHole(value:double); // virtual; begin FHole := value; FOwner.CheckBlades; PutHome; end; //----------------------------------------------------------------------------- destructor TBlade.Destroy; // override; begin // FBlade ei tarvitse tuhota, koska se tuhoutuu omistajansa mukana inherited; end; //----------------------------------------------------------------------------- procedure TBlade.SetBrush(value:TBrush); // virtual; begin Blade.Brush.Assign(value); end; //----------------------------------------------------------------------------- function TBlade.GetBrush : TBrush; // virtual; begin Result := Blade.Brush; end; //----------------------------------------------------------------------------- procedure TBlade.SetPen(value:TPen); // virtual; begin Blade.Pen.Assign(value); end; //----------------------------------------------------------------------------- function TBlade.GetPen : TPen; // virtual; begin Result := Blade.Pen; end; //----------------------------------------------------------------------------- procedure TBlade.SetVisible(value:Boolean); // virtual; begin Blade.Visible := value; end; //----------------------------------------------------------------------------- function TBlade.GetVisible : Boolean; // virtual; begin Result := Blade.Visible; end; { //----------------------------------------------------------------------------- procedure TBlade.Assign(value:TPersistent); // override; var b : TBlade; begin if not ( value is TBlade ) then exit; b := value as TBlade; Min := b.min; end; } //----------------------------------------------------------------------------- procedure TBlade.OnTimerWork(Sender: TObject); begin // Blade.box.p.y := Blade.box.p.y + FSpeed; RelPosY := RelPosY + FSpeed; if direction <= 0 then begin // direction down if ( RelPosY < FGoal ) then begin RelPosY := Org; FGoal := -100000; if Assigned(OnBlade) then OnBlade(self,blmsgDone); if ( AutoCut ) then GoHome; end; if ( RelPosY < Min ) then begin Stop; if Assigned(OnBlade) then OnBlade(self,blmsgOverDone); end; exit; end; // direction up if ( RelPosY > FGoal ) then begin RelPosY := Org; FGoal := 100000; if Assigned(OnBlade) then OnBlade(self,blmsgDone); if ( AutoCut ) then GoHome; end; if ( RelPosY > Max ) then begin Stop; if Assigned(OnBlade) then OnBlade(self,blmsgOverDone); end; end; function TBlade.IsHome:boolean; begin Result := true; if direction <= 0 then begin // direction down if ( RelPosY >= Hole ) then exit; Result := false; Exit; end; // direction up if ( RelPosY <= Hole ) then exit; Result := false; end; //----------------------------------------------------------------------------- procedure TBlade.OnTimerHome(Sender: TObject); begin RelPosY := RelPosY + FSpeed; if direction <= 0 then begin // direction down if ( RelPosY >= FGoal ) then begin RelPosY := Hole; FGoal := 1000000; if ( AutoCut ) then Stop; if Assigned(OnBlade) then OnBlade(self,blmsgHome); end; if ( RelPosY >= Max ) then begin Stop; if Assigned(OnBlade) then OnBlade(self,blmsgOverHome); end; exit; end; // direction up if ( RelPosY <= FGoal ) then begin RelPosY := Hole; FGoal := -1000000; if ( AutoCut ) then Stop; if Assigned(OnBlade) then OnBlade(self,blmsgHome); end; if ( RelPosY <= Min ) then begin Stop; if Assigned(OnBlade) then OnBlade(self,blmsgOverHome); end; end; //----------------------------------------------------------------------------- procedure TBlade.StartCut; // virtual; var dt : double; begin if ( Direction = 0 ) then exit; if Assigned(OnBlade) then OnBlade(self,blmsgStartCut); CalcRel; FGoal := Org; dt := TimeWork; if ( dt = 0 ) then dt := 1; if Fast then begin dt := 1; end; FSpeed := direction*FDs/dt*Interval/1000; if ( FSpeed = 0 ) then FSpeed := direction; FTimer.OnTimer := OnTimerWork; Ftimer.Enabled := true; end; //----------------------------------------------------------------------------- procedure TBlade.GoHome; // virtual; var dt : double; begin if ( Direction = 0 ) or ( FDs = 0 ) then exit; if ( IsHome ) then Exit; if Assigned(OnBlade) then OnBlade(self,blmsgGoHome); CalcRel; FGoal := Hole; dt := TimeRet; if ( dt = 0 ) then dt := 1; FSpeed := -direction*FDs/dt*Interval/1000; if ( FSpeed = 0 ) then FSpeed := -direction; FTimer.OnTimer := OnTimerHome; Ftimer.Enabled := true; end; //----------------------------------------------------------------------------- procedure TBlade.Stop; // virtual; begin Ftimer.Enabled := false; end; //----------------------------------------------------------------------------- procedure TBlade.SetInterval(value:Integer); // virtual; begin FInterval := value; if ( not Fast ) then FTimer.Interval := Interval; end; //----------------------------------------------------------------------------- function TBlade.GetInterval : Integer; // virtual; begin Result := FInterval; end; function TCutter.GetFast: boolean; begin Result := BladeUpper.Fast; end; procedure TCutter.SetFast(const Value: boolean); begin BladeUpper.Fast := Value; BladeLower.Fast := Value; end; procedure TBlade.SetFast(const Value: boolean); begin FFast := Value; if ( Fast ) then FTimer.Interval := 1 else FTimer.Interval := Interval; end; procedure TBlade.SetRelPosY(const Value: double); begin FRelPosY := Value; Blade.box.p.y := Owner.Box.p.y + Value; end; procedure TCutter.PutHome; begin BladeLower.PutHome; BladeUpper.PutHome; end; procedure TBlade.CalcRel; begin FDs := abs(Hole - Org); end; procedure TBlade.PutHome; begin Stop; RelPosY := Hole; if Assigned(OnBlade) then OnBlade(self,blmsgPutHome); end; procedure TCutter.GoHome; begin BladeLower.GoHome; BladeUpper.GoHome; end; procedure TCutter.StartCut; begin BladeLower.StartCut; BladeUpper.StartCut; end; procedure TCutter.Stop; begin BladeLower.Stop; BladeUpper.Stop; end; end.