Revision 20887

View differences:

branches/v2_0_0_prep/libraries/libDwg/src/freenet/support/HexUtil.java
1
package freenet.support;
2

  
3
import java.util.BitSet;
4

  
5
/**
6
 * Number in hexadecimal format are used throughout Freenet.
7
 * 
8
 * <p>Unless otherwise stated, the conventions follow the rules outlined in the 
9
 * Java Language Specification.</p>
10
 * 
11
 * @author syoung
12
 */
13
public class HexUtil {
14
	private HexUtil() {		
15
	}	
16
	
17

  
18
	/**
19
	 * Converts a byte array into a string of upper case hex chars.
20
	 * 
21
	 * @param bs
22
	 *            A byte array
23
	 * @param off
24
	 *            The index of the first byte to read
25
	 * @param length
26
	 *            The number of bytes to read.
27
	 * @return the string of hex chars.
28
	 */
29
	public static final String bytesToHex(byte[] bs, int off, int length) {
30
		StringBuffer sb = new StringBuffer(length * 2);
31
		bytesToHexAppend(bs, off, length, sb);
32
		return sb.toString();
33
	}
34

  
35
	public static final void bytesToHexAppend(
36
		byte[] bs,
37
		int off,
38
		int length,
39
		StringBuffer sb) {
40
		sb.ensureCapacity(sb.length() + length * 2);
41
		for (int i = off; i < (off + length) && i < bs.length; i++) {
42
			sb.append(Character.forDigit((bs[i] >>> 4) & 0xf, 16));
43
			sb.append(Character.forDigit(bs[i] & 0xf, 16));
44
		}
45
	}
46

  
47
	public static final String bytesToHex(byte[] bs) {
48
		return bytesToHex(bs, 0, bs.length);
49
	}
50

  
51
	public static final byte[] hexToBytes(String s) {
52
		return hexToBytes(s, 0);
53
	}
54

  
55
	public static final byte[] hexToBytes(String s, int off) {
56
		byte[] bs = new byte[off + (1 + s.length()) / 2];
57
		hexToBytes(s, bs, off);
58
		return bs;
59
	}
60

  
61
	/**
62
	 * Converts a String of hex characters into an array of bytes.
63
	 * 
64
	 * @param s
65
	 *            A string of hex characters (upper case or lower) of even
66
	 *            length.
67
	 * @param out
68
	 *            A byte array of length at least s.length()/2 + off
69
	 * @param off
70
	 *            The first byte to write of the array
71
	 */
72
	public static final void hexToBytes(String s, byte[] out, int off)
73
		throws NumberFormatException, IndexOutOfBoundsException {
74
		int slen = s.length();
75
		if ((slen % 2) != 0) {
76
			s = '0' + s;
77
		}
78

  
79
		if (out.length < off + slen / 2) {
80
			throw new IndexOutOfBoundsException(
81
				"Output buffer too small for input ("
82
					+ out.length
83
					+ "<"
84
					+ off
85
					+ slen / 2
86
					+ ")");
87
		}
88

  
89
		// Safe to assume the string is even length
90
		byte b1, b2;
91
		for (int i = 0; i < slen; i += 2) {
92
			b1 = (byte) Character.digit(s.charAt(i), 16);
93
			b2 = (byte) Character.digit(s.charAt(i + 1), 16);
94
			if (b1 < 0 || b2 < 0) {
95
				throw new NumberFormatException();
96
			}
97
			out[off + i / 2] = (byte) (b1 << 4 | b2);
98
		}
99
	}
100

  
101
	/**
102
	 * Pack the bits in ba into a byte[].
103
	 */
104
	public final static byte[] bitsToBytes(BitSet ba, int size) {
105
		int bytesAlloc = countBytesForBits(size);
106
		byte[] b = new byte[bytesAlloc];
107
		StringBuffer sb = new StringBuffer();
108
		for(int i=0;i<b.length;i++) {
109
			short s = 0;
110
			for(int j=0;j<8;j++) {
111
				int idx = i*8+j;
112
				boolean val = 
113
					idx > size ? false :
114
						ba.get(idx);
115
				s |= val ? (1<<j) : 0;
116
				sb.append(val ? '1' : '0');
117
			}
118
			if(s > 255) throw new IllegalStateException("WTF? s = "+s);
119
			b[i] = (byte)s;
120
		}
121
		return b;
122
	}
123

  
124
	/**
125
	 * Pack the bits in ba into a byte[] then convert that
126
	 * to a hex string and return it.
127
	 */
128
	public final static String bitsToHexString(BitSet ba, int size) {
129
		return bytesToHex(bitsToBytes(ba, size));
130
	}
131

  
132

  
133
	/**
134
	 * @return the number of bytes required to represent the
135
	 * bitset
136
	 */
137
	public static int countBytesForBits(int size) {
138
		// Brackets matter here! == takes precedence over the rest
139
		return (size/8) + ((size % 8) == 0 ? 0:1);
140
	}
141

  
142

  
143
	/**
144
	 * Read bits from a byte array into a bitset
145
	 * @param b the byte[] to read from
146
	 * @param ba the bitset to write to
147
	 */
148
	public static void bytesToBits(byte[] b, BitSet ba, int maxSize) {
149
		int x = 0;
150
		for(int i=0;i<b.length;i++) {
151
			for(int j=0;j<8;j++) {
152
				if(x > maxSize) break;
153
				int mask = 1 << j;
154
				boolean value = (mask & b[i]) != 0;
155
				ba.set(x, value);
156
				x++;
157
			}
158
		}
159
	}
160

  
161

  
162
	/**
163
	 * Read a hex string of bits and write it into a bitset
164
	 * @param s hex string of the stored bits
165
	 * @param ba the bitset to store the bits in
166
	 * @param length the maximum number of bits to store 
167
	 */
168
	public static void hexToBits(String s, BitSet ba, int length) {
169
		byte[] b = hexToBytes(s);
170
		bytesToBits(b, ba, length);
171
	}
172
}
0 173

  
branches/v2_0_0_prep/libraries/libDwg/src/com/iver/cit/gvsig/fmap/drivers/dgn/ByteUtils.java
1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *  Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib??ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *      +34 963862235
28
 *   gvsig@gva.es
29
 *      www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   IVER T.I. S.A
34
 *   Salamanca 50
35
 *   46005 Valencia
36
 *   Spain
37
 *
38
 *   +34 963163400
39
 *   dac@iver.es
40
 */
41
package com.iver.cit.gvsig.fmap.drivers.dgn;
42
import java.math.BigInteger;
43

  
44

  
45
/**
46
 * Clase que engloba m?todos para trabajar con bytes. 
47
 *
48
 * @author Vicente Caballero Navarro
49
 */
