百科问答小站 logo
百科问答小站 font logo



如何用代码画出一只齿轮? 第1页

  

user avatar   xinsuke 网友的相关建议: 
      

卸腰。。有很多图,请在wifi下观看


齿轮的形状是多种多样的,我没有画渐开线齿轮(对不起各位机械大佬了),简单画一个好实现的思路;

1,把一个圆的边缘均分分成若干点:

       while (angular<(2*Math.PI)+sportAngular){     PointF p = new PointF((float)( centerF.x+(diameter/2)*Math.cos(angular)),(float) (centerF.y+(diameter/2)*Math.sin(angular)));     breadthP.add(new BreadthP(p,angular));     angular+=breadth; }     


2,然后呢,把这些点用path连接起来:

有的同学肯定会说:你骗人,这东西和齿轮有jj关系;

别着急啊,想要画出弯弯曲曲的圆周曲线,我们需要先做一道初中数学题来取用来做贝塞尔曲线的点:

已知O点坐标,日1,日2,x1,y1,x2,y2。求xq,yq的坐标值?

小明同学出色的完成了算术题:

求出贝塞尔点之后,我们的图形变成这个样子:

再将偶数点取负:

这一段的代码实现:

       for(int i =0;i<breadthP.size();i++){     int j ;     float angulaQ;     if(i<breadthP.size()-1){         j = i+1;         angulaQ = (breadthP.get(i).angular+breadthP.get(j).angular)/2;     }else {         j = 0;         angulaQ = (float) ((breadthP.get(i).angular+breadthP.get(j).angular+2*Math.PI)/2);     }      float b = (float) Math.sqrt((breadthP.get(j).f.x-breadthP.get(i).f.x)*(breadthP.get(j).f.x-breadthP.get(i).f.x)+             (breadthP.get(j).f.y-breadthP.get(i).f.y)*(breadthP.get(j).f.y-breadthP.get(i).f.y));     float x1 = (breadthP.get(j).f.x+breadthP.get(i).f.x)/2;     float y1 = (breadthP.get(j).f.y+breadthP.get(i).f.y)/2;     float d = (float) ((float) Math.sqrt((x1-centerF.x)*(x1-centerF.x) +(y1-centerF.y)*(y1-centerF.y))+             ( (i%2==0) ? (-b) : b )     );     float quadPx =(float)( centerF.x+d*Math.cos(angulaQ));     float quadPy =(float)( centerF.y+d*Math.sin(angulaQ));      gearPath.quadTo(quadPx,quadPy,breadthP.get(j).f.x,breadthP.get(j).f.y); }     

我们将取点的密度提高一倍,中间再加个圆圈:

这是不就像是个齿轮了?

再加上个角自增的线程:

       Runnable runnable =new Runnable() {     @Override     public void run() {         angle+=(float) (Math.PI/100);         gear.setSportAngular(angle);         invalidate();         handler.postDelayed(this,5);     } }; handler .postDelayed(runnable,0);     


你以为这样就ok了?那你也太小看我上班闲的程度了,接下来,我们再来点难度,不知道同学们有没有听说过一种九齿联动的指尖陀螺:

国外超火的指尖陀螺,这次是9个齿轮联动!_机械_科技_bilibili_哔哩哔哩

我们先根据规定陀螺转心的位置,画出9个齿轮的圆心:

       /* 5  6  7 4  0  8 3  2  1  */ private void setFixPoints() {     fixPoints .clear();      float d = (float) (diameter/Math.sqrt(2));     fixPoints.add(centerF);     for (int i =1 ;i<9 ; i++ ){         float j = (i%2==0) ? d : diameter;         PointF p = new PointF((float) (centerF.x+ ( j*Math.cos(sportAngular+ Math.PI*i/4))),(float) (centerF.y+j*Math.sin(sportAngular+ Math.PI*i/4)));         fixPoints.add(p);     }  }     

