示例#1
0
/**
  keep all the attributes of selected features in an array
*/
function BuildSelectionArray($featureReader, $layerName, $properties, $bComputedProperties, $srsLayer, $bNeedsTransform, $layerObj, $isLayerNameEncoded)
{
    $agf = new MgAgfReaderWriter();
    $srsFactory = new MgCoordinateSystemFactory();
    if ($isLayerNameEncoded) {
        // Add prefix to avoid layer name beginning with number
        // So $isLayerNameEncoded should be true when and only when the properties will be stored in session
        $layerName = GetEncodedLayerName($layerName);
    }
    $properties->{$layerName}->propertynames = array();
    $properties->{$layerName}->propertyvalues = array();
    $properties->{$layerName}->propertytypes = array();
    $properties->{$layerName}->numelements = 0;
    $properties->{$layerName}->values = array();
    $properties->{$layerName}->metadatanames = array();
    array_push($properties->{$layerName}->metadatanames, 'dimension');
    array_push($properties->{$layerName}->metadatanames, 'bbox');
    array_push($properties->{$layerName}->metadatanames, 'center');
    array_push($properties->{$layerName}->metadatanames, 'area');
    array_push($properties->{$layerName}->metadatanames, 'length');
    if (isset($_SESSION)) {
        $mappings = $_SESSION['property_mappings'][$layerObj->GetObjectId()];
        foreach ((array) $mappings as $name => $value) {
            $propType = $featureReader->GetPropertyType($name);
            array_push($properties->{$layerName}->propertynames, $name);
            array_push($properties->{$layerName}->propertyvalues, $value);
            array_push($properties->{$layerName}->propertytypes, $propType);
        }
    }
    $srsTarget = null;
    $srsXform = null;
    while ($featureReader->ReadNext()) {
        $properties->{$layerName}->values[$properties->{$layerName}->numelements] = array();
        $properties->{$layerName}->metadata[$properties->{$layerName}->numelements] = array();
        $dimension = '';
        $bbox = '';
        $center = '';
        $area = '';
        $length = '';
        if ($bComputedProperties) {
            $classDef = $featureReader->GetClassDefinition();
            $geomName = $classDef->GetDefaultGeometryPropertyName();
            if ($geomName != '') {
                $geomByteReader = $featureReader->GetGeometry($geomName);
                /* is this needed? We declare one outside the loop too?*/
                $agf = new MgAgfReaderWriter();
                $geom = $agf->Read($geomByteReader);
                $envelope = $geom->Envelope();
                $ll = $envelope->GetLowerLeftCoordinate();
                $ur = $envelope->GetUpperRightCoordinate();
                $bbox = $ll->GetX() . ',' . $ll->GetY() . ',' . $ur->GetX() . ',' . $ur->GetY();
                $centroid = $geom->GetCentroid()->GetCoordinate();
                $center = $centroid->GetX() . ',' . $centroid->GetY();
                /* 0 = point, 1 = curve, 2 = surface */
                $dimension = $geom->GetDimension();
                if ($geom->GetDimension() > 0) {
                    //conver the geometry to UTM auto so that local measurements
                    //are accruate in meters
                    if ($bNeedsTransform && $srsTarget == null && $srsXform == null) {
                        $wkt = getUtmWkt($centroid->GetX(), $centroid->GetY());
                        $srsTarget = $srsFactory->Create($wkt);
                        $verMajor = subStr(GetSiteVersion(), 0, 1);
                        if ($verMajor == '1') {
                            $srsXform = new MgCoordinateSystemTransform($srsLayer, $srsTarget);
                        } else {
                            $srsXform = $srsFactory->GetTransform($srsLayer, $srsTarget);
                        }
                    }
                    if ($srsXform != null) {
                        try {
                            $ageom = $geom->Transform($srsXform);
                            $geom = $ageom;
                        } catch (MgException $ee) {
                            echo "/*transform exception:";
                            echo "ERROR: " . $ee->GetExceptionMessage() . "\n";
                            echo $ee->GetDetails() . "\n*/";
                        }
                    }
                    if ($geom->GetDimension() > 1) {
                        $area = $geom->GetArea();
                    }
                    if ($geom->GetDimension() > 0) {
                        $length = $geom->GetLength();
                    }
                }
            }
        }
        array_push($properties->{$layerName}->metadata[$properties->{$layerName}->numelements], $dimension);
        array_push($properties->{$layerName}->metadata[$properties->{$layerName}->numelements], $bbox);
        array_push($properties->{$layerName}->metadata[$properties->{$layerName}->numelements], $center);
        array_push($properties->{$layerName}->metadata[$properties->{$layerName}->numelements], $area);
        array_push($properties->{$layerName}->metadata[$properties->{$layerName}->numelements], $length);
        $numproperties = count($properties->{$layerName}->propertynames);
        for ($j = 0; $j < $numproperties; $j++) {
            $propname = $properties->{$layerName}->propertynames[$j];
            $value = GetPropertyValueFromFeatReader($featureReader, $properties->{$layerName}->propertytypes[$j], $propname);
            $value = htmlentities($value, ENT_COMPAT, 'UTF-8');
            $value = addslashes($value);
            $value = preg_replace("/\r?\n/", "<br>", $value);
            array_push($properties->{$layerName}->values[$properties->{$layerName}->numelements], $value);
            //$properties->$layerName->values[$properties->$layerName->numelements][$propname] = $value;
        }
        $properties->{$layerName}->numelements = $properties->{$layerName}->numelements + 1;
    }
    return $properties;
}
示例#2
0
文件: Query.php 项目: kanbang/Colt
     $spatialContext = $featureService->GetSpatialContexts($featureResId, true);
     $srsLayerWkt = false;
     if ($spatialContext != null && $spatialContext->ReadNext() != null) {
         $srsLayerWkt = $spatialContext->GetCoordinateSystemWkt();
         /* skip this layer if the srs is empty */
     }
     if ($srsLayerWkt == null) {
         $srsLayerWkt = $srsDefMap;
     }
     /* create a coordinate system from the layer's SRS wkt */
     $srsLayer = $srsFactory->Create($srsLayerWkt);
     $verMajor = subStr(GetSiteVersion(), 0, 1);
     if ($verMajor == '1') {
         $srsXform = new MgCoordinateSystemTransform($srsMap, $srsLayer);
     } else {
         $srsXform = $srsFactory->GetTransform($srsMap, $srsLayer);
     }
     $wktRW = new MgWktReaderWriter();
     $geom = $wktRW->Read($spatialFilter, $srsXform);
     $queryOptions->SetSpatialFilter($featureGeometryName, $geom, $variant);
 }
 /* select the features */
 try {
     $featureReader = $featureService->SelectFeatures($featureResId, $class, $queryOptions);
 } catch (MgException $e) {
     echo "ERROR2: " . $e->GetExceptionMessage() . "\n";
     echo $e->GetDetails() . "\n";
     echo $e->GetStackTrace() . "\n";
 }
 $layerName = $layerObj->GetName();
 array_push($properties->layers, $layerName);
