Revision 23114 branches/v10/libraries/libDwg/src/com/iver/cit/jdwglib/dwg/DwgFile.java

View differences:

DwgFile.java
1 1
/* jdwglib. Java Library for reading Dwg files.
2
 * 
2
 *
3 3
 * Author: Jose Morell Rama (jose.morell@gmail.com).
4 4
 * Port from the Pythoncad Dwg library by Art Haas.
5 5
 *
......
22 22
 * For more information, contact:
23 23
 *
24 24
 * Jose Morell (jose.morell@gmail.com)
25
 * 
25
 *
26 26
 * or
27 27
 *
28 28
 * IVER TI S.A.
......
45 45
import java.util.Iterator;
46 46
import java.util.List;
47 47
import java.util.Map;
48
import java.util.Vector;
49 48

  
50 49
import org.apache.log4j.Logger;
51 50

  
......
64 63
 * Reading methods are useful for reading DWG files, and handling methods like
65 64
 * calculateDwgPolylines() are useful for handling more complex
66 65
 * objects in the DWG file
67
 * 
66
 *
68 67
 * @author jmorell
69 68
 * @author azabala
70 69
 */
......
92 91
		acadVersions.put("AC402b", "Autocad pre-2004b");
93 92
		acadVersions.put("AC1018", "Autocad R2004, R2005, R2006");
94 93
		acadVersions.put("AC1021", "Autocad R2007");
95
	
94

  
96 95
	}
97
	
96

  
98 97
	private static Logger logger = Logger.getLogger(DwgFile.class
99 98
			.getName());
100 99
	/**
......
105 104
	 * DWG version of the file (AC1013, AC1018, etc.)
106 105
	 * */
107 106
	private String dwgVersion;
108
	
107

  
109 108
	/**
110 109
	 * Offsets to the DWG sections
111 110
	 */
......
114 113
	 * Header vars readed from the HEADER section of the DWG file
115 114
	 * */
116 115
	private Map headerVars;
117
	
116

  
118 117
	/**
119 118
	 * This list contains what in OpenDWG specification is called
120 119
	 * the object map ( a collection of entries where each entry contains
121 120
	 * the seek of each object, and its size)
122 121
	 * */
123 122
	private ArrayList dwgObjectOffsets;
124
	
123

  
125 124
	/**
126 125
	 * For each entry in dwgObjectOffsets, we have an instance of
127 126
	 * DwgObject in the dwgObjects collection
128
	 * 
127
	 *
129 128
	 * */
130 129
	private List dwgObjects;
131 130
	private HashMap handle_objects;
132
	
133 131

  
132

  
134 133
	private ArrayList dwgClasses;
135
	
136
	
134

  
135

  
137 136
	/**
138 137
	 * hash map that indexes all DwgLayer objects
139 138
	 * by its handle property
140 139
	 * */
141
	private HashMap layerTable; 
142
	
140
	private HashMap layerTable;
141

  
143 142
	/**
144 143
	 * Specific reader of the DWG file version (12, 13, 14, 2000, etc., each
145 144
	 * version will have an specific reader)
......
150 149
	 * Memory mapped byte buffer of the whole DWG file
151 150
	 * */
152 151
	private ByteBuffer bb;
153
	
152

  
154 153
	/*
155 154
	 * Optimizaciones para evitar leer el fichero completo en cada
156 155
	 * pasada.
......
162 161
	/**
163 162
	 * Contains all INSERT entities of the dwg file
164 163
	 * (these entities must be processed in a second pass)
165
	 * 
164
	 *
166 165
	 * */
167 166
	private List insertList;
168
	
167

  
169 168
	private List blockList;
170
	
171 169

  
170

  
172 171
	/**
173 172
	 * Constructor.
174 173
	 * @param fileName an absolute path to the DWG file
175 174
	 */
