版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、概要设计说明书姓名:熊阳、李杰、唐硕1 引言11 编写目的开发一个将移动设备用作手绘输入板,PC端进行展示的装置,用户可以在手机触摸屏上通过手指或触摸笔自由绘制线条,图形等,并可以通过网络服务,将绘制内容实时同步到PC端显示。12 项目背景 用户在使用PC电脑进行手绘创作时,普通的鼠标,键盘等输入设备往往不能满足手绘需要的灵活以及精细控制的需求,而移动设备(手机或平板)的输入方式是直接用手指或触摸笔在触摸屏幕上手绘,正好可以满足手绘的需要,但是移动设备的显示屏幕往往太小,为了解决手绘体验的问题,可将二者结合起来,PC端作为显示终端,移动端作为输入设备,用手指或触摸笔在移动端直接手绘时,PC端可
2、以实时显示出绘制后的结果。这样就能不用购买其他数位板的情况下得到极佳的手绘体验。1.3参考资料 1android 教科书2 百度 2任务概述2.1目标2.2运行环境操作系统:移动设备可选择实现Android或iOS任意一种。PC端可实现为Web端或客户端程序(Windows或Mac系统均可)。 3总体设计 3.1 系统设计流程系统设计主要有五部分组成:需求分析、概要设计、详细设计、编写代码和系统测试。如图4-1所示。 需求分析概要设计详细设计编写代码系统测试图4-1 系统设计流程图 需求分析需要提供PC端与移动端的联接流程,方式不限,例如可以通过账号登录、二维码扫描等,要求联接方式足够便捷移动
3、端的主要功能:根据手指或触摸笔的轨迹,输入轨迹线条,线条要求经过平滑处理支持undo、redo可以对线条设置的粗细,颜色,填充效果等输入端视图支持缩放比例,放大时可以显示整个手绘图的一个局部。实现识别模式,即,切换到识别模式后,对绘制的线条进行智能识别,并自动生成规范化的图形(例如,可以识别矩形,三角形,椭圆,箭头等)。识别的算法在客户端或服务端实现均可。 PC端主要功能实时同步显示在移动端的手绘结果。可以框定完整画面的其中一个区域作为移动端的输入区域自动保存绘制结果。 概要设计 Android 与pc端通过 socket 进行实时通信,并且通过json 进行包装,and
4、roid进行画一笔 ,就发一句json pc端 接搜到进行绘图。 详细设计 Android端通过wifi连接 软件 扫描 接收到 pc端 的socket 进行判断 连接 。画布初始化大小适应屏幕,撤销,反撤销,用两个 list来存放 ,android端的画用 path来换 pc端 用 gdi 来画 ,通信用json 包装 pc端进行解析。 编写代码这一部分主要根据前面的详细设计内容用具体语言实现同步手绘系统,主要采用Java语言实现,这一部分主要是代码实现,将前一阶段的设计思想实现,因为前面已经对该系统的整体设计思路和整体框架作出了说明,并且在详细设计部分对每个设计块中的类如何实现也已给出,所
5、以在这一部分工作量也不是太大。 系统测试系统测试部分主要对前面已经实现的系统作出测试,看该系统是否符合系统设计要求。并对一些特殊的数据进行测试,比如智能识别,看是否符合要求,在测试的基础上,对发现的错误进行改正,使系统逐步得到完善。测试不是一朝一夕就能完成的,必须在今后的使用过程中逐渐完善,并得到用户的反馈后对系统作出修改。 同步手绘系统主要采用了软件工程的设计思路,从需求分析、概要设计、详细设计、编写代码直到系统测试都遵从软件工程的设计要求。3.2功能设计(1)手绘板包含的功能有:画、撤销、反撤销、删除、清空、扫描热点 (2) pc端 能接受android端的数据进行解析 ,并画;4 主程序
6、的设计本系统主要采用Visual Studio 2013软件对pc进行设计,android studio 1.5。软件对 android端进行设计。系统选用.net、Java程序设计语言来完成整个系统应用程序的编写。4.1 主要代码public class Frame_class extends View public Canvas mCanvas;/画布 private int penSize;/笔的大小 private Path mPath;/存放坐标路径 private Paint mBitmapPaint;/画笔 public int bgcolor;/画板背景色 private Bi
7、tmap mBitmap;/画 public Paint mPaint;/画笔 public int cPaint;/画笔颜色 public int cClear;/画笔颜色 private DrawPath dp;/画出路径 public ArrayList<DrawPath> savePath;/存放路径 private RectF rectF; private ArrayList<DrawPath> deletePath;/存放画的是什么内容集合 private float mX, mY,mX1,mY1; private static final float TO
8、UCH_TOLERANCE = 4; public int bitmapWidth,bitmapWidth1;/自定义画布的宽度 public int bitmapHeight,bitmapHeight1;/自定义画布的高度 public String Name;/所画类型 private boolean DianJi;/画椭圆或者矩形是否放开 public boolean PenOrRuller;/判断是画笔还是橡皮檫 public SoketLianjie soketLianjie;/连接 public String IP;/获取连接IP public Bitmap b=null; pub
9、lic boolean f=false; public JSON_shuju json_shuju;/转化数据 public boolean DuoChudian;/判断是否是多触点 public float BeiShu,Ya,Yb,Yc,Beishu2,Beishu3,be1=1.0f,be2=1.0f;/放大倍数 public Bitmap b1=null; public boolean de=false; public boolean sx=false; public boolean zn=false;/智能开关 private List<Point> lis=new Ar
10、rayList<>(); public Frame_class(Context c) super(c); BeiShu=1; Beishu2=1; Beishu3=1; Yc=0; /得到屏幕的分辨率 Name="quxian" DuoChudian=false; IP=""rectF=new RectF(); penSize=10; cPaint=0xFF00FF00; cClear=0xFF00FF00; PenOrRuller=false; DisplayMetrics dm = new DisplayMetrics(); (Activ
11、ity) c).getWindowManager().getDefaultDisplay().getMetrics(dm); bitmapWidth = dm.widthPixels-80; bitmapHeight = dm.heightPixels -240; Toast.makeText(getContext(), "宽度:" + String.valueOf(bitmapWidth), Toast.LENGTH_SHORT).show(); Toast.makeText(getContext(),"高度:"+String.valueOf( bit
12、mapHeight ), Toast.LENGTH_SHORT).show(); initCanvas(); savePath = new ArrayList<DrawPath>(); deletePath = new ArrayList<DrawPath>(); DianJi=false; public Frame_class(Context c, AttributeSet attrs) super(c,attrs); BeiShu=1; Beishu2=1; Beishu3=1; Yc=0; Name="quxian" IP="&quo
13、t; rectF=new RectF(); DuoChudian=false; penSize=10; cPaint=0xFF00FF00; cClear=0xFF00FF00; PenOrRuller=false; /得到屏幕的分辨率 DisplayMetrics dm = new DisplayMetrics(); (Activity) c).getWindowManager().getDefaultDisplay().getMetrics(dm); DianJi=false; bitmapWidth = dm.widthPixels; bitmapWidth1=dm.widthPixel
14、s; bitmapHeight = dm.heightPixels ; bitmapHeight1=dm.heightPixels; Toast.makeText(getContext(),"宽度:"+String.valueOf(bitmapWidth), Toast.LENGTH_SHORT).show(); Toast.makeText(getContext(),"高度:"+String.valueOf( bitmapHeight ), Toast.LENGTH_SHORT).show(); initCanvas(); savePath = new
15、 ArrayList<DrawPath>(); deletePath = new ArrayList<DrawPath>(); /初始化大小 public void ViewSize() ViewGroup.LayoutParams XY=this.getLayoutParams(); XY.width=bitmapWidth; XY.height=bitmapHeight; this.setLayoutParams(XY); public void ViewSize1(float beishu) ViewGroup.LayoutParams XY=this.getLa
16、youtParams(); XY.width=(int)(bitmapWidth*beishu); XY.height=(int)(bitmapHeight*beishu); bitmapWidth1=(int)(bitmapWidth*beishu); bitmapHeight1=(int)(bitmapHeight*beishu); this.setLayoutParams(XY); initCanvas(); chonghui(); invalidate(); /初始化大小 /初始化画布 public void initCanvas() mPaint = new Paint(); mPa
17、int.setAntiAlias(true); mPaint.setDither(true); mPaint.setColor(cPaint); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeJoin(Paint.Join.ROUND); mPaint.setStrokeCap(Paint.Cap.ROUND); mPaint.setStrokeWidth(penSize); mBitmapPaint = new Paint(Paint.DITHER_FLAG); bgcolor=Color.rgb(255,255,255); /画布
18、大小 mBitmap = Bitmap.createBitmap(bitmapWidth1, bitmapHeight1,Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mBitmap); /所有mCanvas画的东西都被保存在了mBitmap中 if (f) / mCanvas.drawBitmap(b, b.getWidth(), b.getHeight(), null); Rect srcRect = new Rect(0, 0, b.getWidth(), b.getHeight(); Rect dstRect = new Rect(0,
19、0, mCanvas.getWidth(), mCanvas.getHeight(); mCanvas.drawBitmap(b, srcRect, dstRect, null); invalidate(); else mCanvas.drawColor(bgcolor); mPath = new Path(); mBitmapPaint = new Paint(Paint.DITHER_FLAG); Override protected void onDraw(Canvas canvas) canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint); /显示
20、旧的画布 if (mPath != null) / 实时的显示 canvas.drawPath(mPath, mPaint); /路径对象 class DrawPath Path path; Paint paint; DrawPath() paint=new Paint(); path=new Path(); /* * 撤销的核心思想就是将画布清空, * 将保存下来的Path路径最后一个移除掉, * 重新将路径画在画布上面。 */ public void undo1() if(savePath!= null && savePath.size() > 0) /调用初始化画布
21、函数以清空画布 mPaint=new Paint(); initCanvas(); DrawPath drawPath; /将路径保存列表中的最后一个元素删除 ,并将其保存在路径删除列表中 drawPath = savePath.get(savePath.size() - 1); deletePath.add(drawPath); savePath.remove(savePath.size() - 1); public void undo() / System.out.println(savePath.size()+"-"); undo1(); chonghui(); in
22、validate();/ 刷新 public void Hua() initCanvas(); chonghui(); invalidate(); mPath.reset();/清空path mPath.moveTo(0, 0); mPath.lineTo(0, 0); mCanvas.drawPath(mPath, mPaint); savePath.add(dp); undo(); if (de) undo(); JSON_shuju sss=new JSON_shuju("cexiao"); soketLianjie=new SoketLianjie(sss); so
23、ketLianjie.XianCheng(IP); de=false; public void chonghui() DrawPath dp1=new DrawPath();/ Iterator<DrawPath> iter = savePath.iterator();/ Iterator<Ellipse> iter1 = savePath1.iterator(); Beishu2=Beishu2+(BeiShu-Beishu3)*2; for(int i=0;i<savePath.size();i+) dp1= savePath.get(i); if(DuoCh
24、udian) Path a = new Path(); Matrix SuoFang = new Matrix(); SuoFang.setScale(Beishu2, Beishu2); dp1.path.transform(SuoFang, dp1.path); mCanvas.drawPath(dp1.path, dp1.paint); de=true; JSON_shuju sss=new JSON_shuju("suofang",0,Color.BLACK,mPaint.getColor(),String.valueOf(mPaint.getStrokeWidth
25、(),mX,mY,mX1,mY1); soketLianjie=new SoketLianjie(sss); soketLianjie.XianCheng(IP); else mCanvas.drawPath(dp1.path, dp1.paint); Beishu2=1; Beishu3=BeiShu; /* * 恢复的核心思想就是将撤销的路径保存到另外一个列表里面(栈), * 然后从redo的列表里面取出最顶端对象, * 画在画布上面即可 */ public void redo() if(deletePath!= null && deletePath.size() >
26、 0) /调用初始化画布函数以清空画布 mPaint=new Paint(); initCanvas(); DrawPath drawPath=new DrawPath(); /将路径保存列表中的最后一个元素删除 ,并将其保存在路径删除列表中 drawPath = deletePath.get(deletePath.size() - 1); savePath.add(drawPath); deletePath.remove(deletePath.size() - 1); /将路径保存列表中的路径重绘在画布上 chonghui(); invalidate();/ 刷新 /* * 清空的主要思想就
27、是初始化画布 * 将保存路径的两个List清空 * */ public void removeAllPaint() /调用初始化画布函数以清空画布 mPaint=new Paint(); initCanvas(); invalidate();/刷新 savePath.clear(); deletePath.clear(); JSON_shuju sss=new JSON_shuju("qingkong"); soketLianjie=new SoketLianjie(sss); soketLianjie.XianCheng(IP); private void touch_s
28、tart(float x, float y) if (zn) lis.add(new Point(int)x,(int)y); if (Name = "ellipse") rectF = new RectF(); rectF.left = x; rectF.top = y; mX = x; mY = y; else if (Name = "rectangle" | Name = "straight_line") mX = x; mY = y; else Hua(); mPath.reset();/清空path mPath.moveTo
29、(x, y); mX = x; mY = y; if(IP!="") / soketLianjie=new SoketLianjie( json_shuju.Fanyi(1,this, new Point(int) mX, (int) mY), new Point(int)mX1, (int) mY1); JSON_shuju sss=new JSON_shuju(Name,-1,Color.BLACK,mPaint.getColor(),String.valueOf(mPaint.getStrokeWidth(),mX,mY,mX1,mY1); soketLianjie=
30、new SoketLianjie(sss); soketLianjie.XianCheng(IP); private void touch_move(float x, float y) throws JSONException if (zn) lis.add(new Point(int)x,(int)y); float dx = Math.abs(x - mX); float dy = Math.abs(y - mY); if(Name="ellipse") if(DianJi=true) undo(); rectF.right=x; rectF.bottom=y; mPa
31、th.addOval(rectF, Path.Direction.CCW); dp = new DrawPath(); dp.path = mPath; dp.paint = mPaint; savePath.add(dp); DianJi=true; else if(Name="rectangle") mPaint=new Paint(); initCanvas(); chonghui(); invalidate(); mPath.reset();/清空path mPath.moveTo(mX, mY); mPath.lineTo(x, mY); mPath.lineTo
32、(x, y); mPath.lineTo(mX, y); mPath.close(); mCanvas.drawPath(mPath, mPaint); else if(Name="straight_line") initCanvas(); chonghui(); invalidate(); mPath.reset();/清空path mPath.moveTo(mX, mY); mPath.lineTo(x, y); mCanvas.drawPath(mPath, mPaint); if (dx >= TOUCH_TOLERANCE | dy >= TOUCH_
33、TOLERANCE) /mPath.quadTo(mX, mY, x, y); mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2); mX = x; mY = y; mX1=(x + mX)/2; mY1=(y + mY)/2; if(IP!="") / String Operator, String BoolUp, int BackColor,int PenColor,String Pensize,float StartpointX,float StartpointY,float UppointX,float UppointY JSO
34、N_shuju sss=new JSON_shuju(Name,0,Color.BLACK,mPaint.getColor(),String.valueOf(mPaint.getStrokeWidth(),mX,mY,mX1,mY1); soketLianjie=new SoketLianjie(sss); soketLianjie.XianCheng(IP); mX1=x; mY1=y; private void touch_up(float x,float y) throws JSONException DianJi = false; dp = new DrawPath(); dp.pat
35、h = mPath; dp.paint = mPaint; if (Name = "ellipse") else if (Name = "rectangle" | Name = "straight_line") savePath.add(dp); else mPath.lineTo(mX, mY); mCanvas.drawPath(mPath, mPaint); savePath.add(dp); mPath = null; if (zn) lis.add(new Point(int)x,(int)y); sta(lis); lis
36、.clear(); if(IP!="") / soketLianjie=new SoketLianjie( json_shuju.Fanyi(1,this, new Point(int) mX, (int) mY), new Point(int)mX1, (int) mY1); JSON_shuju sss=new JSON_shuju(Name,1,Color.BLACK,mPaint.getColor(),String.valueOf(mPaint.getStrokeWidth(),mX,mY,mX1,mY1); soketLianjie=new SoketLianji
37、e(sss); soketLianjie.XianCheng(IP); Hua(); public boolean onTouchEvent(MotionEvent event) try if(deletePath.size()>0) deletePath.clear(); float x = event.getX(); float y = event.getY(); switch (event.getActionMasked() case MotionEvent.ACTION_POINTER_DOWN:/多触点 mX=event.getX(0); mY = event.getY(0);
38、 mX1 = event.getX(1); mY1=event.getY(1); Ya=Math.abs(mY1-mY); DuoChudian=true; Beishu3=BeiShu; break; case MotionEvent.ACTION_DOWN: if(!DuoChudian&&!sx) mPath = new Path(); touch_start(x, y); invalidate(); /清屏 sx=true; break; case MotionEvent.ACTION_MOVE: if (sx) if (!DuoChudian) touch_move(
39、x, y); invalidate(); else mX = event.getX(0); mY = event.getY(0); mX1 = event.getX(1); mY1 = event.getY(1); Yb = Math.abs(mY1 - mY); if (Yc > Math.abs(Yb - Ya) BeiShu = BeiShu - (Yb - Ya) / 40) / bitmapHeight; if (BeiShu < 3 && BeiShu > 0.5) ViewSize1(BeiShu); else BeiShu = BeiShu +
40、 (Yb - Ya) / 40) / bitmapHeight; else BeiShu = BeiShu + (Yb - Ya) / 40) / bitmapHeight; if (BeiShu < 3 && BeiShu > 0.5) ViewSize1(BeiShu); else BeiShu = BeiShu - (Yb - Ya) / 40) / bitmapHeight; Yc = Yb - Ya; break; case MotionEvent.ACTION_UP: if (sx) if(!DuoChudian) touch_up(x,y); sx=false; break; else DuoChudian=false;Beishu2=1;Yc=0; catch (Exception e) return true; public void sta(List<Point> list) int count = 0; int width; int height; int maxtop = list.get(0).x; int ma
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 文化产业发展续约函(4篇)
- 电影制片人影片票房与项目利润绩效考评表
- 矿井调度员考试题库及答案
- (2025版)中国儿童急性荨麻疹诊疗专家共识课件
- 职业素养积分评估办法
- 大学生创新创业合作支持政策
- 2026小学三年级上册道德与法治期中考试题及答案
- 2026年专业技术人员公需科目危废贮存处置知识试题及答案
- 2026年职业技能鉴定考试(水工闸门运行工·初级)综合试题及答案
- 2026年营养配餐国际化评价题库及答案
- 雨季电气安全用电培训课件
- DB46-484-2019 生活垃圾焚烧污染控制标准
- 电池运维管理办法
- 南京公房承租管理办法
- 学校食堂改造工程可研报告
- 工厂处理客诉培训
- 《凝血因子检查》课件
- 老年高血压特点及临床诊治流程专家共识(2024)解读
- 服装厂生产车间员工劳务合同书(34篇)
- 会计从业会计基础
- 装配工人培训产品装配与质量控制
评论
0/150
提交评论