package com.ximple.io.dgn7; //~--- JDK imports ------------------------------------------------------------ import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.List; import com.vividsolutions.jts.geom.Envelope; import com.ximple.util.DgnUtility; /** * FileRecord * * @author Ulysses * @version 0.1 */ public class Element { public static final int CONSTRUCTION_CLASS = 0; public static final int CONSTRUCTION_RULE_CLASS = 0; public static final int DIMENSION_CLASS = 0; public static final int LINEAR_PATTERNED_CLASS = 0; public static final int MAX_ELEMENT_SIZE = 0; public static final int MAX_VERTICES = 100; public static final int PATTERN_AREA = 0; public static final int PATTERN_COMPONENT_CLASS = 0; public static final int PATTERN_CROSSHATCH = 0; public static final int PATTERN_HATCH = 0; public static final int PRIMARY_CLASS = 0; public static final int PRIMARY_RULE_CLASS = 0; protected short[] raw; protected byte attrOffset = 0; protected ByteBuffer rawBuffer; protected boolean newElement = false; Element(byte[] raw) { // this.raw = raw; this.raw = new short[raw.length / 2]; rawBuffer = ByteBuffer.wrap(raw); rawBuffer.order(ByteOrder.LITTLE_ENDIAN); rawBuffer.asShortBuffer().get(this.raw); } public int getLineStyle() { return (raw[17] & 0x0007); } protected void setLineStyle(int value) { if (value > -1 && value < 8) raw[17] = (short) ((raw[17] & 0xfff8) | (value & 0x0007)); else new IllegalArgumentException("Out of Range!"); } public Envelope getRange() { int lowCoorX = ((raw[3] << 16) & 0xffff0000) + (raw[2] & 0x0000ffff); lowCoorX = DgnUtility.convertFromDGN(lowCoorX); int lowCoorY = ((raw[5] << 16) & 0xffff0000) + (raw[4] & 0x0000ffff); lowCoorY = DgnUtility.convertFromDGN(lowCoorY); int highCoorX = ((raw[9] << 16) & 0xffff0000) + (raw[8] & 0x0000ffff); highCoorX = DgnUtility.convertFromDGN(highCoorX); int highCoorY = ((raw[11] << 16) & 0xffff0000) + (raw[10] & 0x0000ffff); highCoorY = DgnUtility.convertFromDGN(highCoorY); return new Envelope(DgnUtility.converUnitToCoord(lowCoorX), DgnUtility.converUnitToCoord(highCoorX), DgnUtility.converUnitToCoord(lowCoorY), DgnUtility.converUnitToCoord(highCoorY)); } public void setRange(Envelope bbox) { int lowCoordX = DgnUtility.converCoordToUnit(bbox.getMinX()); int temp = DgnUtility.converToDGN(lowCoordX); raw[3] = (short) (temp >> 16 & 0x0000ffff); raw[2] = (short) (temp & 0x0000ffff); int lowCoordY = DgnUtility.converCoordToUnit(bbox.getMinY()); temp = DgnUtility.converToDGN(lowCoordY); raw[5] = (short) (temp >> 16 & 0x0000ffff); raw[4] = (short) (temp & 0x0000ffff); // lowZ raw[7] = 0; raw[8] = 0; int highCoorX = DgnUtility.converCoordToUnit(bbox.getMaxX()); temp = DgnUtility.converToDGN(highCoorX); raw[9] = (short) (temp >> 16 & 0x0000ffff); raw[8] = (short) (temp & 0x0000ffff); int highCoorY = DgnUtility.converCoordToUnit(bbox.getMaxY()); temp = DgnUtility.converToDGN(highCoorY); raw[11] = (short) (temp >> 16 & 0x0000ffff); raw[10] = (short) (temp & 0x0000ffff); // highZ raw[13] = (short) 0xffff; raw[12] = (short) 0xffff; } public boolean isComponentElement() { return (short) ((raw[0] >>> 7) & 0x0001) == 1; } protected void setComponentElement(boolean value) { raw[0] = (short) ((raw[0] & 0xff7f) | (value ? 0x0080 : 0x0)); } public boolean removeUserAttributeData(int iLinkageId) { return true; } public boolean removeUserAttributeData(int iLinkageId, int iLinkageIndex) { return true; } public boolean isDeleted() { return (short) ((raw[0] >>> 15) & 0x0001) == 1; } protected void setDeleted(boolean value) { raw[0] = (short) ((raw[0] & 0x7fff) | ((((value) ? 1 : 0) << 15) & 0x8000)); } public int getColorIndex() { return ((raw[17] >>> 8) & 0x00ff); } protected void setColorIndex(int value) { if (value > -1 && value < 256) { raw[17] = (short) ((raw[17] & 0x00ff) | (value << 8 & 0xff00)); } else new IllegalArgumentException("Out of Range!"); } public int getType() { return ((raw[0] >>> 8) & 0x007f); } protected void setType(int value) { raw[0] = (short) ((raw[0] & 0x80ff) | (value << 8) & 0x3f00); } public ElementType getElementType() { return ElementType.forID(getType()); } public int getLevelIndex() { return (raw[0] & 0x003f); } public void setLevelIndex(int value) { raw[0] = (short) ((raw[0] & 0xffc0) | (value & 0x003f)); } public int getWeight() { return ((raw[17] >>> 3) & 0x001f); } public void setWeight(int value) { if (value > -1 && value < 31) { raw[17] = (short) ((raw[17] & 0xff07) | (value << 3 & 0x00f8)); } else { throw new RuntimeException("Out of Range!"); } } public short getFollowLength() { return raw[1]; } protected void setFollowLength(short value) { assert (raw.length >= value + 2); raw[1] = value; } public void addUserAttributeData(byte[] pDataBlock, Class dataClass, int iLinkageId) throws Element.Exception { } public void addUserAttributeData(byte[] pDataBlock, int iLinkageId, Object oDataDef) throws Element.Exception { } public boolean hasUserAttributeData() { if (raw[15] <= 0) { return false; } short index = (short) (raw[15] + 16); if (index == -1) { return false; } return true; } public int getUserAttributeDataOffset() { return (raw[15] + 16); } public List getUserAttributeData() { short[] data; short length, nextAttribute; if (raw[15] <= 0) { return new ArrayList(); } short index = (short) (raw[15] + 16 + attrOffset); if (index == -1) { return null; } ArrayList aLinkageSet = new ArrayList(); while (index < raw.length) { if (raw[index] == 0 || ((short) raw[index]) == 0x8000) { index += 4; aLinkageSet.add(null); continue; } length = (short) (raw[index] & (short) 0x00ff); if (length == 0) { break; } if (length > raw.length - index - 1) { return null; } nextAttribute = (short) (index + length + 1); data = new short[length]; System.arraycopy(raw, index + 1, data, 0, length); if (data[0] == (short) 0x0020) { aLinkageSet.add(new FrammeAttributeData(data)); } else { aLinkageSet.add(new UserAttributeData(data)); } index = nextAttribute; } return aLinkageSet; } public void getUserAttributeData(byte[] pDataBlock, Class dataClass, int iLinkageId, int iLinkageIndex) { } public void getUserAttributeData(byte[] pDataBlock, int iLinkageId, Object oDataDef) { } public ByteBuffer getRawBuffer() { return rawBuffer.asReadOnlyBuffer(); } public short[] getRawArray() { if (raw == null) return null; short[] result = new short[raw.length]; System.arraycopy(raw, 0, result, 0, raw.length); return result; } public static class Exception extends java.lang.Exception { public Exception() { } // Constructs an ElementRecord.Exception with no detail message. public Exception(String oStrMessage) { super(oStrMessage); } } protected static int getOffsetPosition(int offset) { return offset * 2; } public void resyncBuffer() { byte[] tempRaw = new byte[this.raw.length * 2]; ByteBuffer tempBuffer = ByteBuffer.wrap(tempRaw); tempBuffer.order(ByteOrder.LITTLE_ENDIAN); tempBuffer.asShortBuffer().put(this.raw); int pos = rawBuffer.position(); rawBuffer = tempBuffer; rawBuffer.position(pos); } public static class ElementHandler implements IElementHandler { ElementType elementType; public ElementHandler(ElementType elementType) { this.elementType = elementType; } public ElementType getElementType() { return elementType; } public Element read(ByteBuffer buffer, short signature, int length) { byte[] dst = new byte[length]; try { buffer.get(dst, 4, dst.length - 4); } catch (BufferUnderflowException exception) { throw exception; } ByteBuffer tmpBuffer = ByteBuffer.wrap(dst); tmpBuffer.order(ByteOrder.LITTLE_ENDIAN); tmpBuffer.position(0); tmpBuffer.putShort(signature); tmpBuffer.putShort((short) ((length / 2) - 2)); /* ShortBuffer sbuffer = tmpBuffer.asShortBuffer(); short[] rawMem = new short[(length / 2)]; sbuffer.get(rawMem, 2, rawMem.length - 2); rawMem[0] = signature; rawMem[1] = (short) ((length / 2) - 2); */ Element elm = createElement(dst); return elm; } public void write(ByteBuffer buffer, Object element) { buffer.put(((Element) element).rawBuffer); } public int getLength(Object element) { return ((Element) element).raw.length; } public int getBufferLength(Object element) { return ((Element) element).rawBuffer.limit(); } protected Element createElement(byte[] raw) { return new Element(raw); } } public static final class FileRecord { int length; int number = 0; int offset; // Relative to the whole file int start = 0; // Relative to the current loaded buffer short signature = 0; /** * The minimum X value. */ public double minX; /** * The minimum Y value. */ public double minY; /** * The minimum Z value. */ public double minZ; /** * The maximum X value. */ public double maxX; /** * The maximum Y value. */ public double maxY; /** * The maximum Z value. */ public double maxZ; // ElementType type; int end = 0; // Relative to the whole file Object element = null; IElementHandler handler; ByteBuffer buffer; public Object element() { if (element == null) { buffer.position(start); buffer.order(ByteOrder.LITTLE_ENDIAN); if (handler == null) { return null; } element = handler.read(buffer, signature, length); } return element; } public int offset() { return offset; } /** * A summary of the record. */ public String toString() { return "FileRecord " + number + " length " + length + " bounds " + minX + "," + minY + " " + maxX + "," + maxY; } } }