package com.ximple.io.dgn7; import java.nio.ByteOrder; import java.util.ArrayList; import org.apache.log4j.Logger; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; import com.ximple.util.DgnUtility; /** * ArcElement * * @author Ulysses * @version 0.1 * @since 2006/5/26 下午 06:41:45 */ public class ArcElement extends Element implements GeometryConverter { private static final Logger logger = Logger.getLogger(ArcElement.class); public ArcElement(byte[] raw) { super(raw); } public double getStartAngle() { int angle = (raw[18] & 0x0000ffff) << 16 | (raw[19] & 0x0000ffff); return DgnUtility.converIntToRotation(angle); } public void setStartAngle(double value) { int angle = DgnUtility.converRotatioToInt(value); raw[18] = (short) (angle >>> 16 & 0x0000ffff); raw[19] = (short) (angle & 0x0000ffff); } public double getSweepAngle() { int angle = (raw[20] & 0x0000ffff) << 16 | (raw[21] & 0x0000ffff); if (angle < 0) angle = -1 * (angle & 0x7fffffff); return DgnUtility.converIntToRotation(angle); } public void setSweepAngle(double value) { int angle = DgnUtility.converRotatioToInt(value); if (angle < 0) { angle &= 0x7fffffff; angle |= 0x80000000; } raw[20] = (short) (angle >> 16 & 0x0000ffff); raw[21] = (short) (angle & 0x0000ffff); } public double getPrimary() { rawBuffer.position(22 * 2); ByteOrder bo = rawBuffer.order(); rawBuffer.order(ByteOrder.BIG_ENDIAN); byte[] primary = new byte[8]; rawBuffer.get(primary); rawBuffer.order(bo); return DgnUtility.convertDGNToIEEEDouble(primary) / 1000.0; } public void setPrimary(double value) { double temp = value * 1000.0; short[] primary = DgnUtility.convertIEEEDoubleToDGN(temp); System.arraycopy(primary, 0, raw, 22, 4); } public double getSecondary() { rawBuffer.position(26 * 2); ByteOrder bo = rawBuffer.order(); rawBuffer.order(ByteOrder.BIG_ENDIAN); byte[] secondary = new byte[8]; rawBuffer.get(secondary); rawBuffer.order(bo); return DgnUtility.convertDGNToIEEEDouble(secondary) / 1000.0; } public void setSecondary(double value) { double temp = value * 1000.0; short[] secondary = DgnUtility.convertIEEEDoubleToDGN(temp); System.arraycopy(secondary, 0, raw, 26, 4); } public double getRotationAngle() { int rotation = (raw[30] << 16 & 0xffff0000); rotation |= raw[31] & 0x0000ffff; return DgnUtility.converIntToRotation(rotation); } public void setRotationAngle(double value) { int angle = DgnUtility.converRotatioToInt(value); raw[30] = (short) (angle >> 16 & 0x0000ffff); raw[31] = (short) (angle & 0x0000ffff); } public Coordinate getOrigin() { rawBuffer.position(32 * 2); ByteOrder bo = rawBuffer.order(); rawBuffer.order(ByteOrder.BIG_ENDIAN); byte[] rawValue = new byte[8]; rawBuffer.get(rawValue); // x double dx = DgnUtility.converUnitToCoord(DgnUtility.convertDGNToIEEEDouble(rawValue)); rawBuffer.get(rawValue); // y double dy = DgnUtility.converUnitToCoord(DgnUtility.convertDGNToIEEEDouble(rawValue)); rawBuffer.order(bo); return new Coordinate(dx, dy); } public void setOrigin(Coordinate value) { double temp = DgnUtility.converCoordToUnit(value.x); short[] x = DgnUtility.convertIEEEDoubleToDGN(temp); System.arraycopy(x, 0, raw, 32, 4); temp = DgnUtility.converCoordToUnit(value.y); short[] y = DgnUtility.convertIEEEDoubleToDGN(temp); System.arraycopy(y, 0, raw, 36, 4); } public Geometry toGeometry(GeometryFactory factory) { double sweep = getSweepAngle(); double temp = Math.abs(sweep); temp /= 4; int pts = (temp < 3) ? 3 : (int) temp; return factory.createLineString(convertToLineString(pts)); } private Coordinate[] convertToLineString(int pts) { ArrayList result = new ArrayList(); double beta = DgnUtility.converRotationToRadian(-getRotationAngle()); double startAngle = getStartAngle(); double sweepAngle = getSweepAngle(); double endAngle = startAngle + sweepAngle; double steps = sweepAngle / pts; double current; if (sweepAngle < 0) { for (current = startAngle; current > endAngle; current += steps) { Coordinate pt = computePointOnArcByAngle(beta, current); result.add(pt); } } else { for (current = startAngle; current < endAngle; current += steps) { Coordinate pt = computePointOnArcByAngle(beta, current); result.add(pt); } } Coordinate pt = computePointOnArcByAngle(beta, endAngle); result.add(pt); return result.toArray(new Coordinate[result.size()]); } private Coordinate computePointOnArcByAngle(double beta, double current) { double sinbeta = Math.sin(beta); double cosbeta = Math.cos(beta); Coordinate pt = new Coordinate(); double alpha = DgnUtility.converRotationToRadian(current); double sinalpha = Math.sin(alpha); double cosalpha = Math.cos(alpha); pt.x = getOrigin().x + (getPrimary() * cosalpha * cosbeta - getSecondary() * sinalpha * sinbeta); pt.y = getOrigin().y + (getPrimary() * cosalpha * sinbeta + getSecondary() * sinalpha * cosbeta); return pt; } public static class ElementHandler extends Element.ElementHandler { private static ElementHandler instance = null; public ElementHandler() { super(ElementType.ARC); } public static IElementHandler getInstance() { if (instance == null) { instance = new ElementHandler(); } return instance; } protected Element createElement(byte[] raw) { return new ArcElement(raw); } } }