前言:本文全部纯手工打造,如有疏漏之处,还请谅解!

如果需要查看更多文章,请微信搜索公众号 csharp编程大全,需要进C#交流群群请加微信z438679770,备注进群, 我邀请你进群! ! !

这篇文章涉及较多C#重要知识点,如果都能看懂,你至少可以算得上入门了!有兴趣的同志可以下载源码调试.

开始吧:

-》指令格式介绍

激光测距模块

UDP: 192.168.1.200  8008发往8010;192.168.1.201    8008发往8011;

协议:C3 00为195cm

光电开关模块

UDP:192.168.1.202  8008发往8012

帧头59 59

数据 01 01 01 01 为4个光电开关状态,依次为安检通道入口光电开关、安检门光电开关1、安检门光电开关2,安检通道出口光电开关。其中1为无人遮挡状态,0为有人遮挡状态

填充 44 55 66 77 88 99 00 12 23 34 45 56 67 ee

4个光电开关均无人

1、2、3光电开关有人 4光电开关无人

开发软硬件环境:

硬件:1. 4路光电开关,4路测距雷达,数据通过udp发送到主机192.168.1.119

软件:1. vs2017 + win10

-》重要知识点:

1. 多线程操作:thread和task的使用

2. winform的chart控件使用

3.队列Queue和list使用

4.双缓冲用法

5.定时器操作

6.线程中操作主窗体控件:

this.Invoke((EventHandler)delegate

{

richTextBoxEx1.Text += stringData + "\r\n";

}):

7.通过循环的方式遍历操作控件

8.数据类型转换:

Byte[] recv = client.Receive(ref endpoint);

string stringData = "0x" + BitConverter.ToString(recv).Replace("-", " 0x").ToLower();

-》开发难点:

1. chart需要绘制所有采集上来的数据点,光电开关1毫秒就一组数据,绘图时间得跟得上

2. 多线程的灵活使用