176 175
	public DwgFile(String fileName) {
177 176
		this.fileName = fileName;
178
		
177

  
179 178
		dwgSectionOffsets = new ArrayList();
180 179
		dwgObjectOffsets = new ArrayList();
181 180
		headerVars = new HashMap();
182
		
181

  
183 182
		dwgClasses = new ArrayList();
184
		
183

  
185 184
		dwgObjects = new ArrayList();
186 185
		handle_objects = new HashMap();
187
		
186

  
188 187
		layerTable = new HashMap();
189
		
188

  
190 189
		dwgPolylines = new ArrayList();
191 190
		insertList = new ArrayList();
192
		
191

  
193 192
		blockList = new ArrayList();
193

  
194 194
	}
195
	
195

  
196 196
	public String getDwgVersion() {
197 197
		return dwgVersion;
198 198
	}
199
	
199

  
200 200
	/**
201 201
	 * Reads a DWG file and put its objects in the dwgObjects Vector
202 202
	 * This method is version independent
203
	 * 
203
	 *
204 204
	 * @throws IOException If the file location is wrong
205 205
	 */
206
	public void read() throws IOException, 
206
	public void read() throws IOException,
207 207
				DwgVersionNotSupportedException
208 208
	{
209 209
		setDwgVersion();
210 210
		if (dwgVersion.equalsIgnoreCase("Autocad R2000, R2000i, R2002")) {
211 211
			dwgReader = new DwgFileV15Reader();
212
		}else if (dwgVersion.equalsIgnoreCase("Autocad pre-R14")|| 
212
		}else if (dwgVersion.equalsIgnoreCase("Autocad pre-R14")||
213 213
				dwgVersion.equalsIgnoreCase("Autocad R14") ||
214 214
				dwgVersion.equalsIgnoreCase("Autocad R13")) {
215 215
			dwgReader = new DwgFileV14Reader();
216 216
		}else if (dwgVersion.equalsIgnoreCase("Autocad R2004, R2005, R2006")){
217 217
			dwgReader = new DwgFileVR2004Reader();
218
		} else if (dwgVersion.equalsIgnoreCase("Autocad R12")|| 
218
		} else if (dwgVersion.equalsIgnoreCase("Autocad R12")||
219 219
				dwgVersion.equalsIgnoreCase("Autocad pre-R13 a") ||
220 220
				dwgVersion.equalsIgnoreCase("Autocad pre-R13 b")) {
221
			
221

  
222 222
			boolean isR13 = true;
223 223
			if(dwgVersion.equalsIgnoreCase("Autocad R12"))
224 224
					isR13 = false;
225 225
			dwgReader = new DwgFileV12Reader(isR13);
226 226
		}else {
227
			DwgVersionNotSupportedException exception = 
227
			DwgVersionNotSupportedException exception =
228 228
				new DwgVersionNotSupportedException("Version de DWG no soportada");
229 229
			exception.setDwgVersion(dwgVersion);
230 230
			throw exception;
......
236 236
			throw new IOException("Error leyendo dwg");
237 237
		}
238 238
	}
239
	
239

  
240 240
	private void setDwgVersion() throws IOException {
241 241
		File file = new File(fileName);
242 242
		FileInputStream fileInputStream = new FileInputStream(file);
243 243
		FileChannel fileChannel = fileInputStream.getChannel();
244 244
		long channelSize = fileChannel.size();
245 245
		bb = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, channelSize);
246
		byte[] versionBytes = {bb.get(0), 
247
								bb.get(1), 
246
		byte[] versionBytes = {bb.get(0),
247
								bb.get(1),
248 248
								bb.get(2),
249 249
								bb.get(3),
250
								bb.get(4), 
250
								bb.get(4),
251 251
								bb.get(5)};
252 252
		ByteBuffer versionByteBuffer = ByteBuffer.wrap(versionBytes);
253 253
		String[] bs = new String[versionByteBuffer.capacity()];
......
259 259
		String version = (String) acadVersions.get(versionString);
260 260
		if(version == null)
261 261
			version = "Unknown Dwg format";
262
		this.dwgVersion = version;    
262
		this.dwgVersion = version;
263 263
	}
