예제 #1
0
TC_Error_Code TCDS_Ascii_Harmonic::LoadHarmonicData(IDX_entry *pIDX)
{
    Station_Data *psd = NULL;

    //    Look in the index first
    if(pIDX->pref_sta_data)
        return TC_NO_ERROR;         //easy


    // Try the member array of "already-looked-at" master stations
    for(unsigned int i=0 ; i < m_msd_array.GetCount() ; i++)
    {
        psd = &m_msd_array.Item(i);
        //    In the following comparison, it is allowed that the sub-station reference_name may be
        //          a pre-subset of the master station name.
        //          e.g  IDX_refence_name:  The Narrows midchannel New York
        //                            as found in HARMONIC.IDX
        //                 psd_station_name:      The Narrows, Midchannel, New York Harbor, New York Current
        //                            as found in HARMONIC
        if( (!slackcmp(psd->station_name, pIDX->IDX_reference_name)) && (toupper(pIDX->IDX_type) == psd->station_type) )
        {
            pIDX->pref_sta_data = psd;                // save for later
            return TC_NO_ERROR;
        }
    }


    //    OK, have to read and create from the raw file
    psd = NULL;

    //    If reference station was recently sought, and not found, don't bother
    //            if(!strcmp(pIDX->IDX_reference_name, plast_reference_not_found->mb_str()))
    if(m_last_reference_not_found.IsSameAs(wxString(pIDX->IDX_reference_name, wxConvUTF8)))
        return TC_MASTER_HARMONICS_NOT_FOUND;

    //    Clear for this looking
    m_last_reference_not_found.Clear();

    //    Find and load appropriate constituents
    FILE *fp;
    char linrec[linelen];
    fp = fopen (m_harmfile_name.mb_str(), "r");

    while (read_next_line (fp, linrec, 1))
    {
        nojunk (linrec);
        int curonly = 0;
        if (curonly)
            if (!strstr (linrec, "Current"))
                continue;
        //    See the note above about station names
        //                  if(!strncmp(linrec, "Rivi", 4))
        //                        int ggl = 4;

        if (slackcmp (linrec, pIDX->IDX_reference_name))
            continue;

        //    Got the right location, so load the data

        psd = new Station_Data;

        psd->amplitude = (double *)malloc(num_csts * sizeof(double));
        psd->epoch     = (double *)malloc(num_csts * sizeof(double));
        psd->station_name = (char *)malloc(strlen(linrec) +1);

        char junk[80];
        int a;
        strcpy (psd->station_name, linrec);

        //    Establish Station Type
        wxString caplin(linrec, wxConvUTF8);
        caplin.MakeUpper();
        if(caplin.Contains(_T("CURRENT")))
            psd->station_type = 'C';
        else
            psd->station_type = 'T';



        /* Get meridian */
        read_next_line (fp, linrec, 0);
        psd->meridian = hhmm2seconds (linrec);
        psd->zone_offset = 0;
        
        /* Get tzfile, if present */
        if (sscanf (nojunk(linrec), "%s %s", junk, psd->tzfile) < 2)
            strcpy (psd->tzfile, "UTC0");

        /* Get DATUM and units */
        read_next_line (fp, linrec, 0);
        if (sscanf (nojunk(linrec), "%lf %s", &(psd->DATUM), psd->unit) < 2)
            strcpy (psd->unit, "unknown");

        if ((a = findunit (psd->unit)) == -1)
        {
            // Nonsense....
            //                        strcpy (psd->units_abbrv, psd->unit);
            //                        strcpy (psd->units_conv, known_units[a].name);
        }

        psd->have_BOGUS = (findunit(psd->unit) != -1) && (known_units[findunit(psd->unit)].type == BOGUS);

        int unit_c;
        if (psd->have_BOGUS)
            unit_c = findunit("knots");
        else
            unit_c = findunit(psd->unit);

        if (unit_c != -1)
        {
            strcpy (psd->units_conv,       known_units[unit_c].name);
            strcpy (psd->units_abbrv,      known_units[unit_c].abbrv);
        }

        /* Get constituents */
        double loca, loce;
        for (a=0; a<num_csts; a++)
        {
            read_next_line (fp, linrec, 0);
            sscanf (linrec, "%s %lf %lf", junk, &loca, &loce);
            //          loc_epoch[a] *= M_PI / 180.0;
            psd->amplitude[a] = loca;
            psd->epoch[a] = loce * M_PI / 180.;
        }
        fclose (fp);

        break;
    }

    if(!psd) {
        m_last_reference_not_found = wxString(pIDX->IDX_reference_name, wxConvUTF8);
        return TC_MASTER_HARMONICS_NOT_FOUND;
    }
    else {
        m_msd_array.Add(psd);                     // add it to the member array
        pIDX->pref_sta_data = psd;
        return TC_NO_ERROR;
    }

}
예제 #2
0
TC_Error_Code TCDS_Binary_Harmonic::LoadData(const wxString &data_file_path)
{
    if(!open_tide_db (data_file_path.mb_str())) return TC_TCD_FILE_CORRUPT;

    //Build the tables of constituent data

    DB_HEADER_PUBLIC hdr = get_tide_db_header ();

    source_ident = wxString( hdr.version, wxConvUTF8 );

    num_csts = hdr.constituents;
    if(0 == num_csts)
        return TC_GENERIC_ERROR;

    num_nodes = hdr.number_of_years;
    if(0 == num_nodes)
        return TC_GENERIC_ERROR;
    
    //  Allocate a working buffer
    m_work_buffer = (double *) malloc (num_csts * sizeof (double));

    //  Constituent speeds
    m_cst_speeds = (double *) malloc (num_csts * sizeof (double));

    for (int a=0; a<num_csts; a++) {
        m_cst_speeds[a] = get_speed (a);
        m_cst_speeds[a] *= M_PI / 648000; /* Convert to radians per second */
    }

    //  Equilibrium tables by year
    m_first_year = hdr.start_year;
    num_epochs = hdr.number_of_years;

    m_cst_epochs = (double **) malloc (num_csts * sizeof (double *));
    for (int i=0; i<num_csts; i++)
        m_cst_epochs[i] = (double *) malloc (num_epochs * sizeof (double));

    for (int i=0; i<num_csts; i++)
    {
        for (int year=0; year<num_epochs; year++)
        {
            m_cst_epochs[i][year] = get_equilibrium (i, year);
            m_cst_epochs[i][year] *= M_PI / 180.0;
        }
    }

    //  Node factors

    m_cst_nodes = (double **) malloc (num_csts * sizeof (double *));
    for (int a=0; a<num_csts; a++)
        m_cst_nodes[a] = (double *) malloc (num_nodes * sizeof (double));

    for (int a=0; a<num_csts; a++) {
        for (int year=0; year<num_nodes; year++)
            m_cst_nodes[a][year] = get_node_factor (a, year);
    }


    // now load and create the index

    TIDE_RECORD *ptiderec = (TIDE_RECORD *)calloc(sizeof(TIDE_RECORD), 1);
    for(unsigned int i=0 ; i < hdr.number_of_records ; i++) {
        read_tide_record (i, ptiderec);

        num_IDX++; // Keep counting entries for harmonic file stuff
        IDX_entry *pIDX = new IDX_entry;
        pIDX->source_data_type = SOURCE_TYPE_BINARY_HARMONIC;
        pIDX->pDataSource = NULL;

        pIDX->Valid15 = 0;

        pIDX->pref_sta_data = NULL;                     // no reference data yet
        pIDX->IDX_Useable = 1;                          // but assume data is OK
        pIDX->IDX_tzname = NULL;

        pIDX->IDX_lon = ptiderec->header.longitude;
        pIDX->IDX_lat = ptiderec->header.latitude;

        const char *tz = get_tzfile (ptiderec->header.tzfile);
        change_time_zone ((char *)tz);
        if(tz_info)
            pIDX->IDX_time_zone = -tz_info->tzi.Bias;


        strncpy(pIDX->IDX_station_name, ptiderec->header.name, MAXNAMELEN);
//        if(strstr(ptiderec->header.name, "Beaufort") != NULL)
//            int yyp = 4;

        pIDX->IDX_flood_dir = ptiderec->max_direction;
        pIDX->IDX_ebb_dir = ptiderec->min_direction;

        if(REFERENCE_STATION == ptiderec->header.record_type) {
            //    Establish Station Type
            wxString caplin(pIDX->IDX_station_name, wxConvUTF8);
            caplin.MakeUpper();
            if(caplin.Contains(_T("CURRENT")))
                pIDX->IDX_type = 'C';
            else
                pIDX->IDX_type = 'T';

            int t1 = ptiderec->zone_offset;
            double zone_offset = (double)(t1 / 100) + ((double)(t1 % 100))/60.;
//            pIDX->IDX_time_zone = t1a;

            pIDX->IDX_ht_time_off = pIDX->IDX_lt_time_off = 0;
            pIDX->IDX_ht_mpy      = pIDX->IDX_lt_mpy = 1.0;
            pIDX->IDX_ht_off      = pIDX->IDX_lt_off = 0.0;
            pIDX->IDX_ref_dbIndex = ptiderec->header.reference_station;         // will be -1

            //  build a Station_Data class, and add to member array

            Station_Data *psd = new Station_Data;

            psd->amplitude = (double *)malloc(num_csts * sizeof(double));
            psd->epoch     = (double *)malloc(num_csts * sizeof(double));
            psd->station_name = (char *)malloc(ONELINER_LENGTH);

            strncpy(psd->station_name, ptiderec->header.name, MAXNAMELEN);
            psd->station_type = pIDX->IDX_type;


            // Get meridian, which is seconds difference from UTC, not figuring DST, so that New York is always (-300 * 60)
            psd->meridian =  -(tz_info->tzi.Bias * 60);
            psd->zone_offset = zone_offset;

            // Get units
            strncpy (psd->unit, get_level_units (ptiderec->level_units), 40 - 1);
            psd->unit[40 -1] = '\0';

            psd->have_BOGUS = (findunit(psd->unit) != -1) && (known_units[findunit(psd->unit)].type == BOGUS);

            int unit_c;
            if (psd->have_BOGUS)
                unit_c = findunit("knots");
            else
                unit_c = findunit(psd->unit);

            if(unit_c != -1) {
                strncpy (psd->units_conv, known_units[unit_c].name, sizeof(psd->units_conv)-1);
                strncpy (psd->units_abbrv, known_units[unit_c].abbrv, sizeof(psd->units_abbrv)-1);
            }
            else {
                strncpy (psd->units_conv, psd->unit, 40 - 1);
                psd->units_conv[40 - 1] = '\0';
                strncpy (psd->units_abbrv, psd->unit, 20 - 1);
                psd->units_abbrv[20 - 1] = '\0';
            }


            // Get constituents
            for (int a=0; a<num_csts; a++)
            {
                psd->amplitude[a] = ptiderec->amplitude[a];
                psd->epoch[a] = ptiderec->epoch[a] * M_PI / 180.;
            }

            psd->DATUM = ptiderec->datum_offset;

            m_msd_array.Add(psd);                     // add it to the member array
            pIDX->pref_sta_data = psd;
            pIDX->IDX_ref_dbIndex = i;
            pIDX->have_offsets = 0;
        }
        else if(SUBORDINATE_STATION == ptiderec->header.record_type) {
            //    Establish Station Type
            wxString caplin(pIDX->IDX_station_name, wxConvUTF8);
            caplin.MakeUpper();
            if(caplin.Contains(_T("CURRENT")))
                pIDX->IDX_type = 'c';
            else
                pIDX->IDX_type = 't';

            int t1 = ptiderec->max_time_add;
            double t1a = (double)(t1 / 100) + ((double)(t1 % 100))/60.;
            t1a *= 60;                  // Minutes
            pIDX->IDX_ht_time_off = t1a;
            pIDX->IDX_ht_mpy = ptiderec->max_level_multiply;
            if(0. == pIDX->IDX_ht_mpy) pIDX->IDX_ht_mpy = 1.0;
            pIDX->IDX_ht_off = ptiderec->max_level_add;


            t1 = ptiderec->min_time_add;
            t1a = (double)(t1 / 100) + ((double)(t1 % 100))/60.;
            t1a *= 60;                  // Minutes
            pIDX->IDX_lt_time_off = t1a;
            pIDX->IDX_lt_mpy = ptiderec->min_level_multiply;
            if(0. == pIDX->IDX_lt_mpy) pIDX->IDX_lt_mpy = 1.0;
            pIDX->IDX_lt_off = ptiderec->min_level_add;

            pIDX->IDX_ref_dbIndex = ptiderec->header.reference_station;
//           strncpy(pIDX->IDX_reference_name, ptiderec->header.name, MAXNAMELEN);

            if( pIDX->IDX_ht_time_off ||
                    pIDX->IDX_ht_off != 0.0 ||
                    pIDX->IDX_lt_off != 0.0 ||
                    pIDX->IDX_ht_mpy != 1.0 ||
                    pIDX->IDX_lt_mpy != 1.0)
                pIDX->have_offsets = 1;
        }

        m_IDX_array.Add(pIDX);
    }



    //  Mark the index entries individually with invariant harmonic constants
    unsigned int max_index = GetMaxIndex();
    for(unsigned int i=0 ; i < max_index ; i++) {
        IDX_entry *pIDX = GetIndexEntry( i );
        if(pIDX) {
            pIDX->num_nodes = num_nodes;
            pIDX->num_csts = num_csts;
            pIDX->num_epochs = num_epochs;
            pIDX->m_cst_speeds = m_cst_speeds;
            pIDX->m_cst_nodes = m_cst_nodes;
            pIDX->m_cst_epochs = m_cst_epochs;
            pIDX->first_year = m_first_year;
            pIDX->m_work_buffer = m_work_buffer;
        }
    }
    free( ptiderec );

    return TC_NO_ERROR;
}