50
public class ByteUtils {
51
	public static final int SIZE_BOOL = 1;
52
	public static final int SIZE_SHORT = 2;
53
	public static final int SIZE_INT = 4;
54
	public static final int SIZE_LONG = 8;
55
	public static final int SIZE_DOUBLE = 8;
56

  
57
	/** A nibble->char mapping for printing out bytes. */
58
	public static final char[] digits = {
59
			'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
60
			'e', 'f'
61
		};
62

  
63
	/**
64
	 * Return the <code>int</code> represented by the bytes in
65
	 * <code>data</code> staring at offset <code>offset[0]</code>.
66
	 *
67
	 * @param data the array from which to read
68
	 * @param offset A single element array whose first element is the index in
69
	 * 		  data from which to begin reading on function entry, and which on
70
	 * 		  function exit has been incremented by the number of bytes read.
71
	 *
72
	 * @return the value of the <code>int</code> decoded
73
	 */
74
	public static final int bytesToInt(byte[] data, int[] offset) {
75
		/**
76
		 * TODO: We use network-order within OceanStore, but temporarily
77
		 * supporting intel-order to work with some JNI code until JNI code is
78
		 * set to interoperate with network-order.
79
		 */
80
		int result = 0;
81

  
82
		for (int i = 0; i < SIZE_INT; ++i) {
83
			result <<= 8;
84
			result |= byteToUnsignedInt(data[offset[0]++]);
85
		}
86

  
87
		return result;
88
	}
89

  
90
	/**
91
	 * Write the bytes representing <code>i</code> into the byte array
92
	 * <code>data</code>, starting at index <code>offset [0]</code>, and
93
	 * increment <code>offset [0]</code> by the number of bytes written; if
94
	 * <code>data == null</code>, increment <code>offset [0]</code> by the
95
	 * number of bytes that would have been written otherwise.
96
	 *
97
	 * @param i the <code>int</code> to encode
98
	 * @param data The byte array to store into, or <code>null</code>.
99
	 * @param offset A single element array whose first element is the index in
100
	 * 		  data to begin writing at on function entry, and which on
101
	 * 		  function exit has been incremented by the number of bytes
102
	 * 		  written.
103
	 */
104
	public static final void intToBytes(int i, byte[] data, int[] offset) {
105
		/**
106
		 * TODO: We use network-order within OceanStore, but temporarily
107
		 * supporting intel-order to work with some JNI code until JNI code is
108
		 * set to interoperate with network-order.
109
		 */
110
		if (data != null) {
111
			for (int j = (offset[0] + SIZE_INT) - 1; j >= offset[0]; --j) {
112
				data[j] = (byte) i;
113
				i >>= 8;
114
			}
115
		}
116

  
117
		offset[0] += SIZE_INT;
118
	}
119

  
120
	/**
121
	 * Return the <code>short</code> represented by the bytes in
122
	 * <code>data</code> staring at offset <code>offset[0]</code>.
123
	 *
124
	 * @param data the array from which to read
125
	 * @param offset A single element array whose first element is the index in
126
	 * 		  data from which to begin reading on function entry, and which on
127
	 * 		  function exit has been incremented by the number of bytes read.
128
	 *
129
	 * @return the value of the <code>short</code> decoded
130
	 */
131
	public static final short bytesToShort(byte[] data, int[] offset) {
132
		/**
133
		 * TODO: We use network-order within OceanStore, but temporarily
134
		 * supporting intel-order to work with some JNI code until JNI code is
135
		 * set to interoperate with network-order.
136
		 */
137
		short result = 0;
138

  
139
		for (int i = 0; i < SIZE_SHORT; ++i) {
140
			result <<= 8;
141
			result |= (short) byteToUnsignedInt(data[offset[0]++]);
142
		}
143

  
144
		return result;
145
	}
146

  
147
	/**
148
	 * Write the bytes representing <code>s</code> into the byte array
149
	 * <code>data</code>, starting at index <code>offset [0]</code>, and
150
	 * increment <code>offset [0]</code> by the number of bytes written; if
151
	 * <code>data == null</code>, increment <code>offset [0]</code> by the
152
	 * number of bytes that would have been written otherwise.
153
	 *
154
	 * @param s the <code>short</code> to encode
155
	 * @param data The byte array to store into, or <code>null</code>.
156
	 * @param offset A single element array whose first element is the index in
157
	 * 		  data to begin writing at on function entry, and which on
158
	 * 		  function exit has been incremented by the number of bytes
159
	 * 		  written.
160
	 */
161
	public static final void shortToBytes(short s, byte[] data, int[] offset) {
162
		/**
163
		 * TODO: We use network-order within OceanStore, but temporarily
164
		 * supporting intel-order to work with some JNI code until JNI code is
165
		 * set to interoperate with network-order.
166
		 */
167
		if (data != null) {
168
			data[offset[0] + 1] = (byte) s;
169
			data[offset[0]] = (byte) (s >> 8);
170
		}
171

  
172
		offset[0] += SIZE_SHORT;
173
	}
174

  
175
	/**
176
	 * Return the <code>long</code> represented by the bytes in
177
	 * <code>data</code> staring at offset <code>offset[0]</code>.
178
	 *
179
	 * @param data the array from which to read
180
	 * @param offset A single element array whose first element is the index in
181
	 * 		  data from which to begin reading on  function entry, and which
182
	 * 		  on function exit has been incremented by the number of bytes
183
	 * 		  read.
184
	 *
185
	 * @return the value of the <code>long</code> decoded
186
	 */
187
	public static final long bytesToLong(byte[] data, int[] offset) {
188
		long result = 0;
189

  
190
		for (int i = 0; i < SIZE_LONG; ++i) {
191
			result <<= 8;
192

  
193
			int res = byteToUnsignedInt(data[offset[0]++]);
194
			result = result | res;
195
		}
196

  
197
		return result;
198
	}
199

  
200
	/**
201
	 * Write the bytes representing <code>l</code> into the byte array
202
	 * <code>data</code>, starting at index <code>offset [0]</code>, and
203
	 * increment <code>offset [0]</code> by the number of bytes written; if
204
	 * <code>data == null</code>, increment <code>offset [0]</code> by the
205
	 * number of bytes that would have been written otherwise.
206
	 *
207
	 * @param l the <code>long</code> to encode
208
	 * @param data The byte array to store into, or <code>null</code>.
209
	 * @param offset A single element array whose first element is the index in
210
	 * 		  data to begin writing at on function entry, and which on
211
	 * 		  function exit has been incremented by the number of bytes
212
	 * 		  written.
213
	 */
214
	public static final void longToBytes(long l, byte[] data, int[] offset) {
215
		/**
216
		 * TODO: We use network-order within OceanStore, but temporarily
217
		 * supporting intel-order to work with some JNI code until JNI code is
218
		 * set to interoperate with network-order.
219
		 */
220
		if (data != null) {
221
			for (int j = (offset[0] + SIZE_LONG) - 1; j >= offset[0]; --j) {
222
				data[j] = (byte) l;
223
				l >>= 8;
224
			}
225
		}
226

  
227
		offset[0] += SIZE_LONG;
228
	}
229

  
230
	/**
231
	 * Return the <code>double</code> represented by the bytes in
232
	 * <code>data</code> staring at offset <code>offset[0]</code>.
233
	 *
234
	 * @param data the array from which to read
235
	 * @param offset A single element array whose first element is the index in
236
	 * 		  data from which to begin reading on  function entry, and which
237
	 * 		  on function exit has been incremented by the number of bytes
238
	 * 		  read.
239
	 *
240
	 * @return the value of the <code>double</code> decoded
241
	 */
242
	public static final double bytesToDouble(byte[] data, int[] offset) {
243
		long bits = bytesToLong(data, offset);
244

  
245
		return Double.longBitsToDouble(bits);
246
	}
247

  
248
	/**
249
	 * Write the bytes representing <code>d</code> into the byte array
250
	 * <code>data</code>, starting at index <code>offset [0]</code>, and
251
	 * increment <code>offset [0]</code> by the number of bytes written; if
252
	 * <code>data == null</code>, increment <code>offset [0]</code> by the
253
	 * number of bytes that would have been written otherwise.
254
	 *
255
	 * @param d the <code>double</code> to encode
256
	 * @param data The byte array to store into, or <code>null</code>.
257
	 * @param offset A single element array whose first element is the index in
258
	 * 		  data to begin writing at on function entry, and which on
259
	 * 		  function exit has been incremented by the number of bytes
260
	 * 		  written.
261
	 */
262
	public static final void doubleToBytes(double d, byte[] data, int[] offset) {
263
		long bits = Double.doubleToLongBits(d);
264
		longToBytes(bits, data, offset);
265
	}
266

  
267
	/**
268
	 * Return the <code>String</code> represented by the bytes in
269
	 * <code>data</code> staring at offset <code>offset[0]</code>. This method
270
	 * relies on the user using the corresponding <code>stringToBytes</code>
271
	 * method to encode the <code>String</code>, so that it may properly
272
	 * retrieve the <code>String</code> length.
273
	 *
274
	 * @param data the array from which to read
275
	 * @param offset A single element array whose first element is the index in
276
	 * 		  data from which to begin reading on function entry, and which on
277
	 * 		  function exit has been incremented by the number of bytes read.
278
	 *
279
	 * @return the value of the <code>String</code> decoded
280
	 */
281
	public static final String bytesToString(byte[] data, int[] offset) {
282
		offset[0] = 0;
283

  
284
		int length = bytesToInt(data, offset);
285
		String st = null;
286

  
287
		if ((length < 0) || (length > data.length)) {
288
			st = new String(data);
289
		} else {
290
			st = new String(data, offset[0], length);
291
		}
292

  
293
		offset[0] += length;
294

  
295
		return st;
296
	}
297

  
298
	/**
299
	 * Write the bytes representing <code>s</code> into the byte array
300
	 * <code>data</code>, starting at index <code>offset [0]</code>, and
301
	 * increment <code>offset [0]</code> by the number of bytes written; if
302
	 * <code>data == null</code>, increment <code>offset [0]</code> by the
303
	 * number of bytes that would have been written otherwise.
304
	 *
305
	 * @param s the <code>String</code> to encode
306
	 * @param data The byte array to store into, or <code>null</code>.
307
	 * @param offset A single element array whose first element is the index in
308
	 * 		  data to begin writing at on function entry, and which on
309
	 * 		  function exit has been incremented by the number of bytes
310
	 * 		  written.
311
	 */
312
	public static final void stringToBytes(String s, byte[] data, int[] offset) {
313
		byte[] s_bytes = s.getBytes();
314

  
315
		if (data != null) {
316
			intToBytes(s_bytes.length, data, offset);
317
			memcpy(data, offset[0], s_bytes, 0, s_bytes.length);
318
		} else {
319
			offset[0] += SIZE_INT;
320
		}
321

  
322
		offset[0] += s_bytes.length;
323
	}
324

  
325
	/**
326
	 * Return the <code>boolean</code> represented by the bytes in
327
	 * <code>data</code> staring at offset <code>offset[0]</code>.
328
	 *
329
	 * @param data the array from which to read
330
	 * @param offset A single element array whose first element is the index in
331
	 * 		  data from which to begin reading on  function entry, and which
332
	 * 		  on function exit has been incremented by the number of bytes
333
	 * 		  read.
334
	 *
335
	 * @return the value of the <code>boolean</code> decoded
336
	 */
337
	public static final boolean bytesToBool(byte[] data, int[] offset) {
338
		boolean result = true;
339

  
340
		if (data[offset[0]] == 0) {
341
			result = false;
342
		}
343

  
344
		offset[0] += SIZE_BOOL;
345

  
346
		return result;
347
	}
348

  
349
	/**
350
	 * Write the bytes representing <code>b</code> into the byte array
351
	 * <code>data</code>, starting at index <code>offset [0]</code>, and
352
	 * increment <code>offset [0]</code> by the number of bytes written; if
353
	 * <code>data == null</code>, increment <code>offset [0]</code> by the
354
	 * number of bytes that would have been written otherwise.
355
	 *
356
	 * @param b the <code>boolean</code> to encode
357
	 * @param data The byte array to store into, or <code>null</code>.
358
	 * @param offset A single element array whose first element is the index in
359
	 * 		  data to begin writing at on function entry, and which on
360
	 * 		  function exit has been incremented by the number of bytes
361
	 * 		  written.
362
	 */
363
	public static final void boolToBytes(boolean b, byte[] data, int[] offset) {
364
		if (data != null) {
365
			data[offset[0]] = (byte) (b ? 1 : 0);
366
		}
367

  
368
		offset[0] += SIZE_BOOL;
369
	}
370

  
371
	/**
372
	 * Return the <code>BigInteger</code> represented by the bytes in
373
	 * <code>data</code> staring at offset <code>offset[0]</code>.
374
	 *
375
	 * @param data the array from which to read
376
	 * @param offset A single element array whose first element is the index in
377
	 * 		  data from which to begin reading on  function entry, and which
378
	 * 		  on function exit has been incremented by the number of bytes
379
	 * 		  read.
380
	 *
381
	 * @return the <code>BigInteger</code> decoded
382
	 */
383
	public static final BigInteger bytesToBigInteger(byte[] data, int[] offset) {
384
		int length = bytesToInt(data, offset);
385
		byte[] bytes = new byte[length];
386
		offset[0] += memcpy(bytes, 0, data, offset[0], length);
387

  
388
		return new BigInteger(bytes);
389
	}
390

  
391
	/**
392
	 * Write the bytes representing <code>n</code> into the byte array
393
	 * <code>data</code>, starting at index <code>offset [0]</code>, and
394
	 * increment <code>offset [0]</code> by the number of bytes written; if
395
	 * <code>data == null</code>, increment <code>offset [0]</code> by the
396
	 * number of bytes that would have been written otherwise.
397
	 *
398
	 * @param n the <code>BigInteger</code> to encode
399
	 * @param data The byte array to store into, or <code>null</code>.
400
	 * @param offset A single element array whose first element is the index in
401
	 * 		  data to begin writing at on function entry, and which on
402
	 * 		  function exit has been incremented by the number of bytes
403
	 * 		  written.
404
	 */
405
	public static final void bigIntegerToBytes(BigInteger n, byte[] data,
406
		int[] offset) {
407
		byte[] bytes = n.toByteArray();
408
		intToBytes(bytes.length, data, offset);
409
		offset[0] += memcpy(data, offset[0], bytes, 0, bytes.length);
410
	}
411

  
412
	/**
413
	 * Convert an array of <code>bytes</code>s into an array of
414
	 * <code>ints</code>.
415
	 *
416
	 * @param dst the array to write
417
	 * @param dst_offset the start offset in <code>dst</code>, times 4. This
418
	 * 		  measures the offset as if <code>dst</code> were an array of
419
	 * 		  <code>byte</code>s (rather than <code>int</code>s).
420
	 * @param src the array to read
421
	 * @param src_offset the start offset in <code>src</code>
422
	 * @param length the number of <code>byte</code>s to copy.
423
	 */
424
	public static final void bytesToInts(int[] dst, int dst_offset, byte[] src,
425
		int src_offset, int length) {
426
		if ((src == null) || (dst == null) ||
427
				((src_offset + length) > src.length) ||
428
				((dst_offset + length) > (dst.length * 4)) ||
429
				((dst_offset % 4) != 0) || ((length % 4) != 0)) {
430
			croak("bytesToInts parameters are invalid" + " src==" + src +
431
				" dst==" + dst +
432
				(((src == null) || (dst == null)) ? " "
433
												  : (" (src_offset+length)>src.length==" +
434
				(src_offset + length) + ">" + src.length +
435
				" (dst_offset+length)>(dst.length*4)==" +
436
				(dst_offset + length) + ">" + (dst.length * 4) +
437
				" (dst_offset%4)==" + (dst_offset % 4) + " (length%4)==" +
438
				(length % 4) + " dest.length==" + dst.length + " length==" +
439
				length)));
440
		}
441

  
442
		// Convert parameters to normal format
443
		int[] offset = new int[1];
444
		offset[0] = src_offset;
445

  
446
		int int_dst_offset = dst_offset / 4;
447

  
448
		for (int i = 0; i < (length / 4); ++i) {
449
			dst[int_dst_offset++] = bytesToInt(src, offset);
450
		}
451
	}
452

  
453
	/**
454
	 * Convert an array of <code>int</code>s into an array of
455
	 * <code>bytes</code>.
456
	 *
457
	 * @param dst the array to write
458
	 * @param dst_offset the start offset in <code>dst</code>
459
	 * @param src the array to read
460
	 * @param src_offset the start offset in <code>src</code>, times 4. This
461
	 * 		  measures the offset as if <code>src</code> were an array of
462
	 * 		  <code>byte</code>s (rather than <code>int</code>s).
463
	 * @param length the number of <code>byte</code>s to copy.
464
	 */
465
	public static final void intsToBytes(byte[] dst, int dst_offset, int[] src,
466
		int src_offset, int length) {
467
		if ((src == null) || (dst == null) ||
468
				((dst_offset + length) > dst.length) ||
469
				((src_offset + length) > (src.length * 4)) ||
470
				((src_offset % 4) != 0) || ((length % 4) != 0)) {
471
			croak("intsToBytes parameters are invalid:" + " src=" + src +
472
				" dst=" + dst + " (dst_offset=" + dst_offset + " + length=" +
473
				length + ")=" + (dst_offset + length) + " > dst.length=" +
474
				((dst == null) ? 0 : dst.length) + " (src_offset=" +
475
				src_offset + " + length=" + length + ")=" +
476
				(src_offset + length) + " > (src.length=" +
477
				((src == null) ? 0 : src.length) + "*4)=" +
478
				((src == null) ? 0 : (src.length * 4)) + " (src_offset=" +
479
				src_offset + " % 4)=" + (src_offset % 4) + " != 0" +
480
				" (length=" + length + " % 4)=" + (length % 4) + " != 0");
481
		}
482

  
483
		// Convert parameters to normal format
484
		int[] offset = new int[1];
485
		offset[0] = dst_offset;
486

  
487
		int int_src_offset = src_offset / 4;
488

  
489
		for (int i = 0; i < (length / 4); ++i) {
490
			intToBytes(src[int_src_offset++], dst, offset);
491
		}
492
	}
493

  
494
	/**
495
	 * Convert a <code>byte</code> into an unsigned integer.
496
	 *
497
	 * @param b the <code>byte</code> to cast
498
	 *
499
	 * @return a postiive <code>int</code> whose lowest byte contains the bits
500
	 * 		   of <code>b</code>.
501
	 */
502
	public static final int byteToUnsignedInt(byte b) {
503
		return ((int) b) & 0xff;
504
	}
505

  
506
	/**
507
	 * Copy contents of one array of <code>bytes</code> into another. If either
508
	 * array is <code>null</code>, simply return the <code>length</code>
509
	 * parameter directly.
510
	 *
511
	 * @param dst the array to write, or <code>null</code>
512
	 * @param dst_offset the start offset in <code>dst</code>
513
	 * @param src the array to read, or <code>null</code>
514
	 * @param src_offset the start offset in <code>src</code>
515
	 * @param length the number of <code>byte</code>s to copy.
516
	 *
517
	 * @return DOCUMENT ME!
518
	 */
519
	public static int memcpy(byte[] dst, int dst_offset, byte[] src,
520
		int src_offset, int length) {
521
		if ((dst != null) && (src != null)) {
522
			if (dst.length < (dst_offset + length)) {
523
				croak("dst.length = " + dst.length + ", but " +
524
					"dst_offset = " + dst_offset + " and length = " + length +
525
					".");
526
			}
527

  
528
			if (src.length < (src_offset + length)) {
529
				croak("src.length = " + src.length + ", but " +
530
					"src_offset = " + src_offset + " and length = " + length +
531
					".");
532
			}
533

  
534
			for (int i = 0; i < length; ++i, ++dst_offset, ++src_offset)
535
				dst[dst_offset] = src[src_offset];
536
		}
537

  
538
		return length;
539
	}
540

  
541
	/**
542
	 * Compare the contents of one array of <code>bytes</code> to another.
543
	 *
544
	 * @param a the first array
545
	 * @param a_offset the start offset in <code>a</code>
546
	 * @param b the second array
547
	 * @param b_offset the start offset in <code>b</code>
548
	 * @param length the number of <code>byte</code>s to compare.
549
	 *
550
	 * @return DOCUMENT ME!
551
	 */
552
	public static boolean memcmp(byte[] a, int a_offset, byte[] b,
553
		int b_offset, int length) {
554
		if ((a == null) && (b == null)) {
555
			return true;
556
		}
557

  
558
		if ((a == null) || (b == null)) {
559
			return false;
560
		}
561

  
562
		for (int i = 0; i < length; ++i, ++a_offset, ++b_offset)
563
			if (a[a_offset] != b[b_offset]) {
564
				return false;
565
			}
566

  
567
		return true;
568
	}
569

  
570
	/**
571
	 * Fill the given array with zeros.
572
	 *
573
	 * @param array the array to clear
574
	 * @param offset the start offset
575
	 * @param length the number of <code>byte</code>s to clear.
576
	 */
577
	public static void memclr(byte[] array, int offset, int length) {
578
		for (int i = 0; i < length; ++i, ++offset)
579
			array[offset] = 0;
580
	}
581

  
582
	/**
583
	 * Round a number up to a given multiple.
584
	 *
585
	 * @param value the number to be rounded
586
	 * @param multiple the number to which to be rounded
587
	 *
588
	 * @return the smallest <code>int</code> greater than or equal to
589
	 * 		   <code>value</code> which divides <code>multiple</code> exactly.
590
	 */
591
	public static int round_up(int value, int multiple) {
592
		return (((value - 1) / multiple) + 1) * multiple;
593
	}
594

  
595
	/**
596
	 * Return a new array equal to original except zero-padded to an integral
597
	 * mulitple of blocks.  If the original is already an integral multiple of
598
	 * blocks, just return it.
599
	 *
600
	 * @param original the array of <code>byte</code>s to be padded
601
	 * @param block_size the size of the blocks
602
	 *
603
	 * @return an array whose size divides <code>block_size</code> exactly. The
604
	 * 		   array is either <code>original</code> itself, or a copy whose
605
	 * 		   first <code>original.length</code> bytes are equal to
606
	 * 		   <code>original</code>.
607
	 */
608
	public static byte[] zero_pad(byte[] original, int block_size) {
609
		if ((original.length % block_size) == 0) {
610
			return original;
611
		}
612

  
613
		byte[] result = new byte[round_up(original.length, block_size)];
614
		memcpy(result, 0, original, 0, original.length);
615

  
616
		// Unnecessary - jvm sets bytes to 0.
617
		// memclr (result, original.length, result.length - original.length);
618
		return result;
619
	}
620

  
621
	/**
622
	 * Determines whether two arrays of <code>byte</code>s contain the same
623
	 * contents.
624
	 *
625
	 * @param b1 The first array
626
	 * @param b2 The second array
627
	 *
628
	 * @return <code>true</code> if both arrays are <code>null</code>, both
629
	 * 		   empty, or both of the same length with equal contents.
630
	 */
631
	public static boolean equals(byte[] b1, byte[] b2) {
632
		if (b1 == b2) {
633
			return true;
634
		}
635

  
636
		if ((b1 == null) || (b2 == null)) { // only one is null
637

  
638
			return false;
639
		}
640

  
641
		if (b1.length != b2.length) {
642
			return false;
643
		}
644

  
645
		for (int i = 0; i < b1.length; ++i)
646
			if (b1[i] != b2[i]) {
647
				return false;
648
			}
649

  
650
		return true;
651
	}
652

  
653
	/**
654
	 * Produce a <code>String</code> representation for the specified array of
655
	 * <code>byte</code>s.  Print each <code>byte</code> as two hexadecimal
656
	 * digits.
657
	 *
658
	 * @param data The array to print
659
	 * @param offset the start offset in <code>data</code>
660
	 * @param length the number of <code>byte</code>s to print
661
	 *
662
	 * @return DOCUMENT ME!
663
	 */
664
	public static String print_bytes(byte[] data, int offset, int length) {
665
		int size = 2 * length;
666
		size += ((size / 8) + (size / 64));
667

  
668
		char[] buf = new char[size];
669
		int low_mask = 0x0f;
670
		int high_mask = 0xf0;
671
		int buf_pos = 0;
672
		byte b;
673

  
674
		int j = 0;
675

  
676
		for (int i = offset; i < (offset + length); ++i) {
677
			b = data[i];
678
			buf[buf_pos++] = digits[(high_mask & b) >> 4];
679
			buf[buf_pos++] = digits[(low_mask & b)];
680

  
681
			if ((j % 4) == 3) {
682
				buf[buf_pos++] = ' ';
683
			}
684

  
685
			if ((j % 32) == 31) {
686
				buf[buf_pos++] = '\n';
687
			}
688

  
689
			++j;
690
		}
691

  
692
		return new String(buf);
693
	}
694

  
695
	/**
696
	 * DOCUMENT ME!
697
	 *
698
	 * @param data DOCUMENT ME!
699
	 * @param offset DOCUMENT ME!
700
	 * @param length DOCUMENT ME!
701
	 *
702
	 * @return DOCUMENT ME!
703
	 */
704
	public static String print_bytes_exact(byte[] data, int offset, int length) {
705
		int size = 2 * length;
706
		char[] buf = new char[size];
707
		int low_mask = 0x0f;
708
		int high_mask = 0xf0;
709
		int buf_pos = 0;
710
		byte b;
711

  
712
		int j = 0;
713

  
714
		for (int i = offset; i < (offset + length); ++i) {
715
			b = data[i];
716
			buf[buf_pos++] = digits[(high_mask & b) >> 4];
717
			buf[buf_pos++] = digits[(low_mask & b)];
718
			++j;
719
		}
720

  
721
		return new String(buf);
722
	}
723

  
724
	/**
725
	 * DOCUMENT ME!
726
	 *
727
	 * @param data DOCUMENT ME!
728
	 *
729
	 * @return DOCUMENT ME!
730
	 */
731
	public static String print_bytes(byte[] data) {
732
		return print_bytes(data, 0, data.length);
733
	}
734

  
735
	/**
736
	 * DOCUMENT ME!
737
	 *
738
	 * @param msg DOCUMENT ME!
739
	 */
740
	private static void croak(String msg) {
741
		// throw new java.AssertionViolatedException(msg);
742
	}
743

  
744
	/**
745
	 * DOCUMENT ME!
746
	 *
747
	 * @param b DOCUMENT ME!
748
	 *
749
	 * @return DOCUMENT ME!
750
	 */
751
	public static int getUnsigned(byte b) {
752
		return ((b & 0xff)); // >> 8);
753
	}
754
}
0 755

  
branches/v2_0_0_prep/libraries/libDwg/src/com/iver/cit/jdwglib/util/Vector3D.java
1

  
2
package com.iver.cit.jdwglib.util;
3

  
4
/**
5
 *  3dim double vector. A vector is transformed different than a point.
6
 *  The class is now declared final to allow a more aggresive optimization.
7
 *
8
 *  @see       dxfviewer.math.Point3D;
9
 *
10
 *  @version   1.10,?01/13/99
11
 */