全部代码:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Drawing;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Net;
  8. using System.Net.Sockets;
  9. using System.Threading;
  10. using System.Threading.Tasks;
  11. using System.Windows.Forms;
  12. using System.Windows.Forms.DataVisualization.Charting;
  13.  
  14. namespace lidarTest
  15. {
  16. public partial class mainForm : DevComponents.DotNetBar.Office2007Form
  17. {
  18. public mainForm()
  19. {
  20. this.DoubleBuffered = true;//设置本窗体
  21. SetStyle(ControlStyles.UserPaint, true);
  22. SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
  23. SetStyle(ControlStyles.DoubleBuffer, true); // 双缓冲
  24.  
  25. this.EnableGlass = false;
  26. InitializeComponent();
  27. InitChart();
  28. checkBox2.Checked = false;
  29. checkBox1.Checked = false;
  30. }
  31. private Queue<int>[] dataQueue = new Queue<int>[8];//把Queue<double>看成一个类型 int[] a=new int [8]
  32. private List<int>[] dataList = new List<int>[8];
  33. private Queue<string> dQueue = new Queue<string>();
  34. bool isStart = false;
  35. int count = 0;
  36. private static readonly object Lock = new object();
  37. Stopwatch elapsetime = new Stopwatch();
  38. private void mainForm_Load(object sender, EventArgs e)
  39. {
  40. dataQueue[0] = new Queue<int>();
  41. dataQueue[1] = new Queue<int>();
  42. dataQueue[2] = new Queue<int>();
  43. dataQueue[3] = new Queue<int>();
  44. dataQueue[4] = new Queue<int>();
  45. dataQueue[5] = new Queue<int>();
  46. dataQueue[6] = new Queue<int>();
  47. dataQueue[7] = new Queue<int>();
  48.  
  49. dataList[0] = new List<int>();
  50. dataList[1] = new List<int>();
  51. dataList[2] = new List<int>();
  52. dataList[3] = new List<int>();
  53. dataList[4] = new List<int>();
  54. dataList[5] = new List<int>();
  55. dataList[6] = new List<int>();
  56. dataList[7] = new List<int>();
  57.  
  58. this.WindowState = FormWindowState.Normal;
  59. this.FormBorderStyle = FormBorderStyle.Sizable;
  60. this.Top = 0;
  61. this.Left = 0;
  62. this.Width = Screen.PrimaryScreen.WorkingArea.Width;
  63. this.Height = Screen.PrimaryScreen.WorkingArea.Height;
  64. Start();
  65.  
  66. //MessageBox.Show( DateTime.Now.ToString("yyyy_MM_dd_hh_mm_ss_fff"));
  67. }
  68. // 防止闪屏
  69. //protected override CreateParams CreateParams
  70. //{
  71. // get
  72. // {
  73. // CreateParams cp = base.CreateParams;
  74. // cp.ExStyle |= 0x02000000;
  75. // return cp;
  76. // }
  77. //}
  78.  
  79. public void Start()
  80. {
  81. Thread t1 = new Thread(StartDataRevThread1); //第一路激光雷达数据接收线程
  82. t1.Start();
  83. t1.IsBackground = true;
  84.  
  85. Thread t2 = new Thread(StartDataRevThread2); //第二路激光雷达数据接收线程
  86. t2.Start();
  87. t2.IsBackground = true;
  88.  
  89. Thread t3 = new Thread(StartDataRevThread3);//第三路激光雷达数据接收线程
  90. t3.Start();
  91. t3.IsBackground = true;
  92.  
  93. Thread t4 = new Thread(StartDataRevThread4);////第四路激光雷达数据接收线程
  94. t4.Start();
  95. t4.IsBackground = true;
  96.  
  97. Thread t5 = new Thread(StartDataRevThread5);//四个广电开关数据接受线程
  98. t5.Start();
  99. t5.IsBackground = true;
  100.  
  101. Thread t6 = new Thread(dataSaveThread6);//数据写入线程
  102. t6.Start();
  103. t6.IsBackground = true;
  104. }
  105. private void StartDataRevThread1()
  106. {
  107. try
  108. {
  109. UdpClient client = new UdpClient(8021);
  110. //IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 0);//
  111. IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("192.168.1.30"), 8008);
  112. //client.Client.ReceiveBufferSize = 40960;//40960 默认值是8192
  113. while (true)
  114. {
  115. Byte[] recv = client.Receive(ref endpoint);
  116. string stringData = "0x" + BitConverter.ToString(recv).Replace("-", " 0x").ToLower();
  117. this.Invoke((EventHandler)delegate
  118. {
  119. //richTextBoxEx1.Text += stringData + "\r\n";
  120. chartShow( recv[2] + (recv[3]<<8),1);
  121. }
  122. );
  123. }
  124. }
  125. catch(Exception ex)
  126. {
  127. MessageBox.Show(ex.Message + "\n" + ex.StackTrace) ;
  128. }
  129. }
  130. private void StartDataRevThread2()
  131. {
  132. try
  133. {
  134. UdpClient client = new UdpClient(8022);
  135. IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("192.168.1.40"), 8008);
  136. while (true)
  137. {
  138. Byte[] recv = client.Receive(ref endpoint);
  139. string stringData = "0x" + BitConverter.ToString(recv).Replace("-", " 0x").ToLower();
  140. this.Invoke((EventHandler)delegate
  141. {
  142. //richTextBoxEx2.Text += stringData + "\r\n";
  143. chartShow(recv[2] + (recv[3] << 8),2);
  144. }
  145. );
  146. }
  147. }
  148. catch (Exception ex)
  149. {
  150. MessageBox.Show(ex.Message + "\n" + ex.StackTrace);
  151. }
  152. }
  153. private void StartDataRevThread3()
  154. {
  155. try
  156. {
  157. UdpClient client = new UdpClient(8023);
  158. IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("192.168.1.100"), 8008);
  159. while (true)
  160. {
  161. Byte[] recv = client.Receive(ref endpoint);
  162. string stringData = "0x" + BitConverter.ToString(recv).Replace("-", " 0x").ToLower();
  163. this.Invoke((EventHandler)delegate
  164. {
  165. //richTextBoxEx3.Text += stringData + "\r\n";
  166. chartShow( recv[2] + (recv[3] << 8),3);
  167. }
  168. );
  169. }
  170. }
  171. catch (Exception ex)
  172. {
  173. MessageBox.Show(ex.Message + "\n" + ex.StackTrace);
  174. }
  175. }
  176. private void StartDataRevThread4()
  177. {
  178. try
  179. {
  180. UdpClient client = new UdpClient(8024);
  181. IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("192.168.1.200"), 8008);
  182. while (true)
  183. {
  184. Byte[] recv = client.Receive(ref endpoint);
  185. string stringData = "0x" + BitConverter.ToString(recv).Replace("-", " 0x").ToLower();
  186. this.Invoke((EventHandler)delegate
  187. {
  188. //richTextBoxEx4.Text += stringData + "\r\n";
  189. chartShow( recv[2] + (recv[3] << 8),4);
  190. }
  191. );
  192. }
  193. }
  194. catch (Exception ex)
  195. {
  196. MessageBox.Show(ex.Message + "\n" + ex.StackTrace);
  197. }
  198. }
  199.  
  200. private void StartDataRevThread5()
  201. {
  202. try
  203. {
  204. UdpClient client = new UdpClient(8012);
  205. IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("192.168.1.202"), 8008);
  206. client.Client.ReceiveBufferSize = 1024*1024;//默认值是8192
  207. while (true)
  208. {
  209. Byte[] recv = client.Receive(ref endpoint);
  210. elapsetime.Restart();//计时开始
  211. this.Invoke((EventHandler)delegate
  212. {
  213. //if (count >= 100)
  214. {
  215. count = 0;
  216. Task.Run(() =>
  217. {
  218. chartShow(recv[2], 5);
  219. }
  220. );
  221. Task.Run(() =>
  222. {
  223. chartShow(recv[3], 6);
  224. }
  225. );
  226. Task.Run(() =>
  227. {
  228. chartShow(recv[4], 7);
  229. }
  230. );
  231. Task.Run(() =>
  232. {
  233. chartShow(recv[5], 8);
  234. }
  235. );
  236. //chartShow(recv[2], 5);
  237. //chartShow(recv[3], 6);
  238. //chartShow(recv[4], 7);
  239. //chartShow(recv[5], 8);
  240.  
  241. if (checkBox2.Checked == true)
  242. {
  243. string stringData = "0x" + BitConverter.ToString(recv).Replace("-", " 0x").ToLower();
  244. dQueue.Enqueue(DateTime.Now.ToString("yyyy-MM-dd_HH:mm:ss:fff") + " " + stringData);
  245. }
  246.  
  247. }
  248. count++;
  249.  
  250. } );
  251. elapsetime.Stop();//计时结束
  252. this.Invoke((EventHandler)delegate
  253. {
  254. label1.Text = "接收数据耗时:"+ elapsetime.ElapsedMilliseconds.ToString("0000");
  255. });
  256. }
  257. }
  258. catch (Exception ex)
  259. {
  260. MessageBox.Show(ex.Message + "\n" + ex.StackTrace);
  261. }
  262. }
  263. private void dataSaveThread6()
  264. {
  265. while (true)
  266. {
  267. if (checkBox2.Checked == true)
  268. {
  269. String LogPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Log");
  270. if (dQueue.Count() > 0)
  271. strWrite(dQueue.Dequeue(), LogPath, "log.txt");
  272. }
  273. }
  274. }
  275. private void InitChart()
  276. {
  277. Chart[] ch = new Chart[12] { chart1, chart2, chart3, chart4,chart5, chart6, chart7, chart8 , chart_1, chart_2, chart_3, chart_4 };
  278. for (int i = 0; i < 4 ; i++)
  279. {
  280. ch[i].ChartAreas.Clear();
  281. ChartArea chartArea1 = new ChartArea("C1");
  282. ch[i].ChartAreas.Add(chartArea1);
  283. //定义存储和显示点的容器
  284. ch[i].Series.Clear();
  285. Series series1 = new Series("S1");
  286. series1.ChartArea = "C1";
  287. ch[i].Series.Add(series1);
  288.  
  289. ch[i].ChartAreas[0].AxisY.IsStartedFromZero = false;
  290. ch[i].Legends[0].Enabled = false;
  291.  
  292. ch[i].ChartAreas[0].AxisX.Interval = 100;
  293. ch[i].ChartAreas[0].AxisX.Maximum = 1000;
  294. //ch[i].ChartAreas[0].AxisX.ScaleView.Size = 8;//设置图表可视区域数据点数,说白了一次可以看到多少个X轴区域
  295.  
  296. ch[i].ChartAreas[0].Axes[0].MajorGrid.Enabled = false;
  297. ch[i].ChartAreas[0].Axes[1].MajorGrid.Enabled = false;
  298. //y轴上网格
  299. //ct.ChartAreas[0].Axes[1].MajorGrid.Enabled = false;
  300. //ch[i].ChartAreas[0].AxisX.IsStartedFromZero = false;
  301. //ch[i].ChartAreas[0].AxisX.MajorGrid.LineColor = System.Drawing.Color.Silver;
  302. //ch[i].ChartAreas[0].AxisY.MajorGrid.LineColor = System.Drawing.Color.Silver;
  303. //设置标题
  304. ch[i].Titles.Clear();
  305. //ch[i].Titles.Add("S01");
  306. //ch[i].Titles[0].Text = "通道" + (i + 1) + " 折线图显示";
  307. //ch[i].Titles[0].ForeColor = Color.RoyalBlue;
  308. //ch[i].Titles[0].Font = new System.Drawing.Font("Microsoft Sans Serif", 12F);
  309. //设置图表显示样式
  310. ch[i].Series[0].Color = Color.Red;
  311. //this.chart1.Titles[0].Text = string.Format("{0}折线图显示", );
  312. ch[i].Series[0].ChartType = SeriesChartType.FastLine;
  313. ch[i].Series[0].Points.Clear();
  314. }
  315. for (int i = 4; i < 12; i++)
  316. {
  317. ch[i].ChartAreas.Clear();
  318. ChartArea chartArea1 = new ChartArea("C1");
  319. ch[i].ChartAreas.Add(chartArea1);
  320. //定义存储和显示点的容器
  321. ch[i].Series.Clear();
  322. Series series1 = new Series("S1");
  323. series1.ChartArea = "C1";
  324. ch[i].Series.Add(series1);
  325.  
  326. ch[i].ChartAreas[0].AxisY.IsStartedFromZero = false;
  327. ch[i].Legends[0].Enabled = false;
  328.  
  329. //ch[i].ChartAreas[0].AxisX.Interval = 100;
  330. //ch[i].ChartAreas[0].AxisX.Maximum = 10000;
  331. //ch[i].ChartAreas[0].AxisX.ScaleView.Size = 8;//设置图表可视区域数据点数,说白了一次可以看到多少个X轴区域
  332.  
  333. ch[i].ChartAreas[0].Axes[0].MajorGrid.Enabled = false;
  334. ch[i].ChartAreas[0].Axes[1].MajorGrid.Enabled = false;
  335. //y轴上网格
  336. //ct.ChartAreas[0].Axes[1].MajorGrid.Enabled = false;
  337. //ch[i].ChartAreas[0].AxisX.IsStartedFromZero = false;
  338. //ch[i].ChartAreas[0].AxisX.MajorGrid.LineColor = System.Drawing.Color.Silver;
  339. //ch[i].ChartAreas[0].AxisY.MajorGrid.LineColor = System.Drawing.Color.Silver;
  340. //设置标题
  341. ch[i].Titles.Clear();
  342. //ch[i].Titles.Add("S01");
  343. //ch[i].Titles[0].Text = "通道" + (i + 1) + " 折线图显示";
  344. //ch[i].Titles[0].ForeColor = Color.RoyalBlue;
  345. //ch[i].Titles[0].Font = new System.Drawing.Font("Microsoft Sans Serif", 12F);
  346. //设置图表显示样式
  347. ch[i].Series[0].Color = Color.Red;
  348. //this.chart1.Titles[0].Text = string.Format("{0}折线图显示", );
  349. ch[i].Series[0].ChartType = SeriesChartType.FastLine;
  350. ch[i].Series[0].Points.Clear();
  351. }
  352. }
  353.  
  354. public void chartShow(int y, int ch)
  355. {
  356.  
  357. Chart[] chNum = new Chart[8] { chart_1, chart_2, chart_3, chart_4, chart5, chart6, chart7, chart8 };
  358. if (ch <= 8)
  359. chartDisplay(chNum[ch - 1], ch, y);
  360.  
  361. }
  362. delegate void ChartDelegate(Chart chart, int ch, int y);
  363. private void chartDisplay(Chart chart, int ch, int y)
  364. {
  365.  
  366. if (chart.InvokeRequired)
  367. {
  368. ChartDelegate chartDelegate = chartDisplay;
  369. chart.Invoke(chartDelegate, new object[] { chart, ch, y });
  370. }
  371. else
  372. {
  373. lock (Lock)
  374. {
  375. if (isStart == true)
  376. UpdateQueueValue(ch, y);//点击开启按钮后,开始采集收集数据,并更新到队列或列表中
  377.  
  378. }
  379. }
  380. }
  381. private void UpdateQueueValue(int ch, int y)
  382. {
  383. lock (Lock)
  384. {
  385. if (dataQueue[ch - 1].Count > 1000)
  386. //先出列
  387. dataQueue[ch - 1].Dequeue();
  388. dataQueue[ch - 1].Enqueue(y);
  389. //方法二 用list
  390. //if (dataList[ch - 1].Count > 20000)
  391. // dataList[ch - 1].RemoveAt(0);
  392.  
  393. //dataList[ch - 1-4].Add(2);
  394. dataList[ch - 1].Add(y);
  395. }
  396. }
  397. private void btnStart_Click(object sender, EventArgs e)
  398. {
  399.  
  400. if (!isStart)
  401. {
  402. dataQueue[0] = new Queue<int>();
  403. dataQueue[1] = new Queue<int>();
  404. dataQueue[2] = new Queue<int>();
  405. dataQueue[3] = new Queue<int>();
  406. dataQueue[4] = new Queue<int>();
  407. dataQueue[5] = new Queue<int>();
  408. dataQueue[6] = new Queue<int>();
  409. dataQueue[7] = new Queue<int>();
  410.  
  411. dataList[0] = new List<int>();
  412. dataList[1] = new List<int>();
  413. dataList[2] = new List<int>();
  414. dataList[3] = new List<int>();
  415. dataList[4] = new List<int>();
  416. dataList[5] = new List<int>();
  417. dataList[6] = new List<int>();
  418. dataList[7] = new List<int>();
  419.  
  420. chart_1.Series[0].Points.Clear();
  421. chart_2.Series[0].Points.Clear();
  422. chart_3.Series[0].Points.Clear();
  423. chart_4.Series[0].Points.Clear();
  424. chart5.Series[0].Points.Clear();
  425. chart6.Series[0].Points.Clear();
  426. chart7.Series[0].Points.Clear();
  427. chart8.Series[0].Points.Clear();
  428.  
  429. btnStart.Text = @"停止采集";
  430. btnStart.DisabledImage = btnStart.Image;
  431. btnStart.Image = (Image)btnStart.PressedImage.Clone();
  432. isStart = !isStart;
  433.  
  434. }
  435. else
  436. {
  437. btnStart.Text = @"开始采集";
  438. btnStart.Image = btnStart.DisabledImage;
  439. isStart = !isStart;
  440. }
  441. }
  442. /*************文件写入函数**************/
  443. private void strWrite(string str, string filePath, string fileName)
  444. {
  445. lock (Lock)
  446. {
  447. if (!Directory.Exists(filePath))
  448. Directory.CreateDirectory(filePath);
  449. if (!File.Exists(filePath + "\\" + fileName))
  450. File.Create(filePath + "\\" + fileName).Close(); //.Close 很关键,不然会有问题
  451.  
  452. StreamWriter sw = new StreamWriter(filePath + "\\" + fileName, true);//true 追加数据
  453. sw.WriteLine(str);
  454. sw.Close();
  455. }
  456. }
  457. /*************chart图片保存函数**************/
  458. private void imageSave( Chart chart, string filePath, string fileName)
  459. {
  460. lock (Lock)
  461. {
  462. if (!Directory.Exists(filePath))
  463. Directory.CreateDirectory(filePath);
  464. chart.SaveImage(filePath +"\\" + fileName, ChartImageFormat.Png);
  465. }
  466. }
  467.  
  468. /*************定时器中更新chart**************/
  469. private void timer1_Tick(object sender, EventArgs e)
  470. {
  471.  
  472. Chart[] ch = new Chart[8] { chart1, chart2, chart3, chart4, chart5, chart6, chart7, chart8 };
  473. Chart[] cha = new Chart[4] { chart_1, chart_2, chart_3, chart_4 };
  474. string[] str = new string[8] { "chart1", "chart2", "chart3", "chart4", "chart5", "chart6", "chart7", "chart8" };
  475. string[] stri = new string[4] { "chart_1", "chart_2", "chart_3", "chart_4", };
  476. Label[] lb = new Label[4] { label2, label3, label4, label5 };
  477.  
  478. for (int j = 4; j < 8; j++)
  479. {
  480. Stopwatch sw = new Stopwatch();
  481. var k = j;//参数需要传入task中,不然j一直是7
  482. Task.Run(() =>
  483. {
  484.  
  485. sw.Start();
  486. this.Invoke((EventHandler)delegate
  487. {
  488. //chart5.Series[0].Points.Clear();
  489. for (int i = 0; i < dataList[k].Count; i++)
  490. ch[k].Series[0].Points.AddY(dataList[k][i]);//光电开关波形图-所有点
  491. dataList[k].Clear();
  492.  
  493. ch[k-4].Series[0].Points.Clear();
  494. for (int i = 0; i < dataQueue[k].Count; i++)
  495. ch[k - 4].Series[0].Points.AddY(dataQueue[k].ElementAt(i));//光电开关波形图-最近1000个点
  496.  
  497. for (int i = 0; i < dataList[k-4].Count; i++)
  498. cha[k - 4].Series[0].Points.AddY(dataList[k-4][i]);//激光测距雷达波形图--所有点
  499. dataList[k-4].Clear();
  500.  
  501. if (checkBox1.Checked == true)
  502. {
  503. //保存曲线图片
  504. String imagePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "image//" + str[k]);
  505. imageSave(ch[k], imagePath, DateTime.Now.ToString("yyyy_MM_dd_hh_mm_ss_fff") + ".png");
  506. }
  507. sw.Stop();
  508. lb[k - 4].Text = sw.ElapsedMilliseconds.ToString(str[k] + "耗时:" + "0000");//记录chart绘制的好事呢
  509. });
  510.  
  511. });
  512. }
  513.  
  514. }
  515.  
  516. }
  517. }

  运行结果:

