package com.ximple.io.dgn7;
|
|
import java.nio.ByteOrder;
|
import java.util.ArrayList;
|
|
import org.apache.log4j.Logger;
|
|
import com.vividsolutions.jts.algorithm.Angle;
|
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 �U�� 06:41:45
|
*/
|
public class ArcElement extends Element implements GeometryConverter {
|
private static final Logger logger = Logger.getLogger(ArcElement.class);
|
|
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 double validAngle(double value) {
|
if (value < 0.0) value += 360.0;
|
else if (value > 360.0) value -= 360.0;
|
|
return value;
|
}
|
|
private Coordinate[] convertToLineString(int pts) {
|
ArrayList<Coordinate> result = new ArrayList<Coordinate>();
|
double rotation = validAngle(360 - getRotationAngle());
|
double beta = Angle.toRadians(-rotation);
|
double startAngle = validAngle(getStartAngle());
|
double sweepAngle = Math.abs(getSweepAngle());
|
boolean clockwise = (getSweepAngle() < 0.0);
|
double endAngle = validAngle(startAngle + getSweepAngle());
|
double steps = sweepAngle / pts;
|
|
double current;
|
for (int i = 0; i < pts; i++) {
|
if (clockwise)
|
current = startAngle - i * steps;
|
else
|
current = startAngle + i * steps;
|
|
current = validAngle(current);
|
Coordinate pt = computePointOnArcByAngle(beta, current);
|
result.add(pt);
|
}
|
|
current = validAngle(endAngle);
|
Coordinate pt = computePointOnArcByAngle(beta, current);
|
result.add(pt);
|
|
return result.toArray(new Coordinate[result.size()]);
|
}
|
|
private Coordinate computePointOnArcByAngle(double beta, double angle) {
|
double sinbeta = Math.sin(beta);
|
double cosbeta = Math.cos(beta);
|
double alpha = Angle.toRadians(angle);
|
double sinalpha = Math.sin(alpha);
|
double cosalpha = Math.cos(alpha);
|
|
Coordinate pt = new Coordinate();
|
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);
|
}
|
}
|
}
|