264
	
264

  
265 265
	public void setHeader(String key, Object value){
266 266
		headerVars.put(key, value);
267 267
	}
268
	
268

  
269 269
	public Object getHeader(String key){
270 270
		return headerVars.get(key);
271 271
	}
272
	
272

  
273 273
	/*
274 274
	 * A DwgLayer is a DWG drawing entity, so all DwgLayer objects are
275 275
	 * saved in dwgObjects collection.
......
278 278
	 *
279 279
	 */
280 280
	protected void addDwgLayer(DwgLayer dwgLayer){
281
		layerTable.put(new Integer(dwgLayer.getHandle().getOffset()), 
281
		layerTable.put(new Integer(dwgLayer.getHandle().getOffset()),
282 282
				dwgLayer);
283 283
	}
284
	
284

  
285 285
	private void printInfoOfAObject (DwgObject entity){
286 286
		logger.info("index = "+entity.getIndex() + " entity.type = " + entity.type + " entityClassName = "+ entity.getClass().getName());
287 287
		logger.info("handleCode = "+entity.getHandle().getCode());
......
317 317
				logger.info (" reactorHandle = "+hr.getOffset());
318 318
			}
319 319
		}
320
		
320

  
321 321
	}
322 322
	public DwgLayer getDwgLayer(DwgObject entity){
323 323
		DwgHandleReference handle = entity.getLayerHandle();
......
327 327
		int	handleCode = handle.getCode();
328 328
		int	entityLayerHandle = entity.getLayerHandle().getOffset();
329 329
		int layerHandle = -1;
330
		
330

  
331 331
		int entityRecord;
332 332
		DwgObject object;
333
		
334
		
333

  
334

  
335 335
		/*
336 336
		 * OpenDWG spec, v3, page 11. HANDLE REFERENCES
337
		 * 
337
		 *
338 338
		 * A handle is formed by this fields:
339 339
		 * a) CODE (4 bits)
340 340
		 * b) COUNTER (4 bits)
341 341
		 * c) OFFSET of the object (handle itself).
342
		 * 
342
		 *
343 343
		 * CODE could take these values:
344 344
		 * 1) 0x2, 0x3, 0x4, 0x5 -> offset is the handle of the layer
345 345
		 * 2) 0x6 -> offset is the next object handle
346 346
		 * 3) 0x8 -> offset is the previous object handle
347 347
		 * 4) 0xA -> result is reference handle plus offset
348 348
 		 * 5) 0xC -> result is reference handle minus offset
349
		 * 
349
		 *
350 350
		 * */
351
		
351

  
352 352
		// FIXME: Esto no esta terminado. Falta considerar los codigo
353 353
		// 0x2, 0x3, 0x6, 0xA que no han aparecido en los archivos de prueba.
354 354
		switch(handleCode){
......
400 400
		default:
401 401
//			System.out.println ("DwgFile.getDwgLayer: handleCode "+handleCode+" no implementado. entityLayerHandle="+entityLayerHandle);
402 402
		}
403
		
403

  
404 404
		if(layerHandle != -1){
405 405
			Iterator lyrIterator = layerTable.values().iterator();
406 406
			while(lyrIterator.hasNext()){
......
415 415
//		printInfoOfAObject(entity);
416 416
		return null;
417 417
	}
418
	
418

  
419 419
	public DwgObject getDwgSuperEntity(DwgObject entity) {
420 420
		if(entity.hasSubEntityHandle()){
421 421
			int handleCode = entity.subEntityHandle.getCode();
422 422
			int offset = entity.subEntityHandle.getOffset();
423 423
			int handle = -1;
424
			
424

  
425 425
			DwgObject object;
426 426

  
427 427
			switch(handleCode){
......
452 452
		}
453 453
		return null;
454 454
	}
455
   
456
	public String getLayerName(DwgObject entity) {		
455

  
456
	public String getLayerName(DwgObject entity) {
457 457
		DwgLayer dwgLayer = getDwgLayer(entity);
458 458
		if(dwgLayer == null){
459 459
			return "";
......
461 461
			return dwgLayer.getName();
462 462
		}
463 463
	}
464
	
464

  
465 465
	/**
466
     * Returns the color of the layer of a DWG object 
467
	 * 
466
     * Returns the color of the layer of a DWG object
467
	 *
468 468
     * @param entity DWG object which we want to know its layer color
469 469
	 * @return int Layer color of the DWG object in the Autocad color code
470 470
	 */
......
488 488
		/*
489 489
		 * In Dwg 12 format, all vertices of a polyline are between polyline entity
490 490
		 * and endsec entity. Also, polylines dont save any handle of their vertices (first and last).
491
		 * 
491
		 *
492 492
		 * After Dwg 12 version, we have the opposite case: polylines have handles/pointers to their
493 493
		 * first and last vertices.
494
		 * 
494
		 *
495 495
		 * If dwg file is not V12, we must look for all polyline vertices (and we must to wait until
496 496
		 * all entities are readed).
497 497
		 * If dwg file is V12, all polylines already have their vertices.
......
501 501
				DwgObject pol = (DwgObject)dwgPolylines.get(i);
502 502
				if (pol instanceof IDwgPolyline) {
503 503
					((IDwgPolyline)pol).calculateGisModel(this);
504
				}//if 
504
				}//if
505 505
			}//for
506 506
		}
507 507
	}
508
	
508

  
509 509
    /**
510 510
     * Configure the geometry of the polylines in a DWG file from the vertex list in
511 511
     * this DWG file. This geometry is given by an array of Points
......
514 514
     * parameter called bulge associated with the points of the polyline.
515 515
     */
516 516
	//TODO Refactorizar para que solo se aplique a las Polilineas
517
	
517

  
518 518
//	public void calculateCadModelDwgPolylines() {
519 519
//		for (int i=0;i<dwgObjects.size();i++) {
520 520
//			DwgObject pol = (DwgObject)dwgObjects.get(i);
......
585 585
//			}
586 586
//		}
587 587
//	}
588
	
588

  
589 589
	/*
590 590
	 * TODO Revisar los bloques que son XREF
591 591
	 * */
592 592
	public void blockManagement2(){
593 593
		Iterator it = null;
594
		
595
		
594

  
595

  
596 596
		//dwg v12 blocks already has their entities added
597 597
		//for the rest of versions, we add block entities to their owner block
598 598
		if(! (dwgReader instanceof DwgFileV12Reader)){
......
613 613
				}
614 614
			}//while
615 615
		}//if dwgfilev12
616
		
616

  
617 617
		//after that, we process the INSERTs
618 618
		it = insertList.iterator();
619 619
		while(it.hasNext()){
......
629 629
			double rot = insert.getRotation();
630 630
			int blockHandle = insert.getBlockHeaderHandle().getOffset();
631 631
			manageInsert2(point, scale,
632
					rot, blockHandle, 
632
					rot, blockHandle,
633 633
					dwgObjects, handle_objects);
634
		}	
634
		}
635 635

  
636 636
}
637 637

  
638
   
639
	
638

  
639

  
640 640
	public void manageInsert2(Point2D insPoint, double[] scale,
641
			double rot, int bHandle, 
642
			List dwgObjectsWithoutBlocks, 
641
			double rot, int bHandle,
642
			List dwgObjectsWithoutBlocks,
643 643
			Map handleObjectsWithoutBlocks) {
644
		
644

  
645 645
		DwgObject object = (DwgObject) handle_objects.get(new Integer(bHandle));
646 646
		if(object == null){
647 647
			logger.error("No hemos encontrado el BlockHeader cuyo handle es "+bHandle);
......
652 652
			logger.error("handle incorrecto." + object.getClass().getName() + " no es un blockheader");
653 653
			return;
654 654
		}
655
		
655

  
656 656
		DwgBlockHeader blockHeader = (DwgBlockHeader)object;
657 657
		double[] bPoint = blockHeader.getBasePoint();
658 658
		String bname = blockHeader.getName();
659
		if (bname.startsWith("*")) 
659
		if (bname.startsWith("*"))
660 660
			return;
661
		
662
		//TODO Cambiar por List
663
		Vector entities = blockHeader.getObjects();
661

  
662
		//TODO Cambiar por List. Done.
663
		List entities = blockHeader.getObjects();
664 664
		if(entities.size() == 0){
665 665
			logger.warn("El bloque "+blockHeader.getName()+" no tiene ninguna entidad");
666 666
		}
667 667
		Iterator blkEntIt = entities.iterator();
668 668
		while(blkEntIt.hasNext()){
669 669
			DwgObject obj = (DwgObject) blkEntIt.next();
670
			 manageBlockEntity(obj, bPoint, 
671
			 		  insPoint, scale, 
670
			 manageBlockEntity(obj, bPoint,
671
			 		  insPoint, scale,
672 672
			 		  rot, dwgObjectsWithoutBlocks,
673
			 		  handleObjectsWithoutBlocks);	
673
			 		  handleObjectsWithoutBlocks);
674 674
		}//while
675 675
	}
676
	
677
   
676

  
677

  
678 678
	public int getIndexOf(DwgObject dwgObject){
679
		return dwgObjects.indexOf(dwgObject);	
679
		return dwgObjects.indexOf(dwgObject);
680 680
	}
681
	
682
	
683
	
681

  
682

  
683

  
684 684
    /**
685 685
     * Changes the location of an object extracted from a block. This location will be
686 686
     * obtained through the insertion parameters from the block and the corresponding
......
694 694
     * @param dwgObjectsWithoutBlocks, a object list with the elements extracted from
695 695
     * the blocks.
696 696
     */
697
	private void manageBlockEntity(DwgObject entity, 
698
									double[] bPoint, 
699
									Point2D insPoint, 
700
									double[] scale, 
701
									double rot, 
697
	private void manageBlockEntity(DwgObject entity,
698
									double[] bPoint,
699
									Point2D insPoint,
700
									double[] scale,
701
									double rot,
702 702
									List dwgObjectsWithoutBlocks,
703 703
									Map handleObjectsWithoutBlocks) {
704
		
704

  
705 705
		if(entity instanceof IDwgBlockMember){
706 706
			IDwgBlockMember blockMember = (IDwgBlockMember)entity;
707
			blockMember.transform2Block(bPoint, insPoint, scale, rot, 
707
			blockMember.transform2Block(bPoint, insPoint, scale, rot,
708 708
					dwgObjectsWithoutBlocks,
709 709
					handleObjectsWithoutBlocks,this);
710 710
		}
711
		
711

  
712 712
	}
713
	
714
	
713

  
714

  
715 715
	/**
716 716
	 * Add a DWG section offset to the dwgSectionOffsets vector
717
	 * 
717
	 *
718 718
	 * @param key Define the DWG section
719 719
	 * @param seek Offset of the section
720 720
	 * @param size Size of the section
......
723 723
		DwgSectionOffset dso = new DwgSectionOffset(key, seek, size);
724 724
		dwgSectionOffsets.add(dso);
725 725
	}
726
	
726

  
727 727
	/**
728
     * Returns the offset of DWG section given by its key 
729
	 * 
728
     * Returns the offset of DWG section given by its key
729
	 *
730 730
     * @param key Define the DWG section
731 731
	 * @return int Offset of the section in the DWG file
732 732
	 */
......
742 742
		}
743 743
		return offset;
744 744
	}
745
	
745

  
746 746
	/**
747 747
	 * Add a DWG object offset to the dwgObjectOffsets vector
748
	 * 
748
	 *
749 749
	 * @param handle Object handle
750 750
	 * @param offset Offset of the object data in the DWG file
751 751
	 */
......
753 753
		DwgObjectOffset doo = new DwgObjectOffset(handle, offset);
754 754
		dwgObjectOffsets.add(doo);
755 755
	}