项目源码下载地址:

链接:https://pan.baidu.com/s/1QfoIVNarj-rgK449JM40yQ

提取码:v2nu

------------------------------------------------------------------------

如果需要查看更多文章,请微信搜索公众号 csharp编程大全,需要进C#交流群群请加微信z438679770,备注进群, 我邀请你进群! ! !

C#实例(经典):四路光电开关&激光雷达数据采集和波形图绘制的更多相关文章

  1. Emgu-WPF 激光雷达研究-移动物体跟踪

    原文:Emgu-WPF 激光雷达研究-移动物体跟踪 接前两篇博客: 激光雷达数据解析并绘制雷达图 https://blog.csdn.net/u013224722/article/details/80 ...

  2. 第一个简单的Echarts实例

    该示例使用 vue-cli 脚手架搭建 安装echarts依赖 npm install echarts -S 或者使用国内的淘宝镜像: 安装 npm install -g cnpm --registr ...

  3. 基于Oracle的SQL优化(社区万众期待 数据库优化扛鼎巨著)

    基于Oracle的SQL优化(社区万众期待数据库优化扛鼎巨著) 崔华 编   ISBN 978-7-121-21758-6 2014年1月出版 定价:128.00元 856页 16开 编辑推荐 本土O ...

  4. PHP之:多图上传

    撰写日期:2016-6-30 15:17:35 Thursday 参考 http://a3147972.blog.51cto.com/2366547/1381136 (08-05ThinkPHP+sw ...

  5. PS教程1000例

    http://www.missyuan.com/thread-446934-1-1.html Photoshop绘制逼真头发发丝效果http://www.missyuan.com/thread-446 ...

  6. 2014图灵技术图书最受欢迎TOP15

    来自:图灵社区昨晚给我发的邮件,感觉不错,和大家分享,mark下. [小编语] 回首2014,感谢小伙伴们一路相随.让我们2015一起更快乐地玩耍.今天小编为大家盘点一下过去2014年表现最给力的技术 ...

  7. LiDAR、LAS、LAS Dataset与点云

    LiDAR Light Detection And Ranging,激光探测及测距,是一种光学遥感技术,使用激光对地球表面的密集采样,产生高精度X.Y.Z测量值. 激光雷达系统的主要硬件组成部分包括一 ...

  8. 最近学习工作流 推荐一个activiti 的教程文档

    全文地址:http://www.mossle.com/docs/activiti/ Activiti 5.15 用户手册 Table of Contents 1. 简介 协议 下载 源码 必要的软件 ...

  9. Java 静态工厂模式的使用

    多相关文章请参考:http://www.enjoytoday.cn/categorys/java 静态工厂模式给人的第一印象就是:static+abstract.这两个词汇已经说明了一切,一个是周期长 ...