示例#3
0
 function GetTransform()
 {
     $coordSysFactory = new MgCoordinateSystemFactory();
     $resourceService = $this->site->CreateService(MgServiceType::ResourceService);
     $featureService = $this->site->CreateService(MgServiceType::FeatureService);
     $featureSourceId = $this->GetFeatureSource();
     $wkt = null;
     //Get the WKT from spatial context, because SDF only supports one spatial context it will be the first one
     $scReader = $featureService->GetSpatialContexts($featureSourceId, true);
     if ($scReader->ReadNext()) {
         $wkt = $scReader->GetCoordinateSystemWkt();
     }
     $scReader->Close();
     $map = new MgMap();
     $map->Open($resourceService, $this->args['MAPNAME']);
     if (null == $wkt) {
         return null;
     }
     //It's bunk. Assume map SRS
     if (strcmp($wkt, $map->GetMapSRS()) == 0) {
         return null;
     }
     //Identical. No transformation needed
     $source = $coordSysFactory->Create($map->GetMapSRS());
     if (null != $wkt) {
         $target = $coordSysFactory->Create($wkt);
     }
     return $coordSysFactory->GetTransform($source, $target);
 }
示例#4
0
    function Execute()
    {
        $result = array();

        $map = new MgMap($this->site);
        $map->Open($this->args['MAPNAME']);
        $layers = $map->GetLayers();
        $layer = $layers->GetItem($this->args['LAYERNAME']);

        $featureService = $this->site->CreateService(MgServiceType::FeatureService);
        $resId = new MgResourceIdentifier($layer->GetFeatureSourceId());
        $featureClass = $layer->GetFeatureClassName();
        $filter = $layer->GetFilter();
        $featureGeometry = $layer->GetFeatureGeometryName();

        // Initialize the coordinate system transform

        $classDef = $layer->GetClassDefinition();
        $clsProps = $classDef->GetProperties();
        $geomProp = $clsProps->GetItem($featureGeometry);
        $spatialContext = $geomProp->GetSpatialContextAssociation();

        $csTransform = null;
        $csInverseTransform = null;
        $coordSysFactory = new MgCoordinateSystemFactory();

        $scReader = $featureService->GetSpatialContexts($resId, false);
        while ($scReader->ReadNext() && $csTransform == null)
        {
            if ($scReader->GetName() == $spatialContext)
            {
                $sourceCs = $scReader->GetCoordinateSystemWkt();
                $targetCs = $map->GetMapSRS();
                if($sourceCs != '' && $targetCs != '')
                {
                    $source = $coordSysFactory->Create($sourceCs);
                    $target = $coordSysFactory->Create($targetCs);
                    $csTransform = $coordSysFactory->GetTransform($source, $target);
                    $csInverseTransform = $coordSysFactory->GetTransform($target, $source);
                }
            }
        }
        $scReader->Close();

        // Execute the query

        $queryMax = (int) $this->args['QUERYMAX'];
        $queryOptions = new MgFeatureQueryOptions();

        $propertyFilter = '';
        if ($this->args['USEPROPERTYFILTER'] == 'true')
        {
            $propertyFilter = $this->args['PROPERTYNAME'];
            if ($this->args['ISSTRING'] == 'true')
                $propertyFilter .= sprintf($this->strExpressions[$this->args['OPERATOR']], $this->args['VALUE']);
            else
                $propertyFilter .= sprintf($this->numExpressions[$this->args['OPERATOR']], $this->args['VALUE']);

            if($filter != '')
                $propertyFilter = $propertyFilter . ' AND (' . $filter . ')';
        }
        else
        {
            if($filter != '')
                $propertyFilter = $filter;
        }
        if($propertyFilter != '')
            $queryOptions->SetFilter($propertyFilter);

        if ($this->args['USESPATIALFILTER'] == 'true')
        {
            $polygon = $this->CreatePolygonFromGeomText($this->args['GEOMTEXT']);
            if ($csInverseTransform)
                $polygon = $polygon->Transform($csInverseTransform);

            $queryOptions->SetSpatialFilter($featureGeometry, $polygon, MgFeatureSpatialOperations::Intersects);
        }

        $count = 0;
        $geometryReaderWriter = new MgAgfReaderWriter();
        $featureReader = $layer->SelectFeatures($queryOptions);
        while ($featureReader->ReadNext() && ($queryMax <= 0 || $count < $queryMax))
        {
            $displayValue = $this->GetFeaturePropertyValue($featureReader, $this->args['OUTPUTPROPERTY']);

            $byteReader = $featureReader->GetGeometry($featureGeometry);
            $geometry = $geometryReaderWriter->Read($byteReader);
            $centerPoint = $geometry->GetCentroid();
            if ($csTransform)
                $centerPoint = $centerPoint->Transform($csTransform);

            $idList = $this->GetFeatureIdList($map, $layer, $featureReader);

            array_push($result, new Feature($displayValue, $centerPoint, $idList));
            $count++;
        }

        return $result;
    }