12
public final class Vector3D {
13
  public double x, y, z;       // coordinates, allowing direct access
14

  
15
  /**
16
   *
17
   */
18
  public Vector3D() {
19
  }
20

  
21
  /**
22
   *  Copy constructor.
23
   *  @param  v    vector to copy
24
   */
25
  public Vector3D(Vector3D v) {
26
    x = v.x;
27
    y = v.y;
28
    z = v.z;
29
  }
30

  
31
  /**
32
   *  Copy from a point.
33
   *  @param  p   point to copy
34
   */
35
  public Vector3D(Point3D p) {
36
    x = p.x;
37
    y = p.y;
38
    z = p.z;
39
  }
40

  
41
  /**
42
   *  @param   xx    x coord
43
   *  @param   yy    y coord
44
   *  @param   zz    z coord
45
   */
46
  public Vector3D(double xx, double yy, double zz) {
47
    x = xx;
48
    y = yy;
49
    z = zz;
50
  }
51

  
52
  /**
53
   *  Calculate the length.
54
   *  @return  length of vector
55
   */
56
  public double length() {
57
    return (double)Math.sqrt(x*x+y*y+z*z);
58
  }
59

  
60
  /**
61
   *  Scale.
62
   *  @param   f     scaling factor
63
   */
64
  public void scale(double f) {
65
    if (f != 1f) {
66
      x *= f;
67
      y *= f;
68
      z *= f;
69
    }
70
  }
71

  
72
  /**
73
   *  Normalize. Scale vector so it has length 1.
74
   */
75
  public void normalize() {
76
    scale(1.0f/length());
77
  }
78

  
79
  /**
80
   *  Add a vector.
81
   *  @param  v      vector to add
82
   */
83
  public void add(Vector3D v) {
84
    x += v.x;
85
    y += v.y;
86
    z += v.z;
87
  }
88

  
89
  /**
90
   *  Get sum of vectors.
91
   *  @param  v     vector to add
92
   *  @return this+v
93
   */
94
  public Vector3D plus(Vector3D v) {
95
    Vector3D ret = new Vector3D(this);
96
    ret.add(v);
97
    return ret;
98
  }
99
  /**
100
   *  Get sum of this vector and point.
101
   *  @param  p     point to add
102
   *  @return this+p
103
   */
104
  public Point3D plus(Point3D p) {
105
    Point3D ret = new Point3D(p);
106
    ret.add(this);
107
    return ret;
108
  }
109

  
110
  /**
111
   *  Substract a vector from this.
112
   *  @param  v     vector to substract
113
   */
114
  public void sub(Vector3D v) {
115
    x -= v.x;
116
    y -= v.y;
117
    z -= v.z;
118
  }
119

  
120
  /**
121
   *  Get difference with point.
122
   *  @param  p     point to substract
123
   *  @return this-p = -(p-this)
124
   */
125
  public Point3D minus(Point3D p) {
126
    Point3D ret = new Point3D(p);
127
    ret.sub(this);
128
    ret.scale(-1f);
129
    return ret;
130
  }
131

  
132
  /**
133
   *  Get difference with vector.
134
   *  @param  v     vector to substract
135
   *  @return this-v
136
   */
137
  public Vector3D minus(Vector3D v) {
138
    Vector3D ret = new Vector3D(this);
139
    ret.sub(v);
140
    return ret;
141
  }
142

  
143
  /**
144
   *  Scalar product.
145
   *  @param  v     vector to multiply
146
   *  @return this*v
147
   */
148
  public double mult(Vector3D v) {
149
    return x*v.x+y*v.y+z*v.z;
150
  }
151

  
152
  /**
153
   *  Cross product.
154
   *  @param  v     vector to multiply
155
   *  @return this x v
156
   */
157
  public Vector3D cross(Vector3D v) {
158
    return new Vector3D(y*v.z - z*v.y,
159
			z*v.x - x*v.z,
160
			x*v.y - y*v.x);
161
  }
162

  
163
  /**
164
   *  Output.
165
   *  @return  string representation
166
   */
167
  public String toString() {
168
    return new String(new StringBuffer().append("<").append(x).append(",").append(y).append(",").append(z).append(">"));
169
  }
170
}
171

  
0 172

  
branches/v2_0_0_prep/libraries/libDwg/src/com/iver/cit/jdwglib/util/Matrix4D.java
1

  
2
package com.iver.cit.jdwglib.util;
3

  
4

  
5
/**
6
 *  4x4dim double matrix used for perspective transformations.
7
 *  The class is now declared final to allow a more aggresive optimization.
8
 *
9
 */