756
	
756

  
757 757
	/**
758
	 * 
758
	 *
759 759
	 * Add a DWG object to the dwgObject vector
760
	 * 
760
	 *
761 761
	 * @param dwgObject DWG object
762 762
	 */
763 763
	public void addDwgObject(DwgObject dwgObject){
764 764
		//TODO Ver si puedo inicializar las listas especificas
765
		//(IDwgPolyline, etc) aqu� 
765
		//(IDwgPolyline, etc) aqu�
766 766
		dwgObjects.add(dwgObject);
767 767
		/*
768 768
		 * TODO Quitar todos estos if-then y sustituirlos por un metodo callback
769
		 * 
770
		 * 
769
		 *
770
		 *
771 771
		 * (dwgObject.init(this), y que cada objeto haga lo que tenga que hacer
772 772
		 * */
773 773
		if(dwgObject instanceof DwgLayer){
774 774
			this.addDwgLayer((DwgLayer) dwgObject);
775 775
		}
776
		
776

  
777 777
		//Probamos a no aplicar las extrusiones
778
		
778

  
779 779
		if(dwgObject instanceof IDwgExtrusionable){
780 780
			((IDwgExtrusionable)dwgObject).applyExtrussion();
781
				
781

  
782 782
		}
783
		
783

  
784 784
		if(dwgObject instanceof IDwgPolyline){
785 785
			dwgPolylines.add(dwgObject);
786 786
		}
......
792 792
		if(dwgObject instanceof DwgInsert){
793 793
			insertList.add(dwgObject);
794 794
		}
795
		
795

  
796 796
		if(dwgObject instanceof DwgBlockHeader){
797 797
			blockList.add(dwgObject);
798 798
		}
799 799
		handle_objects.put(new Integer(dwgObject.getHandle().getOffset()), dwgObject);
800
		
801 800

  
801

  
802 802
	}
