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; } }
<?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 = '';
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; }
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; }
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; }
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); } }
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; }
//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