10
public final class Matrix4D {
11
  static private final double DEG2RAD = Math.PI/180.0;  // conversion from degree to radians
12

  
13
  public double xx, xy, xz, xw,     // 1st row
14
			   yx, yy, yz, yw,     // 2nd row
15
			   zx, zy, zz, zw,     // 3rd row
16
			   wx, wy, wz, ww;     // 4th row
17

  
18
  /**
19
   *  Create identity matrix.
20
   */
21
  public Matrix4D() {
22
	// set to identity mat
23
	xx = yy = zz = ww = 1f;
24
  }
25

  
26
  /**
27
   *  Copy constructor.
28
   *  @param  m   matrix to copy
29
   */
30
  public Matrix4D(Matrix4D m) {
31
	xx = m.xx;
32
	xy = m.xy;
33
	xz = m.xz;
34
	xw = m.xw;
35
	yx = m.yx;
36
	yy = m.yy;
37
	yz = m.yz;
38
	yw = m.yw;
39
	zx = m.zx;
40
	zy = m.zy;
41
	zz = m.zz;
42
	zw = m.zw;
43
	wx = m.wx;
44
	wy = m.wy;
45
	wz = m.wz;
46
	ww = m.ww;
47
  }
48

  
49
  /**
50
   *  @param  mxx     1st elem in 1st row
51
   *  @param  mxy     2nd elem in 1st row
52
   *  @param  mxz     3rd elem in 1st row
53
   *  @param  mxw     4th elem in 1st row
54
   *  @param  myx     1st elem in 2nd row
55
   *  @param  myy     2nd elem in 2nd row
56
   *  @param  myz     3rd elem in 2nd row
57
   *  @param  myw     4th elem in 2nd row
58
   *  @param  mzx     1st elem in 3rd row
59
   *  @param  mzy     2nd elem in 3rd row
60
   *  @param  mzz     3rd elem in 3rd row
61
   *  @param  mzw     4th elem in 3rd row
62
   *  @param  mwx     1st elem in 4th row
63
   *  @param  mwy     2nd elem in 4th row
64
   *  @param  mwz     3rd elem in 4th row
65
   *  @param  mww     4th elem in 4th row
66
   */
67
  public Matrix4D(double mxx, double mxy, double mxz, double mxw,
68
		  double myx, double myy, double myz, double myw,
69
		  double mzx, double mzy, double mzz, double mzw,
70
		  double mwx, double mwy, double mwz, double mww) {
71
	xx = mxx;
72
	xy = mxy;
73
	xz = mxz;
74
	xw = mxw;
75
	yx = myx;
76
	yy = myy;
77
	yz = myz;
78
	yw = myw;
79
	zx = mzx;
80
	zy = mzy;
81
	zz = mzz;
82
	zw = mzw;
83
	wx = mwx;
84
	wy = mwy;
85
	wz = mwz;
86
	ww = mww;
87
  }
88

  
89
  /**
90
   *  Reset to identity
91
   */
92
  public void identity() {
93
	xx = yy = zz = ww = 1f;
94
	xy = xz = xw =
95
	  yx = yz = yw =
96
	  zx = zy = zw =
97
	  wx = wy = wz = 0f;
98
  }
99

  
100
  /**
101
   *  Transponize.
102
   */
103
  public void transponize() {
104
	// switch rows and columns
105
	double t;
106
	t = xy; xy = yx; yx = t;
107
	t = xz; xz = zx; zx = t;
108
	t = xw; xw = wx; wx = t;
109
	t = yz; yz = zy; zy = t;
110
	t = yw; yw = wy; wy = t;
111
	t = zw; zw = wz; wz = t;
112
  }
113

  
114
  /**
115
   *  Matrix multiplication of vector.
116
   *  @param  v   vector to transform
117
   *  @return transformed vector
118
   */
119
  public Vector3D mult(Vector3D v) {
120
	return new Vector3D(xx*v.x + xy*v.y + xz*v.z,
121
			yx*v.x + yy*v.y + yz*v.z,
122
			zx*v.x + zy*v.y + zz*v.z);
123
  }
124

  
125
  /**
126
   *  Transformation of 1 vector.
127
   *  @param  v   vector to transform
128
   */
129
  public void transform(Vector3D v) {
130
	double x = xx*v.x + xy*v.y + xz*v.z,
131
		  y = yx*v.x + yy*v.y + yz*v.z,
132
		  z = zx*v.x + zy*v.y + zz*v.z;
133

  
134
	v.x = x;
135
	v.y = y;
136
	v.z = z;
137
  }
138

  
139
  /**
140
   *  Matrix multiplication of point.
141
   *  @param  p    point to transform
142
   *  @return transformed point
143
   */
144
  public Point3D mult(Point3D p) {
145
	Point3D ret = new Point3D(xx*p.x + xy*p.y + xz*p.z + xw,
146
				  yx*p.x + yy*p.y + yz*p.z + yw,
147
				  zx*p.x + zy*p.y + zz*p.z + zw);
148
	ret.scale(1f/(wx*p.x + wy*p.y + wz*p.z + ww));
149
	return ret;
150
  }
151

  
152
  /**
153
   *  Transformation of 1 point.
154
   *  @param  p   point to transform
155
   */
156
  public void transform(Point3D p) {
157
	double  x = xx*p.x + xy*p.y + xz*p.z + xw,
158
		   y = yx*p.x + yy*p.y + yz*p.z + yw,
159
		   z = zx*p.x + zy*p.y + zz*p.z + zw,
160
		   w = wx*p.x + wy*p.y + wz*p.z + ww;
161

  
162
	p.x = x/w;
163
	p.y = y/w;
164
	p.z = z/w;
165
  }
166

  
167
  /**Transformacion de un punto considerando solo el plano horizontal
168
   */
169
   public void transformXY(Point3D p){
170
		double  x = xx*p.x + xy*p.y+ xw,
171
		y = yx*p.x + yy*p.y + yw,
172
		w = wx*p.x + wy*p.y + ww;
173
		p.x = x/w;
174
		p.y = y/w;
175
   }
176

  
177
  /**
178
   *  Matrix multiplication.
179
   *  @param  m   matrix to multiply with
180
   *  @return this * m
181
   */
182
  public Matrix4D mult(Matrix4D m) {
183
	if (m != null) {
184
	  return new Matrix4D(xx*m.xx + xy*m.yx + xz*m.zx + xw*m.wx,
185
			  xx*m.xy + xy*m.yy + xz*m.zy + xw*m.wy,
186
			  xx*m.xz + xy*m.yz + xz*m.zz + xw*m.wz,
187
			  xx*m.xw + xy*m.yw + xz*m.zw + xw*m.ww,
188
			  yx*m.xx + yy*m.yx + yz*m.zx + yw*m.wx,
189
			  yx*m.xy + yy*m.yy + yz*m.zy + yw*m.wy,
190
			  yx*m.xz + yy*m.yz + yz*m.zz + yw*m.wz,
191
			  yx*m.xw + yy*m.yw + yz*m.zw + yw*m.ww,
192
			  zx*m.xx + zy*m.yx + zz*m.zx + zw*m.wx,
193
			  zx*m.xy + zy*m.yy + zz*m.zy + zw*m.wy,
194
			  zx*m.xz + zy*m.yz + zz*m.zz + zw*m.wz,
195
			  zx*m.xw + zy*m.yw + zz*m.zw + zw*m.ww,
196
			  wx*m.xx + wy*m.yx + wz*m.zx + ww*m.wx,
197
			  wx*m.xy + wy*m.yy + wz*m.zy + ww*m.wy,
198
			  wx*m.xz + wy*m.yz + wz*m.zz + ww*m.wz,
199
			  wx*m.xw + wy*m.yw + wz*m.zw + ww*m.ww);
200
	}
201
	else {
202
	  return new Matrix4D(this);
203
	}
204
  }
205

  
206
  /**
207
   *  Matrix multiplication.
208
   *  @param  m  matrix to multply with
209
   */
210
  public void multBy(Matrix4D m) {
211
	double x = xx*m.xx + xy*m.yx + xz*m.zx + xw*m.wx,
212
		  y = xx*m.xy + xy*m.yy + xz*m.zy + xw*m.wy,
213
		  z = xx*m.xz + xy*m.yz + xz*m.zz + xw*m.wz,
214
		  w = xx*m.xw + xy*m.yw + xz*m.zw + xw*m.ww;
215
	xx = x;
216
	xy = y;
217
	xz = z;
218
	xw = w;
219

  
220
	x = yx*m.xx + yy*m.yx + yz*m.zx + yw*m.wx;
221
	y = yx*m.xy + yy*m.yy + yz*m.zy + yw*m.wy;
222
	z = yx*m.xz + yy*m.yz + yz*m.zz + yw*m.wz;
223
	w = yx*m.xw + yy*m.yw + yz*m.zw + yw*m.ww;
224
	yx = x;
225
	yy = y;
226
	yz = z;
227
	yw = w;
228

  
229
	x = zx*m.xx + zy*m.yx + zz*m.zx + zw*m.wx;
230
	y = zx*m.xy + zy*m.yy + zz*m.zy + zw*m.wy;
231
	z = zx*m.xz + zy*m.yz + zz*m.zz + zw*m.wz;
232
	w = zx*m.xw + zy*m.yw + zz*m.zw + zw*m.ww;
233
	zx = x;
234
	zy = y;
235
	zz = z;
236
	zw = w;
237

  
238
	x = wx*m.xx + wy*m.yx + wz*m.zx + ww*m.wx;
239
	y = wx*m.xy + wy*m.yy + wz*m.zy + ww*m.wy;
240
	z = wx*m.xz + wy*m.yz + wz*m.zz + ww*m.wz;
241
	w = wx*m.xw + wy*m.yw + wz*m.zw + ww*m.ww;
242
	wx = x;
243
	wy = y;
244
	wz = z;
245
	ww = w;
246
  }
247

  
248
  /**
249
   *  Matrix multiplication from left.
250
   *  @param  m  matrix to multiply with.
251
   */
252
  public void multLeftBy(Matrix4D m) {
253
	double x = m.xx*xx + m.xy*yx + m.xz*zx + m.xw*wx,
254
		  y = m.yx*xx + m.yy*yx + m.yz*zx + m.yw*wx,
255
		  z = m.zx*xx + m.zy*yx + m.zz*zx + m.zw*wx,
256
		  w = m.wx*xx + m.wy*yx + m.wz*zx + m.ww*wx;
257
	xx = x;
258
	yx = y;
259
	zx = z;
260
	wx = w;
261

  
262
	x = m.xx*xy + m.xy*yy + m.xz*zy + m.xw*wy;
263
	y = m.yx*xy + m.yy*yy + m.yz*zy + m.yw*wy;
264
	z = m.zx*xy + m.zy*yy + m.zz*zy + m.zw*wy;
265
	w = m.wx*xy + m.wy*yy + m.wz*zy + m.ww*wy;
266
	xy = x;
267
	yy = y;
268
	zy = z;
269
	wy = w;
270

  
271
	x = m.xx*xz + m.xy*yz + m.xz*zz + m.xw*wz;
272
	y = m.yx*xz + m.yy*yz + m.yz*zz + m.yw*wz;
273
	z = m.zx*xz + m.zy*yz + m.zz*zz + m.zw*wz;
274
	w = m.wx*xz + m.wy*yz + m.wz*zz + m.ww*wz;
275
	xz = x;
276
	yz = y;
277
	zz = z;
278
	wz = w;
279

  
280
	x = m.xx*xw + m.xy*yw + m.xz*zw + m.xw*ww;
281
	y = m.yx*xw + m.yy*yw + m.yz*zw + m.yw*ww;
282
	z = m.zx*xw + m.zy*yw + m.zz*zw + m.zw*ww;
283
	w = m.wx*xw + m.wy*yw + m.wz*zw + m.ww*ww;
284
	xw = x;
285
	yw = y;
286
	zw = z;
287
	ww = w;
288
  }
289

  
290
  /**
291
   *  Translate the origin.
292
   *  @param  x   translation in x
293
   *  @param  y   translation in y
294
   *  @param  z   translation in z
295
   */
296
  public void translate(double x, double y, double z) {
297
	xw += x*xx+y*xy+z*xz;
298
	yw += x*yx+y*yy+z*yz;
299
	zw += x*zx+y*zy+z*zz;
300
	ww += x*wx+y*wy+z*wz;
301
  }
302

  
303
  /**
304
   *  Translate the origin
305
   *  @param  v   translation vector
306
   */
307
  public void translate(Vector3D v) {
308
	translate(v.x, v.y, v.z);
309
  }
310

  
311
  /**
312
   *  Translate.
313
   *  @param  x   translation in x
314
   *  @param  y   translation in y
315
   *  @param  z   translation in z
316
   */
317
  public void translateLeft(double x, double y, double z) {
318
	if (x != 0f) {
319
	  xx += x*wx;  xy += x*wy;  xz += x*wz;  xw += x*ww;
320
	}
321
	if (y != 0f) {
322
	  yx += y*wx;  yy += y*wy;  yz += y*wz;  yw += y*ww;
323
	}
324
	if (z != 0f) {
325
	  zx += z*wx;  zy += z*wy;  zz += z*wz;  zw += z*ww;
326
	}
327
  }
328

  
329
  /**
330
   *  Translate the origin
331
   *  @param  v   tranbslation vector
332
   */
333
  public void translateLeft(Vector3D v) {
334
	translateLeft(v.x, v.y, v.z);
335
  }
336

  
337

  
338
  /**
339
   *  Move the stuff.
340
   *  @param  x   translation in x
341
   *  @param  y   translation in y
342
   *  @param  z   translation in z
343
   */
344
  public void moveBy(double x, double y, double z) {
345
	if (x != 0f) {
346
	  xx += x*xw;  yx += x*yw;  zx += x*zw;  wx += x*ww;
347
	}
348
	if (y != 0f) {
349
	  xy += y*xw;  yy += y*yw;  zy += y*zw;  wy += y*ww;
350
	}
351
	if (z != 0f) {
352
	  xz += z*xw;  yz += z*yw;  zz += z*zw;  wz += z*ww;
353
	}
354
  }
355

  
356
  /**
357
   *  Translate the origin
358
   *  @param  v   translation vector
359
   */
360
  public void moveBy(Vector3D v) {
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff