; docformat = 'rst' ; ; NAME: ; cgShapePointFile ; ; PURPOSE: ; The purpose of this program is to create a shapefile filled with multiple ; individual points as entities. ; ;******************************************************************************************; ; ; ; Copyright (c) 2012, by Fanning Software Consulting, Inc. All rights reserved. ; ; ; ; Redistribution and use in source and binary forms, with or without ; ; modification, are permitted provided that the following conditions are met: ; ; ; ; * Redistributions of source code must retain the above copyright ; ; notice, this list of conditions and the following disclaimer. ; ; * Redistributions in binary form must reproduce the above copyright ; ; notice, this list of conditions and the following disclaimer in the ; ; documentation and/or other materials provided with the distribution. ; ; * Neither the name of Fanning Software Consulting, Inc. nor the names of its ; ; contributors may be used to endorse or promote products derived from this ; ; software without specific prior written permission. ; ; ; ; THIS SOFTWARE IS PROVIDED BY FANNING SOFTWARE CONSULTING, INC. ''AS IS'' AND ANY ; ; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ; ; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT ; ; SHALL FANNING SOFTWARE CONSULTING, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, ; ; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED ; ; TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; ; ; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ; ; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ; ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ; ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ; ;******************************************************************************************; ; ;+-------------------------------------------------------------------------- ; The purpose of this program is to create a shapefile filled with multiple ; individual points as entities. ; ; :Categories: ; Mapping, Utilities ; ; :Author: ; FANNING SOFTWARE CONSULTING:: ; David W. Fanning ; 1645 Sheely Drive ; Fort Collins, CO 80526 USA ; Phone: 970-221-0438 ; E-mail: david@idlcoyote.com ; Coyote's Guide to IDL Programming: http://www.idlcoyote.com ; ; :Params: ; xpts: in, required, type=vector ; The X location of the input points. Presumed to be longitude values unless ; the `MapCoord` keyword is used, in which case they are assumed to be in ; projected meters values that will be converted to longitude values for ; storage in the shapefile. ; ypts: in, required, type=vector ; The Y location of the input points. Presumed to be latitude values unless ; the `MapCoord` keyword is used, in which case they are assumed to be in ; projected meters values that will be converted to latitude values for ; storage in the shapefile. ; ; :Keywords: ; append: in, optional, type=boolean, default=0 ; Set this keyword to append the points to a currently existing file. Otherwise, ; a new file is created. ; attributes: in, optional, type=structure ; An array or scalar of "attribute" structures. If an array, it must be the same length as ; in input data points. If not provided is will consist of the follow structure: {point:indexValue}. ; If appending to a file, it must be defined in exactly the same way as the original file attributes. ; filename: in, optional, type=string ; The name of the shapefile. If not provided, the user will be asked to select a shape ; file. If the file currently exists, it will be written over. ; mapcoord: in, optional, type=object ; A MapCoord object (e.g., cgMap) which will be used to convert the input points from ; projected meter space to lat/lon space prior to saving the data in the shapefile. ; ; :Examples: ; Add two cities to a shapefile:: ; num = 2 ; x = FltArr(num) ; y = FltArr(num) ; attr = Replicate({namedStruct, state:"", city:""}, num) ; x[0] = -104.87270 ; y[0] = 39.768040 ; attr[0] ={namedStruct, 'CO', 'DENVER'} ; x[1] = -105.1 ; y[1] = 40.6 ; attr[1] ={nameStruct, 'CO', 'FORT COLLINS'} ; cgShapePointFile, x, y, ATTRIBUTES=attr, FILENAME='test.shp' ; ; Add two more cities to the same shapefile:: ; num = 2 ; x = FltArr(num) ; y = FltArr(num) ; attr = Replicate({namedStruct, state:"", city:""}, num) ; x[0] = -122.7 ; y[0] = 45.5 ; attr[0] ={namedStruct, 'OR', 'Portland'} ; x[1] = -122.3 ; y[1] = 47.6 ; attr[1] ={namedStruct, 'WA', 'Seattle'} ; cgShapePointFile, x, y, ATTRIBUTES=attr, FILENAME='test.shp', /APPEND ; ; View the file you just created:: ; cgShapeInfo, 'test.shp' ; ; :History: ; Modification History:: ; Written by David W. Fanning, 23 August 2012. ; ; :Copyright: ; Copyright (c) 2012, Fanning Software Consulting, Inc. ;- PRO cgShapePointFile, xpts, ypts, $ APPEND=appending, $ ATTRIBUTES=attributes, $ FILENAME=filename, $ MAPCOORD=mapCoord Compile_Opt idl2 ; Standard error handling. Catch, theError IF theError NE 0 THEN BEGIN Catch, /CANCEL void = cgErrorMsg() Obj_Destroy, shapefile RETURN ENDIF ; Need point input parameters of points. IF N_Params() NE 2 THEN BEGIN void = Dialog_Message('Calling sequence: cgShapePointFile, xpts, ypts, ATTRIBUTES=attributes, FILENAME=filename') RETURN ENDIF ; Do we need a filename? IF N_Elements(filename) EQ 0 THEN BEGIN filename = cgPickfile(/Write, Title='Select a SHAPEFILE for Writing...') IF filename EQ "" THEN RETURN ENDIF ; If the file exists, and you are not appending to it, then delete it. appending = Keyword_Set(appending) IF File_Test(filename) && ~appending THEN BEGIN ; Print, 'Deleting current file: ' + filename File_Delete, filename ENDIF ; Do the points have to be converted to lat/lon? IF Obj_Valid(mapCoord) THEN BEGIN xy = mapCoord -> Inverse(xpts, ypts) x = Reform(xy[0,*]) y = Reform(xy[1,*]) ENDIF ELSE BEGIN x = xpts y = ypts ENDELSE IF N_Elements(xpts) NE N_Elements(ypts) THEN Message, 'The point vectors must be the same length.' numPts = N_Elements(xpts) ; Do we have an attibute structure? IF N_Elements(attributes) EQ 0 THEN BEGIN struct = {point:0L} attributes = Replicate(struct, numPts) attributes.point = LIndgen(numPts) ENDIF IF N_Elements(attributes) EQ 1 THEN attributes = Replicate(attributes, numPts) IF N_Elements(attributes) NE numPts THEN $ Message, 'The number of attribute structures must match the number of points being added.' ; Open the shapefile for writing point data. IF appending THEN BEGIN shapefile = Obj_New('IDLffShape', filename, /UPDATE) ENDIF ELSE BEGIN shapefile = Obj_New('IDLffShape', filename, /UPDATE, ENTITY_TYPE=1) ENDELSE ; Define the attribute names if you are not appending to an already existing shapefile. IF ~appending THEN BEGIN ; Set the attribute names. struct = attributes[0] ; Make sure attribute names are less than 11 characters in length. attrnames = Tag_Names(struct) index = Where(StrLen(attrnames) GT 11, count) IF count GT 0 THEN Message, 'Attribute names cannot be longer than 11 characters.' ; Get the attribute type. FOR j=0,N_Elements(attrnames)-1 DO BEGIN value = struct.(j) dataType = Size(value, /TYPE) CASE dataType OF 1: attrtype = 3 2: attrtype = 3 3: attrtype = 3 4: attrtype = 5 5: attrtype = 5 7: attrtype = 7 12: attrtype = 3 13: attrtype = 3 14: attrtype = 3 ELSE: Message, 'Attribute value of type: ' + Size(value, /TNAME) + ' is not supported.' ENDCASE ; Define the new attribute. CASE attrtype OF 3: shapefile -> AddAttribute, attrnames[j], attrtype, 16 5: shapefile -> AddAttribute, attrnames[j], attrtype, 20, Precision=8 7: shapefile -> AddAttribute, attrnames[j], attrtype, 25 ENDCASE ENDFOR ENDIF ; Loop, creating entities for all the points. Points are saved in the BOUNDS field. FOR j=0,numPts-1 DO BEGIN ; Get a new entity structure. entNew = {IDL_SHAPE_ENTITY} ; Define the new values. entNew.SHAPE_TYPE = 1 entNew.BOUNDS[0] = x[j] entNew.BOUNDS[1] = y[j] entNew.BOUNDS[2] = 0.00000000 entNew.BOUNDS[3] = 0.00000000 entNew.BOUNDS[4] = x[j] entNew.BOUNDS[5] = x[j] entNew.BOUNDS[6] = 0.00000000 entNew.BOUNDS[7] = 0.00000000 entNew.N_VERTICES = 1 ; Create a new attribute structure. attrNew = shapefile -> GetAttributes(/ATTRIBUTE_STRUCTURE) thisAttrStruct = attributes[j] FOR k=0, N_Tags(attrNew)-1 DO BEGIN attrNew.(k) = thisAttrStruct.(k) ENDFOR ; Add the entity to the shapefile. shapefile -> PutEntity, entNew ; Get the entity index. shapefile -> GetProperty, N_ENTITIES=numEntities entity_index = numEntities-1 ; Add the attributes to the shapefile shapefile -> SetAttributes, entity_index, attrNew ENDFOR Obj_Destroy, shapefile END