最近项目 要画 开料图 和 开版图


package org.javafans.print.common;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import javax.imageio.ImageIO;
import org.nutz.log.Logs;


public class DrawKL {

public static void main(String[] args) throws Exception {
getInstanse().CreateSegmentationMap(
new Rectangle2D.Float(0F,0F, 990.0F, 800.0F),
new Rectangle2D.Float(0f,0F, 200.0F, 400.0F), 3, new File("d:/1/real.jpg"), false);
}

/**
* @author tangsu
* @param outside 外面的大矩形
* @param inside 里面的小矩形
* @param type 分割类型 2横着 3 混放 默认竖着
* @param tofile 图片保存到的文件
* @param isbook 是否是书本 true 是
* @return 返回HspaiResult 最后选择的画法的描述 如果outside 最大的边 小于 inside 最大的边 返回 null
*/
public HspaiResult CreateSegmentationMap(Rectangle2D r_outside, Rectangle2D r_inside, int type, File tofile, boolean isbook){
Rectangle2D outside = new Rectangle2D.Double(r_outside.getX(), r_outside.getY(), r_outside.getWidth(), r_outside.getHeight());
Rectangle2D inside = new Rectangle2D.Double(r_inside.getX(), r_inside.getY(), r_inside.getWidth(), r_inside.getHeight());
double a_w = outside.getWidth();
double a_h = outside.getHeight();
double b_w = inside.getWidth();
double b_h = inside.getHeight();
double d_temp = 0d;
if(a_w < a_h){
d_temp = a_w;
a_w = a_h;
a_h = d_temp;
outside.setRect(0d, 0d, a_w, a_h);
}
if(b_w < b_h){
d_temp = b_w;
b_w = b_h;
b_h = d_temp;
inside.setRect(0d, 0d, b_w, b_h);
}

if(a_w < b_w){//大矩形 小于 小矩形 直接返回null
return null;
}
this.isbook = isbook;
resultoutfile = tofile;
if(!resultoutfile.getParentFile().exists()){
resultoutfile.getParentFile().mkdirs();
}
if(isbook){
xuxianbs = new BasicStroke(LINEPX / 2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10F,
new float[]{2, 2f, 4f, 2f, 2f, 2f}, 0F);
xxline = new Line2D.Double();
}
try {
HspaiResult resu = null;
if(type == 2){
resu = StartDrew(CreateTransverse(outside, inside), outside, inside);
}else if(type == 3){
resu = CreateAnyway(outside, inside, false);// true 开启测试 显示计算结果 false 不测试
}else{
resu = StartDrew(CreateVertical(outside, inside), outside, inside);
}
if(resu == null){
return null;
}
resu.outside = r_outside;
resu.inside = r_inside;
resu.clxl = getClxl(resu);
return resu;
} catch (Exception e) {
Logs.getLog(DrawKL.class).error(e);
return null;
}
}


//横放 和 竖放 决定后 开始 画图
private HspaiResult StartDrew(HspaiResult result, Rectangle2D outside, Rectangle2D inside) throws Exception{
Rectangle2D huabu = getBigRect(outside, inside);
BufferedImage img = new BufferedImage((int)huabu.getWidth(), (int)huabu.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = (Graphics2D)img.getGraphics();
BasicStroke basic = new BasicStroke(LINEPX);
g2.setStroke(basic);
g2.setColor(Color.WHITE);
g2.setBackground(Color.WHITE);
g2.fill(huabu);
g2.setColor(Color.RED);
huabu.setRect(0, 0, huabu.getWidth() - LINEPX, huabu.getHeight() - LINEPX);
g2.draw(huabu);
g2.setColor(Color.BLACK);
for(int i = 1; i <= result.description.size(); i++){
for(Rectangle2D r : result.description.get(i)){
if(isbook){
drawXXLine(g2, r, xxline, xuxianbs, basic);
}
g2.draw(r);
}
}
ImageIO.write(img, "JPEG", new FileOutputStream(resultoutfile));
return result;
}

//小矩形只能横放
private HspaiResult CreateTransverse(Rectangle2D outside, Rectangle2D inside) throws Exception{
double dw = outside.getWidth() / inside.getWidth();
int wn = (int) dw;
double dh = outside.getHeight() / inside.getHeight();
int hn = (int) dh;
if(outside.getWidth() < outside.getHeight()){
outside.setRect(0, 0, outside.getHeight(), outside.getWidth());
}
double f_y_t = 0d;
double f_x_t = 0d;
int row = 0;
List<Rectangle2D> dep_arl = new LinkedList<Rectangle2D>();
HashMap<Integer, List<Rectangle2D>> description = new HashMap<Integer, List<Rectangle2D>>();
description.put(++row, dep_arl);
HspaiResult re_temp = new HspaiResult();
re_temp.description = description;
for(int i = 0; i <= hn; i++){
if(outside.getHeight() - f_y_t < inside.getHeight()){
break;
}
f_x_t = 0d;
for(int j = 0; j <= wn; j++){
if(outside.getWidth() - f_x_t < inside.getWidth()){
break;
}
inside.setRect(f_x_t , f_y_t, inside.getWidth(), inside.getHeight());
dep_arl.add(new Rectangle2D.Double(inside.getX(), inside.getY(), inside.getWidth(), inside.getHeight()));
++ re_temp.total;
f_x_t += inside.getWidth();
}
f_y_t += inside.getHeight();
dep_arl = new LinkedList<Rectangle2D>();
description.put(++row, dep_arl);
}
return re_temp;
}

//小矩形只能竖放
private HspaiResult CreateVertical(Rectangle2D outside, Rectangle2D inside) throws Exception{
inside.setRect(inside.getX(), inside.getY(), inside.getHeight(), inside.getWidth());
return CreateTransverse(outside, inside);
}

//小矩形可以随意放
private HspaiResult CreateAnyway(Rectangle2D outside, Rectangle2D inside, boolean debug) throws Exception{
//全部横排
HspaiResult hzfimg = CreateTransverse(outside, inside);
int hp_total = hzfimg.total;
//全部竖排
HspaiResult szfimg = CreateVertical(outside, inside);
int sp_total = szfimg.total;
//混排
int hsp_total = getMaxiMum(outside, inside);

if(debug){
hp_total = 0;
sp_total = 0;
}

if(hp_total >= sp_total && hp_total >= hsp_total){//横排最多
return StartDrew(hzfimg,outside, inside);
}else if(sp_total >= hp_total && sp_total >= hsp_total){//竖排最多
return StartDrew(szfimg,outside, inside);
}else{//横竖混排最多
Rectangle2D huabu = null;
if(maxresult.description.size() > 0){
List<Rectangle2D> frow = maxresult.description.get(1);
double huabu_w = outside.getWidth() + ((frow.size() + 1) * LINEPX);
double huabu_h = outside.getHeight() + ((maxresult.description.size() + 1) * LINEPX);
outside.setRect(0, 0, huabu_w, huabu_h);
huabu = outside;
}else{
huabu = getBigRect(outside, inside);
}
BufferedImage img = new BufferedImage((int)huabu.getWidth(), (int)huabu.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = (Graphics2D)img.getGraphics();
g2.setStroke(new BasicStroke(LINEPX));
g2.setColor(Color.WHITE);
g2.setBackground(Color.WHITE);
g2.fill(huabu);
g2.setColor(Color.RED);
outside.setRect(0, 0, outside.getWidth() - LINEPX, outside.getHeight() - LINEPX);
g2.draw(huabu);
g2.setColor(Color.BLACK);
BasicStroke bases = new BasicStroke(LINEPX);
//--------------------------------测试计算过程-------实际应用中 debug = false ------------------------------------------
int iname = 0;
if(debug){
for(HspaiResult hs_resu_te : relist){
iname++;
for(int i = 1; i <= maxresult.description.size(); i++){
for(Rectangle2D r : maxresult.description.get(i)){
if(isbook){
drawXXLine(g2, r, xxline, xuxianbs, bases);
}
g2.draw(r);
System.out.println(r);
}
}
System.out.println("============================= " + iname + " ===========================");
ImageIO.write(img, "JPEG", new FileOutputStream(new File("d:/1/"+iname+".jpg")));
img = new BufferedImage((int)huabu.getWidth(), (int)huabu.getHeight(), BufferedImage.TYPE_INT_RGB);
g2 = (Graphics2D)img.getGraphics();
g2.setStroke(bases);
g2.setColor(Color.WHITE);
g2.setBackground(Color.WHITE);
g2.fill(huabu);
g2.setColor(Color.RED);
outside.setRect(0, 0, outside.getWidth() - LINEPX, outside.getHeight() - LINEPX);
g2.draw(huabu);
g2.setColor(Color.BLACK);
}
img = new BufferedImage((int)huabu.getWidth(), (int)huabu.getHeight(), BufferedImage.TYPE_INT_RGB);
g2 = (Graphics2D)img.getGraphics();
g2.setStroke(bases);
g2.setColor(Color.WHITE);
g2.setBackground(Color.WHITE);
g2.fill(huabu);
g2.setColor(Color.RED);
outside.setRect(0, 0, outside.getWidth() - LINEPX, outside.getHeight() - LINEPX);
g2.draw(huabu);
g2.setColor(Color.BLACK);
}
//------------------debug code row end ----------------------------------------------------------------------------------------
for(int i = 1; i <= maxresult.description.size(); i++){
for(Rectangle2D r : maxresult.description.get(i)){
if(isbook){
drawXXLine(g2, r, xxline, xuxianbs, bases);
}
g2.draw(r);
if(debug){
System.out.println(r);
}
}
}
System.out.println(maxresult.total);
resultoutfile.deleteOnExit();
if(debug){
ImageIO.write(img, "JPEG", new FileOutputStream(new File("d:/1/"+(iname+1)+".jpg")));
}else{
ImageIO.write(img, "JPEG", new FileOutputStream(resultoutfile));
}
return maxresult;
}
}

private int getMaxiMum(Rectangle2D outside, Rectangle2D inside){//开始混排 分别 2种混排 方式 返回混排最大能排的数量
double a_w = outside.getWidth();
double a_h = outside.getHeight();
double b_w = inside.getWidth();
double b_h = inside.getHeight();
double d_temp = 0d;
if(a_w < a_h){
d_temp = a_w;
a_w = a_h;
a_h = d_temp;
}
if(b_w < b_h){
d_temp = b_w;
b_w = b_h;
b_h = d_temp;
}

getMaxiMumOne(a_w, a_h, b_w, b_h, 3, outside); //使用第一种混排方法 一直排列 竖着的 从1开始

getMaxiMumTwo(a_w, a_h, b_w, b_h, 3, outside); //使用第2种混排方法 每排竖着开始

//全部计算完成 遍历 所有排法 找到最多的
for(HspaiResult r : relist){//循环查找裁剪最多的方法
if(maxresult == null && r != null){
maxresult = r;
}else if(r != null && maxresult.total < r.total){
maxresult = r;
}
}

if(maxresult != null){
return maxresult.total;
}

return 0;
}

private void getMaxiMumOne(double a_w, double a_h, double b_w, double b_h, int type, Rectangle2D outside){//页面 混排法1 一个个 竖排着走
int sp_total = (int)((a_w/b_w) * (a_h/b_h));
List<Rectangle2D> dep_arl = null;
HashMap<Integer, List<Rectangle2D>> description = null;
HspaiResult re_temp = null;
Rectangle2D rectangle2d_cell_temp = null;
int max_sp = (int)(a_w / b_h);
double last_sz_hight = 0d;//最高的一个 竖着的,用于 判断是否画完了
boolean isDown = false;// 是否不能再往下填 竖着的 了
for(int i = 1; i <= sp_total; i++){
if(isDown){//如果不能往下填 竖着的了 直接结束循环
break;
}
int row = 1;
re_temp = new HspaiResult();
description = new HashMap<Integer, List<Rectangle2D>>();
dep_arl = new LinkedList<Rectangle2D>();
re_temp.description = description;
description.put(row, dep_arl);
int first_add_sp_row = i % max_sp == 0 ? i / max_sp : (i / max_sp + 1);
first_add_sp_row = first_add_sp_row == 0 ? 1 : first_add_sp_row;
float first_sp_x = 0F;
float first_sp_y = 0F;
for(int iii = 1; iii <= i; iii++){//填充开始的竖着的图形
if(a_w - first_sp_x < b_h){//横排 竖行 放满了 需要换行
first_sp_y += b_w;
if(a_h - first_sp_y < b_w){//检查是否 无法再 放竖着的了
isDown = true;
break;
}
dep_arl = new LinkedList<Rectangle2D>();
description.put(++row, dep_arl);
first_sp_x = 0F;
rectangle2d_cell_temp = new Rectangle2D.Float(first_sp_x, first_sp_y, (float)b_h, (float)b_w);
dep_arl.add(rectangle2d_cell_temp);
++re_temp.total;
}else{//不用换行
rectangle2d_cell_temp = new Rectangle2D.Float(first_sp_x, first_sp_y, (float)b_h, (float)b_w);
dep_arl.add(rectangle2d_cell_temp);
++re_temp.total;
}
if(rectangle2d_cell_temp.getY() + rectangle2d_cell_temp.getHeight() > last_sz_hight){
last_sz_hight = rectangle2d_cell_temp.getY() + rectangle2d_cell_temp.getHeight();
}
first_sp_x += b_h;
}
Rectangle2D last_sp = rectangle2d_cell_temp;
double x = 0d;
double y = 0d;
//开始计算并且插入横着的图形
if(last_sp != null){
while(true){
if(a_w - rectangle2d_cell_temp.getX() - rectangle2d_cell_temp.getWidth() < b_w){ //判断是否已经裁剪完成了
if(rectangle2d_cell_temp == last_sp){//最后一个是竖着的
if(a_h - last_sz_hight < b_h){
break;
}
}else{
if(last_sz_hight > rectangle2d_cell_temp.getY() + rectangle2d_cell_temp.getHeight()){
if(a_h - last_sz_hight < b_h){
break;
}
}else if(a_h - rectangle2d_cell_temp.getY() - rectangle2d_cell_temp.getHeight() < b_h){
break;
}
}
}
if(rectangle2d_cell_temp == last_sp){//说明最后一个是竖着的 直接比较内存地址
if(a_w - last_sp.getX() - last_sp.getWidth() >= b_w){//还能放下一个横着的
x = last_sp.getX() + last_sp.getWidth();
y = last_sp.getY();
}else{
dep_arl = new LinkedList<Rectangle2D>();
description.put(++row, dep_arl);
x = 0;
y = last_sp.getY() + last_sp.getHeight();
}
}else{//最后一个是横着的
if(a_w - rectangle2d_cell_temp.getX() - rectangle2d_cell_temp.getWidth() >= b_w){
x = rectangle2d_cell_temp.getX() + rectangle2d_cell_temp.getWidth();
y = rectangle2d_cell_temp.getY();
}else{//换行,考虑在不在竖着的影响内
dep_arl = new LinkedList<Rectangle2D>();
description.put(++row, dep_arl);
if(last_sz_hight - rectangle2d_cell_temp.getY() - rectangle2d_cell_temp.getHeight() >= b_h){//就算换行也在竖着的高内 (能够放的下)
x = last_sp.getX() + last_sp.getWidth();
y = rectangle2d_cell_temp.getY() + rectangle2d_cell_temp.getHeight();
}else{
x = 0d;
if(last_sz_hight > rectangle2d_cell_temp.getY() + rectangle2d_cell_temp.getHeight()){
y = last_sz_hight;
}else{
y = rectangle2d_cell_temp.getY() + rectangle2d_cell_temp.getHeight();
}
}
}
}
rectangle2d_cell_temp = new Rectangle2D.Double(x, y, b_w, b_h);
dep_arl.add(rectangle2d_cell_temp);
++re_temp.total;
}
}else{//一个竖着的都放不下
dep_arl = new LinkedList<Rectangle2D>();
description.put(++row, dep_arl);
rectangle2d_cell_temp = new Rectangle2D.Double(0d, 0d, b_w, b_h);
dep_arl.add(rectangle2d_cell_temp);
++re_temp.total;
isDown = true;
}
relist.add(re_temp);
}
}

private void getMaxiMumTwo(double a_w, double a_h, double b_w, double b_h, int type, Rectangle2D outside){//页面 混排法2 每列 开头都是横的 然后用竖的填
int hp_total = (int)((a_w/b_w) * (a_h/b_h));
List<Rectangle2D> dep_arl = null;
HashMap<Integer, List<Rectangle2D>> description = null;
HspaiResult re_temp = null;
Rectangle2D rectangle2d_cell_temp = null;
int max_sp = (int)(a_w / b_h);
boolean isDown = false;// 是否不能再往下填 竖着的 了
for(int i = 1; i <= hp_total; i++){
if(isDown){//如果不能往下填 横着的了 直接结束循环
break;
}
int row = 1;
re_temp = new HspaiResult();
description = new HashMap<Integer, List<Rectangle2D>>();
dep_arl = new LinkedList<Rectangle2D>();
re_temp.description = description;
description.put(row, dep_arl);
int first_add_sp_row = i % max_sp == 0 ? i / max_sp : (i / max_sp + 1);
first_add_sp_row = first_add_sp_row == 0 ? 1 : first_add_sp_row;
double hx = 0d;
double hy = 0d;
for(int iii = 1; iii <= i; iii++){//填充开始的竖着的图形
while(true){//放 横着的
if(a_w - hx - b_w < b_w){//这排 横着的 放满了
if(a_h - hy < b_h){// 已经不能继续循环了查找排法了
isDown = true;
break;
}
}
//没有放完
if(a_h - hy < b_h){
break;
}else{
rectangle2d_cell_temp = new Rectangle2D.Double(hx, hy, b_w, b_h);
dep_arl.add(rectangle2d_cell_temp);
++re_temp.total;
hy += b_h;
}
}
if(isDown){
break;
}
if(iii != i){
hx += b_w;
hy = 0d;
dep_arl = new LinkedList<Rectangle2D>();
description.put(++row, dep_arl);
}
}
// Rectangle2D last_sp = rectangle2d_cell_temp;//最后一个自动模式添加的
double x = hx + b_w;
double y = 0d;
//开始计算并且插入竖着的图形
if(a_w - x >= b_h){
while(true){
if(a_h - y < b_w){//必须换行
if(a_w - x - b_h < b_h){//判断 是否还能继续 换行 添加 竖着的
break;
}
dep_arl = new LinkedList<Rectangle2D>();
description.put(++row, dep_arl);
y = 0d;
x += hx + b_h;
}
rectangle2d_cell_temp = new Rectangle2D.Double(x, y, b_h, b_w);
dep_arl.add(rectangle2d_cell_temp);
++re_temp.total;
y += b_w;
}
}
relist.add(re_temp);
}
}

/**
* 返回 画布的 估计大小
* @param out 大矩形
* @param ins 小矩形
* @return 返回画布
*/
private Rectangle2D getBigRect(Rectangle2D out, Rectangle2D ins){
double a_w = out.getWidth();
double a_h = out.getHeight();
double b_w = ins.getWidth();
double b_h = ins.getHeight();
double d_temp=0d;
if(a_w < a_h){
d_temp = a_w;
a_w = a_h;
a_h = d_temp;
}
if(b_w < b_h){
d_temp = b_h;
b_h = b_w;
b_w = d_temp;
}
double w = a_w + ((int)(a_w / b_h) + 1) * LINEPX;
double h = a_h + ((int)(a_h / b_h) + 1) * LINEPX;
return new Rectangle2D.Double(0d, 0d, w, h);
}

public static DrawKL getInstanse(){
return new DrawKL();
}

private DrawKL() {
}

/**
* 描述 画图结果
* @author 樱花林下
*
*/
public class HspaiResult{
/**
* 小图总数
*/
public int total = 0;
/**
* 画法描述
* key 为 行数 1 2 3以此类推
*/
public HashMap<Integer, List<Rectangle2D>> description = null;
/**
* 材料的利用率
*/
public double clxl = 0d;
/**
* 画图的大小矩形
*/
public Rectangle2D outside = null;
public Rectangle2D inside = null;
/**
* 输出的文件路径
*/
public String filepath = null;
/**
* 理论原纸数
*/
public double papernum = 0d;
}
/**
* 用于画 书籍 的 虚线
* @param g2 画笔
* @param r 当前的小矩形
* @param xxline 要更新的虚线对象
* @param xuxianbs 虚线的样式
* @param bases 原来的样式
*/
private void drawXXLine(Graphics2D g2, Rectangle2D r, Line2D xxline, BasicStroke xuxianbs, BasicStroke bases){
g2.setStroke(xuxianbs);
g2.setColor(Color.RED);
if(r.getWidth() > r.getHeight()){
xxline.setLine(r.getX() + (r.getWidth() / 2), r.getY(), r.getX() + (r.getWidth() / 2), r.getY()+r.getHeight());
}else{
xxline.setLine(r.getX(), r.getY() + (r.getHeight() / 2), r.getX() + r.getWidth(), r.getY() + (r.getHeight() / 2));
}
g2.draw(xxline);
g2.setStroke(bases);
g2.setColor(Color.BLACK);
}
/**
* 计算材料利用率
* @param 画法描述
* @return 利用率
*/
private double getClxl(HspaiResult resu) {
double a_in_m = resu.inside.getWidth() * resu.inside.getHeight() * resu.total;
double a_ou_m = resu.outside.getWidth() * resu.outside.getHeight();
return BigDecimal.valueOf((a_in_m / a_ou_m) * 100).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
}

private File resultoutfile = null; // 要把最后的 结果 画到的 图片文件
private HspaiResult maxresult = null; // 混合排版 最后找到的最多 的 结果
private List<HspaiResult> relist = new LinkedList<HspaiResult>(); // 混合排版 的 所有排法的 描述
private final static int LINEPX = 1; // 图形的 边框 宽度
private boolean isbook = false;//是否是书本
//如果是书本 会初始化
private BasicStroke xuxianbs = null;
private Line2D xxline = null;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值