001package icy.math; 002 003import java.util.Iterator; 004 005import icy.type.geom.Line3D; 006import icy.type.point.Point3D; 007 008/** 009 * Line3D iterator (iterate over Line3D points given a wanted step). 010 * 011 * @author Stephane Dallongeville 012 */ 013public class Line3DIterator implements Iterator<Point3D> 014{ 015 final static protected double DEFAULT_STEP = 1d; 016 017 protected boolean done; 018 protected int count; 019 final protected boolean forceLast; 020 021 final protected Point3D pos; 022 final protected Point3D last; 023 protected double sx, sy, sz; 024 025 /** 026 * Create the Line3D Iterator. 027 * 028 * @param line 029 * the lien we want to iterate points 030 * @param step 031 * step between each point (default = 1d) 032 * @param forceLastPoint 033 * set to <i>true</i> if you want the last point to match the end line position 034 */ 035 public Line3DIterator(Line3D line, double step, boolean forceLastPoint) 036 { 037 super(); 038 039 pos = line.getP1(); 040 last = line.getP2(); 041 done = false; 042 forceLast = forceLastPoint; 043 044 final double dx = last.getX() - pos.getX(); 045 final double dy = last.getY() - pos.getY(); 046 final double dz = last.getZ() - pos.getZ(); 047 final double adx = Math.abs(dx); 048 final double ady = Math.abs(dy); 049 final double adz = Math.abs(dz); 050 051 final double adjStep = (step <= 0d) ? 1d : step; 052 053 // step on X axis 054 if ((adx >= ady) && (adx >= adz)) 055 { 056 if (adx == 0d) 057 { 058 count = 0; 059 sy = 0; 060 sz = 0; 061 } 062 else 063 { 064 count = (int) (adx / adjStep); 065 sy = (ady / adx) * adjStep; 066 sz = (adz / adx) * adjStep; 067 } 068 sx = adjStep; 069 } 070 // adjStep on Y axis 071 else if ((ady >= adx) && (ady >= adz)) 072 { 073 count = (int) (ady / adjStep); 074 sx = (adx / ady) * adjStep; 075 sy = adjStep; 076 sz = (adz / ady) * adjStep; 077 } 078 // adjStep on Z axis 079 else 080 { 081 count = (int) (adz / adjStep); 082 sx = (adx / adz) * adjStep; 083 sy = (ady / adz) * adjStep; 084 sz = adjStep; 085 } 086 // for initial position 087 count++; 088 089 // reverse step if needed 090 if (dx < 0) 091 sx = -sx; 092 if (dy < 0) 093 sy = -sy; 094 if (dz < 0) 095 sz = -sz; 096 } 097 098 /** 099 * Create the Line3D Iterator. 100 * 101 * @param line 102 * the lien we want to iterate points 103 * @param step 104 * step between each point (default = 1d) 105 * @param forceLastPoint 106 * set to <i>true</i> if you want the last point to match the end line position 107 */ 108 public Line3DIterator(Line3D line, double step) 109 { 110 this(line, step, true); 111 } 112 113 /** 114 * Create the Line3D Iterator. 115 * 116 * @param line 117 * the lien we want to iterate points 118 */ 119 public Line3DIterator(Line3D line) 120 { 121 this(line, DEFAULT_STEP, true); 122 } 123 124 @Override 125 public boolean hasNext() 126 { 127 return !done; 128 } 129 130 @Override 131 public Point3D next() 132 { 133 final Point3D result = (Point3D) pos.clone(); 134 135 // done ? 136 if (--count <= 0) 137 { 138 if (forceLast) 139 { 140 // consider done only if pos is equal to last 141 done = pos.equals(last); 142 // force equality with last position 143 pos.setLocation(last); 144 } 145 else 146 done = true; 147 } 148 else 149 pos.setLocation(pos.getX() + sx, pos.getY() + sy, pos.getZ() + sz); 150 151 return result; 152 } 153 154 @Override 155 public void remove() 156 { 157 throw new UnsupportedOperationException(); 158 } 159}