package com.sundablog.clipper;
import com.sundablog.clipper.Clipper.EndType;
import com.sundablog.clipper.Clipper.JoinType;
import com.sundablog.clipper.Point.LongPoint;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 多边形节点类,用于构建多边形树结构
* 表示多边形裁剪结果中的一个节点,可以包含子节点(表示孔或嵌套多边形)
*/
public class PolyNode {
/**
* 节点类型枚举
* ANY:任意类型节点
* OPEN:开放路径节点
* CLOSED:闭合路径节点
*/
enum NodeType {
ANY, OPEN, CLOSED
}
/**
* 父节点引用
*/
private PolyNode parent;
/**
* 存储当前节点的多边形路径
*/
private final Path polygon = new Path();
/**
* 在父节点的子节点列表中的索引位置
*/
private int index;
/**
* 多边形连接类型
*/
private Clipper.JoinType joinType;
/**
* 多边形端点类型
*/
private EndType endType;
/**
* 子节点列表,存储嵌套的多边形(如孔)
*/
final List<PolyNode> childs = new ArrayList<>();
/**
* 标识当前节点是否为开放路径
*/
private boolean isOpen;
/**
* 添加子节点到当前节点
* @param child 要添加的子节点
*/
public void addChild( PolyNode child ) {
final int cnt = childs.size();
childs.add( child );
child.parent = this; // 设置子节点的父引用
child.index = cnt; // 记录子节点在列表中的索引
}
/**
* 获取子节点数量
* @return 子节点数量
*/
public int getChildCount() {
return childs.size();
}
/**
* 获取不可修改的子节点列表
* @return 子节点列表的不可修改视图
*/
public List<PolyNode> getChilds() {
return Collections.unmodifiableList( childs );
}
/**
* 获取多边形轮廓(顶点列表)
* @return 多边形顶点列表
*/
public List<LongPoint> getContour() {
return polygon;
}
/**
* 获取端点类型
* @return 端点类型
*/
public EndType getEndType() {
return endType;
}
/**
* 获取连接类型
* @return 连接类型
*/
public JoinType getJoinType() {
return joinType;
}
/**
* 获取遍历树结构的下一个节点
* 优先返回第一个子节点,如果没有子节点则返回兄弟节点或向上查找
* @return 下一个要遍历的节点,如果是最后一个节点则返回null
*/
public PolyNode getNext() {
if (!childs.isEmpty()) {
return childs.get( 0 ); // 优先返回第一个子节点
}
else {
return getNextSiblingUp(); // 查找兄弟节点或向上遍历
}
}
/**
* 递归查找下一个兄弟节点
* 如果当前节点是父节点的最后一个子节点,则递归查找父节点的下一个兄弟节点
* @return 下一个兄弟节点,如果没有则返回null
*/
private PolyNode getNextSiblingUp() {
if (parent == null) {
return null; // 如果是根节点,没有父节点,返回null
}
else if (index == parent.childs.size() - 1) {
// 如果是父节点的最后一个子节点,递归查找父节点的兄弟节点
return parent.getNextSiblingUp();
}
else {
// 返回父节点的下一个子节点
return parent.childs.get( index + 1 );
}
}
/**
* 获取父节点
* @return 父节点引用
*/
public PolyNode getParent() {
return parent;
}
/**
* 获取多边形路径对象
* @return 多边形路径
*/
public Path getPolygon() {
return polygon;
}
/**
* 判断当前节点是否表示一个孔
* 通过计算嵌套层级确定,奇数层为孔,偶数层为外部轮廓
* @return 如果是孔返回true,否则返回false
*/
public boolean isHole() {
return isHoleNode();
}
/**
* 判断节点是否为孔的内部实现
* 通过向上遍历父节点链,切换孔状态标志
* @return 如果是孔返回true,否则返回false
*/
private boolean isHoleNode() {
boolean result = true; // 初始假设为孔
PolyNode node = parent;
while (node != null) {
result = !result; // 每向上一层切换一次状态
node = node.parent;
}
return result; // 最终结果取决于嵌套深度
}
/**
* 判断多边形是否为开放路径
* @return 如果是开放路径返回true,否则返回false
*/
public boolean isOpen() {
return isOpen;
}
/**
* 设置端点类型
* @param value 要设置的端点类型
*/
public void setEndType( EndType value ) {
endType = value;
}
/**
* 设置连接类型
* @param value 要设置的连接类型
*/
public void setJoinType( JoinType value ) {
joinType = value;
}
/**
* 设置多边形是否为开放路径
* @param isOpen 开放路径标志
*/
public void setOpen( boolean isOpen ) {
this.isOpen = isOpen;
}
/**
* 设置父节点
* @param n 父节点引用
*/
public void setParent( PolyNode n ) {
parent = n;
}
}
最后修改:2025 年 12 月 03 日
© 允许规范转载