Example #1
0
        //public override Vector3 GetNormal(Point3 pos) { return new Vector3((pos - _centre) * _rRadius); }

        public override IntersectResult Intersect(Ray ray, out Ray intersect, out float dist)
        {
            IntersectResult ret = IntersectResult.MISS;

            dist      = 0;
            intersect = null;
            Vector3 v   = new Vector3(ray.Origin - _centre);
            float   b   = -v.Dot(ray.Direction);
            float   det = (b * b) - v.Dot(v) + _sqRadius;

            if (det > 0)
            {
                det = (float)Math.Sqrt(det);
                float i1 = b - det;
                float i2 = b + det;
                if (i2 > 0)
                {
                    if (i1 < 0)
                    {
                        dist = i2;
                        ret  = IntersectResult.INPRIM;
                    }
                    else
                    {
                        dist = i1;
                        ret  = IntersectResult.HIT;
                    }
                    Point3 pt = new Point3(ray.Origin + ray.Direction * dist);
                    intersect = new Ray(pt,
                                        new Vector3((pt - _centre) * _rRadius));
                }
            }
            return(ret);
        }
        public bool findNearest(Ray ray, double farDistance, out double nearest, out Triangle target, out Collision collision)
        {
            nearest = double.PositiveInfinity;
            target  = new Triangle();

            IntersectResult result = new IntersectResult();
            var             found  = false;

            foreach (var primitive in primitives)
            {
                IntersectResult tmpResult;
                if (primitive.intersect(ray, out tmpResult) && Constant.EPSILON < tmpResult.t && tmpResult.t < nearest)
                {
                    result  = tmpResult;
                    nearest = tmpResult.t;
                    target  = primitive;
                    found   = true;
                }
            }

            collision = new Collision();
            if (found)
            {
                collision = new Collision(ray.origin + result.t * ray.direction, -ray.direction, target.getNormal(result.u, result.v));
            }

            return(found);
        }
Example #3
0
        public IntersectResult Intersect(Ray3 ray, double maxDistance)
        {
            if (!BoundingBox.Intersect(ray, maxDistance))
            {
                return(IntersectResult.NoHit());
            }
            double          minDistance = maxDistance;
            IntersectResult minResult   = IntersectResult.NoHit();

            if (nodeTriangles != null)
            {
                foreach (var triangle in nodeTriangles)
                {
                    IntersectResult result = triangle.Intersect(ray, minDistance);
                    if (result.Geometry != null && result.Distance < minDistance)
                    {
                        minDistance = result.Distance;
                        minResult   = result;
                    }
                }
            }
            if (children != null)
            {
                foreach (var child in children)
                {
                    IntersectResult result = child.Intersect(ray, minDistance);
                    if (result.Geometry != null && result.Distance < minDistance)
                    {
                        minDistance = result.Distance;
                        minResult   = result;
                    }
                }
            }
            return(minResult);
        }
Example #4
0
        public IntersectResult Intersect(Ray3 ray, double maxDistance)
        {
            if (!BoundingBox.Intersect(ray, maxDistance))
            {
                return(IntersectResult.NoHit());
            }
            if (normal.SqrLength() == 0)
            {
                return(IntersectResult.NoHit());
            }
            Vector3 w0       = ray.Origin - vertices[0];
            double  x        = -normal ^ w0;
            double  y        = normal ^ ray.Direction;
            double  distance = x / y;

            if (y == 0 || distance < 0)
            {
                return(IntersectResult.NoHit());
            }
            Vector3 position = ray.GetPoint(distance);
            double  uu       = edgeAB ^ edgeAB;
            double  uv       = edgeAB ^ edgeAC;
            double  vv       = edgeAC ^ edgeAC;
            Vector3 w        = position - vertices[0];
            double  wu       = w ^ (edgeAB);
            double  wv       = w ^ (edgeAC);
            double  D        = uv * uv - uu * vv;
            double  beta     = (uv * wv - vv * wu) / D;

            if (beta < 0 || beta > 1)
            {
                return(IntersectResult.NoHit());
            }
            double gamma = (uv * wu - uu * wv) / D;

            if (gamma < 0 || beta + gamma > 1)
            {
                return(IntersectResult.NoHit());
            }
            double  alpha     = 1 - beta - gamma;
            Vector3 newNormal = normal;

            if (distance > 0 && normals != null)
            {
                Vector3 n1Interpolated = normals[0] * alpha;
                Vector3 n2Interpolated = normals[1] * beta;
                Vector3 n3Interpolated = normals[2] * gamma;
                newNormal = n1Interpolated + n2Interpolated + n3Interpolated;
            }
            IntersectResult result = new IntersectResult(this, distance, position, newNormal);

            if (textures != null)
            {
                Vector2 t1Interpolated = textures[0] * alpha;
                Vector2 t2Interpolated = textures[1] * beta;
                Vector2 t3Interpolated = textures[2] * gamma;
                result.TextureCoordinates = t1Interpolated + t2Interpolated + t3Interpolated;
            }
            return(result);
        }
Example #5
0
        /// <summary>
        /// Intersects the specified one.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="one">The one.</param>
        /// <param name="two">The two.</param>
        /// <returns></returns>
        public static IntersectResult <T> Intersect <T>(List <T> one, List <T> two)
        {
            var same    = new List <T>();
            var oneonly = new List <T>();
            var twoonly = new List <T>();

            var merged = one.Select(s => s).ToList();

            merged.AddRange(two);
            merged = merged.Distinct().ToList();

            foreach (var t in merged)
            {
                var onehas = one.Contains(t);
                var twohas = two.Contains(t);
                if (onehas && twohas)
                {
                    same.Add(t);
                }
                else if (onehas)
                {
                    oneonly.Add(t);
                }
                else
                {
                    twoonly.Add(t);
                }
            }

            var ret = new IntersectResult <T>(same, oneonly, twoonly);

            return(ret);
        }