示例#5
0
 public static function GetFeatureClassMBR($app, $featureSrvc, $featuresId, $schemaName, $className, $geomName = null, $transformToCsCode = null)
 {
     $extentGeometryAgg = null;
     $extentGeometrySc = null;
     $extentByteReader = null;
     $mbr = new stdClass();
     $csFactory = new MgCoordinateSystemFactory();
     $clsDef = $featureSrvc->GetClassDefinition($featuresId, $schemaName, $className);
     $props = $clsDef->GetProperties();
     if ($geomName == null) {
         $geomName = $clsDef->GetDefaultGeometryPropertyName();
     }
     $geomProp = $props->GetItem($geomName);
     if ($geomProp->GetPropertyType() != MgFeaturePropertyType::GeometricProperty) {
         throw new Exception($app->localizer->getText("E_NOT_GEOMETRY_PROPERTY", $geomName));
     }
     $spatialContext = $geomProp->GetSpatialContextAssociation();
     // Finds the coordinate system
     $agfReaderWriter = new MgAgfReaderWriter();
     $spatialcontextReader = $featureSrvc->GetSpatialContexts($featuresId, false);
     while ($spatialcontextReader->ReadNext()) {
         if ($spatialcontextReader->GetName() == $spatialContext) {
             $mbr->coordinateSystem = $spatialcontextReader->GetCoordinateSystemWkt();
             $mbr->csCode = $csFactory->ConvertWktToCoordinateSystemCode($mbr->coordinateSystem);
             $mbr->epsg = $csFactory->ConvertWktToEpsgCode($mbr->coordinateSystem);
             // Finds the extent
             $extentByteReader = $spatialcontextReader->GetExtent();
             break;
         }
     }
     $spatialcontextReader->Close();
     if ($extentByteReader != null) {
         // Get the extent geometry from the spatial context
         $extentGeometrySc = $agfReaderWriter->Read($extentByteReader);
     }
     // Try to get the extents using the selectaggregate as sometimes the spatial context
     // information is not set
     $aggregateOptions = new MgFeatureAggregateOptions();
     $featureProp = 'SPATIALEXTENTS("' . $geomName . '")';
     $aggregateOptions->AddComputedProperty('EXTENTS', $featureProp);
     try {
         $dataReader = $featureSrvc->SelectAggregate($featuresId, $className, $aggregateOptions);
         if ($dataReader->ReadNext()) {
             // Get the extents information
             $byteReader = $dataReader->GetGeometry('EXTENTS');
             $extentGeometryAgg = $agfReaderWriter->Read($byteReader);
         }
         $dataReader->Close();
     } catch (MgException $e) {
         if ($extentGeometryAgg == null) {
             //We do have one last hope. EXTENT() is an internal MapGuide custom function that's universally supported
             //as it operates against an underlying select query result. This raw-spins the reader server-side so there
             //is no server -> web tier transmission overhead involved.
             try {
                 $aggregateOptions = new MgFeatureAggregateOptions();
                 $aggregateOptions->AddComputedProperty("COMP_EXTENT", "EXTENT(" . $geomName . ")");
                 $dataReader = $featureSrvc->SelectAggregate($featuresId, $className, $aggregateOptions);
                 if ($dataReader->ReadNext()) {
                     // Get the extents information
                     $byteReader = $dataReader->GetGeometry('COMP_EXTENT');
                     $extentGeometryAgg = $agfReaderWriter->Read($byteReader);
                 }
                 $dataReader->Close();
             } catch (MgException $e2) {
             }
         }
     }
     $mbr->extentGeometry = null;
     // Prefer SpatialExtents() of EXTENT() result over spatial context extent
     if ($extentGeometryAgg != null) {
         $mbr->extentGeometry = $extentGeometryAgg;
     }
     if ($mbr->extentGeometry == null) {
         //Stil null? Now try spatial context
         if ($extentGeometrySc != null) {
             $mbr->extentGeometry = $extentGeometrySc;
         }
     }
     if ($transformToCsCode != null) {
         $sourceCs = $csFactory->CreateFromCode($mbr->csCode);
         $targetCs = $csFactory->CreateFromCode($transformToCsCode);
         $xform = $csFactory->GetTransform($sourceCs, $targetCs);
         $mbr->extentGeometry = $mbr->extentGeometry->Transform($xform);
         $mbr->csCode = $targetCs->GetCsCode();
         $mbr->epsg = $targetCs->GetEpsgCode();
     }
     return $mbr;
 }
 private function _GetKmlForMap($map, $sessionId, $format = "kml", $chunk = "1")
 {
     if ($chunk === "0") {
         $writer = new MgSlimChunkWriter($this->app);
     } else {
         $writer = new MgHttpChunkWriter();
     }
     $doc = new MgKmlDocument($writer);
     $csFactory = new MgCoordinateSystemFactory();
     $doc->StartDocument();
     $doc->WriteString("<visibility>1</visibility>");
     $layers = $map->GetLayers();
     $extent = $map->GetMapExtent();
     if ($extent != NULL) {
         $wkt = $map->GetMapSRS();
         if ($wkt != NULL && strlen($wkt) > 0) {
             $mapCs = $csFactory->Create($wkt);
             $llCs = $csFactory->CreateFromCode("LL84");
             $trans = $csFactory->GetTransform($mapCs, $llCs);
             $trans->IgnoreDatumShiftWarning(true);
             $trans->IgnoreOutsideDomainWarning(true);
             $extent = $trans->Transform($extent);
         }
     }
     $numLayers = $layers->GetCount();
     for ($i = 0; $i < $numLayers; $i++) {
         $layer = $layers->GetItem($i);
         $this->AppendLayer($layer, $extent, $numLayers - $i, $format, $sessionId, $writer);
     }
     $doc->EndDocument();
 }
