首先说一下,教科书上的扫描线算法确实是用c++很好实现,而且网上有很多源码,而java实现的基本没有(可能是我没看到),所以还是打算自己码(实验作业写这个而自己又个是写java的猿0.0)。

对于扫描线的实现过程,我只在这里大概讲下书本上的内容(自己去看),主要还是讲一下自己实现时算法的改动和实现方法

扫描线算法:顾名思义,就是从Ymin开始扫描,然后构建出NET,之后根据NET建立AET。

贴个图:

 

实现的时候首先是构造NET,因为对于java来说不能像c++一样直接用指针所以我用对象数组和Node类(如下代码)构造了类似数组+指针的数据结构。在实现了NET后开始通过NET实现AET,在这里我改变了一种实现方式,教科书上是一次次遍历扫描线,然后将NET插入AET后进行排序等一系列操作,而我因为是自己写的数据结构,如果说再建个表按书上的方式来最后还得自己实现链表排序等一系列操作。所以我这里直接用一个包含Arraylist的对象数组代替了。我的方法是:直接从NET开始遍历每个节点,得到节点后将它以及它自己之后会引申出的插入AET的节点(比如当前扫描线y=0 节点  X:1 dx:-1  Ymax:3 那之后会插入AET的就是 0 -1 1  和   -1  -1  2 )将这些节点不论顺序的先插入AET对应扫描线位置的对象数组的list中,将NET中节点全部遍历完之后再最后对AET中每个对象数组的list进行排序。最后得到了NET在进行打印。

贴个代码(仅供参考学习交流):

package PolygonScanningAndFilling;

public class Node {        //新编表记录x,dx,yMax
public int x;
public float dx;
public int yMax;
public Node next;
public int ymin;
public Node(int x, int dx, int yMax){
this.x=x;
this.dx=dx;
this.yMax=yMax; }
public void getYmin(int Ymin){
this.ymin=Ymin; } }
package PolygonScanningAndFilling;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List; public class classAndArray { public List<Integer> list = new ArrayList<Integer>();
public classAndArray(){ }
public void listSort() {
Collections.sort(list);
}
}
package PolygonScanningAndFilling;

