Example #1
0
function pfind_service($prms, $pfind_defs, $type_names, $p2p_paths, $node_types = FALSE)
{
    clb_timing(__LINE__);
    pfind_def_tables($pfind_defs);
    $result = array('error' => 200, 'error_str' => 'no errors');
    //get the query or way points from the request
    $entries = array();
    if (isset($prms['q']) && $prms['q']) {
        $entries[] = $prms['q'];
    } else {
        $w = 0;
        while (isset($prms['w' . $w])) {
            $entries[] = $prms['w' . $w];
            $w++;
        }
    }
    $prop = array();
    $prop['service'] = strtolower(clb_val('json', $prms, 's'));
    //json, xml
    $prop['mode'] = strtolower(clb_val('', $prms, 'm'));
    $prop['units'] = strtolower(clb_val('mi', $prms, 'u'));
    //km, mi
    $prop['opto'] = strtolower(clb_val('best', $prms, 'o'));
    //dist, change, best
    $prop['opacity'] = strtolower(clb_val(0.5, $prms, 't'));
    $prop['color'] = strtolower(clb_val('#0000FF', $prms, 'c'));
    $prop['stroke'] = strtolower(clb_val(5, $prms, 'k'));
    $dist_only = FALSE != clb_val(0, $prms, 'gd');
    //get result from precalculated distances
    $prop['dist_only'] = $dist_only;
    $prop['getSteps'] = !$dist_only && FALSE != clb_val(0, $prms, 'gs');
    $prop['getPolyline'] = !$dist_only && FALSE != clb_val(0, $prms, 'gp');
    $path = FALSE;
    $mode = $prop['mode'];
    if (is_string($p2p_paths)) {
        $path = $p2p_paths;
    } else {
        if (!is_array($p2p_paths)) {
            $result = array('error' => 500, 'error_str' => 'server configuration error: route tables not specified');
        } else {
            if ($mode && isset($p2p_paths[$mode])) {
                $path = $p2p_paths[$mode];
            } else {
                if (isset($p2p_paths['rtm'])) {
                    $node_types = array('rail', 'tube', 'tram');
                    $path = $p2p_paths['rtm'];
                } else {
                    $path = reset($p2p_paths);
                }
            }
        }
    }
    if (is_array($path)) {
        if (!$node_types) {
            $node_types = clb_val(FALSE, $path, 'types');
        }
        //get the types
        $path = clb_val(FALSE, $path, 'path');
    }
    //if types not given as param or with paths, but the mode name is a node type use it as default.
    if (!$node_types && clb_val(FALSE, $type_names, $prop['mode'])) {
        $node_types = $prop['mode'];
    }
    if ($node_types && !is_array($node_types)) {
        $node_types = array($node_types);
    }
    //make types an array if just a single
    if (!$path || !is_string($path) || !is_file($path)) {
        $result = array('error' => 500, 'error_str' => 'server configuration error: route tables could not be loaded');
    } else {
        $waypoints = array();
        $result = pfind_interpret($entries, $mode, $waypoints, $path, $node_types);
        qlog(__LINE__, $mode, $entries, $result);
        if (IS_LOCAL) {
            foreach ($waypoints as $i => $stage) {
                foreach ($stage as $see) {
                    qlog(__LINE__, $i, join(', ', $see));
                }
            }
        }
        clb_timing('interpret');
    }
    if ($result['error'] == 200) {
        $links = FALSE;
        if (!$prop['dist_only'] && is_file($path)) {
            $data = file_get_contents($path);
            //, FILE_BINARY);	//need different p2p files for different combinations of modes
            $links = clb_blob_dec($data);
        }
        clb_timing('load array');
        if (!$links && !$prop['dist_only']) {
            $result = array('error' => 500, 'error_str' => 'point to point data file could not be found/loaded ' . $mode);
            qlog(__LINE__, $result, $mode, $path, $p2p_paths);
        } else {
            $result = pfind_routes($waypoints, $links, $prop, $type_names);
        }
        qlog(__LINE__, clb_timing('find path'));
    }
    //qlog(__LINE__,clb_xml($result, 'RouteFinder'));
    // qlog(__LINE__,clb_json($result, "'"));
    switch ($prop['service']) {
        case 'json':
            $return_data = json_encode($result);
            rs_response('application/json', $return_data, 'UTF-8');
            break;
        case 'javascript':
            $sid = clb_val('', $prms, 'sid');
            $func = clb_val('mfw_dir_result', $prms, 'callback');
            $return_data = clb_json($result, "'");
            $callback = $func . '(\'' . $sid . '\',' . $return_data . ');';
            clb_response('application/javascript', $callback, 'UTF-8');
            break;
        case 'xml':
            $return_data = clb_xml($result, 'RouteFinder');
            clb_response('xml', $return_data, 'UTF-8');
            break;
        case 'php':
            return $result;
            break;
    }
}
Example #2
0
<?php