803
	
803

  
804 804
	/**
805 805
	 * Returns dwgObjects from its insertion order (position
806 806
	 * in the dwg file)
807
	 * 
807
	 *
808 808
	 * @param index order in the dwg file
809 809
	 * @return position
810 810
	 * */
811 811
	public DwgObject getDwgObject(int index){
812 812
		return (DwgObject) dwgObjects.get(index);
813 813
	}
814
	
814

  
815 815
	public DwgObject getDwgObjectFromHandle(int handle){
816 816
		return (DwgObject) handle_objects.get(new Integer(handle));
817 817
	}
818
	
818

  
819 819
	/**
820 820
	 * Add a DWG class to the dwgClasses vector
821
	 * 
821
	 *
822 822
	 * @param dwgClass DWG class
823 823
	 */
824 824
	public void addDwgClass(DwgClass dwgClass){
825 825
		dwgClasses.add(dwgClass);
826 826
	}
827
	
827

  
828 828
	/**
829 829
	 * Add a DWG class to the dwgClasses vector
830
	 * 
830
	 *
831 831
	 * @param dwgClass DWG class
832 832
	 */
833 833
	public void addDwgClass(DwgClass2004 dwgClass){
834 834
		dwgClasses.add(dwgClass);
835 835
	}
836
	
837
	
836

  
837

  
838 838
	public void printClasses(){
839 839
		logger.info("#### CLASSES ####");
840 840
		for(int i = 0; i < dwgClasses.size(); i++){
......
843 843
		}
844 844
		logger.info("#############");
845 845
	}
846
	
846

  
847 847
	public List getDwgClasses(){
848 848
		return dwgClasses;
849 849
	}
850
	
850

  
851 851
    /**
852 852
     * @return Returns the dwgObjectOffsets.
853 853
     */

Also available in: Unified diff