static void _pgmvcp_gfaCalc ( VG_DBStruct *el, float dx, float dy, Boolean grp ) /************************************************************************ * _pgmvcp_gfaCalc * * * * Internal function for MOVE/COPY GFA's atribute box location. * * * * static void _pgmvcp_gfaCalc () * * *el VG_DBStruct Pointer to gfa element * * dx float Increment on X axis * * dy float Increment on Y axis * * grp Boolean Group mode or not * * * * Input parameters: * * * ** * * Log: * * J. Wu/SAIC 02/04 initial coding * * J. Wu/SAIC 10/04 Access GFA attr with cvg_getFld() * ***********************************************************************/ { int np, ier; float delx, dely, xx, yy, nlat, nlon; char value[32]; /*---------------------------------------------------------------------*/ /* * For group drag/drop, use the given dx, dy as the "delta" increment. */ delx = dx; dely = dy; /* * For single element drag/drop, recalculate the "delta" increment. */ if ( !grp && _dcN > 0 ) { delx = *(_dcX + _nearPt) - _origX; dely = *(_dcY + _nearPt) - _origY; } /* * Adjust attribute text box location. */ np = 1; cvg_getFld ( el, TAG_GFA_LAT, value, &ier ); nlat = atof ( value ); cvg_getFld ( el, TAG_GFA_LON, value, &ier ); nlon = atof ( value ); gtrans ( sys_M, sys_D, &np, &nlat, &nlon, &xx, &yy, &ier, strlen(sys_M), strlen(sys_D) ); xx += delx; yy += dely; gtrans ( sys_D, sys_M, &np, &xx, &yy, &nlat,&nlon, &ier, strlen(sys_D), strlen(sys_M) ); sprintf ( value, "%7.2f", nlat ); cvg_setFld ( el, TAG_GFA_LAT, value, &ier ); sprintf ( value, "%7.2f", nlon ); cvg_setFld ( el, TAG_GFA_LON, value, &ier ); }
static void pgfilterw_updateFilter ( void ) /************************************************************************ * pgfilterw_updateFilter * * * * Updates the current filter string and then refreshes the display. * * * * static void pgfilterw_updateFilter ( void ) * * * * Input parameters: * * Output parameters: * * none * * * ** * * Log: * * J. Wu/SAIC 07/04 initial coding * * J. Wu/SAIC 08/04 link filter change with GFA window * * J. Wu/SAIC 09/04 Restart GFA for any filter changes * * J. Wu/SAIC 10/04 Access GFA attr with cvg_getFld() * * E. Safford/SAIC 07/05 rm sequence # from cvg_scangfa() call * * M. Li/SAIC 03/07 Not reset fcst hour if change from GFA * * E. Safford/SAIC 05/07 fix gfa' connection * * E. Safford/SAIC 06/07 fix bug in preFilterOn determination * * B. Yin/SAIC 12/07 set GFA hr to last selected filter time * ***********************************************************************/ { int ii, filternum, ier, cur_obj, cur_loc, newel_loc, num; int subtyp, areatyp, len; char lastTime[8], value[32], tag[32], timeCmp[10]; Boolean gfaIsUp = False, gfaInAdd = False, preFilterOn = False; Boolean gfaPrimeIsUp = False; VG_DBStruct cur_el, newel; /*---------------------------------------------------------------------*/ cur_el.elem.gfa.info.nblocks = 0; _curFilter[0] = '\0'; filternum = 0; for ( ii = 0; ii < _nFilTime[TIME_FILTER]; ii++ ) { if ( _filterStatus[ii] ) { filternum++; strcat ( _curFilter, _filTime[TIME_FILTER][ii] ); if ( ii < (_nFilTime[TIME_FILTER] - 1) ) { strcat ( _curFilter, ";" ); } } } /* * If no filter is provided but the filter window is up - none * of the elements with time stamp will be displayed. If the * filter window is down, all elements should be displayed. */ if ( filternum == 0 ) { if ( pgfilterw_isUp() ) { strcpy ( _curFilter, ACTV_FILTER ); } else { strcpy ( _curFilter, CANCEL_FILTER ); } } /* * Check if gfaw is up and its mode. */ gfaIsUp = pggfaw_isUp(); gfaPrimeIsUp = pggfawp_isUp(); if( gfaIsUp ) { gfaInAdd = pggfaw_isAddMode(); } else if( gfaPrimeIsUp ) { gfaInAdd = pggfawp_isAddMode(); } cur_obj = pgpalw_getCurObjId (); /* * If gfaw is up, retrieve the current GFA attributes and check * if the previous forecast hour is still "ON" in filter window. * * If it is still on, then take no action. If it is not, and there * is another time selected, set the GFA/GFA' window forecast hour to * the first selected time. * * Note that the GFA/GFA' will ignore the Airmet and Outlook filter * settings. */ cur_loc = -1; preFilterOn = False; if ( gfaIsUp || gfaPrimeIsUp ) { if ( gfaInAdd ) { if( gfaIsUp ) { pggfaw_getAttr ( &cur_el ); ier = 0; } else { pggfawp_getAttr ( &cur_el ); ier = 0; } } else { cur_loc = pgactv_getElmLoc (); cvg_rdrec ( cvg_getworkfile(), cur_loc, &cur_el, &ier ); } cvg_getFld ( &cur_el, TAG_GFA_FCSTHR, value, &ier ); if ( filternum > 0 && ier == 0 ) { for ( ii = 0; ii < _nFilTime[TIME_FILTER]; ii++ ) { if ( _filterStatus[ii] ) { strcpy( timeCmp, _filTime[TIME_FILTER][ii] ); len = strlen( timeCmp ); if( timeCmp[ len-1 ] == '+' ) { timeCmp[ len-1 ] = '\0'; } if ( strcmp ( value, timeCmp ) == 0 ) { preFilterOn = True; break; } } } } } /* * Update filter setting in CVG library. */ cvg_setfilter ( _curFilter, &ier ); /* * Refresh the display. */ pgfilterw_refresh (); /* * Adjust GFA window, if necessary. */ if ( gfaIsUp || gfaPrimeIsUp ) { /* * If previously in "Add" mode, keep drawing. */ if ( gfaInAdd ) { /* * Set the GFA hour to the last selected filter time. * */ pgfilterw_getLastTime ( lastTime ); if ( strlen ( lastTime ) > (size_t)0 ) { if (!_fromGfa) { if( gfaIsUp ) { pggfaw_setHour ( lastTime ); } else { pggfawp_setHour ( lastTime ); } } } } else { /* Previously in "Edit" mode */ /* * The filter matching the active element's forecast hour * is still ON, keep editing it. */ if ( preFilterOn ) { cvg_freeElPtr( &cur_el ); pghdlb_select ( &cur_el, cur_loc ); } else { /* * The filter matching the active element's forecast * hour is OFF, terminate all pending actions. * However, if it is turned off by pressing hotkeys, * and a GFA element matching the same subtype, * and area type number could be found, * set to edit that element. */ if ( _offByHotkey ) { cvg_getFld ( &cur_el, TAG_GFA_SUBTYPE, value, &ier ); subtyp = atoi ( value ); cvg_getFld ( &cur_el, TAG_GFA_AREATYPE, value, &ier ); areatyp = atoi ( value ); cvg_getFld ( &cur_el, TAG_GFA_TAG, tag, &ier ); cvg_scangfa ( NULL, pglayer_getCurLayer(), subtyp, areatyp, tag, &newel, &newel_loc, &ier ); if ( ier == 0 ) { crg_getinx ( cur_loc, &num, &ier); pghdlb_deselectEl ( num, TRUE ); pgactv_setActvElm ( &newel, newel_loc ); pghdlb_select ( &newel, newel_loc ); if( gfaIsUp ) { pggfaw_setAttr ( &newel ); } else { pggfawp_setAttr ( &newel ); } } else { pgevt_unsetOper ( TRUE ); } } else { pgevt_unsetOper ( TRUE ); } _offByHotkey = False; } } /* End "if" in edit mode */ } cvg_freeElPtr( &cur_el ); _fromGfa = False; }
int main ( int argc, char **argv ) /************************************************************************ * clipvgf * * * * This program clips elements in a VGF file based on a bounds * * specification. By default, a simple clipping algorithm is used * * where element points either inside or outside the polygon are kept * * or thrown away based on an input flag. Alternatively, an exact * * algorithm may be requested which clips precisely at the borders. * * * * The bound definition must be in the format: * * bound_name|<area_tag_name>area_tag_value * * and must be enclosed w/ quotes so the shell will ignore directives. * * * * Examples: * * clipvgf input.vgf "STATE_BNDS|<STATE>WY" keep output.vgf rough * * clipvgf input.vgf "STATE_BNDS|<STATE>WY" keep output.vgf exact * * Where "rough" uses the simple clipping algorithm and "exact" yields * * precise clipping at the bounds borders. * * * * The following element classes are not processed: * * CLASS_WATCHES, CLASS_TRACKS, CLASS_SIGMETS * * * * main(argc, argv) * * * * Input parameters: * * argc int number of parameters of command line * * argv char** parameter array of command line * * * * Output parameters: * * Return parameters: * * NONE * * * ** * * Log: * * D.W.Plummer/NCEP 2/02 * * D.W.Plummer/NCEP 5/02 Added exact clipping and label moving * * D.W.Plummer/NCEP 8/02 Account for text grouped with symbol * * D.W.Plummer/NCEP 8/02 Create output VGF, even if it is empty * * H. Zeng/XTRIA 02/03 converted CLASS_CIRCLE to CLASS LINES * * D.W.Plummer/NCEP 8/03 Bug fix - add pt to closed lines * * R. Tian/SAIC 11/04 Added clip jet element * * S. Danz/AWC 07/06 Update to new cvg_writef() parameter * * T. Piper/SAIC 03/07 Added ninout-- for closed line case * * L. Hinson/AWC 07/07 Added clip code for GFA elements * * L. Hinson/AWC 07/07 Add recalcGFAtLblArwLoc function * for GFA elements * * X.Guo/CWS 10/10 Bug fix - Low level graphic don't make * * it all the way north in central US * * L. Hinson/AWC 09/13 Fixed improperly clipped JET_ELM Barbs * * and hashes * ***********************************************************************/ { int ii, jj, ip, ibeg, iend, loc, ne, found, found_txt, joffset, kept, ier; int wrtflg, pagflg; int minpts, maxpts, npts, numpts, npoly; char vg_class, vg_type; char bnd[128], keep[32], bnd_name[64], bnd_tag[64]; char infile[128], ifname[128], outfile[128]; char *cptr; long ifilesize; int more, curpos; float flat, flon, filt, px[LLMXPT], py[LLMXPT]; float plat[LLMXPT], plon[LLMXPT], *ptrlat, *ptrlon; float tlat[LLMXPT], tlon[LLMXPT]; float fltmin, fltmax, flnmin, flnmax; int inout[LLMXPT], tinout[LLMXPT]; char device[8], dfilnam[128], pro[32]; float xsize, ysize, lllat, lllon, urlat, urlon; float prjang1, prjang2, prjang3; int mode, istat, iunit, itype; char errgrp[8]; int ninout; float xinout[LLMXPT], yinout[LLMXPT]; char precision[8]; int tltpts, nbarb, nhash; int tmaxpts, tnpts, tnclip; char hazList[ STD_STRLEN ]; VG_DBStruct el, el_t, el_q, el_lin; FILE *ifptr; int ninxarr, inxarr[100]; /*---------------------------------------------------------------------*/ /* * First check if number of input arguments is correct. */ if ( argc < 5 ) { pagflg = G_FALSE; strcpy ( errgrp, "CLIPVGF" ); ip_help ( errgrp, &pagflg, &ier, strlen(errgrp) ); exit (0); } /* * First input on command line is input vgf file name. */ strcpy ( infile, argv[1] ); wrtflg = 0; cvg_open ( infile, wrtflg, &(ifptr), &ier ); if ( ier != 0 ) { printf("Error opening VGF file %s\n", infile ); exit (0); } cfl_inqr ( infile, NULL, &ifilesize, ifname, &ier ); /* * Second input on command line is bounds name. */ clo_init ( &ier ); strcpy ( bnd, argv[2] ); cptr = cst_split( bnd, '|', sizeof(bnd_name), bnd_name, &ier ); clo_bstype ( bnd_name, &ier ); if ( ier != 0 ) { printf("Error finding bounds type %s\n", bnd_name ); exit (0); } if ( cptr != (char *)NULL ) { strcpy ( bnd_tag, cptr ); clo_bstag ( bnd_tag, &ier ); } fltmin = -90.0F; fltmax = 90.0F; flnmin = -180.0F; flnmax = 180.0F; clo_bsarea ( &fltmin, &flnmin, &fltmax, &flnmax, &ier ); minpts = 3; maxpts = sizeof(px)/sizeof(float); filt = 0.0F; clo_bgnext ( &minpts, &maxpts, &filt, &npoly, px, py, &ier ); if ( ier < 0 ) { printf("Error retrieving bound area %s|%s\n", bnd_name, bnd_tag ); exit (0); } /* * Third input on command line is keep flag. */ strcpy ( keep, argv[3] ); /* * Fourth input on command line is output vgf file name; create it. */ strcpy ( outfile, argv[4] ); cvg_crvgf ( outfile, &ier ); /* * Fifth input on command line is clip precision = "rough" or "exact" */ if ( argv[5] != (char *)NULL ) strcpy ( precision, argv[5] ); else strcpy ( precision, "ROUGH" ); cst_lcuc ( precision, precision, &ier ); /* * All input checks out OK; set up GAREA and PROJ for inpoly. */ mode = 1; ginitp ( &mode, &istat, &ier ); strcpy ( device, "GN" ); iunit = 1; strcpy ( dfilnam, "CLIPVGF" ); itype = 1; xsize = 500.0F; ysize = 500.0F; gsdeva ( device, &iunit, dfilnam, &itype, &xsize, &ysize, &ier, strlen(device), strlen(dfilnam)); /* * Something more sophisticated may be needed here in the future * to set up a proper proj and garea based on the clip area. * For instance, the following definitions probably won't work * on a clipping bound equivalent to Antartica. */ lllat = 0.0F; lllon = -135.0F; urlat = 0.0F; urlon = 45.0F; strcpy ( pro, "str" ); prjang1 = 90.0F; prjang2 = -105.0F; prjang3 = 0.0F; gsmprj ( pro, &prjang1, &prjang2, &prjang3, &lllat, &lllon, &urlat, &urlon, &ier, strlen(pro)); /* * Loop through all the elements to set the range records. */ crg_init ( &ier ); ne = 0; more = G_TRUE; curpos = 0; ifptr = (FILE *) cfl_ropn(ifname, "", &ier); while ( ne < MAX_EDITABLE_ELEMS && more == G_TRUE ) { cvg_rdrecnoc ( ifname, ifptr, curpos, &el, &ier ); if ( ier < 0 ) { more = G_FALSE; } else { crg_set ( &el, curpos, 1, &ier ); curpos += el.hdr.recsz; ne++; } } cfl_clos ( ifptr, &ier ); /* * Loop through all the elements. */ ne = 0; more = G_TRUE; curpos = 0; ifptr = (FILE *) cfl_ropn(ifname, "", &ier); while ( ne < MAX_EDITABLE_ELEMS && more == G_TRUE ) { cvg_rdrecnoc( ifname, ifptr, curpos, &el, &ier ); if ( ier < 0 ) { more = G_FALSE; } else if ( el.hdr.recsz > 0 ) { crg_gginx( el.hdr.grptyp, el.hdr.grpnum, sizeof(inxarr)/sizeof(inxarr[0]), inxarr, &ninxarr, &ier ); /* * Increment file pointer now because element hdrsz may change. */ curpos += el.hdr.recsz; vg_class = el.hdr.vg_class; vg_type = el.hdr.vg_type; switch ( (int)vg_class ) { case CLASS_SYMBOLS: case CLASS_TEXT: case CLASS_WINDS: case CLASS_COMSYM: case CLASS_MARKER: switch ( (int)vg_type ) { case TEXT_ELM: case TEXTC_ELM: flat = el.elem.txt.info.lat; flon = el.elem.txt.info.lon; break; case SPTX_ELM: flat = el.elem.spt.info.lat; flon = el.elem.spt.info.lon; break; case BARB_ELM: case ARROW_ELM: case DARR_ELM: case HASH_ELM: flat = el.elem.wnd.data.latlon[0]; flon = el.elem.wnd.data.latlon[1]; break; case WXSYM_ELM: case CTSYM_ELM: case ICSYM_ELM: case PTSYM_ELM: case PWSYM_ELM: case SKSYM_ELM: case SPSYM_ELM: case TBSYM_ELM: case MARK_ELM: case CMBSY_ELM: flat = el.elem.sym.data.latlon[0]; flon = el.elem.sym.data.latlon[1]; break; } npts = 1; cgr_inpoly ( "M", &npts, &flat, &flon, "M", &npoly, px, py, inout, &ier ); if ( ( inout[0] == 1 && strcmp(keep,"keep") == 0 ) || ( inout[0] == 0 && strcmp(keep,"keep") != 0 ) ) { /* * Check if element is TEXT grouped with a SYMBOL. If this text was going * to be kept but it's symbol was going to be throw away, throw it away also. */ if ( (int)vg_class == CLASS_TEXT && (int)el.hdr.grptyp != 0 && ninxarr > 1 ) { found = G_FALSE; ii = 0; while ( ii < ninxarr && found == G_FALSE ) { crg_goffset ( inxarr[ii], &joffset, &ier ); cvg_rdrecnoc( ifname, ifptr, joffset, &el_q, &ier ); if ( el_q.hdr.vg_class == CLASS_SYMBOLS ) { found = G_TRUE; flat = el_q.elem.sym.data.latlon[0]; flon = el_q.elem.sym.data.latlon[1]; npts = 1; cgr_inpoly ( "M", &npts, &flat, &flon, "M", &npoly, px, py, inout, &ier ); if ((inout[0] == 1 && strcmp(keep,"keep") == 0) || (inout[0] == 0 && strcmp(keep,"keep") != 0)) { cvg_writef( &el, -1, el.hdr.recsz, outfile, FALSE, &loc, &ier ); kept = G_TRUE; } else { kept = G_FALSE; } } ii++; } if ( found == G_FALSE ) { cvg_writef( &el, -1, el.hdr.recsz, outfile, FALSE, &loc, &ier ); kept = G_TRUE; } } else { /* * non-TEXT -- keep it. */ cvg_writef( &el, -1, el.hdr.recsz, outfile, FALSE, &loc, &ier ); kept = G_TRUE; } } else { /* * Element is not to be kept. */ kept = G_FALSE; } /* * Check if element was kept and is a SYMBOL element grouped with TEXT; * make sure any text elements are saved off they were going to be thrown away. */ if ( kept == G_TRUE && (int)vg_class == CLASS_SYMBOLS && (int)el.hdr.grptyp != 0 && ninxarr > 1 ) { ii = 0; while ( ii < ninxarr ) { crg_goffset ( inxarr[ii], &joffset, &ier ); cvg_rdrecnoc( ifname, ifptr, joffset, &el_q, &ier ); if ( el_q.hdr.vg_class == CLASS_TEXT ) { el_t = el_q; switch ( (int)el_t.hdr.vg_type ) { case TEXT_ELM: case TEXTC_ELM: flat = el_t.elem.txt.info.lat; flon = el_t.elem.txt.info.lon; break; case SPTX_ELM: flat = el_t.elem.spt.info.lat; flon = el_t.elem.spt.info.lon; break; } npts = 1; cgr_inpoly ( "M", &npts, &flat, &flon, "M", &npoly, px, py, inout, &ier ); if ( ( kept == G_TRUE ) && ( ( inout[0] == 1 && strcmp(keep,"keep") == 0 ) || ( inout[0] == 0 && strcmp(keep,"keep") != 0 ) ) ) { } else { cvg_writef ( &el_t, -1, el_t.hdr.recsz, outfile, FALSE, &loc, &ier ); } } ii++; } } break; case CLASS_CIRCLE: case CLASS_LINES: case CLASS_FRONTS: /* * convert a circle element to a line element */ if ( vg_class == CLASS_CIRCLE ) { cvg_cir2lin ( &el, 10, &el_lin, &ier ); el = el_lin; vg_class = el.hdr.vg_class; vg_type = el.hdr.vg_type; } switch ( (int)vg_type ) { case LINE_ELM: npts = el.elem.lin.info.numpts; ptrlat = &(el.elem.lin.latlon[ 0]); ptrlon = &(el.elem.lin.latlon[npts]); break; case SPLN_ELM: npts = el.elem.spl.info.numpts; ptrlat = &(el.elem.spl.latlon[ 0]); ptrlon = &(el.elem.spl.latlon[npts]); break; case FRONT_ELM: npts = el.elem.frt.info.numpts; ptrlat = &(el.elem.frt.latlon[ 0]); ptrlon = &(el.elem.frt.latlon[npts]); break; } memcpy ( plat, ptrlat, (size_t)npts*sizeof(float) ); memcpy ( plon, ptrlon, (size_t)npts*sizeof(float) ); if ( el.hdr.closed == 1 ) { plat[npts] = plat[0]; plon[npts] = plon[0]; npts++; } if ( strcmp(precision,"EXACT") == 0 ) { clip_line ( npoly, px, py, npts, plat, plon, (int)el.hdr.closed, sizeof(xinout)/sizeof(float), &ninout, xinout, yinout, inout, &ier ); } else if ( strcmp(precision,"ROUGH") == 0 ) { cgr_inpoly ( "M", &npts, plat, plon, "M", &npoly, px, py, inout, &ier ); ninout = npts; memcpy ( xinout, plat, (size_t)ninout*sizeof(float) ); memcpy ( yinout, plon, (size_t)ninout*sizeof(float) ); } /* * If element is closed, and some points are to be kept and others are not, * then rotate the locations arrays such that a transition point is the first point. */ if ( el.hdr.closed == 1 ) { ip = 0; ninout--; while ( inout[ip] == inout[0] && ip < ninout ) ip++; if ( ip != ninout ) { if (( inout[0] == 1 && strcmp(keep,"keep") == 0 ) || ( inout[0] == 0 && strcmp(keep,"keep") != 0 ) ) { memcpy ( tlat, xinout, (size_t)ninout*sizeof(float) ); memcpy ( tlon, yinout, (size_t)ninout*sizeof(float) ); memcpy ( tinout, inout, (size_t)ninout*sizeof(float) ); for ( ii = 0; ii < ninout; ii++ ) { xinout[ii] = tlat[(ii+ip) % ninout]; yinout[ii] = tlon[(ii+ip) % ninout]; inout[ii] = tinout[(ii+ip) % ninout]; } } } } ip = 0; while ( ip < ninout ) { ibeg = ip; iend = ip; while ( inout[ip] == inout[ibeg] && ip < ninout ) ip++; iend = ip - 1; numpts = iend - ibeg + 1; /* * If element is closed, and some points are to be kept and others are not, * then reset the closed flag. */ if ( el.hdr.closed == 1 && numpts != ninout ) el.hdr.closed = 0; if ( numpts > 1 ) { if (( inout[ibeg] == 1 && strcmp(keep,"keep") == 0 ) || ( inout[ibeg] == 0 && strcmp(keep,"keep") != 0 ) ) { switch ( (int)vg_type ) { case LINE_ELM: el.elem.lin.info.numpts = numpts; ptrlat = &(el.elem.lin.latlon[ 0]); ptrlon = &(el.elem.lin.latlon[numpts]); el.hdr.recsz = ( (int)((sizeof(float) * 2 * (size_t)numpts) + sizeof(VG_HdrStruct) + sizeof(LineInfo) )); break; case SPLN_ELM: el.elem.spl.info.numpts = numpts; ptrlat = &(el.elem.spl.latlon[ 0]); ptrlon = &(el.elem.spl.latlon[numpts]); el.hdr.recsz = ( (int)((sizeof(float) * 2 * (size_t)numpts) + sizeof(VG_HdrStruct) + sizeof(SpLineInfo) )); break; case FRONT_ELM: el.elem.frt.info.numpts = numpts; ptrlat = &(el.elem.frt.latlon[ 0]); ptrlon = &(el.elem.frt.latlon[numpts]); el.hdr.recsz = ( (int)((sizeof(float) * 2 * (size_t)numpts) + sizeof(VG_HdrStruct) + sizeof(FrontInfo) )); break; } memcpy(ptrlat, &(xinout[ibeg]), (size_t)numpts*sizeof(float)); memcpy(ptrlon, &(yinout[ibeg]), (size_t)numpts*sizeof(float)); cvg_writef ( &el, -1, el.hdr.recsz, outfile, FALSE, &loc, &ier ); if ( (int)el.hdr.grptyp != 0 && ninxarr > 1 ) { found = G_FALSE; found_txt = G_FALSE; ii = 0; while ( ii < ninxarr && found == G_FALSE ) { crg_goffset ( inxarr[ii], &joffset, &ier ); cvg_rdrecnoc( ifname, ifptr, joffset, &el_q, &ier ); if ( el_q.hdr.vg_class == CLASS_TEXT ) { found_txt = G_TRUE; el_t = el_q; switch ( (int)el_t.hdr.vg_type ) { case TEXT_ELM: case TEXTC_ELM: flat = el_t.elem.txt.info.lat; flon = el_t.elem.txt.info.lon; break; case SPTX_ELM: flat = el_t.elem.spt.info.lat; flon = el_t.elem.spt.info.lon; break; } npts = 1; cgr_inpoly ( "M", &npts, &flat, &flon, "M", &npoly, px, py, inout, &ier ); if ( ( inout[0] == 1 && strcmp(keep,"keep") == 0 ) || ( inout[0] == 0 && strcmp(keep,"keep") != 0 ) ) { found = G_TRUE; break; } } ii++; } if ( found == G_FALSE && ii == ninxarr && found_txt == G_TRUE ) { switch ( (int)vg_type ) { case LINE_ELM: flat = ( el.elem.lin.latlon[0] + el.elem.lin.latlon[1] ) / 2.0F; flon = ( el.elem.lin.latlon[numpts] + el.elem.lin.latlon[numpts+1] ) / 2.0F; break; case SPLN_ELM: flat = ( el.elem.spl.latlon[0] + el.elem.spl.latlon[1] ) / 2.0F; flon = ( el.elem.spl.latlon[numpts] + el.elem.spl.latlon[numpts+1] ) / 2.0F; break; case FRONT_ELM: flat = ( el.elem.frt.latlon[0] + el.elem.frt.latlon[1] ) / 2.0F; flon = ( el.elem.frt.latlon[numpts] + el.elem.frt.latlon[numpts+1] ) / 2.0F; break; } switch ( (int)el_t.hdr.vg_type ) { case TEXT_ELM: case TEXTC_ELM: el_t.elem.txt.info.lat = flat; el_t.elem.txt.info.lon = flon; break; case SPTX_ELM: el_t.elem.spt.info.lat = flat; el_t.elem.spt.info.lon = flon; break; } cvg_writef ( &el_t, -1, el_t.hdr.recsz, outfile, FALSE, &loc, &ier ); } } } } } break; case CLASS_MET: switch ( (int)vg_type ) { case JET_ELM: npts = tltpts = el.elem.jet.line.spl.info.numpts; ptrlat = &(el.elem.jet.line.spl.latlon[ 0]); ptrlon = &(el.elem.jet.line.spl.latlon[npts]); memcpy ( plat, ptrlat, (size_t)npts*sizeof(float) ); memcpy ( plon, ptrlon, (size_t)npts*sizeof(float) ); if ( strcmp(precision,"EXACT") == 0 ) { clip_line ( npoly, px, py, npts, plat, plon, (int)el.hdr.closed, sizeof(xinout)/sizeof(float), &ninout, xinout, yinout, inout, &ier ); } else if ( strcmp(precision,"ROUGH") == 0 ) { cgr_inpoly ( "M", &npts, plat, plon, "M", &npoly, px, py, inout, &ier ); ninout = npts; memcpy ( xinout, plat, (size_t)ninout*sizeof(float) ); memcpy ( yinout, plon, (size_t)ninout*sizeof(float) ); } ip = 0; while ( ip < ninout ) { ibeg = ip; iend = ip; while ( inout[ip] == inout[ibeg] && ip < ninout ) ip++; iend = ip - 1; numpts = iend - ibeg + 1; if ( numpts > 1 ) { if (( inout[ibeg] == 1 && strcmp(keep,"keep") == 0 ) || ( inout[ibeg] == 0 && strcmp(keep,"keep") != 0 ) ) { memcpy ( &(el_t.hdr), &(el.hdr), sizeof(VG_HdrStruct) ); el_t.elem.jet.line.splcol = el.elem.jet.line.splcol; memcpy ( &(el_t.elem.jet.line.spl.info), &(el.elem.jet.line.spl.info), sizeof(SpLineInfo) ); el_t.elem.jet.line.spl.info.numpts = numpts; ptrlat = &(el_t.elem.jet.line.spl.latlon[ 0]); ptrlon = &(el_t.elem.jet.line.spl.latlon[numpts]); memcpy(ptrlat, &(xinout[ibeg]), (size_t)numpts*sizeof(float)); memcpy(ptrlon, &(yinout[ibeg]), (size_t)numpts*sizeof(float)); nbarb = 0; for ( ii = 0; ii < el.elem.jet.nbarb; ii++ ) { flat = el.elem.jet.barb[ii].wnd.data.latlon[0]; flon = el.elem.jet.barb[ii].wnd.data.latlon[1]; npts = 1; cgr_inpoly ( "M", &npts, &flat, &flon, "M", &npoly, px, py, tinout, &ier ); if (( tinout[0] == 1 && strcmp(keep,"keep") == 0 ) || ( tinout[0] == 0 && strcmp(keep,"keep") != 0 ) ) { memcpy ( &(el_t.elem.jet.barb[nbarb]), &(el.elem.jet.barb[ii]), sizeof(BarbAttr) ); nbarb++; } } el_t.elem.jet.nbarb = nbarb; nhash = 0; for ( ii = 0; ii < el.elem.jet.nhash; ii++ ) { flat = el.elem.jet.hash[ii].wnd.data.latlon[0]; flon = el.elem.jet.hash[ii].wnd.data.latlon[1]; npts = 1; cgr_inpoly ( "M", &npts, &flat, &flon, "M", &npoly, px, py, tinout, &ier ); if (( tinout[0] == 1 && strcmp(keep,"keep") == 0 ) || ( tinout[0] == 0 && strcmp(keep,"keep") != 0 ) ) { memcpy ( &(el_t.elem.jet.hash[nhash]), &(el.elem.jet.hash[ii]), sizeof(HashAttr) ); nhash++; } } el_t.elem.jet.nhash = nhash; cvg_writef ( &el_t, -1, el.hdr.recsz, outfile, FALSE, &loc, &ier ); } } } break; case GFA_ELM: /* Get the Hazard Type... */ cvg_getFld ( &el, TAG_GFA_AREATYPE, hazList, &ier ); npts = el.elem.gfa.info.npts; ptrlat = &(el.elem.gfa.latlon[0]); ptrlon = &(el.elem.gfa.latlon[npts]); memcpy ( plat, ptrlat, (size_t)npts*sizeof(float) ); memcpy ( plon, ptrlon, (size_t)npts*sizeof(float) ); if ( el.hdr.closed == 1 ) { plat[npts] = plat[0]; plon[npts] = plon[0]; npts++; } if(strcmp(hazList,"FZLVL")==0) { /* Is this a Freezing Level? */ if ( strcmp(precision,"EXACT") == 0 ) { clip_line ( npoly, px, py, npts, plat, plon, (int)el.hdr.closed, sizeof(xinout)/sizeof(float), &ninout, xinout, yinout, inout, &ier ); } else if (strcmp(precision,"ROUGH") == 0 ) { cgr_inpoly ( "M", &npts, plat, plon, "M", &npoly, px, py, inout, &ier ); ninout = npts; memcpy ( xinout, plat, (size_t)ninout*sizeof(float) ); memcpy ( yinout, plon, (size_t)ninout*sizeof(float) ); } if ( el.hdr.closed == 1 ) { ip = 0; ninout--; while ( inout[ip] == inout[0] && ip < ninout ) ip++; if ( ip != ninout ) { if (( inout[0] == 1 && strcmp(keep,"keep") == 0 ) || ( inout[0] == 0 && strcmp(keep,"keep") != 0 ) ) { memcpy ( tlat, xinout, (size_t)ninout*sizeof(float) ); memcpy ( tlon, yinout, (size_t)ninout*sizeof(float) ); memcpy ( tinout, inout, (size_t)ninout*sizeof(float) ); for ( ii = 0; ii < ninout; ii++ ) { xinout[ii] = tlat[(ii+ip) % ninout]; yinout[ii] = tlon[(ii+ip) % ninout]; inout[ii] = tinout[(ii+ip) % ninout]; } } } } ip = 0; while ( ip < ninout ) { ibeg = ip; iend = ip; while ( inout[ip] == inout[ibeg] && ip < ninout ) ip++; iend = ip - 1; numpts = iend - ibeg + 1; if (el.hdr.closed == 1 && numpts != ninout ) el.hdr.closed = 0; if ( numpts > 1 ) { if (( inout[ibeg] == 1 && strcmp(keep,"keep") == 0 ) || ( inout[ibeg] == 0 && strcmp(keep,"keep") != 0 )) { el.elem.gfa.info.npts = numpts; ptrlat = &(el.elem.gfa.latlon[ 0]); ptrlon = &(el.elem.gfa.latlon[numpts]); memcpy(ptrlat, &(xinout[ibeg]), (size_t)numpts*sizeof(float)); memcpy(ptrlon, &(yinout[ibeg]), (size_t)numpts*sizeof(float)); /* Recompute Default Text Label & Arrow location */ recalcGFAtLblArwLoc( &el ); el.hdr.recsz = (int) (sizeof(VG_HdrStruct) + sizeof(int)*2 + sizeof(char)* STD_STRLEN * el.elem.gfa.info.nblocks ) + sizeof(float)*numpts*2; cvg_writef ( &el, -1, el.hdr.recsz, outfile, FALSE, &loc, &ier ); } } } } else { /* We have a GFA object (that's not a freezing level) to be clipped */ /* Use clo_clip to clip the GFA Polygon against the specified bounds area. The resulting number of clipped areas (tnclips), and max points (tmaxpts) is returned */ clo_clip(&npts, plat, plon, sys_M, bnd_name, bnd_tag, &tnclip, &tmaxpts, &ier); /* Foreach of the clipped areas, get the clipped area, and write it out to the VGF file */ for (ii = 0; ii < tnclip; ii++) { clo_clipget(&ii, &tnpts, tlat, tlon, &ier); el.elem.gfa.info.npts = tnpts; ptrlat = &(el.elem.gfa.latlon[ 0]); ptrlon = &(el.elem.gfa.latlon[tnpts]); /* Re-Initialize the latlon struct. */ for (jj =0; jj < MAXPTS*2; jj++) { el.elem.gfa.latlon[jj] = 0.00; } memcpy(ptrlat, &(tlat[0]), (size_t)tnpts*sizeof(float)); memcpy(ptrlon, &(tlon[0]), (size_t)tnpts*sizeof(float)); /* Recompute Default Text Label & Arrow location */ recalcGFAtLblArwLoc( &el ); el.hdr.recsz = (int) (sizeof(VG_HdrStruct) + sizeof(int)*2 + sizeof(char)* STD_STRLEN * el.elem.gfa.info.nblocks ) + sizeof(float)*tnpts*2; cvg_writef (&el, -1, el.hdr.recsz, outfile, FALSE, &loc, &ier ); } /* Free up memory left over from the clo routines */ clo_clipdone(&ier); } break; } break; } } ne++; } cfl_clos ( ifptr, &ier ); return(0); }
void cvg_scangfa ( char *fname, int layer, int subtype, int areatype, char *tag, VG_DBStruct *el, int *selected, int *iret ) /************************************************************************ * cvg_scangfa * * * * This function scans a vector graphics file looking for a GFA element * * that matches the layer, subtype, area type (hazard) and tag input. * * The first matching record is returned in "el". Also, * * the element should match one of the active filters. * * * * cvg_scan ( fname, layer, subtype, areatype, tag, el, selected, iret )* * * * Input parameters: * * *fname char Name of file to scan from * * layer int layer to test against * * subtype int subtype to test against * * areatype int area type to test against * * tag char gfa tag to test against * * * * Output parameters: * * *el VG_DBStruct Pointer to VG record structure * * *selected int Offset to selected element * * *iret int Return code * * -1 = error opening VG file * * -2 = error closing VG file * * -6 = element not found * * -13 = error reading VG header * * -14 = error reading VG element * * * ** * * Log: * * J. Wu/SAIC 08/04 initial coding (modified from cvg_scan) * * J. Wu/SAIC 10/04 use cvg_getFld to access GFA attributes * * E. Safford/SAIC 07/05 replace seqnum param with tag * * J. Wu/SAIC 06/06 call cvg_matchfilter * * M. Li/SAIC 03/07 Updated cvg_matchfilter * ***********************************************************************/ { int ii, ier, el_layer, location; float llx,lly,urx,ury; long size; char newfil[133], reqfil[133], cclass, ctype, value[32]; FILE *fp; filter_t el_filter, timeMatched; Boolean filter_match, matchAny = False; /*---------------------------------------------------------------------*/ *iret = 0; *selected = -1; if ( !fname ) { strcpy ( reqfil, work_file ); } else { strcpy ( reqfil, fname ); } /* * Inquire the size of the VG file and open the file for update. */ cfl_inqr ( reqfil, NULL, &size, newfil, &ier ); fp = (FILE *) cfl_uopn ( newfil, &ier ); if ( (ier != 0) || (fp == NULL) ) { *iret = -1; return; } /* * Loop through all elements to find a match. */ for ( ii = 0; ii < MAX_EDITABLE_ELEMS; ii++ ) { crg_goffset ( ii, &location, &ier ); if ( location < 0 ) { continue; } crg_get ( ii, &el_layer, el_filter, &llx, &lly, &urx, &ury, &ier ); if ( ier >= 0 ) { crg_gtyp ( ii, &cclass, &ctype, &ier ); } if ( ier < 0 ) { continue; } /* * Match layer, class, vg type first. */ if ( (el_layer == layer) && (cclass == CLASS_MET) && (ctype == GFA_ELM) ) { /* * Then check if the element matches one of the filters. */ cvg_matchfilter ( el_filter, matchAny, &filter_match, timeMatched, &ier ); if ( !filter_match ) { continue; } /* * Read the element. */ cvg_rdrecnoc ( newfil, fp, location, el, iret ); if ( *iret != 0 ) { continue; } /* * Match the subtype, area type, and tag. */ cvg_getFld ( el, TAG_GFA_SUBTYPE, value, &ier ); if ( subtype == atoi(value) ) { cvg_getFld ( el, TAG_GFA_AREATYPE, value, &ier ); if ( areatype == atoi(value) ) { cvg_getFld ( el, TAG_GFA_TAG, value, &ier ); if( strcmp( tag, value ) == 0 ) { *selected = location; break; } } } } } /* * Check if there is an matching record found. */ if ( *selected < 0 ) { *iret = -6; } /* * Close the VG file. */ cfl_clos(fp, &ier); if ( ier != 0 ) *iret = -2; }
static void pgconn_smear ( int loc1, int loc2, VG_DBStruct *elOut, int *nout, float *outX, float *outY ) /************************************************************************ * pgconn_smear * * * * This function smears two selected GFA elements. If the two GFAs * * intersect, they are combined using "union"; otherwise, they are * * combined using "shrink-wrap" algorithm. * * * * static void pgconn_smear ( loc1, loc2, elOut, nout, outX, outY ) * * * * Input parameters: * * loc1 int Location of first GFA element * * loc2 int Location of second GFA element * * * * Output parameters: * * *elOut VG_DBStruct GFA element * * *nout int number of smear points * * outX[] float x of smear points in sys_D * * outY[] float y of smear points in sys_D * * * * Return parameters: * * None * ** * * Log: * * J. Wu/SAIC 06/07 initial coding * * J. Wu/SAIC 09/07 add "unionOnly" into pgsmear_smear * ***********************************************************************/ { int ii, jj, npts, ier, GFA_loc[2], ntmp; char value[10]; float *xtmp, *ytmp, *lat, *lon; Boolean repeat; /*---------------------------------------------------------------------*/ /* * Set computational projection */ ncw_set ( ); ncw_sproj ( "PREFS" ); /* * Smear * Note: pgsmear_smear() needs following options for "join" GFAs: * "skipFzlvl" - False: closed FZLVL could be joined. * "useAllShapShots" - True: snapshots' status doesn't matter. * "reducePts" - False: no point reduction performed. */ GFA_loc[ 0 ] = loc1; GFA_loc[ 1 ] = loc2; pgsmear_smear ( 2, GFA_loc, False, _primaryEl.hdr.maj_col, 0, NULL, False, False, True, False, True, elOut, nout, outX, outY ); /* * Remove repeated points */ ntmp = *nout; G_MALLOC ( xtmp, float, ntmp, "pgsmear_doSnap xtmp" ); G_MALLOC ( ytmp, float, ntmp, "pgsmear_doSnap ytmp" ); G_MALLOC ( lat, float, ntmp, "pgconn_select: lat" ); G_MALLOC ( lon, float, ntmp, "pgconn_select: lon" ); npts = 0; for ( ii = 0; ii < *nout; ii++ ) { repeat = False; for ( jj = ii + 1; jj < ntmp; jj++ ) { if ( ( fabs ( outX[ ii ] - outX[ jj ] ) < .0001 ) && ( fabs ( outY[ ii ] - outY[ jj ] ) < .0001 ) ) { repeat = True; break; } } if ( !repeat ) { xtmp[ npts ] = outX[ ii ]; ytmp[ npts ] = outY[ ii ]; npts++; } } /* * Convert device (x,y) to (lat,lon) and put into el. */ gtrans ( sys_D, sys_M, &npts, xtmp, ytmp, lat, lon, &ier, strlen(sys_D), strlen(sys_M) ); if ( npts > 0 ) { elOut->elem.gfa.info.npts = npts; for ( ii = 0; ii < npts; ii++ ) { elOut->elem.gfa.latlon[ ii ] = lat[ ii ]; elOut->elem.gfa.latlon[ ii + npts ] = lon[ ii ]; } } /* * Unset computational projection and back to current projection */ ncw_unset ( ); /* * Snap if the first polygon is an airmet or outlook. */ cvg_getFld ( &_primaryEl, TAG_GFA_FCSTHR, value, &ier ); if ( strchr ( value, '-' ) ) { pgsmear_snapEl ( True, elOut, &ier ); } /* * Convert into device for ghosting in current projection. */ *nout = elOut->elem.gfa.info.npts; gtrans ( sys_M, sys_D, nout, elOut->elem.gfa.latlon, &(elOut->elem.gfa.latlon[*nout]), outX, outY, &ier, strlen(sys_M), strlen(sys_D) ); G_MALLOC ( xtmp, float, ntmp, "pgconn_smear xtmp" ); G_MALLOC ( ytmp, float, ntmp, "pgconn_smear ytmp" ); G_MALLOC ( lat, float, ntmp, "pgconn_smear lat" ); G_MALLOC ( lon, float, ntmp, "pgconn_smear lon" ); /* * Adopt the first selected GFA's attributes. */ cvg_getFld ( &_primaryEl, TAG_GFA_FCSTHR, value, &ier ); cvg_setFld ( elOut, TAG_GFA_FCSTHR, value, &ier ); cvg_getFld ( &_primaryEl, TAG_GFA_SUBTYPE, value, &ier ); cvg_setFld ( elOut, TAG_GFA_SUBTYPE, value, &ier ); ces_get( atoi( value ), elOut, &ier ); elOut->hdr.maj_col = _primaryEl.hdr.maj_col; elOut->hdr.min_col = _primaryEl.hdr.min_col; }
static Boolean pgconn_verifyType ( VG_DBStruct *first_el, VG_DBStruct *second_el ) /************************************************************************ * pgconn_verifyType * * * * This function examines the two elements to see if they may be * * connected. True is returned if they are the same type/subtype. * * * * static Boolean pgconn_verifyType ( first_el, second_el ) * * * * Input parameters: * * *first_el VG_DBStruct first element to be examined * * *second_el VG_DBStruct second element to be examined * * Output parameters: * * NONE * * Return: * * Boolean True if the two elements are of * * the same type/subtype * ** * * Log: * * E. Safford/GSC 03/02 moved out of pgconn_select() * * J. Wu/SAIC 10/03 connect jets * * J. Wu/SAIC 05/07 connect GFAs with same hazard type and * * forecast hour * ***********************************************************************/ { int ier; char hazard1[32], fcsthr1[32], hazard2[32], fcsthr2[32]; Boolean test = False; /*---------------------------------------------------------------------*/ /* * Test to insure that elements are the same type and subtype * where appropriate. */ if (first_el->hdr.vg_class == second_el->hdr.vg_class) { if ( first_el->hdr.vg_class == CLASS_FRONTS) { if ((first_el->elem.frt.info.fcode / 100) == (second_el->elem.frt.info.fcode / 100)) { test = TRUE; } } else if (first_el->hdr.vg_type == SPLN_ELM && second_el->hdr.vg_type == SPLN_ELM) { if (first_el->elem.spl.info.spltyp == second_el->elem.spl.info.spltyp) { test = TRUE; } } else if (first_el->hdr.vg_type == LINE_ELM && second_el->hdr.vg_type == LINE_ELM) { if (first_el->elem.lin.info.lintyp == second_el->elem.lin.info.lintyp) { test = TRUE; } } else if (first_el->hdr.vg_type == JET_ELM && second_el->hdr.vg_type == JET_ELM) { if (first_el->elem.jet.line.spl.info.spltyp == second_el->elem.jet.line.spl.info.spltyp) { test = TRUE; } } else if (first_el->hdr.vg_type == GFA_ELM && second_el->hdr.vg_type == GFA_ELM) { /* * To be connected, two GFAs must have same hazard type, * forecast hour, and both closed or both open. */ cvg_getFld ( first_el, TAG_GFA_AREATYPE, hazard1, &ier ); cvg_getFld ( second_el, TAG_GFA_AREATYPE, hazard2, &ier ); if ( strcasecmp( hazard1, hazard2 ) == 0 && first_el->hdr.closed == second_el->hdr.closed ) { cvg_getFld ( first_el, TAG_GFA_FCSTHR, fcsthr1, &ier ); cvg_getFld ( second_el, TAG_GFA_FCSTHR, fcsthr2, &ier ); if ( strcasecmp( fcsthr1, fcsthr2 ) == 0 ) { test = TRUE; } } } if (first_el->hdr.vg_class == CLASS_SIGMETS && first_el->hdr.vg_type == second_el->hdr.vg_type) { if (first_el->hdr.vg_type == SIGCCF_ELM && first_el->elem.ccf.info.subtype == SIGTYP_LINE && second_el->elem.ccf.info.subtype == SIGTYP_LINE) { test = TRUE; } else if (first_el->hdr.vg_type != SIGCCF_ELM && first_el->elem.sig.info.subtype == SIGTYP_LINE && second_el->elem.sig.info.subtype == SIGTYP_LINE) { test = TRUE; } } } return (test); }
void pgconn_start ( VG_DBStruct *el, float currx, float curry ) /************************************************************************ * pgconn_start * * * * Initial setup and original selection * * * * void pgconn_start (el, currx, curry) * * * * Input parameters: * * *el VG_DBStruct selected element * * currx float current x coordinate * * curry float current y coordinate * * * * Output parameters: * * NONE * * * ** * * Log: * * S. Law/GSC 09/98 Initial coding * * G. Krueger/EAI 09/98 Added ghost veiling * * G. Krueger/EAI 10/98 Using table for mouse hints * * S. Law/GSC 09/99 added parameter to mcanvw_set* functions* * H. Zeng/EAI 04/00 changed cursor name * * H. Zeng/EAI 11/00 added _primaryLoc * * J. Wu/GSC 02/01 Modified 'unused1' in VG to 'smooth' * * J. Wu/SAIC 06/07 connect GFAs with same hazard type & * * forecast hour * ***********************************************************************/ { float *dcx, *dcy; int dcn, near, ii, jj, ier; char hazard[32]; /*---------------------------------------------------------------------*/ _primaryEl = *el; _primaryLoc = pgactv_getElmLoc(); /* * Check the type of first selected element - GFAs (except open * FZLVL) are handle differently than other types of VG elements. */ _isGFA = (_primaryEl.hdr.vg_type == GFA_ELM) ? True:False; _isOpenFzlvl = False; if ( _isGFA ) { _primaryEl.elem.gfa.info.nblocks = el->elem.gfa.info.nblocks; G_MALLOC ( _primaryEl.elem.gfa.info.blockPtr[ 0 ], gfaBlock_t, el->elem.gfa.info.nblocks, "pgconn_start: _primaryEl.blockPtr" ); memcpy ( _primaryEl.elem.gfa.info.blockPtr[ 0 ], el->elem.gfa.info.blockPtr[ 0 ], el->elem.gfa.info.nblocks * STD_STRLEN * sizeof ( char ) ); cvg_getFld ( el, TAG_GFA_AREATYPE, hazard, &ier ); if ( strcasecmp( hazard, "FZLVL" ) == 0 ) { if ( _primaryEl.hdr.closed == 0 ) { _isOpenFzlvl = True; } } } _drawGhost = True; if ( _isGFA && !_isOpenFzlvl ) { _drawGhost = False; } /* * Start another mouse click. */ pggst_veilGhost ( FALSE ); mcanvw_setPressFunc((XtEventHandler)&pgconn_select, CURS_DEFAULT); /* * No drag function for closed GFAs - except open FZLVLs. */ if ( _drawGhost ) { mcanvw_setDragFunc((XtEventHandler)&pgconn_ghost, CURS_DEFAULT); } pgactv_getDevPts (&dcn, &dcx, &dcy); /* * Ghost only for non-GFAs and open FZLVLs. */ if ( _drawGhost ) { near = pgactv_getNearPt (); _ghostN = (dcn < 3) ? dcn : 3; if (FindNearEnd (0, near, (dcn - 1))) { /* ghost last 2 or 3 points */ jj = 0; for (ii = (dcn - _ghostN); ii < dcn; ii++) { _ghostX[jj] = *(dcx + ii); _ghostY[jj] = *(dcy + ii); jj++; } } else { /* ghost first 2 or 3 points */ jj = 0; for (ii = (_ghostN - 1); ii > -1; ii--) { _ghostX[jj] = *(dcx + ii); _ghostY[jj] = *(dcy + ii); jj++; } } _ghostX[jj] = currx; _ghostY[jj] = curry; pggst_clearGhost (TRUE); pggst_setLineAttr (_primaryEl.hdr.smooth, (Boolean) _primaryEl.hdr.closed); pggst_addGhostPts ( (_ghostN+1), _ghostX, _ghostY, &ier ); pggst_drawGhost (GST_NORMAL); } mbotw_mouseSet(LMHINT_NEXT, MMHINT_DONE); }
/* ARGSUSED */ static void pgconn_select ( Widget wid, XtPointer clnt, XEvent *event, Boolean *ctdr ) /************************************************************************ * pgconn_select * * * * This function handles the selection callbacks * * * * static void pgconn_select (wid, clnt, event, ctdr ) * * * * Input parameters: * * wid Widget calling widget * * clnt XtPointer * * *event XEvent * * * * Output parameters: * * NONE * * * ** * * Log: * * S. Law/GSC 09/98 Initial coding * * S. Law/GSC 09/98 Removed unnecessary refreshes * * E. Safford/GSC 09/98 fix ghost problem conn to 2 pt lines * * G. Krueger/EAI 10/98 Using table for mouse hints * * S. Law/GSC 09/98 added CLASS_SIGMETS * * S. Law/GSC 09/99 added parameter to mcanvw_set* functions* * E. Safford/GSC 10/99 update for new xwcmn.h * * S. Law/GSC 02/00 added CCF * * S. Law/GSC 03/00 added parameter to pgutls_prepNew * * H. Zeng/EAI 04/00 changed cursor name * * S. Law/GSC 06/00 changed to use xgtoff * * H. Zeng/EAI 11/00 modified for the new undo design * * A. Hardy/GSC 11/00 renamed coordinate system declaration * * H. Zeng/EAI 12/00 modified for multiple undo steps * * J. Wu/GSC 03/01 added "EXIT" hint to bottom panel * * J. Wu/SAIC 01/02 scan the current PGEN layer only * * E. Safford/SAIC 03/02 rename from _pgconn_select, add * * pgutls_regroup(), clean up * * E. Safford/SAIC 04/02 check ier from cvg_scan to avoid UMR * * T. Lee/SAIC 11/03 added user directory to work_file * * T. Lee/SAIC 11/03 used cvg_getworkfile * * S. Danz/AWC 08/06 New flag to pgvgf_saveNewElm to place el* * J. Wu/SAIC 06/07 connect GFAs * ***********************************************************************/ { float xx, yy, llx, lly, urx, ury; float *primary_x, *primary_y; float secondary_x[MAXPTS], secondary_y[MAXPTS]; int primary_n, primary_loc, secondary_n; int ier, near, test, xoff, yoff, cur_layer; int start, grp_num1, grp_num2; char grp_typ1, grp_typ2, warnMsg[256], value[10]; char mesg[] = {"Maximum vertices exceeded."}; Boolean primary_grouped = FALSE; Boolean secondary_grouped = FALSE; static int secondary_elnum; static int secondary_loc; static Boolean reverse_flag = FALSE; static VG_DBStruct secondary_el; static VG_DBStruct GFA_el; int GFA_pts, GFA_newloc; float GFA_x[MAXPTS], GFA_y[MAXPTS]; /*---------------------------------------------------------------------*/ xgtoff (&xoff, &yoff, &ier); cur_layer = pglayer_getCurLayer (); if (event->xbutton.button == Button1) { if (_selectFlag) { /* confirming secondary element */ grp_typ1 = _primaryEl.hdr.grptyp; grp_num1 = _primaryEl.hdr.grpnum; if ( grp_typ1 > 0 && grp_num1 > 0 ) { primary_grouped = TRUE; } cvg_todev (&secondary_el, &secondary_n, secondary_x, secondary_y, &ier); grp_typ2 = secondary_el.hdr.grptyp; grp_num2 = secondary_el.hdr.grpnum; if ( grp_typ2 > 0 && grp_num2 > 0 ) { secondary_grouped = TRUE; } if ( _drawGhost ) { near = pgactv_getNearPt (); pgactv_getDevPts (&primary_n, &primary_x, &primary_y); start = (FindNearEnd (0, near, (primary_n - 1)) == 0) ? 0 : primary_n; if (reverse_flag) { pgutls_fReverseArray (secondary_n, secondary_x, secondary_y); } pgactv_addPts (secondary_x, secondary_y, secondary_n, start, &ier); } if (ier == 0) { if ( _drawGhost ) { pgactv_getDevPts (&primary_n, &primary_x, &primary_y); } /* * Grouping the new element: * * If the primary element was grouped, the new element stays in * that group. If the primary element was not grouped, but the * secondary element was, then put the new element in the * secondary element's group. */ if ( !primary_grouped && secondary_grouped ) { _primaryEl.hdr.grptyp = grp_typ2; _primaryEl.hdr.grpnum = grp_num2; } /* * Save the new element: * * For non-GFAs or open FZLVLs, use points of both the primary * and secondary elements. * * For closed GFAs, use points resulting from smearing the primary * and secondary elements. * * Note: The new GFA element will use the the primary element's * forecast hour, color, and line attributes. */ if ( _drawGhost ) { pgundo_newStep(); pgundo_storeThisLoc ( _primaryLoc, UNDO_DEL, &ier ); pgundo_storeThisLoc ( secondary_loc, UNDO_DEL, &ier ); pgutls_prepNew ( -1, &_primaryEl, &llx, &lly, &urx, &ury, &ier); pgvgf_saveNewElm ( cvg_getworkfile(), sys_D, &_primaryEl, primary_n, primary_x, primary_y, TRUE, &primary_loc, &ier ); pgutls_redraw ( primary_loc, &_primaryEl, &ier ); pgundo_storeThisLoc ( primary_loc, UNDO_ADD, &ier); } else { pgvgf_saveNewElm ( cvg_getworkfile(), sys_M, &GFA_el, 0, GFA_x, GFA_y, TRUE, &GFA_newloc, &ier ); if ( ier >= 0 ) { pgundo_newStep(); pgundo_storeThisLoc ( _primaryLoc, UNDO_DEL, &ier ); pgundo_storeThisLoc ( secondary_loc, UNDO_DEL, &ier ); pgactv_setActvElm ( &_primaryEl, _primaryLoc ); pgutls_prepNew ( _primaryLoc, &_primaryEl, &llx, &lly, &urx, &ury, &ier); pgutls_redraw ( GFA_newloc, &GFA_el, &ier ); pgundo_storeThisLoc ( GFA_newloc, UNDO_ADD, &ier ); } else if ( ier == -28 ) { /* too few points in resulting smear */ cvg_getFld ( &GFA_el, TAG_GFA_TAG, value, &ier ); sprintf( warnMsg, "Unable to connect tag %s.\n It has too few points after smearing and/or snapping.\n", value ); NxmWarn_show( mcanvw_getDrawingW(), warnMsg ); } cvg_freeElPtr ( &GFA_el ); } /* * set the secondary element as the active * one, so that prepNew can remove it */ pgactv_setActvElm (&secondary_el, secondary_loc); pgutls_prepNew (secondary_loc, &secondary_el, &llx, &lly, &urx, &ury, &ier); /* * If both elements were grouped, then move all elements * grouped with the secondary element into the primary * element's group. */ if ( primary_grouped && secondary_grouped ) { pgutls_regroup ( grp_typ2, grp_num2, grp_typ1, grp_num1, &ier ); } pgundo_endStep(); /* * Clean up for next connection. */ if ( _isGFA ) { cvg_freeElPtr ( &secondary_el ); cvg_freeElPtr ( &_primaryEl ); } pghdlb_deselectAll (); pgactv_clearActv (); pggst_clearGhost ( FALSE ); } else { NxmWarn_show (wid, mesg); } mcanvw_setPressFunc ((XtEventHandler)&pgevt_locateElmCb, CURS_DEFAULT); if ( _drawGhost ) mcanvw_disarmDrag (); _selectFlag = FALSE; mbotw_mouseSet(LMHINT_SELECT, MMHINT_EXIT); } else { /* selecting secondary element */ xx = (float) (event->xbutton.x + xoff); yy = (float) (event->xbutton.y + yoff); test = False; cvg_scan (NULL, cur_layer, (char)_primaryEl.hdr.vg_class, xx, yy, 0, &secondary_el, &secondary_loc, &near, &ier); /* * Verify elements only if no error returned from cvg_scan. */ if ( ier >= 0 ) { test = pgconn_verifyType ( &_primaryEl, &secondary_el); } /* * Verify there are actually 2 elements, not the same element. */ if (test) { if (secondary_loc == pgactv_getElmLoc () || secondary_loc == 0) { test = FALSE; } } if ( test ) { crg_getinx ( secondary_loc, &secondary_elnum, &ier ); /* * Get the points for the potential connect/join and use it * to draw the ghost line so the user can have a feel of the * result before making the confirmation. * * For non-GFAs or open FZLVLs, connect points of both the primary * and secondary elements. * * For closed GFAs, get points by smearing the primary and * secondary elements. * */ if ( !_drawGhost ) { /* * Select the second GFA. */ pghdlb_select ( &secondary_el, secondary_loc ); /* * Smear two GFA polygons. */ GFA_pts = 0; GFA_el.elem.gfa.info.nblocks = 0; pgconn_smear ( _primaryLoc, secondary_loc, &GFA_el, &GFA_pts, GFA_x, GFA_y ); /* * Ghost the resulting polygon. */ pggst_clearGhost (TRUE); pggst_setLineAttr ( _primaryEl.hdr.smooth, (Boolean)_primaryEl.hdr.closed ); pggst_addGhostPts ( GFA_pts, GFA_x, GFA_y, &ier ); pggst_drawGhost ( GST_NORMAL ); } else { pggst_drawGhost (GST_NORMAL); mcanvw_disarmDrag (); cvg_todev (&secondary_el, &secondary_n, secondary_x, secondary_y, &ier); if (FindNearEnd (0, near, (secondary_n - 1))) { reverse_flag = TRUE; pgutls_fReverseArray (secondary_n, secondary_x, secondary_y); } else { reverse_flag = FALSE; } pggst_replaceGhostPts (1, &secondary_x[0], &secondary_y[0], &ier); pggst_addGhostPts ((secondary_n - 1), &secondary_x[1], &secondary_y[1], &ier); pggst_drawGhost (GST_NORMAL); } _selectFlag = TRUE; mbotw_mouseSet(LMHINT_CONFIRM, MMHINT_CANCEL); } } } else { if (_selectFlag) { /* unselecting secondary element */ pghdlb_deselectEl ( secondary_elnum, TRUE ); pghdlb_displayAllSel (); if ( _drawGhost ) { xx = (float) (event->xbutton.x + xoff); yy = (float) (event->xbutton.y + yoff); _ghostX[_ghostN] = xx; _ghostY[_ghostN] = yy; pggst_clearGhost (FALSE); pggst_addGhostPts ((_ghostN + 1), _ghostX, _ghostY, &ier); pggst_drawGhost (GST_NORMAL); } _selectFlag = FALSE; mbotw_mouseSet(LMHINT_NEXT, MMHINT_DONE); if ( _drawGhost ) { mcanvw_setDragFunc((XtEventHandler)&pgconn_ghost, CURS_DEFAULT); } if ( _isGFA ) { cvg_freeElPtr ( &secondary_el ); if ( !_drawGhost ) cvg_freeElPtr ( &GFA_el ); } } else { /* unselecting primary element */ if ( _isGFA ) { cvg_freeElPtr ( &_primaryEl ); } mcanvw_disarmDynamic (); _selectFlag = FALSE; pghdlb_deselectAll(); mcanvw_setPressFunc ((XtEventHandler)&pgevt_locateElmCb, CURS_DEFAULT); _selectFlag = FALSE; mbotw_mouseSet(LMHINT_SELECT, MMHINT_EXIT); } } }