示例#7
0
function GetLayerToMapCSTrans($classDef, $geomPropName, $featureSrvc, $fsId, $map)
{
    $props = $classDef->GetProperties();
    $geomProp = $props->GetItem($geomPropName);
    $scAssociation = $geomProp->GetSpatialContextAssociation();
    $csrdr = $featureSrvc->GetSpatialContexts($fsId, false);
    $layerwkt = '';
    
    while($csrdr->ReadNext())
    {
        $csrName = $csrdr->GetName();
        if($csrName == $scAssociation)
        {
            // Match found for the association
            $layerwkt = $csrdr->GetCoordinateSystemWkt();
            break;
        }
    }
    $csrdr->Close();
    $cf = new MgCoordinateSystemFactory();
    $layerCS = $cf->Create($layerwkt);
    $mapCS = $cf->Create($map->GetMapSRS());
    $trans = $cf->GetTransform ($layerCS, $mapCS);
    
    return $trans;
}
示例#8
0
文件: buffer.php 项目: kanbang/Colt
 if ($arbitraryDsSrs != $arbitraryMapSrs || $arbitraryDsSrs && $dsSrsUnits != $mapSrsUnits) {
     $excludedLayers++;
     continue;
 }
 // calculate distance in the data source SRS units
 //
 $dist = $srsDs->ConvertMetersToCoordinateSystemUnits($distance);
 // calculate great circle unless data source srs is arbitrary
 if (!$arbitraryDsSrs) {
     $measure = $srsDs->GetMeasure();
 } else {
     $measure = null;
 }
 // create a SRS transformer if necessary.
 if ($srsDefDs != $srsDefMap) {
     $srsXform = $srsFactory->GetTransform($srsDs, $srsMap);
 } else {
     $srsXform = null;
 }
 $featureClassName = $selLayer->GetFeatureClassName();
 $filter = $sel->GenerateFilter($selLayer, $featureClassName);
 if ($filter == "") {
     continue;
 }
 $query = new MgFeatureQueryOptions();
 $query->SetFilter($filter);
 $featureSource = new MgResourceIdentifier($selLayer->GetFeatureSourceId());
 $features = $featureSrvc->SelectFeatures($featureSource, $featureClassName, $query);
 if ($features->ReadNext()) {
     $classDef = $features->GetClassDefinition();
     $geomPropName = $classDef->GetDefaultGeometryPropertyName();
示例#9
0
文件: Buffer.php 项目: alonso/fusion
 $verMajor = subStr(GetSiteVersion(), 0, 1);
 if (!$arbitraryDsSrs) {
     if ($verMajor == '1') {
         $measure = new MgCoordinateSystemMeasure($layerCs);
     } else {
         $measure = $layerCs->GetMeasure();
     }
 } else {
     $measure = null;
 }
 // create a SRS transformer if necessary.
 if ($layerSrsWkt != $srsDefMap) {
     if ($verMajor == '1') {
         $srsXform = new MgCoordinateSystemTransform($layerCs, $srsMap);
     } else {
         $srsXform = $srsFactory->GetTransform($layerCs, $srsMap);
     }
 } else {
     $srsXform = null;
 }
 while ($featureReader->ReadNext()) {
     $oGeomAgf = $featureReader->GetGeometry($geomPropName);
     $oGeom = $agfRW->Read($oGeomAgf);
     $wktReaderWriter = new MgWktReaderWriter();
     $agfTextPoint = $wktReaderWriter->Write($oGeom);
     //echo "<!-- wkt: ".$agfTextPoint." -->\n";
     if (!$merge) {
         /* use measure to accomodate differences in SRS */
         $oNewGeom = $oGeom->Buffer($dist, $measure);
         $geomProp = new MgGeometryProperty("GEOM", $agfRW->Write($oNewGeom));
         $oPropertyColl = new MgPropertyCollection();
 public function GetTileXYZ($resId, $groupName, $x, $y, $z, $type, $layerNames = NULL)
 {
     $fmt = $this->ValidateRepresentation($type, array("json", "png", "png8", "jpg", "gif"));
     $path = self::GetTilePath($this->app, $resId, $groupName, $z, $x, $y, $type, $layerNames);
     clearstatcache();
     $dir = dirname($path);
     $lockPath = "{$dir}/lock_" . $y . ".lck";
     $attempts = 0;
     while (!@is_dir($dir)) {
         try {
             mkdir($dir, 0777, true);
         } catch (Exception $e) {
             //Another tile request may have already created this since
             $attempts++;
             //Bail after MAX_RETRY_ATTEMPTS
             if ($attempts >= self::MAX_RETRY_ATTEMPTS) {
                 $this->ServerError($this->app->localizer->getText("E_FAILED_TO_CREATE_DIR_AFTER_N_ATTEMPTS", $attempts), $this->GetMimeTypeForFormat($type));
             }
         }
     }
     //If there's a dangling lock file, attempt to remove it
     if (file_exists($lockPath)) {
         unlink($lockPath);
     }
     $fpLockFile = fopen($lockPath, "a+");
     //Message of any exception caught will be set to this variable
     $tileError = null;
     $requestId = rand();
     $this->app->log->debug("({$requestId}) Checking if {$path} exists");
     $attempts = 0;
     while (!file_exists($path)) {
         //Bail after MAX_RETRY_ATTEMPTS
         if ($attempts >= self::MAX_RETRY_ATTEMPTS) {
             $this->ServerError($this->app->localizer->getText("E_FAILED_TO_GENERATE_TILE_AFTER_N_ATTEMPTS", $attempts), $this->GetMimeTypeForFormat($type));
         }
         $attempts++;
         $this->app->log->debug("({$requestId}) {$path} does not exist. Locking for writing");
         $bLocked = false;
         flock($fpLockFile, LOCK_EX);
         fwrite($fpLockFile, ".");
         $bLocked = true;
         $this->app->log->debug("({$requestId}) Acquired lock for {$path}. Checking if path exists again.");
         //check once more to see if the cache file was created while waiting for
         //the lock
         clearstatcache();
         if (!file_exists($path)) {
             try {
                 $this->app->log->debug("({$requestId}) Rendering tile to {$path}");
                 $bOldPath = true;
                 if ($type != "json") {
                     //if this is MGOS 3.0 and we're dealing with a tile set, we invoke GETTILEIMAGE as that we can pass in Tile Set Definition
                     //resource ids without issues. We cannot create MgMaps from Tile Set Definitions that are not using the default tile provider.
                     //
                     //The given tile set is assumed to be using the XYZ provider, the case where the Tile Set Definition is using the default provider
                     //is not handled
                     if ($this->app->MG_VERSION[0] >= 3 && $resId->GetResourceType() == "TileSetDefinition") {
                         $bOldPath = false;
                         $sessionId = "";
                         if ($resId->GetRepositoryType() === MgRepositoryType::Session && $this->app->request->get("session") == null) {
                             $sessionId = $resId->GetRepositoryName();
                         }
                         $resIdStr = $resId->ToString();
                         $that = $this;
                         $this->EnsureAuthenticationForHttp(function ($req, $param) use($that, $resIdStr, $groupName, $x, $y, $z, $requestId, $path) {
                             $param->AddParameter("OPERATION", "GETTILEIMAGE");
                             $param->AddParameter("VERSION", "1.2.0");
                             $param->AddParameter("MAPDEFINITION", $resIdStr);
                             $param->AddParameter("BASEMAPLAYERGROUPNAME", $groupName);
                             $param->AddParameter("SCALEINDEX", $z);
                             $param->AddParameter("TILEROW", $x);
                             $param->AddParameter("TILECOL", $y);
                             $that->app->log->debug("({$requestId}) Executing GETTILEIMAGE");
                             $that->ExecuteHttpRequest($req, function ($result, $status) use($path) {
                                 if ($status == 200) {
                                     //Need to dump the rendered tile to the specified path so the caching stuff below can still do its thing
                                     $resultObj = $result->GetResultObject();
                                     $sink = new MgByteSink($resultObj);
                                     $sink->ToFile($path);
                                 }
                             });
                         }, true, "", $sessionId);
                         //Tile access can be anonymous, so allow for it if credentials/session specified, but if this is a session-based Map Definition, use the session id as the nominated one
                     }
                 }
                 //Pre MGOS 3.0 code path
                 if ($bOldPath) {
                     $this->app->log->debug("({$requestId}) Going down old code path");
                     $this->EnsureAuthenticationForSite("", true);
                     $siteConn = new MgSiteConnection();
                     $siteConn->Open($this->userInfo);
                     $map = new MgMap($siteConn);
                     $map->Create($resId, "VectorTileMap");
                     $renderSvc = $siteConn->CreateService(MgServiceType::RenderingService);
                     $groups = $map->GetLayerGroups();
                     $baseGroup = $groups->GetItem($groupName);
                     //Will throw MgObjectNotFoundException -> 404 if no such group exists
                     $factory = new MgCoordinateSystemFactory();
                     $mapCsWkt = $map->GetMapSRS();
                     $mapCs = $factory->Create($mapCsWkt);
                     $mapExtent = $map->GetMapExtent();
                     $mapExLL = $mapExtent->GetLowerLeftCoordinate();
                     $mapExUR = $mapExtent->GetUpperRightCoordinate();
                     $metersPerUnit = $mapCs->ConvertCoordinateSystemUnitsToMeters(1.0);
                     $this->app->log->debug("({$requestId}) Calc bounds from XYZ");
                     //XYZ to lat/lon math. From this we can convert to the bounds in the map's CS
                     //
                     //Source: http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
                     $n = pow(2, $z);
                     $lonMin = $x / $n * 360.0 - 180.0;
                     $latMin = rad2deg(atan(sinh(pi() * (1 - 2 * $y / $n))));
                     $lonMax = ($x + 1) / $n * 360.0 - 180.0;
                     $latMax = rad2deg(atan(sinh(pi() * (1 - 2 * ($y + 1) / $n))));
                     $boundsMinX = min($lonMin, $lonMax);
                     $boundsMinY = min($latMin, $latMax);
                     $boundsMaxX = max($lonMax, $lonMin);
                     $boundsMaxY = max($latMax, $latMin);
                     if ($mapCs->GetCsCode() != "LL84") {
                         $llCs = $factory->CreateFromCode("LL84");
                         $trans = $factory->GetTransform($llCs, $mapCs);
                         $ul = $trans->Transform($lonMin, $latMin);
                         $lr = $trans->Transform($lonMax, $latMax);
                         $boundsMinX = min($lr->GetX(), $ul->GetX());
                         $boundsMinY = min($lr->GetY(), $ul->GetY());
                         $boundsMaxX = max($lr->GetX(), $ul->GetX());
                         $boundsMaxY = max($lr->GetY(), $ul->GetY());
                     }
                     //Set all layers under group to be visible
                     $layers = $map->GetLayers();
                     $layerCount = $layers->GetCount();
                     $groupCount = $groups->GetCount();
                     //Turn all groups that are not the given group to be hidden
                     for ($i = 0; $i < $groupCount; $i++) {
                         $group = $groups->GetItem($i);
                         if ($group->GetName() != $groupName) {
                             $group->SetVisible(false);
                         } else {
                             $group->SetVisible(true);
                         }
                     }
                     for ($i = 0; $i < $layerCount; $i++) {
                         $layer = $layers->GetItem($i);
                         $group = $layer->GetGroup();
                         if (null == $group) {
                             continue;
                         }
                         if ($group->GetName() != $groupName && $layer->GetLayerType() == MgLayerType::Dynamic) {
                             $layer->SetVisible(false);
                             continue;
                         }
                         if ($layer->GetLayerType() == MgLayerType::Dynamic) {
                             $layer->SetVisible(true);
                         }
                     }
                     if ($type == "json") {
                         //error_log("($requestId) Render vector tile");
                         $this->PutVectorTileXYZ($map, $groupName, $siteConn, $metersPerUnit, $factory, $path, $boundsMinX, $boundsMinY, $boundsMaxX, $boundsMaxY, $layerNames);
                     } else {
                         $format = strtoupper($type);
                         //error_log("($requestId) Render image tile");
                         $this->PutTileImageXYZ($map, $groupName, $renderSvc, $path, $format, $boundsMinX, $boundsMinY, $boundsMaxX, $boundsMaxY, $layerNames, $requestId);
                     }
                 }
             } catch (MgException $ex) {
                 if ($bLocked) {
                     $this->app->log->debug("({$requestId}) MgException caught " . $ex->GetDetails() . "\n" . $ex->getTraceAsString() . "\n. Releasing lock for {$path}");
                     $tileError = $ex->GetExceptionMessage();
                     flock($fpLockFile, LOCK_UN);
                     $bLocked = false;
                 }
                 if ($ex instanceof MgResourceNotFoundException || $ex instanceof MgObjectNotFoundException) {
                     $this->NotFound($ex->GetExceptionMessage(), $this->GetMimeTypeForFormat($fmt));
                 } else {
                     if ($ex instanceof MgConnectionFailedException) {
                         $this->ServiceUnavailable($ex->GetExceptionMessage(), $this->GetMimeTypeForFormat($fmt));
                     }
                 }
             } catch (Exception $ex) {
                 if ($bLocked) {
                     $tileError = get_class($ex) . " - " . $ex->getMessage();
                     $this->app->log->debug("({$requestId}) Exception caught ({$tileError}). Releasing lock for {$path}");
                     flock($fpLockFile, LOCK_UN);
                     $bLocked = false;
                 }
             }
         }
         if ($bLocked) {
             $this->app->log->debug("({$requestId}) Releasing lock for {$path}");
             flock($fpLockFile, LOCK_UN);
             $bLocked = false;
         }
     }
     //An exception occurred, try to clean up lock before bailing
     if ($tileError != null) {
         try {
             fclose($fpLockFile);
             unlink($lockPath);
         } catch (Exception $ex) {
             $this->app->log->debug("({$requestId}) Failed to delete lock file. Perhaps another concurrent request to the same tile is happening?");
         }
         throw new Exception($tileError);
     }
     $modTime = filemtime($path);
     $this->app->lastModified($modTime);
     $this->app->log->debug("({$requestId}) Acquiring shared lock for {$path}");
     //acquire shared lock for reading to prevent a problem that could occur
     //if a tile exists but is only partially generated.
     flock($fpLockFile, LOCK_SH);
     $this->app->log->debug("({$requestId}) Outputting {$path}");
     $ext = strtoupper(pathinfo($path, PATHINFO_EXTENSION));
     $mimeType = "";
     switch ($ext) {
         case "PNG":
             //MgImageFormats::Png:
             $mimeType = MgMimeType::Png;
             break;
         case "GIF":
             //MgImageFormats::Gif:
             $mimeType = MgMimeType::Gif;
             break;
         case "JPG":
             //MgImageFormats::Jpeg:
             $mimeType = MgMimeType::Jpeg;
             break;
         case "JSON":
             $mimeType = MgMimeType::Json;
             break;
     }
     $this->app->response->header("Content-Type", $mimeType);
     $this->app->expires("+6 months");
     $this->app->response->header("Cache-Control", "max-age=31536000, must-revalidate");
     $this->app->response->setBody(file_get_contents($path));
     $this->app->log->debug("({$requestId}) Releasing shared lock for {$path}");
     //Release lock
     flock($fpLockFile, LOCK_UN);
     //Try to delete the lock file
     try {
         fclose($fpLockFile);
         unlink($lockPath);
     } catch (Exception $ex) {
         $this->app->log->debug("({$requestId}) Failed to delete lock file. Perhaps another concurrent request to the same tile is happening?");
     }
 }
 public function TransformCoordinates()
 {
     $source = $this->app->request->post("from");
     $target = $this->app->request->post("to");
     $coordList = $this->app->request->post("coords");
     $format = $this->app->request->post("format");
     if ($format == null) {
         $format = "xml";
     }
     $fmt = $this->ValidateRepresentation($format, array("xml", "json"));
     if ($source == null) {
         $this->BadRequest($this->app->localizer->getText("E_MISSING_REQUIRED_PARAMETER", "from"), $this->GetMimeTypeForFormat($format));
     }
     if ($target == null) {
         $this->BadRequest($this->app->localizer->getText("E_MISSING_REQUIRED_PARAMETER", "to"), $this->GetMimeTypeForFormat($format));
     }
     if ($coordList == null) {
         $this->BadRequest($this->app->localizer->getText("E_MISSING_REQUIRED_PARAMETER", "coords"), $this->GetMimeTypeForFormat($format));
     }
     try {
         $factory = new MgCoordinateSystemFactory();
         $sourceCs = $factory->CreateFromCode($source);
         $targetCs = $factory->CreateFromCode($target);
         $trans = $factory->GetTransform($sourceCs, $targetCs);
         $coords = explode(",", $coordList);
         $output = "<?xml version=\"1.0\" encoding=\"utf-8\"?><CoordinateCollection>";
         foreach ($coords as $coordPair) {
             $tokens = explode(" ", trim($coordPair));
             $tokenCount = count($tokens);
             if ($tokenCount === 2) {
                 $txCoord = $trans->Transform(floatval($tokens[0]), floatval($tokens[1]));
                 $output .= "<Coordinate><X>" . $txCoord->GetX() . "</X><Y>" . $txCoord->GetY() . "</Y></Coordinate>";
             } else {
                 //TODO: We should accept a partial response, but there's currently no way an empty <Coordinate/> tag survives the
                 //XML to JSON conversion, so we have to throw lest we return an inconsisten partial result
                 $this->ServerError($this->app->localizer->getText("E_INVALID_COORDINATE_PAIR", $coordPair, $tokenCount), $this->GetMimeTypeForFormat($format));
             }
         }
         $output .= "</CoordinateCollection>";
         if ($fmt === "json") {
             $this->app->response->header("Content-Type", MgMimeType::Json);
             $json = MgUtils::Xml2Json($output);
             $this->app->response->write($json);
         } else {
             $this->app->response->header("Content-Type", MgMimeType::Xml);
             $this->app->response->write($output);
         }
     } catch (MgException $ex) {
         $this->OnException($ex, $this->GetMimeTypeForFormat($format));
     }
 }