private function checkAreaAlarm($device, $location, $rule) { // Log::write("" . // "\ncheckAreaAlarm\n" .$rule['id']. // "\nRule:\n".print_r($rule, true)."" . // "\nDevice\n".print_r($device, true)."" . // "\nLocation\n".print_r($location, true) . // "", Log::INFO); $polygon = $this->getPathAreaPoints($rule['path_area_id']); //将有关数字转成数字形式(否则是字符串形式,某些比较运算会有问题的) $rule['speed'] += 0; $location['speed'] += 0; $rule['long'] += 0; $rule['distance'] += 0; $speedMsg = $this->getSpeedLimitAlarmMsg($location['speed'], $rule['speed']); if ($rule['in_out'] == '进入') { if (Geometry::geoPointInPolygon2($location['baidu_lat'], $location['baidu_lng'], $polygon)) { if (empty($rule['long'])) { $msg = '按照规则[' . $rule['label'] . '],' . $device['target_type'] . '[' . $device['target_name'] . '],' . '不允许在此时[' . date('Y-m-d H:i:s') . ']进入区域[' . $rule['path_area_label'] . '],' . "而现在检测到目标在区域内(坐标:{$location['baidu_lat']}, {$location['baidu_lng']})"; $msg .= empty($speedMsg) ? '' : ',并且' . $speedMsg; return $this->startAlarm($device, $location, $rule, $msg); } else { //允许进入时间 不为0 $longInSeconds = $rule['long'] * 60; while ($previousLocation = $this->getPreviousLocation($device['id'], $location['id'])) { if (!Geometry::geoPointInPolygon2($previousLocation['baidu_lat'], $previousLocation['baidu_lng'], $polygon)) { return empty($speedMsg) ? null : $this->startSpeedAlarm($device, $location, $rule); //历史轨迹点不在区域内,不用报警(如果不超速的话) } $timeDiff = $this->getTimeDifference('now', $previousLocation['time']); if ($timeDiff >= $longInSeconds) { $msg = '按照规则[' . $rule['label'] . '],' . $device['target_type'] . '[' . $device['target_name'] . '],' . '不允许在此时[' . date('Y-m-d H:i:s') . ']进入区域[' . $rule['path_area_label'] . ']' . '超过' . $rule['long'] . '分钟,' . "而现在检测到目标在区域内(坐标:{$location['baidu_lat']}, {$location['baidu_lng']})," . "并且时间已经超过" . floor($timeDiff / 60) . "分钟"; $msg .= empty($speedMsg) ? '' : ',并且' . $speedMsg; return $this->startAlarm($device, $location, $rule, $msg); } } return empty($speedMsg) ? null : $this->startSpeedAlarm($device, $location, $rule); //已经 没有上一个定位了(时间仍不够长),不用报警 } } else { //不允许进入,但是现在点不在区域内,仍有可能需要报警:如果当前点和上一个轨迹点的线段切割区域多边形的话。 $previousLocation = $this->getPreviousLocation($device['id'], $location['id']); $timeDiff = floor($this->getTimeDifference('now', $previousLocation['time']) / 60); if ($timeDiff >= $rule['long'] && Geometry::geoSegmentCuttingPolygon($previousLocation['baidu_lat'], $previousLocation['baidu_lng'], $location['baidu_lat'], $location['baidu_lng'], $polygon)) { $msg = '按照规则[' . $rule['label'] . '],' . $device['target_type'] . '[' . $device['target_name'] . '],' . '不允许在此时[' . date('Y-m-d H:i:s') . ']进入区域[' . $rule['path_area_label'] . ']' . (empty($rule['long']) ? '' : '超过' . $rule['long'] . '分钟') . ",而现在检测到目标的当前位置与上一个定位点的轨迹路线经过该区域" . (empty($rule['long']) ? '' : ',并且两轨迹点时间间隔已经超过' . $timeDiff . '分钟'); $msg .= empty($speedMsg) ? '' : ',并且' . $speedMsg; return $this->startAlarm($device, $location, $rule, $msg); } return null; } } else { //离开区域报警 $distance = round(Geometry::geoPointDistancePolygon($location['baidu_lat'], $location['baidu_lng'], $polygon)); if (!Geometry::geoPointInPolygon2($location['baidu_lat'], $location['baidu_lng'], $polygon) && $distance >= $rule['distance']) { if (empty($rule['long'])) { // 时长限制为0 $msg = '按照规则[' . $rule['label'] . '],' . $device['target_type'] . '[' . $device['target_name'] . '],' . '不允许在此时[' . date('Y-m-d H:i:s') . ']离开区域[' . $rule['path_area_label'] . ']' . $rule['distance'] . '米,' . "而现在检测到目标在区域外(坐标:{$location['baidu_lat']}, {$location['baidu_lng']}),距离区域" . $distance . '米'; $msg .= empty($speedMsg) ? '' : ',并且' . $speedMsg; return $this->startAlarm($device, $location, $rule, $msg); } else { //允许离开一段时间 $longInSeconds = $rule['long'] * 60; $curLocationId = $location['id']; while ($previousLocation = $this->getPreviousLocation($device['id'], $curLocationId)) { $historyDist = Geometry::geoPointDistancePolygon($previousLocation['baidu_lat'], $previousLocation['baidu_lng'], $polygon); if (Geometry::geoPointInPolygon2($previousLocation['baidu_lat'], $previousLocation['baidu_lng'], $polygon) || $historyDist < $rule['distance']) { //历史轨迹点在区域内或者离开距离不够 return empty($speedMsg) || $distance < $rule['distance'] ? null : $this->startSpeedAlarm($device, $location, $rule); } $timeDiff = $this->getTimeDifference('now', $previousLocation['time']); if ($timeDiff >= $longInSeconds) { $msg = '按照规则[' . $rule['label'] . '],' . $device['target_type'] . '[' . $device['target_name'] . '],' . '不允许在此时[' . date('Y-m-d H:i:s') . ']离开区域[' . $rule['path_area_label'] . ']' . $rule['distance'] . '米,' . '超过' . $rule['long'] . '分钟,' . "而现在检测到目标在区域外(坐标:{$location['baidu_lat']}, {$location['baidu_lng']})," . "并且离开区域至少" . $rule['distance'] . '米' . "已经超过" . floor($timeDiff / 60) . "分钟"; $msg .= empty($speedMsg) ? '' : ',并且' . $speedMsg; return $this->startAlarm($device, $location, $rule, $msg); } $curLocationId = $previousLocation['id']; } return empty($speedMsg) || $distance < $rule['distance'] ? null : $this->startSpeedAlarm($device, $location, $rule); //已经 没有上一个定位了(时间仍不够长),不用报警 } } return null; //轨迹点在区域里面,不用报警 } }
public function test8() { $point = array('latitude' => 39.915, 'longitude' => 116.404); $polygon = array(array('latitude' => 21.827688, 'longitude' => 90.279838), array('latitude' => 49.004931, 'longitude' => 114.269914), array('latitude' => 36.251841, 'longitude' => 126.780075), array('latitude' => 9.739644, 'longitude' => 128.546216), array('latitude' => 21.827688, 'longitude' => 90.279838)); echo "<pre>"; print_r(Geometry::geoPointPedalPolygon(39.915, 116.404, $polygon)); print_r(Geometry::geoPointDistancePolygon(39.915, 116.404, $polygon)); echo "</pre>"; }