然后把它们画出来:

       double r = diameter/Math.sqrt(2); for(int i =0;i<shell.getFixPoints().size();i++){     Gear gear = null;      if (i==0){         gear = new Gear(shell.getFixPoints().get(i), (float) (r),angleV_C ,context);     }else {         gear = new Gear(shell.getFixPoints().get(i), (float) (r), (i%2==0) ? angleV_G : angleV_G2,context);     }     gears.add(gear); }     

再套上外壳,关于外壳的完成,其实也是贝塞尔曲线的一种应用,请参考我的另一篇回答:

zhihu.com/question/3723


再加上单独齿轮旋转的效果:


最后,再把touch事件写好:

@Override
public boolean onTouchEvent(MotionEvent event){

getTracker(event);
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
startY = event.getY();
startX = event.getX();
float r = (float) (nineGearLinkage.getShell().getDiameter()/Math.sqrt(2)+nineGearLinkage.getShell().getR());
boolean a = Math.abs(centerF.x-startX)<r;
boolean a1 = Math.abs(centerF.y-startY)<r;
if(a&&a1){
isOut = false;
}else {
isOut = true;
}
dV = 0;
startThread();
sA = (float) Math.atan((startY-centerF.y)/(startX-centerF.x));
if(mTracker==null){
mTracker = VelocityTracker.obtain();
}else{
mTracker.clear();
}
mTracker.addMovement(event);
break;
case MotionEvent.ACTION_MOVE:
X = event.getX();
Y = event.getY();
mA = (float) Math.atan((Y-centerF.y)/(X-centerF.x));

if(isOut){
nineGearLinkage.setAngleV(0,mA-sA);
}else {
angle = mA-sA;
nineGearLinkage.setAngleV(angle ,0);
}

invalidate();
mTracker.addMovement(event);
mTracker.computeCurrentVelocity(1000);

break;
case MotionEvent.ACTION_UP:
float b = Math.abs(X-startX)>Math.abs(Y-startY)? (startX-X): (Y-startY);
mV = (b>0)? getSpeed(): -(getSpeed());
dV = mV;
cancelTracker();
startThread();

break;
}
return true;
}


照例,我要把源码放出来给各位同学参考:

wuyongxiang/Gear


从看见这个问题,到完成效果,我差不多花了15,6个小时,还不算我偷偷避开老板的时间,各位同学你们看到这真的忍心不赞一下吗?


其他在知乎上放的Android效果源码:

如何制作一个手机桌面宠物?

如何用代码画出一只齿轮?

QQ 未读消息的拖拽动态效果是如何实现的?

QQ上发送么么哒时候,弹出弹跳表情,是如何实现的?

一个人可以 DIY 出什么有意思的东西?

知乎网页登录背景的动画是怎么做出来的?

祥子:【Android源码分享】一个果冻质感弹性控件&高仿MIUI9时钟表盘

祥子:如何用安卓手机当做遥控器控制家里的非智能电器?




  

相关话题

  为什么很多计算机上的阿拉伯数字零(0)中间都有一个斜杠(/)? 
  什么才算是真正的编程能力? 
  以王垠的水平,他可以开发出像 nginx 和 redis 这样的软件吗? 
  面向对象(OOP)是编程语言发展中的弯路吗?为什么? 
  程序员如何应对诸如「给我弄个网站吧」的请求? 
  同事离职,我接盘了个垃圾项目,该如何是好? 
  日期格式化(yyyy-MM-dd)中,为什么 M 多大写? 
  谁能用通俗的语言解释一下什么是 RPC 框架? 
  LeetCode 刷不下去怎么办? 
  大一学生,刚开始学习编程,但感觉自己并没有天赋怎么办? 

前一个讨论
你对于 2017 年诺贝尔物理学奖的预测是什么?
下一个讨论
如何看待 2017 年美国拉斯维加斯枪击案死亡 50 余人,伤 500 余人?





© 2024-06-02 - tinynew.org. All Rights Reserved.
© 2024-06-02 - tinynew.org. 保留所有权利