Exemplo n.º 1
0
int pj_apply_gridshift( const char *nadgrids, int inverse, 
                        long point_count, int point_offset,
                        double *x, double *y, double *z )

{
    int grid_count = 0;
    PJ_GRIDINFO   **tables;
    int  i;
    int debug_flag = getenv( "PROJ_DEBUG" ) != NULL;
    static int debug_count = 0;

    pj_errno = 0;

    tables = pj_gridlist_from_nadgrids( nadgrids, &grid_count);
    if( tables == NULL || grid_count == 0 )
        return pj_errno;

    for( i = 0; i < point_count; i++ )
    {
        long io = i * point_offset;
        LP   input, output;
        int  itable;

        input.phi = y[io];
        input.lam = x[io];
        output.phi = HUGE_VAL;
        output.lam = HUGE_VAL;

        /* keep trying till we find a table that works */
        for( itable = 0; itable < grid_count; itable++ )
        {
            PJ_GRIDINFO *gi = tables[itable];
            struct CTABLE *ct = gi->ct;

            /* skip tables that don't match our point at all.  */
            if( ct->ll.phi > input.phi || ct->ll.lam > input.lam
                || ct->ll.phi + (ct->lim.phi-1) * ct->del.phi < input.phi
                || ct->ll.lam + (ct->lim.lam-1) * ct->del.lam < input.lam )
                continue;

            /* If we have child nodes, check to see if any of them apply. */
            if( gi->child != NULL )
            {
                PJ_GRIDINFO *child;

                for( child = gi->child; child != NULL; child = child->next )
                {
                    struct CTABLE *ct1 = child->ct;

                    if( ct1->ll.phi > input.phi || ct1->ll.lam > input.lam
                      || ct1->ll.phi+(ct1->lim.phi-1)*ct1->del.phi < input.phi
                      || ct1->ll.lam+(ct1->lim.lam-1)*ct1->del.lam < input.lam)
                        continue;

                    break;
                }

                /* we found a more refined child node to use */
                if( child != NULL )
                {
                    gi = child;
                    ct = child->ct;
                }
            }

            /* load the grid shift info if we don't have it. */
            if( ct->cvs == NULL && !pj_gridinfo_load( gi ) )
            {
                pj_errno = -38;
                return pj_errno;
            }
            
            output = nad_cvt( input, inverse, ct );
            if( output.lam != HUGE_VAL )
            {
                if( debug_flag && debug_count++ < 20 )
                    fprintf( stderr,
                             "pj_apply_gridshift(): used %s\n",
                             ct->id );
                break;
            }
        }

        if( output.lam == HUGE_VAL )
        {
            if( debug_flag )
            {
                fprintf( stderr, 
                         "pj_apply_gridshift(): failed to find a grid shift table for\n"
                         "                      location (%.7fdW,%.7fdN)\n",
                         x[io] * RAD_TO_DEG, 
                         y[io] * RAD_TO_DEG );
                fprintf( stderr, 
                         "   tried: %s\n", nadgrids );
            }
        
            pj_errno = -38;
            return pj_errno;
        }
        else
        {
            y[io] = output.phi;
            x[io] = output.lam;
        }
    }

    return 0;
}
Exemplo n.º 2
0
int pj_gc_apply_gridshift( PJ *defn, int inverse, 
                           long point_count, int point_offset, 
                           double *x, double *y, double *z )