import java.util.Iterator;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException; public class PolygonScanning extends JPanel { static int X0;
static int Y0;
static int X1;
static int Y1;
static int a[]=new int [10]; //保存点击的10个x坐标
static int b[]=new int [10]; //保存点击的10个y坐标
static int index=0;
static int time=0;
static int time2=0;
static boolean add;
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
this.addMouseListener(new MouseAdapter() {
public void mouseExited(MouseEvent e) {
time++;
repaint(); }
public void mouseClicked(MouseEvent e) { if(e.getButton() == e.BUTTON1) {
add=true;
if(index!=0)
{
for(int i=0;i<index;i++)
{
if(a[i]==e.getX()&&b[i]==e.getY())
add=false;
}
}
if(add)
{ a[index]=e.getX();
b[index]=e.getY(); System.out.println("坐标为("+a[index]+","+b[index]+")");
index++; //frame.setVisible(true);
repaint();
System.out.print(time2);
if(time2==0)
time2++;
}
} // if(e.getButton() == e.BUTTON3)
// {
//
// }
} }); Graphics2D g2d = (Graphics2D)g;
int Ymax=0;
for(int i=0;i<b.length;i++)
{
if(Ymax<b[i])
Ymax=b[i];
}
// System.out.println("Ymax"+Ymax); /*
* 画出多边形
*/
if(time2>0)
{
System.out.print("开始");
int Sum=0;
for(;Sum<=index;Sum++) {
if(Sum==index-1)
{
g2d.drawLine(a[Sum], b[Sum], a[0],b[0]); break;
}
else
{
g2d.drawLine(a[Sum], b[Sum], a[Sum+1],b[Sum+1]); } }
} if(time!=0) { Node [] head =new Node [Ymax]; //建立对应扫描边数的链表长度
for(int i=0;i<index-1;i++)
{ if(b[i]<b[i+1]) //从第一个点开始若前一个点小于后一个点
{
if(head[b[i]]==null)
head[b[i]]=new Node(0,0,0);
head[b[i]].ymin=b[i]; if(head[b[i]].next==null) //该点是第一个插入的节点
{
head[b[i]].next=new Node(0,0,0);
head[b[i]].next.x=a[i];
head[b[i]].next.dx=(float)(a[i]-a[i+1])/(b[i]-b[i+1]);
head[b[i]].next.yMax=b[i+1]; //ymax为后一点的y
}
else { //该点不是第一个插入的节点
if(head[b[i]].next.next==null)
head[b[i]].next.next=new Node(0,0,0);
if((float)(a[i]-a[i+1])/(b[i]-b[i+1])<head[b[i]].next.dx) //当前插入x比之前存在的节点x小
{
head[b[i]].next.next.x=head[b[i]].next.x;
head[b[i]].next.next.dx=head[b[i]].next.dx;
head[b[i]].next.next.yMax=head[b[i]].next.yMax;
head[b[i]].next.x=a[i];
head[b[i]].next.dx=(float)(a[i]-a[i+1])/(b[i]-b[i+1]);
head[b[i]].next.yMax=b[i+1];
}
else
{
head[b[i]].next.next.x=a[i];
head[b[i]].next.next.dx=(float)(a[i]-a[i+1])/(b[i]-b[i+1]);
head[b[i]].next.next.yMax=b[i+1];
}
}
}
else
{
if(head[b[i+1]]==null)
head[b[i+1]]=new Node(0,0,0);
head[b[i+1]].ymin=b[i+1];
if(head[b[i+1]].next==null) //该点是第一个插入的节点
{
head[b[i+1]].next=new Node(0,0,0);
head[b[i+1]].next.x=a[i+1];
head[b[i+1]].next.dx=(float)(a[i]-a[i+1])/(b[i]-b[i+1]);
head[b[i+1]].next.yMax=b[i]; //ymax为后一点的y
}
else { //该点不是第一个插入的节点
if(head[b[i+1]].next.next==null)
head[b[i+1]].next.next=new Node(0,0,0);
if((float)(a[i]-a[i+1])/(b[i]-b[i+1])<head[b[i+1]].next.dx) //当前插入x比之前存在的节点x小
{
head[b[i+1]].next.next.x=head[b[i+1]].next.x;
head[b[i+1]].next.next.dx=(float)head[b[i+1]].next.dx;
head[b[i+1]].next.next.yMax=head[b[i+1]].next.yMax;
head[b[i+1]].next.x=a[i+1];
head[b[i+1]].next.dx=(float)(a[i]-a[i+1])/(b[i]-b[i+1]);
head[b[i+1]].next.yMax=b[i];
}
else
{
head[b[i+1]].next.next.x=a[i+1];
head[b[i+1]].next.next.dx=(float)(a[i]-a[i+1])/(b[i]-b[i+1]);
head[b[i+1]].next.next.yMax=b[i];
}
}
} }
if(index>0)
{ if(b[0]<b[index-1]) //从第一个点到最后一个点
{
if(head[b[0]]==null)
head[b[0]]=new Node(0,0,0);
head[b[0]].ymin=b[0]; if(head[b[0]].next==null) //该点是第一个插入的节点
{
head[b[0]].next=new Node(0,0,0);
head[b[0]].next.x=a[0];
head[b[0]].next.dx=(float)(a[0]-a[index-1])/(b[0]-b[index-1]);
head[b[0]].next.yMax=b[index-1]; //ymax为后一点的y
}
else { //该点不是第一个插入的节点
if(head[b[0]].next.next==null)
head[b[0]].next.next=new Node(0,0,0);
if((float)(a[0]-a[index-1])/(b[0]-b[index-1])<head[b[0]].next.dx) //当前插入x比之前存在的节点x小
{
head[b[0]].next.next.x=head[b[0]].next.x;
head[b[0]].next.next.dx=head[b[0]].next.dx;
head[b[0]].next.next.yMax=head[b[0]].next.yMax;
head[b[0]].next.x=a[0];
head[b[0]].next.dx=(float)(a[0]-a[index-1])/(b[0]-b[index-1]);
head[b[0]].next.yMax=b[index-1];
}
else
{
head[b[0]].next.next.x=a[0];
head[b[0]].next.next.dx=(float)(a[0]-a[index-1])/(b[0]-b[index-1]);
head[b[0]].next.next.yMax=b[index-1];
}
}
}
else
{
if(head[b[index-1]]==null)
head[b[index-1]]=new Node(0,0,0);
head[b[index-1]].ymin=b[index-1];
if(head[b[index-1]].next==null) //该点是第一个插入的节点
{
head[b[index-1]].next=new Node(0,0,0);
head[b[index-1]].next.x=a[index-1];
head[b[index-1]].next.dx=(float)(a[0]-a[index-1])/(b[0]-b[index-1]);
head[b[index-1]].next.yMax=b[0]; //ymax为后一点的y
}
else { //该点不是第一个插入的节点
if(head[b[index-1]].next.next==null)
head[b[index-1]].next.next=new Node(0,0,0);
if((float)(a[0]-a[index-1])/(b[0]-b[index-1])<head[b[index-1]].next.dx) //当前插入x比之前存在的节点x小
{
head[b[index-1]].next.next.x=head[b[index-1]].next.x;
head[b[index-1]].next.next.dx=head[b[index-1]].next.dx;
head[b[index-1]].next.next.yMax=head[b[index-1]].next.yMax;
head[b[index-1]].next.x=a[index-1];
head[b[index-1]].next.dx=(float)(a[0]-a[index-1])/(b[0]-b[index-1]);
head[b[index-1]].next.yMax=b[0];
}
else
{
head[b[index-1]].next.next.x=a[index-1];
head[b[index-1]].next.next.dx=(float)(a[0]-a[index-1])/(b[0]-b[index-1]);
head[b[index-1]].next.next.yMax=b[0];
}
}
}
} for(int i=0;i<Ymax;i++)
if(head[i]!=null)
while(head[i].next!=null)
{ System.out.println("新编表y"+head[i].ymin+"新编表x"+head[i].next.x+"新编表dx"+head[i].next.dx+"新编表yMax"+head[i].next.yMax);
if(head[i].next.next!=null)
{ System.out.println("多的"+"新编表y"+head[i].ymin+"新编表x"+head[i].next.next.x+"新编表dx"+head[i].next.next.dx+"新编表yMax"+head[i].next.next.yMax);
}
break;
}
int YMIN=b[0];
for(int i=0;i<b.length;i++)
{
if(YMIN>b[i]&&b[i]!=0)
YMIN=b[i]; } classAndArray [] ca=new classAndArray [Ymax];
for(int i=YMIN;i<Ymax;i++)
ca[i]=new classAndArray();
//一个点一个点的全装入ca中再排序打印出点
for(int i=0;i<Ymax;i++)
{
if(head[i]!=null)
if(head[i].next!=null)
{
//System.out.println("新编表y"+head[i].ymin+"新编表x"+head[i].next.x+"新编表dx"+head[i].next.dx+"新编表yMax"+head[i].next.yMax);
for(int j=head[i].ymin;j<head[i].next.yMax;j++)
{ ca[i+j-head[i].ymin].list.add(head[i].next.x+(int)(0.5+((j-head[i].ymin)*head[i].next.dx)));
//System.out.print("ca[i+j-head[i].ymin]为"+(i+j-head[i].ymin)+"值为"+ca[i+j-head[i].ymin].list.toString());
//System.out.println("Ymin为"+i+" x为"+(head[i].next.x+(j-head[i].ymin)*head[i].next.dx));
} if(head[i].next.next!=null)
{ for(int j=head[i].ymin;j<head[i].next.next.yMax;j++)
{ ca[i+j-head[i].ymin].list.add(head[i].next.next.x+(int)(0.5+(j-head[i].ymin)*head[i].next.next.dx));
//System.out.print("next中ca[i+j-head[i].ymin]为"+(i+j-head[i].ymin)+"值为"+ca[i+j-head[i].ymin].list.toString());
//System.out.println("Ymin为"+i+" x为"+head[i].next.next.x+(j-head[i].ymin)*head[i].next.next.dx);
}
//System.out.println("多的"+"新编表y"+head[i].ymin+"新编表x"+head[i].next.next.x+"新编表dx"+head[i].next.next.dx+"新编表yMax"+head[i].next.next.yMax);
} }
} //
for(int i=YMIN;i<Ymax;i++)
{
ca[i].listSort();
for (int j = 0; j < ca[i].list.size(); j++) {
if(j%2==0||(j==0))
{
g2d.drawLine(ca[i].list.get(j), i, ca[i].list.get(j+1), i);
}
}
System.out.println(ca[i].list.toString());
}
}
} private static void createAndShowGUI() {
JFrame frame = new JFrame(); frame.setLocationRelativeTo(null); frame.setLayout(null);
JPanel jp=new JPanel(); frame.setVisible(true); frame.setContentPane(new PolygonScanning()); frame.setSize(600, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} public static void main(String[] args) throws IOException { createAndShowGUI(); }
}