随机推荐

  1. oracle修改管理员密码

    运行到C盘根目录 2.输入:SET ORACLE_SID = 你的SID名称 3.输入:sqlplus/nolog 4.输入:connect/as sysdba 5.输入:altre user ris ...

  2. .NET CORE命令行

    目录 0. 基础命令行 1. 基础命令 2. SDK命令 3. 使用命令行创建. net Core项目 shanzm-2020年9月7日 22:00:00 0. 基础命令行 D:默认路径跳转到D盘 c ...

  3. 19_Python算法

    1.冒泡算法 list = [1, 5, 2, 6, 9, 3, 4, 0] print(len(list)) # conunt = 1 while conunt < len(list): fo ...

  4. 如何让SpringBoot工程在log/控制台中实时打印MyBatis执行的SQL语句

    工程下载:https://files.cnblogs.com/files/xiandedanteng/gatling20200429-4.zip 其实就是一句话设置的事情,实现步骤: 在applica ...

  5. docker打包项目

    nginx镜像制作实战 docker容器的主业 docker理念里,容器启动时,应当为它指定主业是什么,如nginx容器主业就是nginx代理服务,tomcat容器就是web服务等等 1.容器创建时, ...

  6. SpringIOC初始化过程--详解

    SpringIOC初始化过程 相信大家都知道Spring这个东西,我们经常来用他一些特性,比如说他的AOP,IOC,那今天就带大家解析下SpringIOC的加载过程. 我们来看一个例子 Annotat ...

  7. Java SPI详细的例子

    先翻一个来自于Baeldung的介绍: 为了更通俗易懂我就没有直译,如果有不严谨的地方请大神指教. JavaSPI的定义 Java SPI defines four main components S ...

  8. python循环输出

    python 目录 python 1.九九乘法表 2.循环输出数字0-9,数字为六,跳出循环,执行其他循环,数字为八,结束循环 3.使用循环计算0-100素数的和 4.使用for循环输出三角形 1.九 ...

  9. js实现隔行变色

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  10. github无法访问

    打开 C:\Windows\System32\Drivers\etc 找到hosts文件. 添加以下代码 #github 192.30.255.112 github.com git 185.31.16 ...