Example #6
0
        /// <summary>
        /// Gets index of closest intersection.
        /// </summary>
        /// <param name="intersectionResults"></param>
        /// <returns></returns>
        protected int PollIntersections(params IntersectResult[] intersectionResults)
        {
            int             index  = -1;
            IntersectResult result = null;


            for (int i = 0; i < intersectionResults.Length; i++)
            {
                var intersection = intersectionResults[i];

                if (intersection.Hit)
                {
                    if (result == null)
                    {
                        index  = i;
                        result = intersection;
                    }
                    else
                    {
                        if (intersection.PickDistance < result.PickDistance)
                        {
                            result = intersection;
                            index  = i;
                        }
                    }
                }
            }

            return(index);
        }
        private async void MyDrawObject_DrawComplete(object sender, DrawEventArgs args)
        {
            try
            {
                _myDrawObject.IsEnabled = false;

                if (_cts != null)
                {
                    _cts.Cancel();
                }

                _cts = new CancellationTokenSource();

                QueryTask queryTask =
                    new QueryTask("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/TaxParcel/AssessorsParcelCharacteristics/MapServer/1");
                Query query = new Query()
                {
                    Geometry            = args.Geometry,
                    ReturnGeometry      = true,
                    OutSpatialReference = MyMap.SpatialReference
                };

                QueryResult parcelsToIntersectResult = await queryTask.ExecuteTaskAsync(query, _cts.Token);

                List <Graphic> graphicList = new List <Graphic>();
                graphicList.Add(new Graphic()
                {
                    Geometry = args.Geometry
                });
                SimplifyResult simplifiedIntersectGeometryResult = await _geometryService.SimplifyTaskAsync(graphicList, _cts.Token);

                IntersectResult intersectedParcelsResult = await _geometryService.IntersectTaskAsync(parcelsToIntersectResult.FeatureSet.ToList(), simplifiedIntersectGeometryResult.Results[0].Geometry, _cts.Token);

                Random random = new Random();
                foreach (Graphic g in intersectedParcelsResult.Results)
                {
                    SimpleFillSymbol symbol = new SimpleFillSymbol()
                    {
                        Fill = new System.Windows.Media.SolidColorBrush(
                            System.Windows.Media.Color.FromArgb(255, (byte)random.Next(0, 255), (byte)random.Next(0, 255),
                                                                (byte)random.Next(0, 255))),
                        BorderBrush     = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.Black),
                        BorderThickness = 1
                    };
                    g.Symbol = symbol;
                    _intersectGraphicsLayer.Graphics.Add(g);
                }
            }
            catch (Exception ex)
            {
                if (ex is ServiceException)
                {
                    MessageBox.Show(String.Format("{0}: {1}", (ex as ServiceException).Code.ToString(), (ex as ServiceException).Details[0]), "Error", MessageBoxButton.OK);
                    return;
                }
            }
        }
        private IntersectResult Intersect2Curves(Curve a, Curve b)
        {
            int             clipperPrecision = 100;
            IntersectResult result           = new IntersectResult();

            if (Curve.PlanarCurveCollision(a, b, Plane.WorldXY, 0.001f))
            {
                Clipper clipper  = new Clipper();
                Path    subjectA = CurveToPath(a, clipperPrecision);
                Path    subjectB = CurveToPath(b, clipperPrecision);
                Paths   solution = new Paths();

                clipper.AddPath(subjectA, PolyType.ptClip, true);
                clipper.AddPath(subjectB, PolyType.ptSubject, true);

                clipper.Execute(ClipType.ctIntersection, solution, PolyFillType.pftNonZero, PolyFillType.pftNonZero);

                if (solution.Count > 0)
                {
                    result.intersect = true;
                    PolylineCurve pl = PathToPolyline(solution[0], clipperPrecision);
                    result.unionCurve = pl;

                    Point3d minPoint = pl.GetBoundingBox(false).Min;
                    Point3d maxPoint = pl.GetBoundingBox(false).Max;

                    if (maxPoint.X - minPoint.X > maxPoint.Y - minPoint.Y)
                    {
                        result.reboundingVector = new Vector2d(0, -(maxPoint.Y - minPoint.Y));
                        if (AreaMassProperties.Compute(a).Centroid.Y > AreaMassProperties.Compute(b).Centroid.Y)
                        {
                            result.reboundingVector.Y *= -1;
                        }
                    }
                    else
                    {
                        result.reboundingVector = new Vector2d(-(maxPoint.X - minPoint.X), 0);
                        if (AreaMassProperties.Compute(a).Centroid.X > AreaMassProperties.Compute(b).Centroid.X)
                        {
                            result.reboundingVector.X *= -1;
                        }
                    }
                }
            }
            else
            {
                result.intersect        = false;
                result.reboundingVector = Vector2d.Unset;
                result.unionCurve       = null;
            }
            return(result);
        }
Example #9
0
        public override IntersectResult Intersect(Ray3 ray)
        {
            double a = ray.Direction ^ normal;

            if (a >= 0)
            {
                return(IntersectResult.NoHit());
            }
            double b        = normal ^ (ray.Origin - position);
            double distance = -b / a;

            return(new IntersectResult(this, distance, ray.GetPoint(distance), normal));
        }
 public override LightSample Sample(Geometry geometry, Vector3 position)
 {
     if (shadow)
     {
         Ray3            shadowRay    = new Ray3(position, vector);
         IntersectResult shadowResult = geometry.Intersect(shadowRay);
         if (shadowResult.Geometry != null)
         {
             return(LightSample.Zero);
         }
     }
     return(new LightSample(vector, irradiance));
 }
        public override IntersectResult Intersect(Ray3 ray)
        {
            double          minDistance = Constant.Infinity;
            IntersectResult minResult   = IntersectResult.NoHit();

            foreach (Geometry geometry in geometries)
            {
                IntersectResult result = geometry.Intersect(ray);
                if (result.Geometry != null && result.Distance < minDistance)
                {
                    minDistance = result.Distance;
                    minResult   = result;
                }
            }
            return(minResult);
        }
