⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 continuous2d.java

📁 MASON代表多主体邻里或网络仿真(Multi-Agent Simulator of Neighborhoods or Networks)。它是乔治梅森大学用Java开发的离散事件多主体仿真核心库
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package sim.field.continuous;import sim.field.*;import sim.util.*;import java.util.*;/**   A storage facility for objects located in a continuous 2D environment.  This facility relates   objects with 2D double tuples (in the form of Double2D).  The facility extends SparseField, and like   other objects which extend SparseField (such as SparseGrid2D), the facility can only relate any given   object with a single location at a time -- that is, an object cannot hold two locations at once in    the Continuous2D field.   <p>Because hashtable lookups are more expensive than just storing the object, we suggest that you ALSO   store the location of an object in the object itself, so you can read from the object rather than having   to call getObjectLocation(object).   <p>The Continuous2D has been arranged to make neighborhood lookup information reasonably efficient.   It discretizes the space into grid buckets.  The discretization size of the buckets is   provided in the constructor and cannot be changed thereafter.  If the discretization was 0.7,   for example, then one bucket would be (0,0) to (under 0.7, under 0.7), another bucket would be (0,0,0.7)   to (under 0.7, under 1.4), etc.      <p>You can use Continuous2D to look up objects in a given region by asking for objects within the   enclosing buckets, then rummaging through the buckets to find the individuals actually in the desired   region.  The trick here is to come up with a good bucket size.  If the bucket size is much larger than   the typical size of a neighborhood lookup, then a typical lookup will include large numbers of objects   you don't care about; in the worst case, this is an O(n) lookup for something that could have been much   smaller.  On the other hand, if the bucket size is much smaller than the typical size of a neighborhood   lookup, then you have to do lots of bucket lookups to cover your range; many if not most of these buckets   could be empty.  This can also be highly inefficient.   <p>Stored objects are best thought of as one of two types: <b>point objects</b> and <b>non-point objects</b>.   A point object is represented in space by a single point.  It has no area or volume.  A non-point object   has area or volume.  You specify whether or not your objects are point or non-point objects when calling   getObjectsWithinDistance().  The distinction matters when you care about this function returning either all   the objects whose point location is within the distance range, or returning all the (non-point) the objects which   could possibly overlap with the range.     <p>This distinction also is important when determining the discretization size   of your grid.  If your objects are point objects, you have no minimum bound on the discretization size.  But if   the object are non-point location objects (that is, they have dimensions of width, height, etc.), and   you care about this overlap when you do distance lookups, then you have a minimum bound on your   discretization.  In this case, you want to make certain that your discretization is at LEAST larger than   the LARGEST dimension of any object you plan on putting in the Continuous2D.  The idea here is that if an   any part of an object fell within the bounding box for your distance lookup task    (see getObjectsWithinDistance(...)), you're guaranteed that the stored location of the object must be within   a bounding box 1 discretization larger in each direction.   <p>Okay, so that gives you the minimum discretization you should use.  What about the maximum discretization?   It depends largely on the number of objects expected to occupy a given discretized bucket region, and on what   kind of lookups you need to do for objects within a given distance.  Searching through one bucket is a hash   table lookup.  A smaller discretization returns a more accurate sample of objects within the requested   bounding box, but requires more hash table lookups.  If you have <b>point location</b> objects, and    your field is very dense (LOTS of objects in a bucket on average), then we recommend a   discretization equal to the maximum range distance you are likely to look up; but if your field is very sparse,   then we recommend a discretization equal to twice the maximum range distance.  You have to tune it.  If you   have <b>non-point-location</b> objects, then you have two choices.  One approach is to assume a discretization    equal to the maximum range distance, but when doing lookups with getObjectsWithinDistance(...), you need to   state that you're using non-point-location objects.  If you're fairly sparse and your objects aren't big, you   can set the discretization to twice the maximum range distance, and you should be safe calling getObjectsWithinDistance()   pretending that your objects are point-location; this saves you a lot of hash table lookups.   <p>At any rate, do NOT go below the minimum discretization rules.    <p>But wait, you say, I have objects of widely varying sizes.  Or I have many different neighborhood lookup   range needs.  Never fear.  Just use multiple Continuous2Ds of different discretizations.  Depending on your   needs, you can put all the objects in all of the Continuous2Ds (making different range lookups efficient)   or various-sized classes of objects in their own Continuous2Ds perhaps.  You have to think this through based   on your needs.  If all the objects were in all of the Continuous2Ds, you'd think that'd be inefficient in   moving objects around.  Not really: if the discretizations doubled (or more) each time, you're looking at    typically an O(ln n) number of Continuous2Ds, and a corresponding number of lookups.   <p>Continuous2D objects have a width and a height, but this is used for two functions: first, to determine   the bounds for toroidal functions.  Second, to determine the bounds for drawing on the screen in a portrayal.   Otherwise, width and height are not used.  If your space is bounded, you should set the width and height to   those bounds.  If it's unbounded, then you should set the width and height to the bounds you would like   displayed on-screen.      <p><b>Warning about getObjectsAtLocation() and numObjectsAtLocation()</b>     Because this class uses its superclass (the SparseField) to store the <i>discretized region</i>,   getObjectsAtLocation(...) and numObjectsAtLocation(...) will not work as you might expect.  The Sparse   Field is storing Int2Ds (the discretized grid locations), not Double2Ds.  While you could get all the   objects in the same discretization cell as a given Double2D location with   getObjectsAtLocation(discretize(theDouble2D)), almost certainly you're going to retain sanity better   by using the neighborhood functions (getObjectsWithinDistance(...)).     The same goes for getObjectsAtLocationOfObject() and numObjectsAtLocationOfObject().*/public /*strictfp*/ class Continuous2D extends SparseField    {    /** Where we store the Double2D values hashed by object */    public HashMap doubleLocationHash = new HashMap();        public double width;    public double height;        public final double discretization;        /** Provide expected bounds on the SparseContinuous2D */    public Continuous2D(final double discretization, double width, double height)        {        this.discretization = discretization;        this.width = width;        this.height = height;        }    public final Double2D getObjectLocation(Object obj)        {        return (Double2D) doubleLocationHash.get(obj);        }        public final Int2D discretize(final Double2D location)        {        return new Int2D((int)(location.x / discretization), (int)(location.y / discretization));        }        public final boolean setObjectLocation(Object obj, final Double2D location)        {        boolean result = super.setObjectLocation(obj, discretize(location));        if (result) doubleLocationHash.put(obj,location);        return result;        }            public final Bag clear()        {        doubleLocationHash = new HashMap();        return super.clear();        }            public final Object remove(final Object obj)        {        Object result = super.remove(obj);        doubleLocationHash.remove(obj);        return result;        }        /** Get the width */    public double getWidth() { return width; }        /** Get the height */    public double getHeight() { return height; }        /** Toroidal x */    public final double tx(final double x)         {         final double width = this.width;         if (x >= 0) return (x % width);         final double width2 = (x % width) + width;         if (width2 < width) return width2;        return 0;        }            /** Toroidal y */    public final double ty(final double y)         {         final double height = this.height;         if (y >= 0) return (y % height);         final double height2 = (y % height) + height;        if (height2 < height) return height2;        return 0;        }            /** Simple [and fast] toroidal x.  Use this if the values you'd pass in never stray        beyond (-width ... width * 2) not inclusive.  It's a bit faster than the full        toroidal computation as it uses if statements rather than two modulos.        The following definition:<br>        { double width = this.width; if (x >= 0) { if (x < width) return x; return x - width; } return x + width; } <br>        ...produces the shortest code (24 bytes) and is inlined in Hotspot for 1.4.1.   However removing        the double width = this.width; is likely to be a little faster if most objects are within the        toroidal region. */    public double stx(final double x)         { if (x >= 0) { if (x < width) return x; return x - width; } return x + width; }        /** Simple [and fast] toroidal y.  Use this if the values you'd pass in never stray        beyond (-height ... height * 2) not inclusive.  It's a bit faster than the full        toroidal computation as it uses if statements rather than two modulos.        The following definition:<br>        { double height = this.height; if (y >= 0) { if (y < height) return y ; return y - height; } return y + height; } <br>        ...produces the shortest code (24 bytes) and is inlined in Hotspot for 1.4.1.   However removing        the double height = this.height; is likely to be a little faster if most objects are within the        toroidal region. */    public double sty(final double y)         { if (y >= 0) { if (y < height) return y ; return y - height; } return y + height; }                // some efficiency to avoid width lookups    double _stx(final double x, final double width)         { if (x >= 0) { if (x < width) return x; return x - width; } return x + width; }    /** Minimum toroidal distance between two values in the X dimension. */    public double tdx(final double x1, final double x2)        {        double width = this.width;        if (Math.abs(x1-x2) <= width / 2)            return x1 - x2;  // no wraparounds  -- quick and dirty check                double dx = _stx(x1,width) - _stx(x2,width);        if (dx * 2 > width) return dx - width;        if (dx * 2 < -width) return dx + width;        return dx;        }        // some efficiency to avoid height lookups    double _sty(final double y, final double height)         { if (y >= 0) { if (y < height) return y ; return y - height; } return y + height; }    /** Minimum toroidal distance between two values in the Y dimension. */    public double tdy(final double y1, final double y2)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -