java 图形处理_课内资源 - 基于Java实现的几何图形处理系统

本文介绍了基于Java实现的几何图形处理系统,涵盖了直线、矩形、圆、椭圆、多边形等图形的输入、编辑、裁剪、变换等功能。系统支持用户界面交互,包括选择画笔形状、大小、颜色,以及保存和读取图形。算法方面,文章详细阐述了DDA算法、中点生成算法、Cohen-Sutherland裁剪算法等。系统使用Java Swing/AWT库,结合OpenGL进行三维模型显示,开发环境为IntelliJ IDEA。
摘要由CSDN通过智能技术生成

1 综述

针对《计算机图形学》课程开发的几何图形处理系统实现的功能包括:在UI界面中通过鼠标点击拖拽等方式可视化地输入二维图形的功能;编辑最近输入的二维图形的功能;裁剪直线的功能,支持的图形包括任意涂鸦、直线、矩形、圆、椭圆、多边形、填充多边形、B样条曲线、Bezier 曲线;变换二维图形的功能;用文件/路径选择器将绘制出来的图形保存为图像以及选取载入显示图片文件的存储和读取二维图形的功能;载入并显示一个 OFF 格式的三维模型的功能;

此外,系统中还支持选择画笔的形状大小,颜色,选择多边形填充颜色,清理画板,并提供了一个美观的用户使用界面。

在实现算法时要考虑许多实际的问题,在图形系统的画布上建立坐标系,由于在画布上是以像素的形式呈现、编辑以及输入输出图形的,所以图形绘制算法的一个主要的任务是将图形的数学表达式尽可能准确地绘制成画布上的像素点。

2 算法介绍

2.1 二维图形的输入功能

2.1.1 直线

输入直线(或者线段)采用数值差分分析DDA算法,主要过程是,鼠标点击确定直线的起点,然后拖动鼠标实时改变直线的方向,对每一个时刻,鼠标起点与目前所在的点就确定了当前的直线。由两点坐标就可以求出直线方程。求出直线的斜率,对于具有不大于 1 的正斜率的直线,在 x 方向以单位间隔取样,以增量形式顺序计算每个 y 的值,依据该增量在 y 轴寻找最接近路径的整数值,这样选取坐标轴的目的是为了取较多的样本点,绘制出来的像素点不会过于稀疏.对于具有大于 1 的斜率的直线,在 y 方向以单位间隔取样算 x 方向的增量,在 x 方向取最接近直线的点;对于具有绝对值不大于 1 的负斜率的直线,在 x 方向取增量;对于具有绝对值大于 1 的负斜率的直线,在 y 方向取增量。

2.1.2 矩形

矩形的绘制只要确定对角的两个顶点就比较容易完成。在确定两顶点的坐标后,由于矩形的边都是水平或垂直的线,与像素点重合,故只需要单个坐标轴递增绘出即可。

2.1.3 圆/椭圆

圆和椭圆的绘制应用中点生成算法。中点生成算法可以避免平方根运算,直接采用像素与圆距离的平方作为判决依据,通过检验两个候选像素中点与圆周边界的相对位置关系,即圆周边界内或圆周边界外,来选择像素. 首先通过鼠标点击和拖动可以确定圆心和圆边界上的某个点,进而可以确定任意时刻的圆半径以及圆函数,以圆函数作为决策参数,将候选像素的中点位置的数据代入圆函数中,依据函数符号来判断其与圆的相对位置关系。若以圆心为原点建立坐标轴,考虑不同象限内圆弧的生成,结合候选像素中点在圆函数计算得的符号决定保留低像素还是高像素,椭圆也可以采用类似的算法。

由于圆和椭圆的对称性,椭圆可以只考虑一个象限内的生成,而圆可以只考虑 1/4 象限的生成,剩下的部分通过对称运算来节省计算量。

8263fc59fec3c8217c44331c2519251d.png

由圆的方程

cbadb9c432838f0a9a9de4cb3e3f15ff.png

