public string BoundingBoxInfo(ObjectAnchorsBoundingBox boundingBox)
 {
     return
         ($"Center: {boundingBox.Center}\n" +
          $"Extents: {boundingBox.Extents}\n" +
          $"Orientation: {boundingBox.Orientation}");
 }
        /// <summary>
        /// creates queries around the user for all known models
        /// </summary>
        private void RefillGlobalQueryQueue()
        {
            Debug.Log("Prepping queries");
            // Then do a global query for any new objects
            ObjectAnchorsBoundingBox globalBoundingBox = new ObjectAnchorsBoundingBox();

            globalBoundingBox.Center      = _mainCamera.transform.position;
            globalBoundingBox.Extents     = Vector3.one * 5;
            globalBoundingBox.Orientation = _mainCamera.transform.rotation;
            QueueQueriesInBounds(globalBoundingBox);
        }
        /// <summary>
        /// Queues queries for all known models around the requested bounds
        /// </summary>
        /// <param name="queryBounds"></param>
        public void QueueQueriesInBounds(ObjectAnchorsBoundingBox queryBounds)
        {
            List <ObjectQuery> nextQuerySet = new List <ObjectQuery>();

            SpatialGraph.SpatialGraphCoordinateSystem?coordinateSystem = ObjectAnchorsWorldManager.GlobalCoordinateSystem;
            if (!coordinateSystem.HasValue)
            {
                Debug.LogError("no coordinate system?");
                return;
            }

            foreach (TrackableObjectData tod in _trackableObjectDataLoader.TrackableObjects)
            {
                ObjectQuery nextQuery = _objectAnchorsService.CreateObjectQuery(tod.ModelId);

                nextQuery.MaxScaleChange = MaxScaleChange;

                if (tod.UseCustomParameters)
                {
                    nextQuery.MinSurfaceCoverage = tod.MinSurfaceCoverage;
                    nextQuery.IsExpectedToBeStandingOnGroundPlane     = tod.IsExpectedToBeStandingOnGroundPlane;
                    nextQuery.ExpectedMaxVerticalOrientationInDegrees = tod.ExpectedMaxVerticalOrientationInDegrees;
                    nextQuery.MaxScaleChange = tod.MaxScaleChange;
                }
                else
                {
                    nextQuery.MinSurfaceCoverage *= CoverageThresholdFactor;
                    nextQuery.ExpectedMaxVerticalOrientationInDegrees = AllowedVerticalOrientationInDegrees;
                }

                nextQuery.SearchAreas.Add(ObjectSearchArea.FromOrientedBox(
                                              coordinateSystem.Value,
                                              queryBounds.ToOuSdk())
                                          );

                nextQuerySet.Add(nextQuery);
            }

            _queryQueue.Enqueue(new Tuple <ObjectAnchorsBoundingBox, IEnumerable <ObjectQuery> >(queryBounds, nextQuerySet));
            Debug.Log($"{Time.frameCount} next query size {nextQuerySet.Count} query queue size {_queryQueue.Count} max scale change {MaxScaleChange} AllowedVerticalOrientationInDegrees {AllowedVerticalOrientationInDegrees}");
        }
    private Task DetectObjectAsync(Microsoft.Azure.ObjectAnchors.SpatialGraph.SpatialGraphCoordinateSystem?coordinateSystem, ObjectAnchorsLocation cameraLocation)
    {
        //
        // Coordinate system may not be available at this time, try it later.
        //

        if (!coordinateSystem.HasValue)
        {
            return(Task.CompletedTask);
        }

        //
        // Get camera location and coordinate system.
        //

        var cameraForward           = cameraLocation.Orientation * Vector3.forward;
        var estimatedTargetLocation = new ObjectAnchorsLocation
        {
            Position    = cameraLocation.Position + cameraForward * SearchFrustumFarDistance * 0.5f,
            Orientation = Quaternion.Euler(0.0f, cameraLocation.Orientation.eulerAngles.y, 0.0f),
        };

        //
        // Remove detected objects far away from the camera.
        //

        foreach (var instance in _objectAnchorsService.TrackingResults)
        {
            var location = instance.Location;
            if (location.HasValue)
            {
                var modelBbox = _objectAnchorsService.GetModelBoundingBox(instance.ModelId);
                Debug.Assert(modelBbox.HasValue);

                // Compute the coordinate of instance bounding box center in Unity world.
                var instancePosition = location.Value.Position + location.Value.Orientation * modelBbox.Value.Center;

                var offset = instancePosition - cameraLocation.Position;

                if (offset.magnitude > SearchFrustumFarDistance * 1.5f)
                {
                    _objectAnchorsService.RemoveObjectInstance(instance.InstanceId);
                }
            }
        }

        //
        // Detect object(s) in field of view, bounding box, or sphere.
        //

        var objectQueries = new List <Microsoft.Azure.ObjectAnchors.ObjectQuery>();

        var trackingResults = _objectAnchorsService.TrackingResults;

        lock (_objectQueries)
            foreach (var objectQuery in _objectQueries)
            {
                var modelId = objectQuery.Key;
                var query   = objectQuery.Value.Query;

                //
                // Optionally skip a model detection if an instance is already found.
                //

                if (SearchSingleInstance)
                {
                    if (trackingResults.Where(r => r.ModelId == modelId).Count() > 0)
                    {
                        continue;
                    }
                }

                var modelBox = _objectAnchorsService.GetModelBoundingBox(modelId);
                Debug.Assert(modelBox.HasValue);

                query.SearchAreas.Clear();
                switch (SearchAreaShape)
                {
                case SearchAreaKind.Box:
                {
                    // Adapt bounding box size to model size. Note that Extents.z is model's height.
                    float modelXYSize = new Vector2(modelBox.Value.Extents.x, modelBox.Value.Extents.y).magnitude;

                    var boundingBox = new ObjectAnchorsBoundingBox
                    {
                        Center      = estimatedTargetLocation.Position,
                        Orientation = estimatedTargetLocation.Orientation,
                        Extents     = new Vector3(modelXYSize * SearchAreaScaleFactor, modelBox.Value.Extents.z * SearchAreaScaleFactor, modelXYSize * SearchAreaScaleFactor),
                    };

                    query.SearchAreas.Add(
                        Microsoft.Azure.ObjectAnchors.ObjectSearchArea.FromOrientedBox(
                            coordinateSystem.Value,
                            boundingBox.ToSpatialGraph()));
                    break;
                }

                case SearchAreaKind.FieldOfView:
                {
                    var fieldOfView = new ObjectAnchorsFieldOfView
                    {
                        Position    = cameraLocation.Position,
                        Orientation = cameraLocation.Orientation,
                        FarDistance = SearchFrustumFarDistance,
                        HorizontalFieldOfViewInDegrees = SearchFrustumHorizontalFovInDegrees,
                        AspectRatio = SearchFrustumAspectRatio,
                    };

                    query.SearchAreas.Add(
                        Microsoft.Azure.ObjectAnchors.ObjectSearchArea.FromFieldOfView(
                            coordinateSystem.Value,
                            fieldOfView.ToSpatialGraph()));
                    break;
                }

                case SearchAreaKind.Sphere:
                {
                    // Adapt sphere radius to model size.
                    float modelDiagonalSize = modelBox.Value.Extents.magnitude;

                    var sphere = new ObjectAnchorsSphere
                    {
                        Center = estimatedTargetLocation.Position,
                        Radius = modelDiagonalSize * 0.5f * SearchAreaScaleFactor,
                    };

                    query.SearchAreas.Add(
                        Microsoft.Azure.ObjectAnchors.ObjectSearchArea.FromSphere(
                            coordinateSystem.Value,
                            sphere.ToSpatialGraph()));
                    break;
                }
                }

                objectQueries.Add(query);
            }

        //
        // Pause a while if detection is not required.
        //

        if (objectQueries.Count == 0)
        {
            Thread.Sleep(100);

            return(Task.CompletedTask);
        }

        //
        // Run detection.
        //

        // Add event to the queue.
        _objectAnchorsEventQueue.Enqueue(
            new ObjectAnchorsServiceEvent
        {
            Kind = ObjectAnchorsServiceEventKind.DetectionAttempted,
            Args = null
        });

        return(_objectAnchorsService.DetectObjectAsync(objectQueries.ToArray()));
    }