Example #12
0
        public override void Execute(IRaySceneQueryListener listener)
        {
            var list = new List <PCZSceneNode>();

            //find the nodes that intersect the AAB
            ((PCZSceneManager)creator).FindNodesIn(ray, ref list, this.startZone, (PCZSceneNode)this.excludeNode);

            //grab all moveables from the node that intersect...

            foreach (PCZSceneNode node in list)
            {
                foreach (MovableObject m in node.Objects)
                {
                    if ((m.QueryFlags & queryMask) != 0 && (m.TypeFlags & this.queryTypeMask) != 0 && m.IsAttached)
                    {
                        IntersectResult result = ray.Intersects(m.GetWorldBoundingBox());
                        if (result.Hit)
                        {
                            listener.OnQueryResult(m, result.Distance);
                            // deal with attached objects, since they are not directly attached to nodes
                            if (m.MovableType == "Entity")
                            {
                                //Check: not sure here...
                                var e = (Entity)m;
                                foreach (MovableObject c in e.SubEntities)
                                {
                                    if ((c.QueryFlags & queryMask) > 0)
                                    {
                                        result = ray.Intersects(c.GetWorldBoundingBox());
                                        if (result.Hit)
                                        {
                                            listener.OnQueryResult(c, result.Distance);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            // reset startzone and exclude node
            this.startZone   = null;
            this.excludeNode = null;
        }
        private IntersectResult Intersect2Curves(Curve a, Curve b)
        {
            IntersectResult result = new IntersectResult();

            if (Curve.PlanarCurveCollision(a, b, Plane.WorldXY, 0.01f))
            {
                Curve[] unionCurveArray = Curve.CreateBooleanIntersection(a, b);
                if (unionCurveArray.Length > 0)
                {
                    result.intersect  = true;
                    result.unionCurve = unionCurveArray[0];

                    // Find the smallest dimesion of unionCurve
                    Point3d minPoint = result.unionCurve.GetBoundingBox(false).Min;
                    Point3d maxPoint = result.unionCurve.GetBoundingBox(false).Max;

                    if (maxPoint.X - minPoint.X > maxPoint.Y - minPoint.Y)
                    {
                        result.reboundingVector = new Vector2d(0, -(maxPoint.Y - minPoint.Y));
                        if (AreaMassProperties.Compute(a).Centroid.Y > AreaMassProperties.Compute(b).Centroid.Y)
                        {
                            result.reboundingVector.Y *= -1;
                        }
                    }
                    else
                    {
                        result.reboundingVector = new Vector2d(-(maxPoint.X - minPoint.X), 0);
                        if (AreaMassProperties.Compute(a).Centroid.X > AreaMassProperties.Compute(b).Centroid.X)
                        {
                            result.reboundingVector.X *= -1;
                        }
                    }
                }
            }
            else
            {
                result.intersect        = false;
                result.reboundingVector = Vector2d.Unset;
                result.unionCurve       = null;
            }
            return(result);
        }
Example #14
0
        public override void FindNodes(Ray t, ref List <PCZSceneNode> list, List <Portal> visitedPortals, bool includeVisitors,
                                       bool recurseThruPortals, PCZSceneNode exclude)
        {
            // if this zone has an enclosure, check against the enclosure AABB first
            if (null != mEnclosureNode)
            {
                IntersectResult nsect = t.Intersects(mEnclosureNode.WorldAABB);
                if (!nsect.Hit)
                {
                    // AABB of zone does not intersect t, just return.
                    return;
                }
            }

            // use the Octree to more efficiently find nodes intersecting the ray
            this.rootOctree._findNodes(t, ref list, exclude, includeVisitors, false);

            // if asked to, recurse through portals
            if (recurseThruPortals)
            {
                foreach (Portal portal in mPortals)
                {
                    // check portal versus boundign box
                    if (portal.intersects(t))
                    {
                        // make sure portal hasn't already been recursed through

                        if (!visitedPortals.Contains(portal))
                        {
                            // save portal to the visitedPortals list
                            visitedPortals.Add(portal);
                            // recurse into the connected zone
                            portal.getTargetZone().FindNodes(t, ref list, visitedPortals, includeVisitors, recurseThruPortals, exclude);
                        }
                    }
                }
            }
        }
Example #15
0
        public override IntersectResult Intersect(Ray3 ray)
        {
            Vector3 v     = ray.Origin - center;
            double  a0    = v.SqrLength() - radius * radius;
            double  DdotV = ray.Direction ^ v;

            if (DdotV <= 0)
            {
                double discr = DdotV * DdotV - a0;
                if (discr >= 0)
                {
                    double          distance = -DdotV - Math.Sqrt(discr);
                    Vector3         position = ray.GetPoint(distance);
                    Vector3         normal   = (position - center).Normalize();
                    IntersectResult result   = new IntersectResult(this, distance, position, normal);
                    result.TextureCoordinates = new Vector2(
                        (Math.PI + Math.Atan2(position.Z - center.Z, position.X - center.X)) / (Math.PI * 2),
                        1.0 - ((Math.PI / 2) + Math.Asin((position.Y - center.Y) / radius)) / Math.PI);
                    return(result);
                }
            }
            return(IntersectResult.NoHit());
        }
        private List <Curve> CollisionDetectionMain(List <Curve> roomCurves, Curve boundary)
        {
            List <int> indexes = new List <int>();

            for (int i = 0; i < roomCurves.Count; i++)
            {
                indexes.Add(i);
            }

            Shuffle(ref indexes);

            for (int l = 0; l < roomCurves.Count; l++)
            {
                int i = indexes[l];

                // Check roomCurves[i] and roomCurves[j] intersection
                // Then let's move both rooms by 1/2 of the rebounding vector
                for (int j = i + 1; j < roomCurves.Count; j++)

                {
                    IntersectResult intersectResult = new IntersectResult();
                    intersectResult = Intersect2Curves(roomCurves[i], roomCurves[j]);

                    if (intersectResult.intersect)
                    {
                        if (intersectResult.reboundingVector.X != 0)
                        {
                            // Change the proportions of rooms
                            double  iScaleFactor = 1 - Math.Abs(intersectResult.reboundingVector.X / roomCurves[i].GetBoundingBox(false).Diagonal.X / 2);
                            Point3d iScaleAnchor = roomCurves[i].GetBoundingBox(false).Center + new Vector3d(intersectResult.reboundingVector.X > 0 ?
                                                                                                             roomCurves[i].GetBoundingBox(false).Diagonal.X / 2 : -roomCurves[i].GetBoundingBox(false).Diagonal.X / 2, 0, 0);


                            double  jScaleFactor = 1 - Math.Abs(intersectResult.reboundingVector.X / roomCurves[j].GetBoundingBox(false).Diagonal.X / 2);
                            Point3d jScaleAnchor = roomCurves[j].GetBoundingBox(false).Center + new Vector3d(intersectResult.reboundingVector.X > 0 ?
                                                                                                             -roomCurves[j].GetBoundingBox(false).Diagonal.X / 2 : roomCurves[j].GetBoundingBox(false).Diagonal.X / 2, 0, 0);

                            roomCurves[j].Transform(Transform.Scale(new Plane(jScaleAnchor, Vector3d.ZAxis), jScaleFactor, 1 / jScaleFactor, 1));
                            roomCurves[i].Transform(Transform.Scale(new Plane(iScaleAnchor, Vector3d.ZAxis), iScaleFactor, 1 / iScaleFactor, 1));


                            // If the proportions of both rooms are in [0.5; 2] -> ok
                            // Else - change the position of the rooms and return previous scale
                            if (!(GetRoomXYProportion(roomCurves[i]) > 1 / proportionThreshold &&
                                  GetRoomXYProportion(roomCurves[i]) < proportionThreshold &&
                                  GetRoomXYProportion(roomCurves[j]) > 1 / proportionThreshold &&
                                  GetRoomXYProportion(roomCurves[j]) < proportionThreshold))
                            {
                                roomCurves[j].Transform(Transform.Scale(new Plane(jScaleAnchor, Vector3d.ZAxis), 1 / jScaleFactor, jScaleFactor, 1));
                                roomCurves[i].Transform(Transform.Scale(new Plane(iScaleAnchor, Vector3d.ZAxis), 1 / iScaleFactor, iScaleFactor, 1));

                                roomCurves[i].Translate(new Vector3d(intersectResult.reboundingVector.X / 2, 0, 0));
                                roomCurves[j].Translate(new Vector3d(-intersectResult.reboundingVector.X / 2, 0, 0));
                            }
                        }
                        else
                        {
                            // Change the proportions of rooms
                            double  iScaleFactor = 1 - Math.Abs(intersectResult.reboundingVector.Y / roomCurves[i].GetBoundingBox(false).Diagonal.Y / 2);
                            Point3d iScaleAnchor = roomCurves[i].GetBoundingBox(false).Center + new Vector3d(0, intersectResult.reboundingVector.Y > 0 ?
                                                                                                             roomCurves[i].GetBoundingBox(false).Diagonal.Y / 2 : -roomCurves[i].GetBoundingBox(false).Diagonal.Y / 2, 0);


                            double  jScaleFactor = 1 - Math.Abs(intersectResult.reboundingVector.Y / roomCurves[j].GetBoundingBox(false).Diagonal.Y / 2);
                            Point3d jScaleAnchor = roomCurves[j].GetBoundingBox(false).Center + new Vector3d(0, intersectResult.reboundingVector.Y > 0 ?
                                                                                                             -roomCurves[j].GetBoundingBox(false).Diagonal.Y / 2 : roomCurves[j].GetBoundingBox(false).Diagonal.Y / 2, 0);

                            roomCurves[i].Transform(Transform.Scale(new Plane(iScaleAnchor, Vector3d.ZAxis), 1 / iScaleFactor, iScaleFactor, 1));
                            roomCurves[j].Transform(Transform.Scale(new Plane(jScaleAnchor, Vector3d.ZAxis), 1 / jScaleFactor, jScaleFactor, 1));


                            // If the proportions of both rooms are in [0.5; 2]
                            // Else - change the position of the rooms
                            if (!(GetRoomXYProportion(roomCurves[i]) > 1 / proportionThreshold &&
                                  GetRoomXYProportion(roomCurves[i]) < proportionThreshold &&
                                  GetRoomXYProportion(roomCurves[j]) > 1 / proportionThreshold &&
                                  GetRoomXYProportion(roomCurves[j]) < proportionThreshold))
                            {
                                roomCurves[i].Transform(Transform.Scale(new Plane(iScaleAnchor, Vector3d.ZAxis), iScaleFactor, 1 / iScaleFactor, 1));
                                roomCurves[j].Transform(Transform.Scale(new Plane(jScaleAnchor, Vector3d.ZAxis), jScaleFactor, 1 / jScaleFactor, 1));

                                roomCurves[i].Translate(new Vector3d(0, intersectResult.reboundingVector.Y / 2, 0));
                                roomCurves[j].Translate(new Vector3d(0, -intersectResult.reboundingVector.Y / 2, 0));
                            }
                        }
                    }
                    else
                    {
                        if (Curve.PlanarClosedCurveRelationship(roomCurves[i], roomCurves[j], Plane.WorldXY, 0.0001f) != RegionContainment.Disjoint)
                        {
                            BoundingBox aRoomBB = roomCurves[j].GetBoundingBox(false);
                            BoundingBox bRoomBB = roomCurves[i].GetBoundingBox(false);
                            double      xDist   = Math.Abs((aRoomBB.Center - bRoomBB.Center).X) - (aRoomBB.Diagonal.X / 2 - bRoomBB.Diagonal.X / 2);
                            double      yDist   = Math.Abs((aRoomBB.Center - bRoomBB.Center).Y) - (aRoomBB.Diagonal.Y / 2 - bRoomBB.Diagonal.Y / 2);
                            if (xDist > yDist)
                            {
                                if ((aRoomBB.Center - bRoomBB.Center).X > 0)
                                {
                                    roomCurves[i].Translate(new Vector3d(xDist - bRoomBB.Diagonal.X, 0, 0));
                                }
                                else
                                {
                                    roomCurves[i].Translate(new Vector3d(-xDist + bRoomBB.Diagonal.X, 0, 0));
                                }
                            }
                            else
                            {
                                if ((aRoomBB.Center - bRoomBB.Center).Y > 0)
                                {
                                    roomCurves[i].Translate(new Vector3d(0, yDist - bRoomBB.Diagonal.Y, 0));
                                }
                                else
                                {
                                    roomCurves[i].Translate(new Vector3d(0, -yDist + bRoomBB.Diagonal.Y, 0));
                                }
                            }
                        }
                    }
                }

                // Check roomCurves[i] and boundary intersection
                // Let's do it twice to be sure that X and Y positions are both defined perfectly
                for (int t = 0; t < 1; t++)
                {
                    IntersectResult intersectResult = new IntersectResult();
                    intersectResult = Intersect2Curves(roomCurves[i], boundary);

                    if (intersectResult.intersect)
                    {
                        double boundaryProportionThreshold = 1;// proportionThreshold;

                        if (Math.Abs(intersectResult.reboundingVector.X) > 0.01f)
                        {
                            // Change the proportions of rooms
                            double  iScaleFactor = Math.Abs(intersectResult.reboundingVector.X / roomCurves[i].GetBoundingBox(false).Diagonal.X);
                            Point3d iScaleAnchor = roomCurves[i].GetBoundingBox(false).Center + new Vector3d(intersectResult.reboundingVector.X > 0 ?
                                                                                                             -roomCurves[i].GetBoundingBox(false).Diagonal.X / 2 : roomCurves[i].GetBoundingBox(false).Diagonal.X / 2, 0, 0);

                            roomCurves[i].Transform(Transform.Scale(new Plane(iScaleAnchor, Vector3d.ZAxis), iScaleFactor, 1 / iScaleFactor, 1));


                            // If the proportions of both rooms are in [0.5; 2] -> ok
                            // Else - change the position of the rooms and return previous scale
                            if (!(GetRoomXYProportion(roomCurves[i]) > 1 / boundaryProportionThreshold &&
                                  GetRoomXYProportion(roomCurves[i]) < boundaryProportionThreshold))
                            {
                                roomCurves[i].Transform(Transform.Scale(new Plane(iScaleAnchor, Vector3d.ZAxis), 1 / iScaleFactor, iScaleFactor, 1));
                                roomCurves[i].Translate(new Vector3d((intersectResult.reboundingVector.X > 0 ? -1 : 1) * (roomCurves[i].GetBoundingBox(false).Diagonal.X - Math.Abs(intersectResult.reboundingVector.X)), 0, 0));
                            }
                        }
                        else if (Math.Abs(intersectResult.reboundingVector.Y) > 0.01f)
                        { // Change the proportions of rooms
                            double  iScaleFactor = Math.Abs(intersectResult.reboundingVector.Y / roomCurves[i].GetBoundingBox(false).Diagonal.Y);
                            Point3d iScaleAnchor = roomCurves[i].GetBoundingBox(false).Center + new Vector3d(0, intersectResult.reboundingVector.Y > 0 ?
                                                                                                             -roomCurves[i].GetBoundingBox(false).Diagonal.Y / 2 : roomCurves[i].GetBoundingBox(false).Diagonal.Y / 2, 0);

                            roomCurves[i].Transform(Transform.Scale(new Plane(iScaleAnchor, Vector3d.ZAxis), 1 / iScaleFactor, iScaleFactor, 1));


                            // If the proportions of both rooms are in [0.5; 2] -> ok
                            // Else - change the position of the rooms and return previous scale
                            if (!(GetRoomXYProportion(roomCurves[i]) > 1 / boundaryProportionThreshold &&
                                  GetRoomXYProportion(roomCurves[i]) < boundaryProportionThreshold))
                            {
                                roomCurves[i].Transform(Transform.Scale(new Plane(iScaleAnchor, Vector3d.ZAxis), iScaleFactor, 1 / iScaleFactor, 1));
                                roomCurves[i].Translate(new Vector3d(0, (intersectResult.reboundingVector.Y > 0 ? -1 : 1) * (roomCurves[i].GetBoundingBox(false).Diagonal.Y - Math.Abs(intersectResult.reboundingVector.Y)), 0));
                            }
                        }
                    }
                    else
                    {
                        if (Curve.PlanarClosedCurveRelationship(roomCurves[i], boundary, Plane.WorldXY, 0.0001f) != RegionContainment.AInsideB)
                        {
                            BoundingBox boundaryBB = boundary.GetBoundingBox(false);
                            BoundingBox roomBB     = roomCurves[i].GetBoundingBox(false);
                            double      xDist      = Math.Abs((boundaryBB.Center - roomBB.Center).X) - boundaryBB.Diagonal.X / 2 - roomBB.Diagonal.X / 2;
                            double      yDist      = Math.Abs((boundaryBB.Center - roomBB.Center).Y) - boundaryBB.Diagonal.Y / 2 - roomBB.Diagonal.Y / 2;
                            if (xDist > yDist)
                            {
                                if ((boundaryBB.Center - roomBB.Center).X > 0)
                                {
                                    roomCurves[i].Translate(new Vector3d(xDist + roomBB.Diagonal.X, 0, 0));
                                }
                                else
                                {
                                    roomCurves[i].Translate(new Vector3d(-xDist - roomBB.Diagonal.X, 0, 0));
                                }
                            }
                            else
                            {
                                if ((boundaryBB.Center - roomBB.Center).Y > 0)
                                {
                                    roomCurves[i].Translate(new Vector3d(0, yDist + roomBB.Diagonal.Y, 0));
                                }
                                else
                                {
                                    roomCurves[i].Translate(new Vector3d(0, -yDist - roomBB.Diagonal.Y, 0));
                                }
                            }
                        }
                    }
                }
            }
            return(roomCurves);
        }
 public bool intersect(Ray ray, out IntersectResult result)
 {
     return(intersectAlgorithm.intersect(ray, this, out result));
 }
        public bool RayIntersection(Ray ray, out int x, out int z)
        {
            // generate a bounding box for the heightmap in its local space
            AxisAlignedBox axisAlignedBox = new AxisAlignedBox(new Vector3(0, minHeight, 0),
                    new Vector3(width, maxHeight, height));

            Vector3 rayLoc = new Vector3((ray.Origin.x - offsetX) / xzScale,
                                        ray.Origin.y / yScale,
                                        (ray.Origin.z - offsetZ) / xzScale);


            Vector3 rayDir = new Vector3(ray.Direction.x / xzScale, ray.Direction.y / yScale, ray.Direction.z / xzScale);
            rayDir.Normalize();

            // convert the ray to local heightmap space
            Ray tmpRay = new Ray(rayLoc, rayDir);

            // see if the ray intersects with the bounding box
            IntersectResult result = tmpRay.Intersects(axisAlignedBox);

            if (result.Hit)
            {
                // move rayLoc up to just before the point of intersection
                rayLoc = rayLoc + rayDir * ( result.Distance - 1 );

                //
                // deal with edge case where ray is coming from outside the heightmap
                // and is very near edge of map at intersection.
                //
                int insideCounter = 20;
                while ((!Inside(rayLoc)) && (insideCounter > 0))
                {
                    rayLoc += ( rayDir * 0.1f );
                    insideCounter--;
                }
                if (insideCounter == 0)
                {
                    x = 0;
                    z = 0;
                    return false;
                }

                x = (int)Math.Round(rayLoc.x);
                z = (int)Math.Round(rayLoc.z);

                if (x < 0)
                {
                    x = 0;
                }
                if (x >= width)
                {
                    x = width - 1;
                }
                if (z < 0)
                {
                    z = 0;
                }
                if (z >= height)
                {
                    z = height - 1;
                }

                bool above = rayLoc.y > heightData[x + z * width];

                while (Inside(rayLoc))
                {
                    // increment the ray
                    rayLoc += rayDir;

                    x = (int)Math.Round(rayLoc.x);
                    z = (int)Math.Round(rayLoc.z);

                    if (x < 0)
                    {
                        x = 0;
                    }
                    if (x >= width)
                    {
                        x = width - 1;
                    }
                    if (z < 0)
                    {
                        z = 0;
                    }
                    if (z >= height)
                    {
                        z = height - 1;
                    }

                    if (above != (rayLoc.y > heightData[x + z * width]))
                    {
                        // we found a hit
                        return true;
                    }
                }
            }
            x = 0;
            z = 0;
            return false;
        }
        internal static IntersectResult oldIntersectSegmentPoly2D(float[] p0, float[] p1, float[] verts, int nverts)
        {
            /*TODO:��Ҫ�Ż�*/
            IntersectResult result = new IntersectResult();
            float           EPS    = 0.00000001f;

            float[] dir = new float[3];
            vSub(dir, p1, p0);

            float[] edge = new float[3];
            float[] diff = new float[3];

            VectorPtr p0v = new VectorPtr(p0);
            VectorPtr vpj;

            for (int i = 0, j = nverts - 1; i < nverts; j = i++)
            {
                vpj = new VectorPtr(verts, j * 3);
                vSub(edge, new VectorPtr(verts, i * 3), vpj);
                vSub(diff, p0v, vpj);
                float n = vPerp2D(edge, diff);
                float d = vPerp2D(dir, edge);
                if (Math.Abs(d) < EPS)
                {
                    // S is nearly parallel to this edge
                    if (n < 0)
                    {
                        return(result);
                    }
                    else
                    {
                        continue;
                    }
                }
                float t = n / d;
                if (d < 0)
                {
                    // segment S is entering across this edge
                    if (t > result.tmin)
                    {
                        result.tmin   = t;
                        result.segMin = j;
                        // S enters after leaving polygon
                        if (result.tmin > result.tmax)
                        {
                            return(result);
                        }
                    }
                }
                else
                {
                    // segment S is leaving across this edge
                    if (t < result.tmax)
                    {
                        result.tmax   = t;
                        result.segMax = j;
                        // S leaves before entering polygon
                        if (result.tmax < result.tmin)
                        {
                            return(result);
                        }
                    }
                }
            }
            result.intersects = true;
            return(result);
        }
Example #20
0
        public void Query(HashSet <ISpatialTreeNode> hashSet, CoordinateRectangle rectangle, IntersectResult parentResult, SpatialQueryIterator i)
        {
            //Query elements on the map by coordinate ractengle(indexed search)
            lock (this)
            {
                if (!IsBottomSheet)
                {
                    if (Sheets.HasChilds)
                    {
                        foreach (var sheet in Sheets.Values)
                        {
                            var res = parentResult == IntersectResult.Supersets ? IntersectResult.Supersets : IntersectResult.None;

                            if (res != IntersectResult.Supersets)
                            {
                                i.Next();

                                res = sheet.Rectangle.RectangleContains(rectangle);
                            }
                            if (res != IntersectResult.None)
                            {
                                sheet.Query(hashSet, rectangle, res, i);
                            }
                            if (res == IntersectResult.Contains)
                            {
                                break;
                            }
                        }
                    }
                }
                else if (Content.HasChilds)
                {
                    foreach (var node in Content.Values)
                    {
                        var res = parentResult == IntersectResult.Supersets ? IntersectResult.Supersets : IntersectResult.None;
                        if (res != IntersectResult.Supersets)
                        {
                            i.Next();

                            switch (node.NodeType)
                            {
                            case SpatialTreeNodeTypes.Point:
                                res = rectangle.PointContains(node.Coordinate);
                                break;

                            case SpatialTreeNodeTypes.Line:
                                res = rectangle.LineContains(node.Rectangle);
                                break;

                            case SpatialTreeNodeTypes.Rectangle:
                                res = rectangle.RectangleContains(node.Rectangle);
                                break;

                            case SpatialTreeNodeTypes.Poligon:
                                res = rectangle.PoligonContains(node.Poligon);
                                break;
                            }
                        }
                        if (res != IntersectResult.None)
                        {
                            hashSet.Add(node);
                        }
                    }
                }
            }
        }
Example #21
0
        public override void FindNodes(Ray t, ref List <PCZSceneNode> list, List <Portal> visitedPortals, bool includeVisitors,
                                       bool recurseThruPortals, PCZSceneNode exclude)
        {
            // if this zone has an enclosure, check against the enclosure AABB first
            if (null != mEnclosureNode)
            {
                IntersectResult nsect = t.Intersects(mEnclosureNode.WorldAABB);
                if (!nsect.Hit)
                {
                    // AABB of zone does not intersect t, just return.
                    return;
                }
            }

            // check nodes at home in this zone
            foreach (PCZSceneNode pczsn in mHomeNodeList)
            {
                if (pczsn != exclude)
                {
                    // make sure node is not already in the list (might have been added in another
                    // zone it was visiting)
                    if (!list.Contains(pczsn))
                    {
                        IntersectResult nsect = t.Intersects(pczsn.WorldAABB);
                        if (nsect.Hit)
                        {
                            list.Add(pczsn);
                        }
                    }
                }
            }

            if (includeVisitors)
            {
                // check visitor nodes
                foreach (PCZSceneNode pczsn in mVisitorNodeList)
                {
                    if (pczsn != exclude)
                    {
                        // make sure node is not already in the list (might have been added in another
                        // zone it was visiting)

                        if (!list.Contains(pczsn))
                        {
                            IntersectResult nsect = t.Intersects(pczsn.WorldAABB);
                            if (nsect.Hit)
                            {
                                list.Add(pczsn);
                            }
                        }
                    }
                }
            }

            // if asked to, recurse through portals
            if (recurseThruPortals)
            {
                foreach (Portal portal in mPortals)
                {
                    // check portal versus boundign box
                    if (portal.intersects(t))
                    {
                        // make sure portal hasn't already been recursed through
                        if (!visitedPortals.Contains(portal))
                        {
                            // save portal to the visitedPortals list
                            visitedPortals.Add(portal);
                            // recurse into the connected zone
                            portal.getTargetZone().FindNodes(t, ref list, visitedPortals, includeVisitors, recurseThruPortals, exclude);
                        }
                    }
                }
            }
        }
Example #22
0
        // Check if a portal intersects a ray
        // NOTE: Kinda using my own invented routine here for quad portals... Better do a lot of testing!
        public bool intersects(Ray ray)
        {
            // Only check if portal is open
            if (this.mOpen)
            {
                if (this.mType == PORTAL_TYPE.PORTAL_TYPE_QUAD)
                {
                    // since ogre doesn't have built in support for a quad, I'm going to first
                    // find the intersection point (if any) of the ray and the portal plane.  Then
                    // using the intersection point, I take the cross product of each side of the portal
                    // (0,1,intersect), (1,2, intersect), (2,3, intersect), and (3,0,intersect).  If
                    // all 4 cross products have vectors pointing in the same direction, then the
                    // intersection point is within the portal, otherwise it is outside.

                    IntersectResult result = ray.Intersects(this.mDerivedPlane);

                    if (result.Hit)
                    {
                        // the ray intersects the plane, now walk around the edges
                        Vector3 isect = ray.GetPoint(result.Distance);
                        Vector3 cross, vect1, vect2;
                        Vector3 cross2, vect3, vect4;
                        vect1  = this.mDerivedCorners[1] - this.mDerivedCorners[0];
                        vect2  = isect - this.mDerivedCorners[0];
                        cross  = vect1.Cross(vect2);
                        vect3  = this.mDerivedCorners[2] - this.mDerivedCorners[1];
                        vect4  = isect - this.mDerivedCorners[1];
                        cross2 = vect3.Cross(vect4);
                        if (cross.Dot(cross2) < 0)
                        {
                            return(false);
                        }
                        vect1 = this.mDerivedCorners[3] - this.mDerivedCorners[2];
                        vect2 = isect - this.mDerivedCorners[2];
                        cross = vect1.Cross(vect2);
                        if (cross.Dot(cross2) < 0)
                        {
                            return(false);
                        }
                        vect1 = this.mDerivedCorners[0] - this.mDerivedCorners[3];
                        vect2 = isect - this.mDerivedCorners[3];
                        cross = vect1.Cross(vect2);
                        if (cross.Dot(cross2) < 0)
                        {
                            return(false);
                        }
                        // all cross products pointing same way, so intersect
                        // must be on the inside of the portal!
                        return(true);
                    }

                    return(false);
                }
                else if (this.mType == PORTAL_TYPE.PORTAL_TYPE_AABB)
                {
                    var             aabb   = new AxisAlignedBox(this.mDerivedCorners[0], this.mDerivedCorners[1]);
                    IntersectResult result = ray.Intersects(aabb);
                    return(result.Hit);
                }
                else // sphere
                {
                    IntersectResult result = ray.Intersects(this.mDerivedSphere);
                    return(result.Hit);
                }
            }
            return(false);
        }
Example #23
0
        private static byte[] ExtractHandler(NameValueCollection boundVariables,
                                             JsonObject operationInput,
                                             string outputFormat,
                                             string requestProperties,
                                             out string responseProperties)
        {
            responseProperties = null;
            const string methodName = "ExtractIntersection";
            var          errors     = new ResponseContainer(HttpStatusCode.BadRequest, "");
            double?      featureId;

            if (!operationInput.TryGetAsDouble("id", out featureId) && featureId.HasValue)
            {
                errors.AddMessage("The id of the shape is required.");
            }

            if (errors.HasErrors)
            {
                return(Json(errors));
            }

#if !DEBUG
            _logger.LogMessage(ServerLogger.msgType.infoStandard, methodName, MessageCode, "Params received");
#endif

            var fireLayerMap = _featureClassIndexMap.First(x => x.LayerName == "Fire Perimeter");
            var fireLayer    = fireLayerMap.FeatureClass;

            var perimeterFeature = fireLayer.GetFeature(Convert.ToInt32(featureId.Value));
            var inputGeometry    = perimeterFeature.ShapeCopy;

#if !DEBUG
            _logger.LogMessage(ServerLogger.msgType.infoStandard, methodName, MessageCode, "Params valid");
#endif

            var filterGeometry = (ITopologicalOperator4)inputGeometry;
            if (filterGeometry == null)
            {
                errors.Message = "input geometry could not become a topological operator.";

                return(Json(errors));
            }

            filterGeometry.IsKnownSimple_2 = false;
            filterGeometry.Simplify();

            var totalArea = ((IArea)inputGeometry).Area;
            if (totalArea < 0)
            {
                ((ICurve)inputGeometry).ReverseOrientation();
            }

            var filter = new SpatialFilter
            {
                Geometry   = inputGeometry,
                SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects
            };

            var whole = (ITopologicalOperator4)inputGeometry;
            whole.Simplify();

            var searchResults = new Dictionary <string, IList <IntersectAttributes> >
            {
                {
                    "fire", new[]
                    {
                        new IntersectAttributes(new[]
                        {
                            new KeyValuePair <string, object>("total", "total")
                        })
                        {
                            Intersect = totalArea
                        }
                    }
                }
            };

            var criterias = new List <Criteria>
            {
                new Criteria
                {
                    LayerIndex         = _featureClassIndexMap.First(x => x.LayerName == "Municipal Boundary").Index,
                    Attributes         = new[] { "NAME" },
                    JsonPropertyName   = "muni",
                    CalculationCommand = new CalculateIntersectionCommand(whole, _logger)
                },
                new Criteria
                {
                    LayerIndex           = _featureClassIndexMap.First(x => x.LayerName == "Municipal Boundary").Index,
                    FeatureClassIndexMap = _featureClassIndexMap,
                    Attributes           = new[] { "NAME" },
                    JsonPropertyName     = "muniPrivate",
                    CalculationCommand   = new CalculateMuniPrivateCommand(whole, _logger)
                    {
                        LandOwnership = _featureClassIndexMap.Single(x => x.LayerName == "Land Ownership")
                    }
                },
                new Criteria
                {
                    LayerIndex         = _featureClassIndexMap.First(x => x.LayerName == "County Boundary").Index,
                    Attributes         = new[] { "NAME" },
                    JsonPropertyName   = "county",
                    CalculationCommand = new CalculateIntersectionCommand(whole, _logger)
                },
                new Criteria
                {
                    LayerIndex         = _featureClassIndexMap.First(x => x.LayerName == "County Boundary").Index,
                    Attributes         = new[] { "NAME" },
                    JsonPropertyName   = "countyPrivate",
                    CalculationCommand = new CalculateCountyPrivateCommand(whole, _logger)
                    {
                        LandOwnership  = _featureClassIndexMap.Single(x => x.LayerName == "Land Ownership"),
                        Municipalities = _featureClassIndexMap.First(x => x.LayerName == "Municipal Boundary")
                    }
                },
                new Criteria
                {
                    LayerIndex         = _featureClassIndexMap.Single(x => x.LayerName == "Land Ownership").Index,
                    Attributes         = new[] { "OWNER" },
                    JsonPropertyName   = "owner",
                    CalculationCommand = new CalculateIntersectionCommand(whole, _logger)
                },
                new Criteria
                {
                    LayerIndex         = _featureClassIndexMap.Single(x => x.LayerName == "Land Ownership").Index,
                    Attributes         = new[] { "ADMIN" },
                    JsonPropertyName   = "admin",
                    CalculationCommand = new CalculateIntersectionCommand(whole, _logger)
                },
                new Criteria
                {
                    LayerIndex         = _featureClassIndexMap.Single(x => x.LayerName == "States Boundary").Index,
                    Attributes         = new[] { "STATE_NAME" },
                    JsonPropertyName   = "state",
                    CalculationCommand = new CalculateIntersectionCommand(whole, _logger)
                }
            };

            foreach (var criteria in criterias)
            {
                // get the IFeatureClass
                var container = _featureClassIndexMap.Single(x => x.Index == criteria.LayerIndex);
                // get the index of the fields to calculate intersections for
                var fieldMap = container.FieldMap.Select(x => x.Value)
                               .Where(y => criteria.Attributes.Contains(y.Field.ToUpper()))
                               .ToList();
#if !DEBUG
                _logger.LogMessage(ServerLogger.msgType.infoStandard, methodName, MessageCode,
                                   string.Format("Querying {0} at index {1}", container.LayerName, container.Index));
#endif
                var      cursor = container.FeatureClass.Search(filter, true);
                IFeature feature;
                while ((feature = cursor.NextFeature()) != null)
                {
                    var values     = new GetValueAtIndexCommand(fieldMap, feature).Execute();
                    var attributes = new IntersectAttributes(values);
#if !DEBUG
                    _logger.LogMessage(ServerLogger.msgType.infoStandard, methodName, MessageCode,
                                       "intersecting " + container.LayerName);
#endif
                    IntersectionPart intersectionPart;
                    try
                    {
                        intersectionPart = criteria.GetIntersectionWith(feature);
                    }
                    catch (Exception ex)
                    {
                        return(Json(new ResponseContainer(HttpStatusCode.InternalServerError, ex.Message)));
                    }

                    attributes.Intersect = intersectionPart.Size;

                    if (searchResults.ContainsKey(criteria.JsonPropertyName))
                    {
                        if (searchResults[criteria.JsonPropertyName].Any(x => new MultiSetComparer <object>().Equals(x.Attributes, attributes.Attributes)))
                        {
                            var duplicate = searchResults[criteria.JsonPropertyName]
                                            .Single(x => new MultiSetComparer <object>().Equals(x.Attributes, attributes.Attributes));

                            duplicate.Intersect += attributes.Intersect;
                        }
                        else
                        {
                            searchResults[criteria.JsonPropertyName].Add(attributes);
                        }
                    }
                    else
                    {
                        searchResults[criteria.JsonPropertyName] = new Collection <IntersectAttributes> {
                            attributes
                        };
                    }
                }
            }

            var response = new IntersectResult(searchResults);

#if !DEBUG
            _logger.LogMessage(ServerLogger.msgType.infoStandard, methodName, MessageCode, string.Format("Returning results {0}", searchResults.Count));
#endif

            return(Json(new ResponseContainer <IntersectResult>(response)));
        }
Example #24
0
        /// <summary>
        ///		<see cref="RaySceneQuery"/>
        /// </summary>
        public void Execute(IRaySceneQueryListener listener, Camera camera)
        {
            clearFragmentList();

            // if the world is not initialized, then just quit out now with no hits
            if (!TerrainManager.Instance.Initialized)
            {
                return;
            }

            ulong mask = QueryMask;

            SceneQuery.WorldFragment frag;

            bool terrainQuery = (mask & (ulong)RaySceneQueryType.AllTerrain) != 0 || (mask & (ulong)RaySceneQueryType.FirstTerrain) != 0;

            // if the query is a terrain query that is exactly vertical, then force it into the "Height" fastpath
            if (((mask & (ulong)RaySceneQueryType.Height) != 0) || (terrainQuery && (this.Ray.Direction.x == 0.0f) && (this.Ray.Direction.z == 0.0f)))
            {
                // we don't want to bother checking for entities because a
                // UNIT_Y ray is assumed to be a height test, not a ray test
                frag = new SceneQuery.WorldFragment();
                fragmentList.Add(frag);

                frag.FragmentType = WorldFragmentType.SingleIntersection;
                Vector3 origin = this.Ray.Origin;
                origin.y = 0; // ensure that it's within bounds
                frag.SingleIntersection = getHeightAt(origin);
                listener.OnQueryResult(frag, Math.Abs(frag.SingleIntersection.y - this.Ray.Origin.y));
            }
            else
            {
                // Check for all entity contacts
                if ((mask & (ulong)RaySceneQueryType.Entities) != 0)
                {
                    base.Execute(listener);
                }

                // Check for contact with the closest entity triangle
                // or all entity triangles.  Ignores entities that
                // don't have a TriangleIntersector associated with
                // their meshes.
                bool firstTriangleQuery = (mask & (ulong)(RaySceneQueryType.FirstEntityTriangle)) != 0;
                bool allTrianglesQuery  = (mask & (ulong)(RaySceneQueryType.AllEntityTriangles)) != 0;
                if (firstTriangleQuery | allTrianglesQuery)
                {
                    rayOrigin = this.ray.Origin;
                    // Start by getting the entities whose bounding
                    // boxes intersect the ray.  If there are none,
                    // we're done.
                    List <MovableObject> candidates = new List <MovableObject>();
                    foreach (Dictionary <string, MovableObject> objectMap in creator.MovableObjectMaps)
                    {
                        foreach (MovableObject obj in objectMap.Values)
                        {
                            // skip if unattached or filtered out by query flags
                            if (!obj.IsAttached || (obj.QueryFlags & queryMask) == 0)
                            {
                                continue;
                            }

                            // test the intersection against the world bounding box of the entity
                            IntersectResult results = MathUtil.Intersects(ray, obj.GetWorldBoundingBox());
                            if (results.Hit)
                            {
                                candidates.Add(obj);
                            }
                        }
                    }

                    // Get the camera.Near value
                    Camera  cam                 = camera;
                    float   nearDistance        = cam.Near;
                    float   closestDistance     = float.MaxValue;
                    Vector3 closestIntersection = Vector3.Zero;
                    Entity  closestEntity       = null;
                    List <EntityAndIntersection> allEntities = new List <EntityAndIntersection>();
                    foreach (MovableObject obj in candidates)
                    {
                        // skip if unattached or filtered out by query flags
                        if (!obj.IsAttached || (obj.QueryFlags & queryMask) == 0)
                        {
                            continue;
                        }

                        Entity entity = obj as Entity;
                        if (entity == null)
                        {
                            continue;
                        }

                        // skip if its mesh doesn't have triangles
                        if (entity.Mesh == null || entity.Mesh.TriangleIntersector == null)
                        {
                            continue;
                        }

                        // transform the ray to the space of the mesh
                        Matrix4 inverseTransform          = entity.ParentNodeFullTransform.Inverse();
                        Matrix4 inverseWithoutTranslation = inverseTransform;
                        inverseWithoutTranslation.Translation = Vector3.Zero;
                        Vector3 transformedOrigin = inverseTransform * ray.Origin;
                        Ray     transformedRay    = new Ray(transformedOrigin,
                                                            (inverseWithoutTranslation * ray.Direction).ToNormalized());

                        // test the intersection against the world bounding box of the entity
                        Vector3 untransformedIntersection;
                        if (entity.Mesh.TriangleIntersector.ClosestRayIntersection(transformedRay, Vector3.Zero,
                                                                                   nearDistance, out untransformedIntersection))
                        {
                            Vector3 intersection = entity.ParentNodeFullTransform * untransformedIntersection;
                            if (allTrianglesQuery)
                            {
                                allEntities.Add(new EntityAndIntersection(entity, intersection));
                            }
                            float distance = (ray.Origin - intersection).Length;
                            if (firstTriangleQuery && distance < closestDistance)
                            {
                                closestDistance     = distance;
                                closestEntity       = entity;
                                closestIntersection = intersection;
                            }
                        }
                    }
                    if (firstTriangleQuery && closestEntity != null)
                    {
                        frag = new SceneQuery.WorldFragment();
                        fragmentList.Add(frag);
                        frag.FragmentType       = WorldFragmentType.SingleIntersection;
                        frag.SingleIntersection = closestIntersection;
                        listener.OnQueryResult(frag, closestDistance);
                    }
                    else if (allTrianglesQuery && allEntities.Count > 0)
                    {
                        allEntities.Sort(distanceToCameraCompare);
                        foreach (EntityAndIntersection ei in allEntities)
                        {
                            listener.OnQueryResult(ei.entity, (rayOrigin - ei.intersection).Length);
                        }
                    }
                }

                if (terrainQuery)
                {
                    Vector3 ray = Ray.Origin;
                    Vector3 land = getHeightAt(ray);
                    float   dist = 0, resFactor = TerrainManager.oneMeter;

                    // find the larger of x and z directions of the ray direction
                    float maxXZ = Math.Max(Math.Abs(Ray.Direction.x), Math.Abs(Ray.Direction.z));

                    // Only bother if the non-default mask has been set
                    if ((mask & (ulong)RaySceneQueryType.OnexRes) != 0)
                    {
                        if ((mask & (ulong)RaySceneQueryType.TwoxRes) != 0)
                        {
                            resFactor = TerrainManager.oneMeter / 2;
                        }
                        else if ((mask & (ulong)RaySceneQueryType.FourxRes) != 0)
                        {
                            resFactor = TerrainManager.oneMeter / 4;
                        }
                        else if ((mask & (ulong)RaySceneQueryType.EightxRes) != 0)
                        {
                            resFactor = TerrainManager.oneMeter / 8;
                        }
                    }

                    // this scales the res factor so that we move along the ray by a distance that results
                    // in shift of one meter along either the X or Z axis (whichever is longer)
                    resFactor = resFactor / maxXZ;

                    SubPageHeightMap sp;
                    // bool east = false; (unused)
                    // bool south = false; (unused)

                    // if ( Ray.Origin.x > 0 )
                    // {
                    //	east = true;
                    // }
                    // if ( Ray.Origin.z > 0 )
                    // {
                    //	south = true;
                    // }

                    ray = Ray.Origin;
                    sp  = TerrainManager.Instance.LookupSubPage(ray);

                    while (sp != null)
                    {
                        SubPageHeightMap newsp;
                        AxisAlignedBox   tileBounds = sp.BoundingBox;

                        IntersectResult intersect = MathUtil.Intersects(Ray, tileBounds);

                        if (intersect.Hit)
                        {
                            // step through this tile
                            while ((newsp = TerrainManager.Instance.LookupSubPage(RoundRay(ray))) == sp)
                            {
                                land = getHeightAt(ray);
                                if (ray.y < land.y)
                                {
                                    frag = new SceneQuery.WorldFragment();
                                    fragmentList.Add(frag);

                                    frag.FragmentType       = WorldFragmentType.SingleIntersection;
                                    frag.SingleIntersection = land;
                                    listener.OnQueryResult(frag, dist);

                                    if ((mask & (ulong)RaySceneQueryType.FirstTerrain) != 0)
                                    {
                                        return;
                                    }
                                }

                                ray  += Ray.Direction * resFactor;
                                dist += 1 * resFactor;
                            }
                            // if we fall off the end of the above loop without getting a hit, then the hit should be
                            // right at the far edge of the tile, so handle that case.
                            land = getHeightAt(ray);
                            if (ray.y < land.y)
                            {
                                frag = new SceneQuery.WorldFragment();
                                fragmentList.Add(frag);

                                frag.FragmentType       = WorldFragmentType.SingleIntersection;
                                frag.SingleIntersection = land;
                                listener.OnQueryResult(frag, dist);

                                //LogManager.Instance.Write("MVSM:RaySceneQuery:End of tile ray collision");

                                if ((mask & (ulong)RaySceneQueryType.FirstTerrain) != 0)
                                {
                                    return;
                                }
                            }
                            else
                            {
                                //LogManager.Instance.Write("MVSM:RaySceneQuery:End of tile reached without expected intersection");
                            }
                        }
                        else
                        {
                            // step over this tile
                            while ((newsp = TerrainManager.Instance.LookupSubPage(RoundRay(ray))) == sp)
                            { // XXX - this is not the most efficient method...
                                ray  += Ray.Direction * resFactor;
                                dist += 1 * resFactor;
                            }
                        }

                        sp = newsp;
                    }
                }
            }
        }