随鼠标移动的十字线的快速画法

文章介绍了一种优化方法,在画十字坐标线时避免刷新画面导致的闪烁现象,通过在画新线前抹去老线来提高用户体验。详细步骤包括初始化变量、检查鼠标位置并判断是否在指定范围内,最终实现流畅的交互效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在鼠标移动事件中画当前点的十字坐标线时,为抹掉老线常采用刷新画面的方法,这样就产生了非常严重的闪烁现象。因此,我们采用在画新线前将老线抹去的方法就能很好的解决这个问题,而且速度非常快。现举例如下:
var  
  OldX, OldY: Longint;// 使用前初始化OldX:=-1;   

procedure TfrmMain.PaintBoxCMouseMove(Sender: TObject; Shift: TShiftState;   
  X, Y: Integer);   

  Procedure DrawCross(AX, AY: Integer);   
  begin  
    With PaintBoxC.Canvas do  
    begin  
      Pen.Color := CrossColor;   
      Pen.Style := CrossStyle;   
      Pen.Mode := pmXor;   
      Pen.Width := 1;   
      MoveTo(AX, 0);   
      LineTo(AX, PaintBoxC.Height);   
      MoveTo(0, AY);   
      LineTo(PaintBoxC.Width, AY);   
    end;   
  end;   

begin  
  if (OldX <> -1) then  
  begin  
    DrawCross(OldX, OldY); { 画旧十字线 }  
    OldX := -1;   
  end;   
  { 检查当前鼠标点是否在指定范围内 }  
  if PtInRect(Rect(0, 0, PaintBoxC.Width, PaintBoxC.Height), Point(X, Y)) then  
  begin  
    DrawCross(X, Y); { 在当前鼠标点画十字线 }  
    { 保存旧鼠标点 }  
    OldX := X;   
    OldY := Y;   
  end;   
end;
原文链接: http://www.tansoo.cn/?p=9
最终模型结构如下:-加速度(-g)->积分器1(初始0)->速度v-速度v->积分器2(初始h0)->高度h-高度h->HitCrossing模块(设置过零值0,方向为下降穿越)->输出信号hit-速度v->RelationalOperator(<0)->输出信号v_negative-将hit和v_negative进行LogicalAND->条件信号(condition)-速度v->Memory模块(输出v_prev)-高度h->Memory模块(输出h_prev)[注意:高度重置不需要用上一时刻的高度,所以这里可以不用,但为了统一,我们也可以使用]-条件信号->连接到速度积分器的重置端口(重置触发类型选择rising,重置值:-kv_prev)-条件信号->连接到高度积分器的重置端口(重置值:0)-注意:为了避免重置后立即再次触发(因为高度重置为0,可能下一个时间步会再次满足h<=0),我们在高度重置后设置一个小的偏移,比如重置为1e-5(一个小的正数),这样就不会立即触发。但是,重置高度为0时,过零检测模块会立即检测到穿越(因为从正到负,而重置为0后,下一个时间步高度可能为负?)。为了避免这种情况,我们重置高度为一个很小的正数(如0.01米)。另外,当篮球弹跳多次后,弹跳高度越来越低,最后停止。我们可以设置一个终止条件:当篮球的弹跳高度低于某个阈值(如0.001米)且速度为0(或接近0)时,结束仿真。但题目没有要求,我们可以让仿真持续一段时间。开始建模:步骤1:打开Simulink,新建模型。步骤2:添加以下模块:-Constant模块(值:-9.8,命名为g)-Integrator模块(两个,分别命名为Integrator_v和Integrator_h)-HitCrossing模块(在Discontinuities库中,设置HitCrossingoffset为0,Direction设置为falling)-RelationalOperator模块(运算符<0)-LogicalOperator模块(选择AND)-Memory模块(两个,分别命名为Memory_v和Memory_h)-Gain模块(值:-k,其中k=sqrt(4/5),命名为k_gain)注意:输入是v_prev,输出是-kv_prev-将各个模块连接起来。连接:-g->Integrator_v->Integrator_h-Integrator_v的输出(v)分两路:一路到Memory_v的输入,另一路到RelationalOperator模块(用于判断v<0)以及连接到k_gain的输入(但注意:k_gain的输入应该是Memory_v的输出v_prev,以避免代数环)-Integrator_h的输出(h)分两路:一路到HitCrossing模块的输入,另一路到Memory_h的输入(这里其实可以不用,因为重置高度不需要用上一时刻的值,但为了对称,我们保留)-HitCrossing模块的输出->LogicalAND的一个输入-RelationalOperator模块的输出(v<0)->LogicalAND的另一个输入-LogicalAND的输出->连接到Integrator_v和Integrator_h的重置端口(在Integrator模块的参数中,设置外部重置为rising,并设置重置值)Integrator_v的重置值:k_gain的输出(即-k*v_prev)Integrator_h的重置值:0.01(我们用一个Constant模块,值设为0.01,连接到Integrator_h的重置值输入端口)-注意:重置值输入端口需要单独连接。因此,我们使用两个Constant模块:一个用于提供高度重置值(0.01),另一个用于提供速度重置值(但速度重置值需要计算,所以使用k_gain模块,而k_gain的输入来自Memory_v的输出v_prev)步骤3:设置初始值。-Integrator_v的初始值:0(初始速度0)-Integrator_h的初始值:10(初始高度10米)步骤4:添加Scope模块,连接到高度h,以观察高度随时间的变化。步骤5:设置仿真参数。-仿真时间:0~10秒-求解器:ode45(变步长),相对容差和绝对容差可以设置小一点(如1e-6),最大步长0.01。步骤6:运行仿真。保存运动轨迹图像:-将高度h通过ToWorkspace模块输出到MATLAB工作空间(设置变量名为h,保存格式为Array)。-在MATLAB命令窗口绘制:plot(tout,h)分析:-观察图像,可以看到篮球高度随时间的变化,每次弹跳的最高点逐渐降低,且每次弹跳的最高高度为前一次的4/5。注意:由于模型中使用了Memory模块,并且重置值依赖于上一时间步的速度,因此仿真步长不能太大,否则在碰撞时刻会有误差。但使用过零检测后,Simulink会在过零点附近自动减小步长,所以精度可以接受。另外,当篮球多次弹跳后,在最高点速度为零,然后下落。我们不需要在最高点做任何处理。以上是模型的基本构建过程。由于无法在此处直接运行Simulink,因此需要用户自行搭建并调试。integrator v只有一个输出怎么分两路
06-24
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值