得到判定函数 fcirc(x,y) < 0 时点 (x , y)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ImageComparerUI——基于Java语言实现的相似图像识别,基于直方图比较算法。 import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.MediaTracker; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JPanel; public class ImageComparerUI extends JComponent implements ActionListener { /** * */ private static final long serialVersionUID = 1L; private JButton browseBtn; private JButton histogramBtn; private JButton compareBtn; private Dimension mySize; // image operator private MediaTracker tracker; private BufferedImage sourceImage; private BufferedImage candidateImage; private double simility; // command constants public final static String BROWSE_CMD = "Browse..."; public final static String HISTOGRAM_CMD = "Histogram Bins"; public final static String COMPARE_CMD = "Compare Result"; public ImageComparerUI() { JPanel btnPanel = new JPanel(); btnPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); browseBtn = new JButton("Browse..."); histogramBtn = new JButton("Histogram Bins"); compareBtn = new JButton("Compare Result"); // buttons btnPanel.add(browseBtn); btnPanel.add(histogramBtn); btnPanel.add(compareBtn); // setup listener... browseBtn.addActionListener(this); histogramBtn.addActionListener(this); compareBtn.addActionListener(this); mySize = new Dimension(620, 500); JFrame demoUI = new JFrame("Similiar Image Finder"); demoUI.getContentPane().setLayout(new BorderLayout()); demoUI.getContentPane().add(this, BorderLayout.CENTER); demoUI.getContentPane().add(btnPanel, BorderLayout.SOUTH); demoUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); demoUI.pack(); demoUI.setVisible(true); } public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; if(sourceImage != null) { Image scaledImage = sourceImage.getScaledInstance(300, 300, Image.SCALE_FAST); g2.drawImage(scaledImage, 0, 0, 300, 300, null); } if(candidateImage != null) { Image scaledImage = candidateImage.getScaledInstance(300, 330, Image.SCALE_FAST); g2.drawImage(scaledImage, 310, 0, 300, 300, null); } // display compare result info here Font myFont = new Font("Serif", Font.BOLD, 16); g2.setFont(myFont); g2.setPaint(Color.RED); g2.drawString("The degree of similarity : " + simility, 50, 350); } public void actionPerformed(ActionEvent e) { if(BROWSE_CMD.equals(e.getActionCommand())) { JFileChooser chooser = new JFileChooser(); chooser.showOpenDialog(null); File f = chooser.getSelectedFile(); BufferedImage bImage = null; if(f == null) return; try { bImage = ImageIO.read(f); } catch (IOException e1) { e1.printStackTrace(); } tracker = new MediaTracker(this); tracker.addImage(bImage, 1); // blocked 10 seconds to load the image data try { if (!tracker.waitForID(1, 10000)) { System.out.println("Load error."); System.exit(1); }// end if } catch (InterruptedException ine) { ine.printStackTrace(); System.exit(1); } // end catch if(sourceImage == null) { sourceImage = bImage; }else if(candidateImage == null) { candidateImage = bImage; } else { sourceImage = null; candidateImage = null; }
Eclipse平台JAVA实现 1. 实验内容 用基本增量算法和Bresenham算法画直线 2.实验目的 1)理解在显示器上画图与在纸上画图的本质区别; 2)掌握直线的光栅扫描转换过程; 3)掌握不同算法绘制直线的思路和优缺点。 3. 实验要求 1)将像素网格表现出来,建立网格坐标系; 2)用橡皮筋的形式输入参数; 3)鼠标移动时,显示鼠标当前位置; 4)显示判别式的计算过程和下一点的选择策略; 5)记录生成点的坐标,建议用表的形式; 6)图形生成过程可以重复进行。 1. 实验内容 用正负法和Bresenham算法画弧 2.实验目的 1)掌握弧的光栅扫描转换过程; 2)掌握不同算法绘制弧的技巧和优缺点。 3. 实验要求 1)将像素网格表现出来,建立网格坐标系; 2)用橡皮筋的形式输入参数; 3)鼠标移动时,显示鼠标当前位置; 4)显示判别式的计算过程和下一点的选择策略; 5)记录生成点的坐标,建议用表的形式; 6)图形生成过程可以重复进行。 1. 实验内容 用Cohen-SutherLand算法和liang _barsky算法进行线段裁剪 2.实验目的 1)理解裁剪的相关概念 2)掌握直线段的一般裁剪过程; 3)理解并掌握Cohen-SutherLand 算法的编码思想; 4)理解并掌握Liang_Barsky算法的参数化裁剪思想; 3. 实验要求 1)将像素网格表现出来,建立网格坐标系; 2)用橡皮筋的形式输入剪裁线段和裁剪窗口; 3)鼠标移动时,显示鼠标当前位置; 4)对于线段裁剪,线段被窗口的四条边裁剪的过程要显示出来; 6)裁剪过程可以重复进行。 1. 实验内容 用Sutherland-Hodgman算法进行多边形裁剪 2.实验目的 1)理解多边形裁剪与直线段裁剪的区别; 2)掌握多边形的裁剪过程; 3)理解并掌握Sutherland-Hodgman算法的裁剪思想。 3. 实验要求 1)将像素网格表现出来,建立网格坐标系; 2)用橡皮筋的形式输入剪裁多边形和裁剪窗口; 3)鼠标移动时,显示鼠标当前位置; 4)多边形被窗口的四条边裁剪的过程以及多边形顶点增删的过程要显示出来; 5)裁剪过程可以重复进行。
好的,关于使用信号量实现理发师问题,你可以参考以下步骤: 1. 定义信号量 使用Java提供的Semaphore类定义两个信号量,一个表示等待理发的顾客数量,一个表示理发师是否忙碌: ```java Semaphore customers = new Semaphore(0); Semaphore barber = new Semaphore(0); ``` 2. 定义线程 定义两个线程,一个代表理发师,一个代表顾客: ```java class Barber extends Thread { public void run() { while (true) { try { // 等待顾客到来 customers.acquire(); // 开始理发 System.out.println("Barber is cutting hair"); sleep(3000); // 理发完成 barber.release(); } catch (InterruptedException e) { e.printStackTrace(); } } } } class Customer extends Thread { public void run() { try { // 到理发店等待 System.out.println("Customer is waiting"); customers.release(); // 等待理发师理发 barber.acquire(); // 理发完成 System.out.println("Customer is done with hair cut"); } catch (InterruptedException e) { e.printStackTrace(); } } } ``` 3. 启动线程 在main函数中创建理发师和顾客线程,并启动: ```java public static void main(String[] args) { Barber barber = new Barber(); Customer customer1 = new Customer(); Customer customer2 = new Customer(); Customer customer3 = new Customer(); barber.start(); customer1.start(); customer2.start(); customer3.start(); } ``` 这样就完成了使用信号量实现理发师问题的编写。在这个程序中,顾客线程等待理发师线程,而理发师线程等待顾客线程。通过信号量的机制,实现两个线程之间的同步。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值