//look for config below root first but then same folder, if in wp, there will not be a config file, as it is only to give db info
if (!defined('DB_NAME')) {
    $path = dirname($_SERVER['SCRIPT_FILENAME']) . '/config.php';
    if (!is_file($path)) {
        $path = dirname(dirname($_SERVER['SCRIPT_FILENAME'])) . '/config.php';
    }
    require_once $path;
}
require_once dirname(__FILE__) . '/edit_ajax.php';
//in same directory as this file
qlog(__LINE__, '=========', $_REQUEST);
if (isset($_REQUEST['ajax'])) {
    ajax_request($_REQUEST['ajax']);
}
function map_js_defs($spec, $options, $btns)
{
    $key = clb_tag('script', '', '', array('src' => 'http://www.google.com/jsapi?key=' . GOOGLE_API_KEY, 'type' => 'text/javascript'));
    $script = 'google.load(\'maps\', \'2\');' . "\n";
    $script .= 'Event.observe(window, \'load\', function (){map_setup(' . clb_json($options) . ',' . clb_json($btns) . ');});' . "\n";
    $script .= 'var map_marker_spec = ' . clb_json($spec);
    $script = clb_tag('script', '', $script, array('type' => 'text/javascript'));
    return $key . "\n" . $script;
}
/*
	echo map_show_types('the_map', 'btn_types', $editor_types);
*/
function map_show_types($map, $id, $types)
{
    $html = '';
Example #3
0
function pbuild_make_link(&$p2p_links, $ends, $dist = FALSE)
{
    global $wpdb;
    $rec = reset($ends);
    $name = clb_val('', $rec, RF_NODES_TYPE) . ': ' . clb_val('', $rec, RF_NODES_NAME);
    $lat1 = clb_val(0, $rec, 'lat');
    $lng1 = clb_val(0, $rec, 'lng');
    $pnum1 = clb_val(0, $rec, RF_LINKS_KEY);
    $rec = next($ends);
    $name .= clb_val('', $rec, RF_NODES_TYPE) . ': ' . clb_val('', $rec, RF_NODES_NAME);
    $lat2 = clb_val(0, $rec, 'lat');
    $lng2 = clb_val(0, $rec, 'lng');
    $pnum2 = clb_val(0, $rec, RF_LINKS_KEY);
    //checking for existing links, and specifically any existing walk link
    $linkpnum = '';
    $makelink = TRUE;
    if (isset($p2p_links['nodes'][$pnum1]) && isset($p2p_links['nodes'][$pnum2])) {
        //get the list of link_pnums for both nodes and intersect to see if they are already connected
        $connections = array_intersect(explode(',', $p2p_links['nodes'][$pnum1]), explode(',', $p2p_links['nodes'][$pnum2]));
        $makelink = count($connections) <= 0;
        //dont make a link if there is already a direct link
        //if there are links see if one of them is a walk link in which case we may want to update it if the ends have moved.
        foreach ($connections as $ref) {
            if (isset($p2p_links['links'][$ref]['ptype']) && $p2p_links['links'][$ref]['ptype'] == 'walk') {
                $linkpnum = $ref;
                $makelink = TRUE;
                //comment this out if dont want to update walk links
                if (isset($p2p_links['links'][$ref]['pt_count']) && $p2p_links['links'][$ref]['pt_count'] > 2) {
                    $makelink = FALSE;
                }
                //if the walk link has more than 2 points then
                break;
            }
        }
        if (count($connections) > 1 && $linkpnum) {
            qlog(__LINE__, 'walk link and other link types', $pnum1, $pnum2, $connections);
        }
    }
    /*
    	$p2p_links may not include existing "walk" interchanges if there were no routes involving the stops
    	but to prevent creating duplicates do a search and do nothing if a walk exists
    */
    if ($makelink && !$linkpnum) {
        $pair = clb_join(array($pnum1, $pnum2), TRUE);
        $query = 'SELECT ' . RF_LINKS_KEY . ' FROM ' . RF_LINKS_FROM . ' WHERE ' . RF_LINKS_TYPE . '="walk" AND ' . RF_LINKS_END1 . ' IN ' . $pair . ' AND ' . RF_LINKS_END2 . ' IN ' . $pair;
        $check = $wpdb->get_results($query, ARRAY_A);
        if (is_array($check) && clb_val('', reset($check), RF_LINKS_KEY)) {
            $makelink = FALSE;
        }
    }
    if ($makelink) {
        if ($dist === FALSE) {
            $dist = pline_surface_dist($lat1, $lng1, $lat2, $lng2);
        }
        $processed = clb_now_utc();
        $query = '';
        $query .= ', ' . RF_LINKS_DIST . '=' . $dist * 2;
        //double the distance so this is not chosen over actual tracks
        $query .= ', ' . RF_LINKS_TIME . '=' . ceil($dist / 80);
        //80 meters per minute is about 3 miles per hour
        $query .= ', ' . RF_LINKS_MODIFIED . '=' . clb_escape($processed);
        $query .= ', ' . RF_LINKS_NAME . '=' . clb_escape($name);
        $query .= ', lat=' . round(($lat1 + $lat2) / 2, PT_PRECISION);
        $query .= ', lng=' . round(($lng1 + $lng2) / 2, PT_PRECISION);
        $points = array();
        $points[] = array($lat1, $lng1, 0);
        $points[] = array($lat2, $lng2, 0);
        if ($polyline = pline_make($points, array('color' => '#00FF00'))) {
            $query .= ', ' . RF_LINKS_LINE . '=' . clb_escape(clb_join($polyline, '', '&', '='));
            $query .= ', ' . RF_LINKS_POINTS . '=' . clb_escape(clb_blob_enc($points));
        }
        if ($linkpnum) {
            $query = 'UPDATE ' . RF_LINKS_FROM . ' SET ' . trim($query, ', ') . ' WHERE ' . RF_LINKS_KEY . '=' . clb_escape($linkpnum);
        } else {
            $linkpnum = pbuild_new_pnum(RF_LINKS_FROM, RF_LINKS_KEY);
            $query .= ', ' . RF_LINKS_KEY . '=' . clb_escape($linkpnum);
            $query .= ', ' . RF_LINKS_CREATED . '=' . clb_escape($processed);
            $query .= ', ' . RF_LINKS_END1 . '=' . clb_escape($pnum1);
            $query .= ', ' . RF_LINKS_END2 . '=' . clb_escape($pnum2);
            $query .= ', ' . RF_LINKS_TYPE . '=' . clb_escape('walk');
            $query = 'INSERT INTO ' . RF_LINKS_FROM . ' SET ' . trim($query, ', ');
        }
        // qlog(__LINE__, $query);
        $wpdb->query($query);
    }
    return $makelink;
}
Example #4
0
 function clb_b64e($input, $dec = 100000.0)
 {
     $val = $input;
     $neg = $input < 0;
     if ($dec) {
         //convert 5 decimal places for long/lat values
         $val = $val * $dec;
         //convert real to integer with 5 decimal places
         //	$val = floor(round($val,1));	//round before floor to correct precission error in floor
         $val = (int) round($val, 1);
         //round before floor to correct precission error in floor
         $val <<= 1;
         //shift left
         //php was keeping high bit set but we never want it set so mask it off.
         if ($neg) {
             $val = ($val ^ 0xffffffff) & 0x7fffffff;
         }
         //invert bits if negative
     }
     $txt = '';
     if ($val < 0) {
         qlog('negative value mid calculation in val2base64, something has gone wrong:', $input, $val);
         return '?';
     }
     do {
         $digit = $val & 0x1f;
         //mask of all but lowest 5 bits
         $val >>= 5;
         if ($val) {
             $digit |= 0x20;
         }
         //if there are more bits to come mask on 32
         $txt .= chr(63 + $digit);
     } while ($val);
     return $txt;
 }
Example #5
0
function pline_splice($db, $route, $pnum1 = FALSE, $pnum2 = FALSE, $stopsegs = FALSE)
{
    //$route is an array of link pnums
    if (!is_array($route) || count($route) == 0) {
        qlog(__LINE__, __FUNCTION__, 'bad route', $route, $pnum1, $pnum2);
        //exit();
        return '';
    }
    $raw = is_array($stopsegs);
    //TRUE => segment end points are points not pnums
    if ($raw) {
        //in the raw case we have to trim the ends so prepare information we will need
        $key1 = pline_arr_match($stopsegs['stoppnums'], $pnum1, $stopsegs['segpnums'], reset($route));
        $key1 = reset($key1);
        //should only be one match but still need to turn array into single value
        $cut1 = clb_val(FALSE, $stopsegs['data'], $key1);
        $key2 = pline_arr_match($stopsegs['stoppnums'], $pnum2, $stopsegs['segpnums'], end($route));
        $key2 = reset($key2);
        //should only be one match but still need to turn array into single value
        $cut2 = clb_val(FALSE, $stopsegs['data'], $key2);
    }
    //load all segs in one hit
    $query = 'SELECT ' . RF_LINKS_SELECT . ',' . RF_LINKS_POINTS . ' FROM ' . RF_LINKS_FROM . ' WHERE ' . RF_LINKS_KEY . ' IN ' . clb_join($route, TRUE);
    $segs = $db->get_results($query, ARRAY_A);
    $segs = clb_rekey($segs, 'pnum');
    $last_end1 = $last_end2 = $flip = FALSE;
    $flipfirst = FALSE;
    //if the first seg is flipped this holds the nubmer of points so we can work out how many to trim
    $points = array();
    $count = 0;
    $max = count($route);
    foreach ($route as $seg_pnum) {
        $count++;
        //so will be 1 on first loop, 2 on second etc
        $rec = clb_val(FALSE, $segs, $seg_pnum);
        $aoe_text = clb_val('', $rec, RF_LINKS_POINTS);
        $aoe_data = pline_pts_arr($aoe_text);
        if (!is_array($aoe_data)) {
            qlog(__FUNCTION__, __LINE__, 'failed to get points list for route segment', $seg_pnum, $count, $aoe_data);
            continue;
        }
        $this_end1 = clb_val('', $rec, RF_LINKS_END1);
        $this_end2 = clb_val('', $rec, RF_LINKS_END2);
        $flip = FALSE;
        if ($max == 1) {
            if ($raw) {
                //if the position within the segment of the second point is before the first, then we need to reverse
                $flip = isset($cut1['pos']) && isset($cut2['pos']) && $cut2['pos'] < $cut1['pos'];
            } else {
                if ($pnum1) {
                    $flip = $this_end2 == $pnum1;
                    //on a stop to stop link, need to reverse if start pnum is at tail end of link
                }
            }
            if ($flip) {
                $flipfirst = count($aoe_data);
            }
        } else {
            if ($count <= 1 || $this_end1 == $last_end2) {
                //no action
            } else {
                if ($count == 2 && $this_end1 == $last_end1) {
                    $points = array_reverse($points, TRUE);
                    //TRUE=preserve_keys
                    $flipfirst = count($points);
                } else {
                    if ($count == 2 && $this_end2 == $last_end1) {
                        $points = array_reverse($points, TRUE);
                        //TRUE=preserve_keys
                        $flipfirst = count($points);
                        $flip = TRUE;
                    } else {
                        $flip = $this_end2 == $last_end2;
                    }
                }
            }
        }
        if ($flip) {
            $aoe_data = array_reverse($aoe_data, TRUE);
            //TRUE=preserve_keys
            list($this_end1, $this_end2) = array($this_end2, $this_end1);
            //reverse end points too
        }
        //check if first point on this seg is same as last point on previous seg and if so remove it
        if (count($points) && count($aoe_data)) {
            $last = end($points);
            $first = reset($aoe_data);
            //do an array_pop on the existing points rather than removing the duplicate from $aoe_data since that alters the cutting math on raw segs
            if (round($last[0], 5) == round($first[0], 5) && round($last[1], 5) == round($first[1], 5)) {
                array_pop($points);
            }
        }
        $points = array_merge($points, $aoe_data);
        //$seg_idx[$this_end2] = count($points) - 1;
        $last_end1 = $this_end1;
        $last_end2 = $this_end2;
    }
    if ($raw) {
        //if the first seg was reversed then we want to keep the number of points on the other side
        $pos = is_int($flipfirst) ? $flipfirst - $cut1['pos'] : $cut1['pos'];
        //cut off end points and insert the stops own point.  If this is duplicate it will be cleaned by polyline later
        array_splice($points, 0, $pos, array(array($cut1['lat'], $cut1['lng'], 0)));
        //if the last seg was reversed then we want to keep the number of points on the other side
        $pos = $flip ? $cut2['pos'] : count($aoe_data) - $cut2['pos'];
        //aoe_data still around after last itteration of loop
        //cut off end points and insert the stops own point.  If this is duplicate it will be cleaned by polyline later
        array_splice($points, -$pos, $pos, array(array($cut2['lat'], $cut2['lng'], 0)));
        //qlog(__FUNCTION__, __LINE__, $pnum1, $cut1, $pnum2, $cut2);
    }
    //return array($points, $seg_idx);	//not using this because the positions may change when making a polyline and makes returning the points list more cumbersome
    return $points;
}
Example #6
0
function ajax_request()
{
    global $editor_types, $editor_tables;
    $xml = '';
    $msg = '';
    $rec_count = 0;
    $db = new wpdb(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);
    $pnum = clb_val(FALSE, $_REQUEST, 'pnum');
    if ($new_mark = preg_match('/^b(\\w{7})(\\w{7})/', $pnum, $m)) {
        $_REQUEST['lat'] = hexdec($m[1]) / 100000 - 180;
        $_REQUEST['lng'] = hexdec($m[2]) / 100000 - 180;
        $_REQUEST['coords'] = clb_b64e($_REQUEST['lat']) . clb_b64e($_REQUEST['lng']);
    }
    $ptype = clb_val(FALSE, $_REQUEST, 'ptype');
    //if the ptype is cust, default to the first table and type in the definitions that does or does not have a polyline
    if ($ptype == 'cust' && $new_mark) {
        foreach ($editor_types as $ptype => $spec) {
            if (clb_val(FALSE, $spec, 'polyline') == isset($_REQUEST['polyline'])) {
                break;
            }
        }
    }
    $table = FALSE;
    $prefixes = clb_column($editor_tables, 'prefix');
    if ($pnum && preg_match('/^(\\w+)_\\w+$/', $pnum, $m)) {
        $table = array_search($m[1], $prefixes);
    } else {
        if ($ptype) {
            $table = clb_val(FALSE, $editor_types, $ptype, 'table');
        }
    }
    $spec = clb_val(FALSE, $editor_tables, $table);
    $ajax = clb_val(FALSE, $_REQUEST, 'ajax');
    qlog(__LINE__, '>>>>', $ajax, $pnum, $ptype, $table, $new_mark ? 'new' : 'old');
    //, $spec);
    switch ($ajax) {
        case 'show':
            $sel = FALSE;
            if ($spec) {
                $select = clb_val(FALSE, $spec, 'select');
                $query = 'SELECT ' . clb_join($select, '`') . ' FROM ' . $table . ' WHERE pnum=' . clb_escape($pnum);
                $sel = $db->get_results($query, ARRAY_A);
            }
            //if not found via pnum, try title in each table.
            if (!$sel) {
                foreach ($editor_tables as $table => $spec) {
                    if (($select = clb_val(FALSE, $spec, 'select')) && in_array('title', $select)) {
                        $query = 'SELECT ' . clb_join($select, '`') . ' FROM ' . $table . ' WHERE title like ' . clb_escape($pnum . '%');
                        $sel = $db->get_results($query, ARRAY_A);
                        if ($sel) {
                            break;
                        }
                    }
                }
            }
            if (!$sel) {
                $msg = 'No matches found for: ' . $pnum;
            } else {
                $titles = clb_column($sel, 'title');
                $msg = count($sel) . ' matches found: ' . join(', ', $titles);
                $rec = reset($sel);
                $pnum = clb_val(FALSE, $rec, 'pnum');
                $xml .= clb_tag('response', '', '', array_merge(array('type' => 'centre'), array_intersect_key($rec, array('lat' => 0, 'lng' => 0)))) . "\n";
                $xml .= refesh_marker($db, $table, $pnum);
                $xml .= marker_bubble($db, $spec, $table, $pnum);
            }
            break;
        case 'route_list':
            //shows bubble on station showing list of routes
            $html = '';
            //find the route table and which field(s) hold the stop list
            $route_flds = '';
            foreach ($editor_tables as $route_tab => $info) {
                if ($route_flds = clb_val(FALSE, $info, 'routes')) {
                    break;
                }
            }
            if (!$route_flds) {
                break;
            }
            $route_flds = explode('/', $route_flds);
            //can be more than one field with '/' as a separator
            //build query to get route list
            $select = clb_val(FALSE, $editor_tables, $route_tab, 'select');
            $where = array();
            foreach ($route_flds as $fld) {
                $where[] = ' (`' . $fld . '` LIKE ' . clb_escape('%' . $pnum . '%') . ')';
            }
            $query = 'SELECT ' . clb_join(array_merge($select, $route_flds), '`') . ' FROM ' . $route_tab . ' WHERE ' . join(' OR ', $where);
            $sel = $db->get_results($query, ARRAY_A);
            if (clb_count($sel) == 0) {
                $msg = 'There are no routes for node: ' . $pnum;
            } else {
                $list = '';
                $alt = 0;
                foreach ($sel as $rec) {
                    foreach ($route_flds as $pos => $fld) {
                        $rnum = reset($rec);
                        $route_key = key($rec);
                        $script = 'map_ajax(the_map, \'show_route\', {\'pnum\':\'' . $rnum . '\',\'fld\':\'' . $fld . '\', \'stop\':\'' . $pnum . '\'});';
                        $name = $rnum . ':' . $pos . ': ' . clb_val(FALSE, $rec, 'title');
                        $list .= clb_tag('li', '', clb_tag('a', $name, '', array('onclick' => $script, 'href' => 'javascript:void(0);')), array('class' => 'alt' . $alt++ % 2));
                    }
                }
                $html .= clb_tag('ul', '', $list, array('class' => 'route_list')) . "\n";
                $form = clb_tag('form', '', $html, array('id' => 'info_win', 'action' => '', 'method' => 'get', 'onsubmit' => 'return false;')) . "\n";
                $xml .= clb_tag('response', '', htmlspecialchars($form), array('type' => 'bubble', 'pnum' => $pnum)) . "\n";
            }
            break;
        case 'new_route':
            //create new route
        //create new route
        case 'route_stop':
            //add stop to route
        //add stop to route
        case 'route_unstop':
            //remove stop from route
        //remove stop from route
        case 'show_route':
            //show route
            //		qlog(__LINE__, $table, $pnum, $spec);
            require_once CODE_DIR . 'pline_lib.php';
            //scan tables to find routes
            foreach ($editor_tables as $table => $info) {
                if ($routes = clb_val(FALSE, $info, 'routes')) {
                    break;
                }
            }
            if (!$routes) {
                break;
            }
            //did not find route table
            $routes = explode('/', $routes);
            $route_tab = $table;
            $select = clb_val(FALSE, $editor_tables, $route_tab, 'select');
            $route_key = reset($select);
            $stops = FALSE;
            $new_route = 'new_route' == $ajax;
            if ($new_route) {
                $fld = reset($routes);
                $newstop = $pnum;
                $stopindex = 0;
                $list = '';
                $title = clb_val(FALSE, $_REQUEST, 'title');
                $pnum = new_pnum($db, $table, $route_key);
                $ajax = 'route_stop';
            } else {
                $stopindex = clb_val(FALSE, $_REQUEST, 'stopindex');
                //this only come with route_stop and route_unstop
                $newstop = clb_val(FALSE, $_REQUEST, 'newstop');
                //this only come with route_stop
                $fld = clb_val(FALSE, $_REQUEST, 'fld');
                $select = array_merge($select, $routes);
                //select route record
                $query = 'SELECT ' . clb_join($select, '`') . ' FROM ' . $route_tab . ' WHERE ' . $route_key . '=' . clb_escape($pnum);
                $sel = $db->get_results($query, ARRAY_A);
                $rec = clb_count($sel) ? reset($sel) : FALSE;
                $list = clb_val(FALSE, $rec, $fld);
                $ptype = clb_val(FALSE, $rec, 'ptype');
                $title = clb_val(FALSE, $rec, 'title');
                //if (empty($list) && (reset($routes) == $fld) && ($fld
                if (empty($list)) {
                    $newstop = clb_val(FALSE, $_REQUEST, 'stop');
                    $stopindex = 0;
                    $ajax = 'route_stop';
                }
            }
            if (preg_match_all('/^(\\w+)\\s+(.*)/m', $list, $m)) {
                $stops = $m[1];
            }
            if (in_array($ajax, array('route_stop', 'route_unstop')) && is_numeric($stopindex)) {
                if (!$stops) {
                    $stops = array(FALSE);
                }
                //ensure loop runs at least once
                $new = '';
                foreach ($stops as $i => $stop_pnum) {
                    if ('route_unstop' == $ajax && $i == $stopindex) {
                        continue;
                    }
                    //skip the stop that is to be deleted
                    //add the stop on this line
                    if ($stop_pnum) {
                        $new .= $m[1][$i] . ' ' . trim($m[2][$i]) . "\n";
                    }
                    //add new station if this is the right position
                    if ('route_stop' == $ajax && $i == $stopindex && $newstop) {
                        //find maker table via ptype
                        $table = clb_val(FALSE, $editor_types, $ptype, 'table');
                        $query = 'SELECT lat, lng, pnum, ptype, title FROM ' . $table . ' WHERE pnum=' . clb_escape($newstop);
                        $sel = $db->get_results($query, ARRAY_A);
                        if ($sel) {
                            $new .= $newstop . ' ' . clb_val('', reset($sel), 'title') . "\n";
                        }
                    }
                }
                if (preg_match_all('/^(\\w+)\\s+(.*)/m', $new, $m)) {
                    $stops = $m[1];
                }
                //if forward direction and changing last item update orig, dest and title
                $rename = '';
                if (reset($routes) == $fld && clb_count($stops) <= $stopindex + 2) {
                    $orig = reset($m[2]);
                    $dest = end($m[2]);
                    $rename .= ', title=' . clb_escape($orig . ' - ' . $dest);
                    $rename .= ', orig=' . clb_escape($orig);
                    $rename .= ', dest=' . clb_escape($dest);
                }
                if ($new_route) {
                    $query = 'SELECT area, count(*) AS c FROM ' . $route_tab . ' WHERE ptype=' . clb_escape($ptype) . ' GROUP BY area';
                    $sel = $db->get_results($query, ARRAY_A);
                    $area = is_array($sel) ? clb_val('', reset($sel), 'area') : '';
                    $query = '';
                    $query .= ', ' . $route_key . '=' . clb_escape($pnum);
                    $query .= ', area=' . clb_escape($area);
                    $query .= ', ptype=' . clb_escape($ptype);
                    $query .= ', ' . $fld . '=' . clb_escape($new);
                    $query .= ', created=' . clb_escape(clb_now_utc());
                    $query = 'INSERT INTO ' . $route_tab . ' SET ' . trim($query, ', ') . $rename;
                } else {
                    $query = 'UPDATE ' . $route_tab . ' SET ' . $fld . '=' . clb_escape($new) . $rename . ' WHERE ' . $route_key . '=' . clb_escape($pnum);
                }
                $db->query($query);
            }
            if ($stops) {
                $index = array_search(clb_val(FALSE, $_REQUEST, 'stop'), $stops);
                //index of the stop we opened route from
                if (is_numeric($stopindex)) {
                    $index = Min($stopindex + ($newstop ? 1 : 0), clb_count($stops) - 1);
                }
                //use new index if provided and add one if new stop
                if (preg_match('/^(\\w+)_\\w+$/', reset($stops), $m)) {
                    $table = array_search($m[1], $prefixes);
                    $spec = clb_val(FALSE, $editor_tables, $table);
                    $points = array();
                    $names = array();
                    $pnums = array();
                    $query = 'SELECT lat, lng, pnum, ptype, title FROM ' . $table . ' WHERE pnum IN ' . clb_join($stops, TRUE);
                    $sel = $db->get_results($query, ARRAY_A);
                    //in theory could be multiple stop instances and need to give points in order so loop on $stops and look up record via xref
                    $xref = clb_column($sel, 'pnum');
                    if (clb_count($sel)) {
                        foreach ($stops as $stop_pnum) {
                            $rec = clb_val(FALSE, $sel, array_search($stop_pnum, $xref));
                            $points[] = array($rec['lat'], $rec['lng'], 0);
                            $names[] = str_replace('|', ',', $rec['title']);
                            $pnums[] = $rec['pnum'];
                            $rec['type'] = 'marker';
                            $xml .= clb_tag('response', '', '', $rec) . "\n";
                            $rec_count++;
                        }
                    }
                    foreach ($points as $i => $pt) {
                        if (!is_array($pt)) {
                            unset($points[$i]);
                        }
                    }
                    //remove non points if there are any
                    $line = pline_make($points, array('color' => '#FF0000'));
                    $line['names'] = join('|', $names);
                    $line['pnums'] = join('|', $pnums);
                    if ($line) {
                        $line = clb_join($line, '', '&', '=');
                    }
                    $attr = array('type' => 'route_pline', 'pnum' => $pnum, 'title' => $title, 'fld' => $fld, 'ptype' => $ptype, 'index' => $index);
                    if ($line) {
                        $xml .= clb_tag('response', '', htmlspecialchars($line), $attr) . "\n";
                    }
                }
            } else {
                $msg = 'This route (in this direction) has no stops. ';
            }
            break;
        case 'overlays':
            if (clb_val(FALSE, $_REQUEST, 'zm') < 9) {
                $msg = 'Zoom in to get markers to download.';
            } else {
                $rect = array();
                $rect[] = 'lat >= ' . clb_val(FALSE, $_REQUEST, 'bot');
                $rect[] = 'lng >= ' . clb_val(FALSE, $_REQUEST, 'lft');
                $rect[] = 'lat <= ' . clb_val(FALSE, $_REQUEST, 'top');
                $rect[] = 'lng <= ' . clb_val(FALSE, $_REQUEST, 'rgt');
                $qtypes = preg_split('/;/', clb_val(FALSE, $_REQUEST, 'types'), -1, PREG_SPLIT_NO_EMPTY);
                $tables = array();
                foreach ($qtypes as $ptype) {
                    $tables[clb_val('bad', $editor_types, $ptype, 'table')][] = $ptype;
                }
                if (!count($qtypes)) {
                    $msg = 'No marker types selected.';
                } else {
                    foreach ($tables as $table => $list) {
                        if ($table != 'bad' && count($list)) {
                            $prefix = clb_val(FALSE, $editor_tables, $table, 'prefix');
                            $types = preg_replace('/\\w+_/', '', clb_join($list, TRUE));
                            $query = '';
                            $query .= 'SELECT lat, lng, pnum, ptype, title FROM ' . $table . ' WHERE ';
                            $query .= ' ptype IN ' . $types . ' AND (' . join(' AND ', $rect) . ') ';
                            $sel = $db->get_results($query, ARRAY_A);
                            if (clb_count($sel)) {
                                foreach ($sel as $rec) {
                                    $rec['type'] = 'marker';
                                    if (!in_array($rec['ptype'], $list)) {
                                        $rec['ptype'] = $prefix . '_' . $rec['ptype'];
                                    }
                                    $xml .= clb_tag('response', '', '', $rec) . "\n";
                                    $rec_count++;
                                }
                            }
                        }
                    }
                }
                $msg = $rec_count ? count($sel) . ' markers loaded' : 'No markers found.';
                if ('purge' == clb_val(FALSE, $_REQUEST, 'purge')) {
                    $xml .= clb_tag('response', '', '', array('type' => 'purge')) . "\n";
                }
            }
            break;
        case 'saveline':
            require_once CODE_DIR . 'pline_lib.php';
            //fall through
        //fall through
        case 'save':
            //no real validation so just save and close
            if (!$spec) {
                $msg = 'could not identify the marker type.';
                break;
            }
            //('polyline'=>'line', 'select'=>' lat, lng, pnum, ptype, title, line, aoe_data')
            if ($new_mark) {
                $pnum = new_pnum($db, $table);
            }
            //get field names and types
            $def = array();
            $sel = $db->get_results('describe ' . $table, ARRAY_A);
            foreach ($sel as $rec) {
                $def[$rec['Field']] = $rec['Type'];
            }
            /*
            	normally save line is handled by the normal save 
            	but if we are saving a cut line, we need to save off the first part and 
            	then use the normal save to create the latter part as a new record
            	dont cut on first or last point of line
            */
            $points = FALSE;
            if ('saveline' == $ajax) {
                $points = pline_pts_arr(clb_val(FALSE, $_REQUEST, 'polyline'));
                //the rest of this is only for cutting a line
                if (($cut = clb_val(FALSE, $_REQUEST, 'cut')) && $cut + 1 < clb_count($points)) {
                    $first = array_slice($points, 0, $cut + 1);
                    //keep points up to and including cut
                    $points = array_slice($points, $cut);
                    //reduce points on and after cut for new record
                    $query = save_line_query($first, $spec);
                    $query .= '`' . 'lat' . '`=' . clb_escape($_REQUEST['lat']) . ',';
                    $query .= '`' . 'lng' . '`=' . clb_escape($_REQUEST['lng']) . ',';
                    $query .= '`' . 'end1' . '`=' . clb_escape($_REQUEST['end1']) . ',';
                    //adjusts mid point
                    $query .= '`' . 'end2' . '`=' . clb_escape($_REQUEST['end2']) . ',';
                    if ($new_mark) {
                        $query .= '`' . 'pnum' . '`=' . clb_escape($pnum) . ',';
                        $query .= '`' . 'ptype' . '`=' . clb_escape($ptype) . ',';
                        if (isset($def['created'])) {
                            $query .= '`' . 'created' . '`=' . clb_escape(clb_now_utc()) . ',';
                        }
                        $query = 'INSERT INTO ' . $table . ' SET ' . trim($query, ', ');
                    } else {
                        $query = 'UPDATE ' . $table . ' SET ' . trim($query, ', ') . ' WHERE pnum=' . clb_escape($pnum);
                    }
                    $res = $db->query($query);
                    $xml .= refesh_marker($db, $table, $pnum, $pnum);
                    unset($_REQUEST['pnum']);
                    //clear this so that the new marker does not remove the repositioned marker
                    $pnum = new_pnum($db, $table);
                    //new pnum for marker
                    $new_mark = TRUE;
                }
            }
            $query = '';
            if ('saveline' == $ajax && is_array($points)) {
                $query .= save_line_query($points, $spec);
            }
            foreach ($def as $fld => $type) {
                switch ($fld) {
                    case 'pnum':
                        if ($new_mark) {
                            $query .= '`' . $fld . '`=' . clb_escape($pnum) . ',';
                        }
                        break;
                    case 'created':
                        if ($new_mark) {
                            $query .= '`' . $fld . '`=' . clb_escape(clb_now_utc()) . ',';
                        }
                        break;
                    case 'ptype':
                        $query .= '`' . $fld . '`=' . clb_escape($ptype) . ',';
                        break;
                    default:
                        if (isset($_REQUEST[$fld])) {
                            $query .= '`' . $fld . '`=' . clb_escape($_REQUEST[$fld]) . ',';
                        }
                        break;
                }
            }
            qlog(__LINE__, $query);
            if ($new_mark) {
                $query = 'INSERT INTO ' . $table . ' SET ' . trim($query, ', ');
            }
            if (!$new_mark) {
                $query = 'UPDATE ' . $table . ' SET ' . trim($query, ', ') . ' WHERE pnum=' . clb_escape($pnum);
            }
            $res = $db->query($query);
            //when saving a marker remember the type to be used as the default for next new marker.
            $name = clb_val(FALSE, $spec, 'polyline') ? 'type_line' : 'type_mark';
            $xml .= clb_tag('response', '', $ptype, array('type' => 'state', 'pnum' => $name)) . "\n";
            //pnum is the "id" name is the "id" of the state we are setting
            $xml .= refesh_marker($db, $table, $pnum, clb_val(FALSE, $_REQUEST, 'pnum'));
            //want to fall through to show a bubble if saving a line
            //so break when either condition fails
            if ('saveline' == $ajax) {
                $xml .= marker_bubble($db, $spec, $table, $pnum);
            }
            break;
        case 'bubble':
            if (!$spec || !$pnum) {
                $msg = 'could not identify the marker type.';
                break;
            }
            $xml .= marker_bubble($db, $spec, $table, $pnum);
            break;
        case 'delete':
            $query = 'DELETE FROM ' . $table . ' WHERE pnum=' . clb_escape($pnum);
            $sel = $db->query($query);
            //remove old marker, which closes info box
            $xml .= clb_tag('response', '', '', array('type' => 'remove', 'pnum' => $_REQUEST['pnum'])) . "\n";
            break;
    }
    if ($ajax) {
        if ($msg) {
            $xml .= clb_tag('response', $msg, '', array('type' => 'info')) . "\n";
        }
        if (!$xml) {
            $xml .= clb_tag('response', '', '', array('type' => 'null')) . "\n";
        }
        // qlog(__LINE__, $xml);
        clb_response('xml', $xml);
    }
}
Example #7
0
function blow_backout($node1, $node2, $network_d, $links)
{
    //now run the shortest path on the new network of shortest paths but measure shortest by number of changes
    $seq = 0;
    $network_c = array();
    $queue = array();
    $queue_sort = array();
    //since change distances will be the same a lot of the time inclde a parallel distance array to pick the shortest within change groups
    $dist_limit = FALSE;
    foreach ($node2 as $pnum) {
        $pos_c = $seq++;
        $network_c[$pos_c]['node'] = $pnum;
        //start at the destination end
        $network_c[$pos_c]['dist'] = 0;
        //distance up to the node on this leaf
        $network_c[$pos_c]['changes'] = 0;
        //number of changes to get to this leaf
        $network_c[$pos_c]['link'] = FALSE;
        //link pnum from the parent
        $network_c[$pos_c]['routes'] = array();
        //routes that the node was arrived through
        $network_c[$pos_c]['past'] = array();
        //will build up list of past nodes going forward
        $network_c[$pos_c]['ptype'] = '';
        //used to check we do not get multiple 'walk' links in a row
        $queue['x' . $pos_c] = 0;
        //the initial distance makes little difference since it is only used to choose which of the one items we use.
        $queue_sort['x' . $pos_c] = 0;
        if (isset($network_d[$pnum]) && ($dist_limit === FALSE || $dist_limit > $network_d[$pnum]['dist'])) {
            $dist_limit = $network_d[$pnum]['dist'];
        }
    }
    $dist_limit *= 1.1;
    //don't allow paths to get more than 20% longer than the best.
    $complete = array();
    //collects one or more paths
    $best = FALSE;
    //will hold the lowest score of an actual match so we can stop looking after other options get to large to be contenders
    $range = 2;
    //allow range of best+2 extra stops
    $used = array();
    $time = microtime(true);
    while (count($queue)) {
        //asort($queue);	//put lowest score first
        array_multisort($queue, SORT_ASC, $queue_sort, SORT_DESC);
        //$queue = changes, $queue_sort = dist
        if ((microtime(true) - $time) * 1000 > 5000) {
            $time = microtime(true);
            qlog(__LINE__, 'queue', count($queue));
        }
        $est_changes = reset($queue);
        //set first element current, and get estimated distance for this route
        $cursor = 1 * substr(key($queue), 1);
        //get the key removing 'x' which makes the keys strings and prevents renumbering on arrays shift.
        array_shift($queue);
        //remove item from queue since it will not need processing after this
        array_shift($queue_sort);
        //remove item from queue since it will not need processing after this
        //$cursor is our index into the $network_c
        if (!isset($network_c[$cursor])) {
            continue;
        }
        //the parent should always exist, just being safe.
        $noden = $network_c[$cursor]['node'];
        //$noden is the node identifier of the leaf we want to continue the path from
        $last_dist = $network_c[$cursor]['dist'];
        //distance up to the node on this leaf
        $last_changes = $network_c[$cursor]['changes'];
        //number of changes to get to this leaf
        $last_routes = $network_c[$cursor]['routes'];
        //routes that the node was arrived through
        $last_link = $network_c[$cursor]['link'];
        //link pnum from the parent
        $past = $network_c[$pos_c]['past'];
        //will build up list of past going forward
        $past[] = $last_link;
        $last_ptype = $network_c[$cursor]['ptype'];
        //link pnum from the parent
        //if we have a match and all remaining options are worse by a margin then stop looking
        if (count($complete) && $best + $range < $est_changes) {
            break;
        }
        $used[$noden] = $pos_c;
        //our "links" are now coming from the leaves of the previous shortest path structure
        //$old_leaf = clb_val(FALSE, $network_d, $noden);	//get actual node
        $old_leaf = isset($network_d[$noden]) ? $network_d[$noden] : FALSE;
        //get actual node
        //$preds = clb_val(FALSE, $old_leaf, 'prev');		//the predecessors to that node
        $preds = isset($old_leaf['prev']) ? $old_leaf['prev'] : FALSE;
        //the predecessors to that node
        //now loop though the candidate links from this node
        if (clb_count($preds)) {
            foreach ($preds as $via_link => $pre_link) {
                //$ptype = clb_val('', $pre_link, 'ptype');
                $ptype = isset($pre_link['ptype']) ? $pre_link['ptype'] : '';
                // qlog(__LINE__,$ptype, $last_ptype, $noden, (isset($pre_link['prev_node']) ? $pre_link['prev_node'] : ''));
                if ($ptype == 'walk' && $last_ptype == 'walk') {
                    continue;
                }
                //don't allow a route to be constructed from a series of walk interconnections
                if (in_array($via_link, $past)) {
                    continue;
                }
                //already have this link on this path so skip it
                if ($via_link == $last_link) {
                    continue;
                }
                //dont double back, this test should be redundent due to the previous line
                //$remainder = clb_val(0, $pre_link, 'path_dist');	//each pre link from the network_d array knows how far it is from the origin as a minimum
                $remainder = isset($pre_link['path_dist']) ? $pre_link['path_dist'] : 0;
                //each pre link from the network_d array knows how far it is from the origin as a minimum
                //qlog(__LINE__, $last_dist, $remainder, ($last_dist + $remainder), $dist_limit, ((($last_dist + $remainder) > $dist_limit)?' culled':''));
                if ($last_dist + $remainder > $dist_limit) {
                    continue;
                }
                //when expanding routes, combinations may get long so chop them out
                //$dest_node = clb_val('', $pre_link,'prev_node');
                $dest_node = isset($pre_link['prev_node']) ? $pre_link['prev_node'] : '';
                //$link_len = clb_val(0, $pre_link, 'link_len');
                $link_len = isset($pre_link['link_len']) ? $pre_link['link_len'] : 0;
                $dist = $last_dist + $link_len;
                //$link_routes = clb_val(FALSE, $pre_link, 'common');
                $link_routes = isset($pre_link['common']) ? $pre_link['common'] : FALSE;
                $link_routes = $link_routes ? explode(',', $link_routes) : array();
                //convert comma separated list into array
                $routes_common = array_intersect($last_routes, $link_routes);
                $changes = count($routes_common) == 0 ? 2 : 0;
                //if no common routes then give a change a 2 score
                if ($changes) {
                    //see if there are any routes which have the same beginning up to '_' which indicates a branch on a line like underground lines
                    foreach ($last_routes as $rl) {
                        if (clb_contains($rl, '_')) {
                            foreach ($link_routes as $rn) {
                                if (clb_contains($rn, '_')) {
                                    if (preg_replace('/_.*$/', '', $rl) == preg_replace('/_.*$/', '', $rn)) {
                                        $changes = 1;
                                        break;
                                    }
                                }
                            }
                            if ($changes == 1) {
                                break;
                            }
                        }
                    }
                    $routes_common = $link_routes;
                    //since we are changing, can now use all routes between the two nodes
                }
                $changes += $last_changes;
                if (is_int($best) && $changes > $best + $range) {
                    continue;
                }
                $pos_c = $seq++;
                //prepare the index for the $network_c array, we may skip the node but do not mind gaps
                $network_c[$pos_c]['node'] = $dest_node;
                //start at the destination end
                $network_c[$pos_c]['prev'] = $cursor;
                //way back to the previous leaf
                $network_c[$pos_c]['dist'] = $dist;
                //distance up to the node on this leaf
                $network_c[$pos_c]['changes'] = $changes;
                //number of changes to get to this leaf
                $network_c[$pos_c]['link'] = $via_link;
                //link pnum from the parent
                $network_c[$pos_c]['routes'] = $routes_common;
                //routes that the node was arrived through
                $network_c[$pos_c]['past'] = $past;
                //will build up list of past going forward
                $network_c[$pos_c]['ptype'] = $ptype;
                // qlog(__LINE__,$dest_node, $node1);
                if (in_array($dest_node, $node1)) {
                    $complete[] = $pos_c;
                    if (is_bool($best) || $changes < $best) {
                        $best = $changes;
                    }
                } else {
                    $queue['x' . $pos_c] = $changes;
                    //primary sort on changes keeps minimum changes top of list
                    $queue_sort['x' . $pos_c] = $dist;
                    //distance ranks routes with same number of changes.
                }
            }
        }
    }
    //if (count($complete) == 0) {qpre($node1, $node2, $network_d, $network_c, $preds);	exit();}
    $result = array();
    if (is_array($complete)) {
        foreach ($complete as $pos_c) {
            $run = array();
            while ($link = $network_c[$pos_c]['link']) {
                $run[$link] = $network_c[$pos_c];
                //['routes'];
                $pos_c = $network_c[$pos_c]['prev'];
            }
            $result[] = $run;
        }
    }
    //qlog(__LINE__,count($complete), count($used), count($network_c), count($network_d));
    //qlog(__LINE__, clb_timing('shortest changes'));
    //qlog(__LINE__, $node2, $complete);
    return $result;
}
Example #8
0
     //arrays connecting nodes to raw segs
     $data = file_get_contents($map_path, FILE_BINARY);
     $stopsegs = clb_blob_dec($data);
     $best = array('8OPGJHWH');
     $aoe_data = splice_links($best, 'IEIQTRQ', 'DAKSXUO', $stopsegs);
     $polyline = make_polyline($aoe_data, array('color' => '#0000FF'));
     qpre($aoe_data);
     //remove any unused points from the points list and save as a structure
     $temp = $aoe_data;
     $aoe_data = array();
     foreach ($temp as $i => $pt) {
         if (isset($pt['gran'])) {
             $aoe_data[] = $pt;
             qlog(__LINE__, $i);
         } else {
             qlog(__LINE__, $i);
         }
     }
     break;
 case 'metaphone':
     $name = 'cambridge';
     $name = unify_names($name);
     $name = metaphone($name);
     qpre($name);
     $name = metaphone('(wales)');
     qpre($name);
     $path = __FILE__;
     $folder = '/Users/tobylewis/Sites/buses_sched/temp/';
     //if local use a folde that can be written to
     $folder = is_dir($folder) ? $folder . 'file' : $path;
     //otherwise use same folder as the p2p files