{
    int i;

    if( defn->catalog == NULL ) 
    {
        defn->catalog = pj_gc_findcatalog( defn->ctx, defn->catalog_name );
        if( defn->catalog == NULL )
            return defn->ctx->last_errno;
    }

    defn->ctx->last_errno = 0;

    for( i = 0; i < point_count; i++ )
    {
        long io = i * point_offset;
        LP   input, output_after, output_before;
        double mix_ratio;
        PJ_GRIDINFO *gi;

        input.phi = y[io];
        input.lam = x[io];

        /* make sure we have appropriate "after" shift file available */
        if( defn->last_after_grid == NULL
            || input.lam < defn->last_after_region.ll_long
            || input.lam > defn->last_after_region.ur_long
            || input.phi < defn->last_after_region.ll_lat
            || input.phi > defn->last_after_region.ll_lat ) {
            defn->last_after_grid = 
                pj_gc_findgrid( defn->ctx, defn->catalog, 
                                1, input, defn->datum_date, 
                                &(defn->last_after_region), 
                                &(defn->last_after_date));
        }
        gi = defn->last_after_grid;
        assert( gi->child == NULL );

        /* load the grid shift info if we don't have it. */
        if( gi->ct->cvs == NULL && !pj_gridinfo_load( defn->ctx, gi ) )
        {
            pj_ctx_set_errno( defn->ctx, -38 );
            return -38;
        }
            
        output_after = nad_cvt( input, inverse, gi->ct );
        if( output_after.lam == HUGE_VAL )
        {
            if( defn->ctx->debug_level >= PJ_LOG_DEBUG_MAJOR )
            {
                pj_log( defn->ctx, PJ_LOG_DEBUG_MAJOR,
                        "pj_apply_gridshift(): failed to find a grid shift table for\n"
                        "                      location (%.7fdW,%.7fdN)",
                        x[io] * RAD_TO_DEG, 
                        y[io] * RAD_TO_DEG );
            }
            continue;
        }

        if( defn->datum_date == 0.0 ) 
        {
            y[io] = output_after.phi;
            x[io] = output_after.lam;
            continue;
        }

        /* make sure we have appropriate "before" shift file available */
        if( defn->last_before_grid == NULL
            || input.lam < defn->last_before_region.ll_long
            || input.lam > defn->last_before_region.ur_long
            || input.phi < defn->last_before_region.ll_lat
            || input.phi > defn->last_before_region.ll_lat ) {
            defn->last_before_grid = 
                pj_gc_findgrid( defn->ctx, defn->catalog, 
                                0, input, defn->datum_date, 
                                &(defn->last_before_region), 
                                &(defn->last_before_date));
        }

        gi = defn->last_before_grid;
        assert( gi->child == NULL );

        /* load the grid shift info if we don't have it. */
        if( gi->ct->cvs == NULL && !pj_gridinfo_load( defn->ctx, gi ) )
        {
            pj_ctx_set_errno( defn->ctx, -38 );
            return -38;
        }
            
        output_before = nad_cvt( input, inverse, gi->ct );
        if( output_before.lam == HUGE_VAL )
        {
            if( defn->ctx->debug_level >= PJ_LOG_DEBUG_MAJOR )
            {
                pj_log( defn->ctx, PJ_LOG_DEBUG_MAJOR,
                        "pj_apply_gridshift(): failed to find a grid shift table for\n"
                        "                      location (%.7fdW,%.7fdN)",
                        x[io] * RAD_TO_DEG, 
                        y[io] * RAD_TO_DEG );
            }
            continue;
        }

        mix_ratio = (defn->datum_date - defn->last_before_date) 
            / (defn->last_after_date - defn->last_before_date);

        y[io] = mix_ratio * output_after.phi 
            + (1.0-mix_ratio) * output_before.phi;
        x[io] = mix_ratio * output_after.lam 
            + (1.0-mix_ratio) * output_before.lam;
    }

    return 0;
}
Exemplo n.º 3
0
static double read_vgrid_value( PJ *defn, LP input, int *gridlist_count_p, PJ_GRIDINFO **tables, struct CTABLE *ct) {
    int  itable = 0;
    double value = HUGE_VAL;
    double grid_x, grid_y;
    long   grid_ix, grid_iy;
    long   grid_ix2, grid_iy2;
    float  *cvs;
    /* do not deal with NaN coordinates */
    /* cppcheck-suppress duplicateExpression */
    if( isnan(input.phi) || isnan(input.lam) )
        itable = *gridlist_count_p;

    /* keep trying till we find a table that works */
    for ( ; itable < *gridlist_count_p; itable++ )
    {
        PJ_GRIDINFO *gi = tables[itable];

        ct = gi->ct;

        /* skip tables that don't match our point at all.  */
        if( ct->ll.phi > input.phi || ct->ll.lam > input.lam
            || ct->ll.phi + (ct->lim.phi-1) * ct->del.phi < input.phi
            || ct->ll.lam + (ct->lim.lam-1) * ct->del.lam < input.lam )
            continue;

        /* If we have child nodes, check to see if any of them apply. */
        while( gi->child != NULL )
        {
            PJ_GRIDINFO *child;

            for( child = gi->child; child != NULL; child = child->next )
            {
                struct CTABLE *ct1 = child->ct;

                if( ct1->ll.phi > input.phi || ct1->ll.lam > input.lam
                  || ct1->ll.phi+(ct1->lim.phi-1)*ct1->del.phi < input.phi
                  || ct1->ll.lam+(ct1->lim.lam-1)*ct1->del.lam < input.lam)
                    continue;

                break;
            }

            /* we didn't find a more refined child node to use, so go with current grid */
            if( child == NULL )
            {
                break;
            }

            /* Otherwise let's try for childrens children .. */
            gi = child;
            ct = child->ct;
        }

        /* load the grid shift info if we don't have it. */
        if( ct->cvs == NULL && !pj_gridinfo_load( pj_get_ctx(defn), gi ) )
        {
            pj_ctx_set_errno( defn->ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
            return PJD_ERR_FAILED_TO_LOAD_GRID;
        }


        /* Interpolation a location within the grid */
        grid_x = (input.lam - ct->ll.lam) / ct->del.lam;
        grid_y = (input.phi - ct->ll.phi) / ct->del.phi;
        grid_ix = lround(floor(grid_x));
        grid_iy = lround(floor(grid_y));
        grid_x -= grid_ix;
        grid_y -= grid_iy;

        grid_ix2 = grid_ix + 1;
        if( grid_ix2 >= ct->lim.lam )
            grid_ix2 = ct->lim.lam - 1;
        grid_iy2 = grid_iy + 1;
        if( grid_iy2 >= ct->lim.phi )
            grid_iy2 = ct->lim.phi - 1;

        cvs = (float *) ct->cvs;
        {
            float value_a = cvs[grid_ix + grid_iy * ct->lim.lam];
            float value_b = cvs[grid_ix2 + grid_iy * ct->lim.lam];
            float value_c = cvs[grid_ix + grid_iy2 * ct->lim.lam];
            float value_d = cvs[grid_ix2 + grid_iy2 * ct->lim.lam];
            double total_weight = 0.0;
            int n_weights = 0;
            value = 0.0f;
            if( !is_nodata(value_a) )
            {
                double weight = (1.0-grid_x) * (1.0-grid_y);
                value += value_a * weight;
                total_weight += weight;
                n_weights ++;
            }
            if( !is_nodata(value_b) )
            {
                double weight = (grid_x) * (1.0-grid_y);
                value += value_b * weight;
                total_weight += weight;
                n_weights ++;
            }
            if( !is_nodata(value_c) )
            {
                double weight = (1.0-grid_x) * (grid_y);
                value += value_c * weight;
                total_weight += weight;
                n_weights ++;
            }
            if( !is_nodata(value_d) )
            {
                double weight = (grid_x) * (grid_y);
                value += value_d * weight;
                total_weight += weight;
                n_weights ++;
            }
            if( n_weights == 0 )
                value = HUGE_VAL;
            else if( n_weights != 4 )
                value /= total_weight;
        }

    }

    return value;
}
Exemplo n.º 4
0
int pj_apply_gridshift_3( projCtx ctx, PJ_GRIDINFO **tables, int grid_count,
                          int inverse, long point_count, int point_offset,
                          double *x, double *y, double *z )

{
    int  i;
    static int debug_count = 0;

    if( tables == NULL || grid_count == 0 )
    {
        pj_ctx_set_errno( ctx, -38);
        return -38;
    }

    ctx->last_errno = 0;

    for( i = 0; i < point_count; i++ )
    {
        long io = i * point_offset;
        LP   input, output;
        int  itable;

        input.phi = y[io];
        input.lam = x[io];
        output.phi = HUGE_VAL;
        output.lam = HUGE_VAL;

        /* keep trying till we find a table that works */
        for( itable = 0; itable < grid_count; itable++ )
        {
            PJ_GRIDINFO *gi = tables[itable];
            struct CTABLE *ct = gi->ct;
            double epsilon = (fabs(ct->del.phi)+fabs(ct->del.lam))/10000.0;

            /* skip tables that don't match our point at all.  */
            if( ct->ll.phi - epsilon > input.phi 
                || ct->ll.lam - epsilon > input.lam
                || (ct->ll.phi + (ct->lim.phi-1) * ct->del.phi + epsilon 
                    < input.phi)
                || (ct->ll.lam + (ct->lim.lam-1) * ct->del.lam + epsilon 
                    < input.lam) )
                continue;

            /* If we have child nodes, check to see if any of them apply. */
            if( gi->child != NULL )
            {
                PJ_GRIDINFO *child;

                for( child = gi->child; child != NULL; child = child->next )
                {
                    struct CTABLE *ct1 = child->ct;
                    double epsilon = 
                        (fabs(ct1->del.phi)+fabs(ct1->del.lam))/10000.0;

                    if( ct1->ll.phi - epsilon > input.phi 
                        || ct1->ll.lam - epsilon > input.lam
                        || (ct1->ll.phi+(ct1->lim.phi-1)*ct1->del.phi + epsilon 
                            < input.phi)
                        || (ct1->ll.lam+(ct1->lim.lam-1)*ct1->del.lam + epsilon 
                            < input.lam) )
                        continue;

                    break;
                }

                /* we found a more refined child node to use */
                if( child != NULL )
                {
                    gi = child;
                    ct = child->ct;
                }
            }

            /* load the grid shift info if we don't have it. */
            if( ct->cvs == NULL && !pj_gridinfo_load( ctx, gi ) )
            {
                pj_ctx_set_errno( ctx, -38 );
                return -38;
            }
            
            output = nad_cvt( input, inverse, ct );
            if( output.lam != HUGE_VAL )
            {
                if( debug_count++ < 20 )
                    pj_log( ctx, PJ_LOG_DEBUG_MINOR,
                            "pj_apply_gridshift(): used %s", ct->id );
                break;
            }
        }

        if( output.lam == HUGE_VAL )
        {
            if( ctx->debug_level >= PJ_LOG_DEBUG_MAJOR )
            {
                pj_log( ctx, PJ_LOG_DEBUG_MAJOR,
                    "pj_apply_gridshift(): failed to find a grid shift table for\n"
                    "                      location (%.7fdW,%.7fdN)",
                    x[io] * RAD_TO_DEG, 
                    y[io] * RAD_TO_DEG );
                for( itable = 0; itable < grid_count; itable++ )
                {
                    PJ_GRIDINFO *gi = tables[itable];
                    if( itable == 0 )
                        pj_log( ctx, PJ_LOG_DEBUG_MAJOR,
                                "   tried: %s", gi->gridname );
                    else
                        pj_log( ctx, PJ_LOG_DEBUG_MAJOR,
                                ",%s", gi->gridname );
                }
            }

            /* 
             * We don't actually have any machinery currently to set the 
             * following macro, so this is mostly kept here to make it clear 
             * how we ought to operate if we wanted to make it super clear 
             * that an error has occured when points are outside our available
             * datum shift areas.  But if this is on, we will find that "low 
             * value" points on the fringes of some datasets will completely 
             * fail causing lots of problems when it is more or less ok to 
             * just not apply a datum shift.  So rather than deal with
             * that we just fallback to no shift. (see also bug #45).
             */
#ifdef ERR_GRID_AREA_TRANSIENT_SEVERE
            y[io] = HUGE_VAL;
            x[io] = HUGE_VAL;
#else
            /* leave x/y unshifted. */
#endif
        }
        else
        {
            y[io] = output.phi;
            x[io] = output.lam;
        }
    }

    return 0;
}
Exemplo n.º 5
0
int pj_apply_vgridshift(PJ *defn, const char *listname, PJ_GRIDINFO ***gridlist_p, int *gridlist_count_p, int inverse,
                        long point_count, int point_offset, double *x, double *y, double *z)

{
	int i;
	static int debug_count = 0;
	PJ_GRIDINFO **tables;

	if (*gridlist_p == NULL) {
		*gridlist_p =
		    pj_gridlist_from_nadgrids(pj_get_ctx(defn), pj_param(defn->ctx, defn->params, listname).s, gridlist_count_p);

		if (*gridlist_p == NULL || *gridlist_count_p == 0)
			return defn->ctx->last_errno;
	}

	if (*gridlist_count_p == 0) {
		pj_ctx_set_errno(defn->ctx, -38);
		return -38;
	}

	tables = *gridlist_p;
	defn->ctx->last_errno = 0;

	for (i = 0; i < point_count; i++) {
		long io = i * point_offset;
		LP input;
		int itable;
		double value = HUGE_VAL;

		input.phi = y[io];
		input.lam = x[io];

		/* keep trying till we find a table that works */
		for (itable = 0; itable < *gridlist_count_p; itable++) {
			PJ_GRIDINFO *gi = tables[itable];
			struct CTABLE *ct = gi->ct;
			double grid_x, grid_y;
			int grid_ix, grid_iy;
			float *cvs;

			/* skip tables that don't match our point at all.  */
			if (ct->ll.phi > input.phi || ct->ll.lam > input.lam || ct->ll.phi + (ct->lim.phi - 1) * ct->del.phi < input.phi ||
			    ct->ll.lam + (ct->lim.lam - 1) * ct->del.lam < input.lam)
				continue;

			/* If we have child nodes, check to see if any of them apply. */
			if (gi->child != NULL) {
				PJ_GRIDINFO *child;

				for (child = gi->child; child != NULL; child = child->next) {
					struct CTABLE *ct1 = child->ct;

					if (ct1->ll.phi > input.phi || ct1->ll.lam > input.lam ||
					    ct1->ll.phi + (ct1->lim.phi - 1) * ct1->del.phi < input.phi ||
					    ct1->ll.lam + (ct1->lim.lam - 1) * ct1->del.lam < input.lam)
						continue;

					break;
				}

				/* we found a more refined child node to use */
				if (child != NULL) {
					gi = child;
					ct = child->ct;
				}
			}

			/* load the grid shift info if we don't have it. */
			if (ct->cvs == NULL && !pj_gridinfo_load(pj_get_ctx(defn), gi)) {
				pj_ctx_set_errno(defn->ctx, -38);
				return -38;
			}

			/* Interpolation a location within the grid */
			grid_x = (input.lam - ct->ll.lam) / ct->del.lam;
			grid_y = (input.phi - ct->ll.phi) / ct->del.phi;
			grid_ix = (int)floor(grid_x);
			grid_iy = (int)floor(grid_y);
			grid_x -= grid_ix;
			grid_y -= grid_iy;

			cvs = (float *)ct->cvs;
			value = cvs[grid_ix + grid_iy * ct->lim.lam] * (1.0 - grid_x) * (1.0 - grid_y) +
			        cvs[grid_ix + 1 + grid_iy * ct->lim.lam] * (grid_x) * (1.0 - grid_y) +
			        cvs[grid_ix + (grid_iy + 1) * ct->lim.lam] * (1.0 - grid_x) * (grid_y) +
			        cvs[grid_ix + 1 + (grid_iy + 1) * ct->lim.lam] * (grid_x) * (grid_y);

			if (value > 1000 || value < -1000) /* nodata? */
				value = HUGE_VAL;
			else {
				if (inverse)
					z[io] -= value;
				else
					z[io] += value;
			}

			if (value != HUGE_VAL) {
				if (debug_count++ < 20)
					pj_log(defn->ctx, PJ_LOG_DEBUG_MINOR, "pj_apply_gridshift(): used %s", ct->id);
				break;
			}
		}

		if (value == HUGE_VAL) {
			char gridlist[3000];

			pj_log(defn->ctx, PJ_LOG_DEBUG_MAJOR,
			       "pj_apply_vgridshift(): failed to find a grid shift table for\n"
			       "                       location (%.7fdW,%.7fdN)",
			       x[io] * RAD_TO_DEG, y[io] * RAD_TO_DEG);

			gridlist[0] = '\0';
			for (itable = 0; itable < *gridlist_count_p; itable++) {
				PJ_GRIDINFO *gi = tables[itable];
				if (strlen(gridlist) + strlen(gi->gridname) > sizeof(gridlist) - 100) {
					strcat(gridlist, "...");
					break;
				}

				if (itable == 0)
					sprintf(gridlist, "   tried: %s", gi->gridname);
				else
					sprintf(gridlist + strlen(gridlist), ",%s", gi->gridname);
			}
			pj_log(defn->ctx, PJ_LOG_DEBUG_MAJOR, "%s", gridlist);

			pj_ctx_set_errno(defn->ctx, PJD_ERR_GRID_AREA);
			return PJD_ERR_GRID_AREA;
		}
	}

	return 0;
}