效果截图(先在面板里点击点,鼠标移出面板填充)

JAVA实现扫描线算法的更多相关文章

  1. Spark案例分析

    一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...

  2. hdu-1542 Atlantis(离散化+线段树+扫描线算法)

    题目链接: Atlantis Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 65536/32768 K (Java/Others) ...

  3. JAVA实现种子填充算法

    种子填充算法原理在网上很多地方都能找到,这篇是继上篇扫描线算法后另一种填充算法,直接上实现代码啦0.0 我的实现只是实现了种子填充算法,但是运行效率不快,如果大佬有改进方法,欢迎和我交流,谢谢! 最后 ...

  4. 故障重现(内存篇2),JAVA内存不足导致频繁回收和swap引起的性能问题

    背景起因: 记起以前的另一次也是关于内存的调优分享下   有个系统平时运行非常稳定运行(没经历过大并发考验),然而在一次活动后,人数并发一上来后,系统开始卡. 我按经验开始调优,在每个关键步骤的加入如 ...

  5. Elasticsearch之java的基本操作一

    摘要   接触ElasticSearch已经有一段了.在这期间,遇到很多问题,但在最后自己的不断探索下解决了这些问题.看到网上或多或少的都有一些介绍ElasticSearch相关知识的文档,但个人觉得 ...

  6. 论:开发者信仰之“天下IT是一家“(Java .NET篇)

    比尔盖茨公认的IT界领军人物,打造了辉煌一时的PC时代. 2008年,史蒂夫鲍尔默接替了盖茨的工作,成为微软公司的总裁. 2013年他与微软做了最后的道别. 2013年以后,我才真正看到了微软的变化. ...

  7. 故障重现, JAVA进程内存不够时突然挂掉模拟

    背景,服务器上的一个JAVA服务进程突然挂掉,查看产生了崩溃日志,如下: # Set larger code cache with -XX:ReservedCodeCacheSize= # This ...

  8. 死磕内存篇 --- JAVA进程和linux内存间的大小关系

    运行个JAVA 用sleep去hold住 package org.hjb.test; public class TestOnly { public static void main(String[] ...

  9. 【小程序分享篇 一 】开发了个JAVA小程序, 用于清除内存卡或者U盘里的垃圾文件非常有用

    有一种场景, 手机内存卡空间被用光了,但又不知道哪个文件占用了太大,一个个文件夹去找又太麻烦,所以我开发了个小程序把手机所有文件(包括路径下所有层次子文件夹下的文件)进行一个排序,这样你就可以找出哪个 ...

随机推荐

  1. 【linux】【Go】Centos7安装go1.13环境

    前言     Go(又称Golang)是Google开发的一种静态强类型.编译型.并发型,并具有垃圾回收功能的编程语言. 罗伯特·格瑞史莫(Robert Griesemer),罗勃·派克(Rob Pi ...

  2. 网络编程之多线程——GIL全局解释器锁

    网络编程之多线程--GIL全局解释器锁 一.引子 定义: In CPython, the global interpreter lock, or GIL, is a mutex that preven ...

  3. 工厂模式(整理自李建忠<C++设计模式>视频)

    整理自李建忠<C++设计模式>视频 一.导入:"对象创建"模式和工厂模式 工厂模式只是该模式下的一种. 二.举例说明 有这样一个场景:需要在MainForm中设计一个按 ...

  4. layui-table 对表格数据进行处理之后的排序问题

    使用layui table过程中,将某一列的数据格式进行转换,或者将0/1状态改为是/否,或者将数字改为星星评分显示的时候都会遇到一个问题,我的表格数据转换成其他形式,同时设置了sort:true,此 ...

  5. 集合查询表--Map

    查询表 Map接口java提供了一组可以以键值对(key-value)的形式存储数据的数据结构,这种数据结构成为Map.我们可以把Map看成一个多行两列的表格,其中第一列存放key,第二列存放valu ...

  6. Spark 学习笔记之 优雅地关闭Spark Streaming

    优雅地关闭Spark Streaming: 当touch stop文件后,程序仍然会再执行一次,执行完成后退出.

  7. .Net Core上传文件到服务器

    /// <summary> /// 上传文件 /// </summary> /// <returns></returns> [HttpPost(&quo ...

  8. .NetCore WebApi —— Swagger版本控制

    目录: .NetCore WebApi——Swagger简单配置 .NetCore WebApi——基于JWT的简单身份认证与授权(Swagger) .NetCore WebApi —— Swagge ...

  9. js中try、catch、finally的执行规则

    首先一个常识就是,在浏览器执行JS脚本过程中,当出现脚本错误,并且你没有手动进行异常捕捉时,他会在浏览器下面出现黄色的叹号,这是正常的,这也不是最重要的,最重要的是,出错行以下的所有JS代码将中停执行 ...

  10. COGS 2510. 拯救紫萱学姐

    [题目描述] 其实在开考前半个小时题面并不是这样的. 由于明天要考试,同学们要把抽屉里的书都搬空,书很多而且办了走读不能回寝室的学长一眼就看到了回班撩他的学姐,于是就把学姐当学长用♂了:“帮我把这摞书 ...