Ticket #3685: roundObstructions.diff

File roundObstructions.diff, 29.2 KB (added by sanderd17, 8 years ago)

Partial implementation of round obstructions. It works nicely for placing buildings, and works good with the long-range pathfinder, but supporting the vertex pathfinder is hard.

  • binaries/data/mods/public/simulation/templates/structures/brit_wonder.xml

     
    1010    <History>Stonehenge is a monumental structure built by pre-historic peoples from Britain from approximately 2500 BC to 2000 BC. Evidence suggests that the structure and the surrounding site served as a place of religious significance, time-keeping, and other societal functions, like burial.</History>
    1111  </Identity>
    1212  <Obstruction>
    13     <Static width="30.0" depth="30.0"/>
     13    <Static width="60.0" depth="60.0" circular="true"/>
    1414  </Obstruction>
    1515  <VisualActor>
    1616    <FoundationActor>structures/fndn_theatron.xml</FoundationActor>
  • source/simulation2/components/CCmpObstruction.cpp

     
    5757
    5858    entity_pos_t m_Size0; // radius or width
    5959    entity_pos_t m_Size1; // radius or depth
     60    bool m_Circular; // set for circular shapes
    6061    flags_t m_TemplateFlags;
    6162    entity_pos_t m_Clearance;
    6263
     
    6465        entity_pos_t dx, dz;
    6566        entity_angle_t da; 
    6667        entity_pos_t size0, size1;
     68        bool circular;
    6769        flags_t flags;
    6870    } Shape;
    6971
     
    122124                            "<param name='minInclusive'>1.5</param>"
    123125                        "</data>"
    124126                    "</attribute>"
     127                    "<optional>"
     128                        "<attribute name='circular'>"
     129                            "<data type='boolean'/>"
     130                        "</attribute>"
     131                    "</optional>"
    125132                "</element>"
    126133                "<element name='Unit'>"
    127134                    "<empty/>"
     
    140147                                    "<data type='decimal'/>"
    141148                                "</attribute>"
    142149                            "</optional>"
     150                            "<optional>"
     151                                "<attribute name='circular'>"
     152                                    "<data type='boolean'/>"
     153                                "</attribute>"
     154                            "</optional>"
    143155                            "<attribute name='width'>"
    144156                                "<data type='decimal'>"
    145157                                    "<param name='minInclusive'>1.5</param>"
     
    218230            m_Size1 = paramNode.GetChild("Static").GetChild("@depth").ToFixed();
    219231            ENSURE(m_Size0 > minObstruction);
    220232            ENSURE(m_Size1 > minObstruction);
     233            m_Circular = paramNode.GetChild("Static").GetChild("@circular").ToBool();
     234            ENSURE(!m_Circular || m_Size0 == m_Size1);
    221235        }
    222236        else
    223237        {
     
    232246                b.size1 = it->second.GetChild("@depth").ToFixed();
    233247                ENSURE(b.size0 > minObstruction);
    234248                ENSURE(b.size1 > minObstruction);
     249                b.circular = it->second.GetChild("@circular").ToBool();
     250                ENSURE(!b.circular || b.size0 == b.size1);
    235251                b.dx = it->second.GetChild("@x").ToFixed();
    236252                b.dz = it->second.GetChild("@z").ToFixed();
    237253                b.da = entity_angle_t::FromInt(0);
     
    244260            }
    245261            m_Size0 = fixed::FromInt(2).Multiply(MAX(max.X, -min.X));
    246262            m_Size1 = fixed::FromInt(2).Multiply(MAX(max.Y, -min.Y));
     263            m_Circular = false;
    247264        }
    248265
    249266        m_Active = paramNode.GetChild("Active").ToBool();
     
    335352                // Need to create a new pathfinder shape:
    336353                if (m_Type == STATIC)
    337354                    m_Tag = cmpObstructionManager->AddStaticShape(GetEntityId(),
    338                         data.x, data.z, data.a, m_Size0, m_Size1, m_Flags, m_ControlGroup, m_ControlGroup2);
     355                        data.x, data.z, data.a, m_Size0, m_Size1, m_Circular, m_Flags, m_ControlGroup, m_ControlGroup2);
    339356                else if (m_Type == UNIT)
    340357                    m_Tag = cmpObstructionManager->AddUnitShape(GetEntityId(),
    341358                        data.x, data.z, m_Clearance, (flags_t)(m_Flags | (m_Moving ? ICmpObstructionManager::FLAG_MOVING : 0)), m_ControlGroup);
     
    392409            CFixedVector2D pos = cmpPosition->GetPosition2D();
    393410            if (m_Type == STATIC)
    394411                m_Tag = cmpObstructionManager->AddStaticShape(GetEntityId(),
    395                     pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, m_Flags, m_ControlGroup, m_ControlGroup2);
     412                    pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, m_Circular, m_Flags, m_ControlGroup, m_ControlGroup2);
    396413            else if (m_Type == UNIT)
    397414                m_Tag = cmpObstructionManager->AddUnitShape(GetEntityId(),
    398415                    pos.X, pos.Y, m_Clearance, (flags_t)(m_Flags | (m_Moving ? ICmpObstructionManager::FLAG_MOVING : 0)), m_ControlGroup);
     
    492509        if (m_Type == UNIT)
    493510            out = cmpObstructionManager->GetUnitShapeObstruction(pos.X, pos.Y, m_Clearance);
    494511        else
    495             out = cmpObstructionManager->GetStaticShapeObstruction(pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1);
     512            out = cmpObstructionManager->GetStaticShapeObstruction(pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, m_Circular);
    496513        return true;
    497514    }
    498515
     
    508525    {
    509526        if (m_Type == UNIT)
    510527            return m_Clearance;
     528        else if (m_Circular)
     529            return m_Size0;
    511530        else
    512531            return CFixedVector2D(m_Size0 / 2, m_Size1 / 2).Length();
    513532    }
     
    562581        if (m_Type == UNIT)
    563582            return cmpPathfinder->CheckUnitPlacement(filter, pos.X, pos.Y, m_Clearance, passClass, onlyCenterPoint);
    564583        else
    565             return cmpPathfinder->CheckBuildingPlacement(filter, pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, GetEntityId(), passClass, onlyCenterPoint);
     584            return cmpPathfinder->CheckBuildingPlacement(filter, pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, m_Circular, GetEntityId(), passClass, onlyCenterPoint);
    566585    }
    567586
    568587    virtual bool CheckDuplicateFoundation()
     
    594613        if (m_Type == UNIT)
    595614            return !cmpObstructionManager->TestUnitShape(filter, pos.X, pos.Y, m_Clearance, NULL);
    596615        else
    597             return !cmpObstructionManager->TestStaticShape(filter, pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, NULL );
     616            return !cmpObstructionManager->TestStaticShape(filter, pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, m_Circular, NULL );
    598617    }
    599618
    600619    virtual std::vector<entity_id_t> GetUnitCollisions()
     
    710729            ICmpObstructionManager::FLAG_BLOCK_FOUNDATION);
    711730
    712731        std::vector<entity_id_t> collisions;
    713         if (cmpObstructionManager->TestStaticShape(filter, pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, &collisions))
     732        if (cmpObstructionManager->TestStaticShape(filter, pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, m_Circular, &collisions))
    714733        {
    715734            std::vector<entity_id_t> persistentEnts, normalEnts;
    716735
     
    770789        flags &= (flags_t)(~ICmpObstructionManager::FLAG_BLOCK_PATHFINDING);
    771790       
    772791        m_Tag = cmpObstructionManager->AddStaticShape(GetEntityId(),
    773             x, z, a, m_Size0, m_Size1, flags, m_ControlGroup, m_ControlGroup2);
     792            x, z, a, m_Size0, m_Size1, m_Circular, flags, m_ControlGroup, m_ControlGroup2);
    774793
    775794        fixed s, c;
    776795        sincos_approx(a, s, c);
     
    779798        {
    780799            Shape& b = m_Shapes[i];
    781800            tag_t tag = cmpObstructionManager->AddStaticShape(GetEntityId(),
    782                 x + b.dx.Multiply(c) + b.dz.Multiply(s), z + b.dz.Multiply(c) - b.dx.Multiply(s), a + b.da, b.size0, b.size1, b.flags, m_ControlGroup, m_ControlGroup2);
     801                x + b.dx.Multiply(c) + b.dz.Multiply(s), z + b.dz.Multiply(c) - b.dx.Multiply(s), a + b.da, b.size0, b.size1, b.circular, b.flags, m_ControlGroup, m_ControlGroup2);
    783802            m_ClusterTags.push_back(tag);   
    784803        }
    785804    }
  • source/simulation2/components/CCmpObstructionManager.cpp

     
    6767    entity_pos_t x, z; // world-space coordinates
    6868    CFixedVector2D u, v; // orthogonal unit vectors - axes of local coordinate space
    6969    entity_pos_t hw, hh; // half width/height in local coordinate space
     70    bool circular;
    7071    ICmpObstructionManager::flags_t flags;
    7172    entity_id_t group;
    7273    entity_id_t group2;
     
    289290        return UNIT_INDEX_TO_TAG(id);
    290291    }
    291292
    292     virtual tag_t AddStaticShape(entity_id_t ent, entity_pos_t x, entity_pos_t z, entity_angle_t a, entity_pos_t w, entity_pos_t h, flags_t flags, entity_id_t group, entity_id_t group2 /* = INVALID_ENTITY */)
     293    virtual tag_t AddStaticShape(entity_id_t ent, entity_pos_t x, entity_pos_t z,
     294        entity_angle_t a, entity_pos_t w, entity_pos_t h, bool circular,
     295        flags_t flags, entity_id_t group, entity_id_t group2 /* = INVALID_ENTITY */)
    293296    {
    294297        fixed s, c;
    295298        sincos_approx(a, s, c);
     
    296299        CFixedVector2D u(c, -s);
    297300        CFixedVector2D v(s, c);
    298301
    299         StaticShape shape = { ent, x, z, u, v, w/2, h/2, flags, group, group2 };
     302        StaticShape shape = { ent, x, z, u, v, w/2, h/2, circular, flags, group, group2 };
    300303        u32 id = m_StaticShapeNext++;
    301304        m_StaticShapes[id] = shape;
    302305
     
    317320        return o;
    318321    }
    319322
    320     virtual ObstructionSquare GetStaticShapeObstruction(entity_pos_t x, entity_pos_t z, entity_angle_t a, entity_pos_t w, entity_pos_t h)
     323    virtual ObstructionSquare GetStaticShapeObstruction(entity_pos_t x, entity_pos_t z, entity_angle_t a, entity_pos_t w, entity_pos_t h, bool circular)
    321324    {
    322325        fixed s, c;
    323326        sincos_approx(a, s, c);
     
    324327        CFixedVector2D u(c, -s);
    325328        CFixedVector2D v(s, c);
    326329
    327         ObstructionSquare o = { x, z, u, v, w/2, h/2 };
     330        ObstructionSquare o = { x, z, u, v, w/2, h/2, circular };
    328331        return o;
    329332    }
    330333
     
    460463        else
    461464        {
    462465            StaticShape& shape = m_StaticShapes[TAG_TO_INDEX(tag)];
    463             ObstructionSquare o = { shape.x, shape.z, shape.u, shape.v, shape.hw, shape.hh };
     466            ObstructionSquare o = { shape.x, shape.z, shape.u, shape.v, shape.hw, shape.hh, shape.circular };
    464467            return o;
    465468        }
    466469    }
    467470
    468471    virtual bool TestLine(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, entity_pos_t r, bool relaxClearanceForUnits = false);
    469     virtual bool TestStaticShape(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, entity_pos_t h, std::vector<entity_id_t>* out);
     472    virtual bool TestStaticShape(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, entity_pos_t h, bool circular, std::vector<entity_id_t>* out);
    470473    virtual bool TestUnitShape(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t r, std::vector<entity_id_t>* out);
    471474
    472475    virtual void Rasterize(Grid<NavcellData>& grid, const std::vector<PathfinderPassability>& passClasses, bool fullUpdate);
     
    711714
    712715bool CCmpObstructionManager::TestStaticShape(const IObstructionTestFilter& filter,
    713716    entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, entity_pos_t h,
    714     std::vector<entity_id_t>* out)
     717    bool circular, std::vector<entity_id_t>* out)
    715718{
    716719    PROFILE("TestStaticShape");
    717720
     
    746749
    747750        CFixedVector2D center1(it->second.x, it->second.z);
    748751
    749         if (Geometry::PointIsInSquare(center1 - center, u, v, CFixedVector2D(halfSize.X + it->second.clearance, halfSize.Y + it->second.clearance)))
     752        bool isInShape;
     753        if (circular)
     754            isInShape = (center1 - center).CompareLength(halfSize.X) > 0;
     755        else
     756            isInShape = Geometry::PointIsInSquare(center1 - center, u, v, CFixedVector2D(halfSize.X + it->second.clearance, halfSize.Y + it->second.clearance));
     757
     758        if (isInShape)
    750759        {
    751760            if (out)
    752761                out->push_back(it->second.entity);
     
    762771
    763772        CFixedVector2D center1(it->second.x, it->second.z);
    764773        CFixedVector2D halfSize1(it->second.hw, it->second.hh);
    765         if (Geometry::TestSquareSquare(center, u, v, halfSize, center1, it->second.u, it->second.v, halfSize1))
     774        bool isInShape;
     775        if (circular)
     776            isInShape = Geometry::DistanceToSquare(center - center1, it->second.u, it->second.v, halfSize1, true) < halfSize.X;
     777        else
     778            isInShape = Geometry::TestSquareSquare(center, u, v, halfSize, center1, it->second.u, it->second.v, halfSize1);
     779
     780        if (isInShape)
    766781        {
    767782            if (out)
    768783                out->push_back(it->second.entity);
     
    894909            continue;
    895910
    896911        // TODO: it might be nice to rasterize with rounded corners for large 'expand' values.
    897         ObstructionSquare square = { shape.x, shape.z, shape.u, shape.v, shape.hw, shape.hh };
     912        ObstructionSquare square = { shape.x, shape.z, shape.u, shape.v, shape.hw, shape.hh, shape.circular };
    898913        SimRasterize::Spans spans;
    899914        SimRasterize::RasterizeRectWithClearance(spans, square, clearance, Pathfinding::NAVCELL_SIZE);
    900915        for (SimRasterize::Span& span : spans)
     
    9861001
    9871002        // TODO: maybe we should use Geometry::GetHalfBoundingBox to be more precise?
    9881003
    989         squares.emplace_back(ObstructionSquare{ it->second.x, it->second.z, it->second.u, it->second.v, it->second.hw, it->second.hh });
     1004        squares.emplace_back(ObstructionSquare{ it->second.x, it->second.z, it->second.u, it->second.v, it->second.hw, it->second.hh, it->second.circular });
    9901005    }
    9911006}
    9921007
  • source/simulation2/components/CCmpPathfinder.cpp

     
    826826}
    827827
    828828ICmpObstruction::EFoundationCheck CCmpPathfinder::CheckBuildingPlacement(const IObstructionTestFilter& filter,
    829     entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w,
    830     entity_pos_t h, entity_id_t id, pass_class_t passClass)
     829    entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, entity_pos_t h,
     830    bool circular, entity_id_t id, pass_class_t passClass)
    831831{
    832     return CCmpPathfinder::CheckBuildingPlacement(filter, x, z, a, w, h, id, passClass, false);
     832    return CCmpPathfinder::CheckBuildingPlacement(filter, x, z, a, w, h, circular, id, passClass, false);
    833833}
    834834
    835835
    836836ICmpObstruction::EFoundationCheck CCmpPathfinder::CheckBuildingPlacement(const IObstructionTestFilter& filter,
    837     entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w,
    838     entity_pos_t h, entity_id_t id, pass_class_t passClass, bool UNUSED(onlyCenterPoint))
     837    entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, entity_pos_t h,
     838    bool circular, entity_id_t id, pass_class_t passClass, bool UNUSED(onlyCenterPoint))
    839839{
    840840    // Check unit obstruction
    841841    CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
     
    842842    if (!cmpObstructionManager)
    843843        return ICmpObstruction::FOUNDATION_CHECK_FAIL_ERROR;
    844844
    845     if (cmpObstructionManager->TestStaticShape(filter, x, z, a, w, h, NULL))
     845    if (cmpObstructionManager->TestStaticShape(filter, x, z, a, w, h, circular, NULL))
    846846        return ICmpObstruction::FOUNDATION_CHECK_FAIL_OBSTRUCTS_FOUNDATION;
    847847
    848848    // Test against terrain:
  • source/simulation2/components/CCmpPathfinder_Common.h

     
    214214
    215215    virtual ICmpObstruction::EFoundationCheck CheckUnitPlacement(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t r, pass_class_t passClass, bool onlyCenterPoint);
    216216
    217     virtual ICmpObstruction::EFoundationCheck CheckBuildingPlacement(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, entity_pos_t h, entity_id_t id, pass_class_t passClass);
     217    virtual ICmpObstruction::EFoundationCheck CheckBuildingPlacement(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, entity_pos_t h, bool circular, entity_id_t id, pass_class_t passClass);
    218218
    219     virtual ICmpObstruction::EFoundationCheck CheckBuildingPlacement(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, entity_pos_t h, entity_id_t id, pass_class_t passClass, bool onlyCenterPoint);
     219    virtual ICmpObstruction::EFoundationCheck CheckBuildingPlacement(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, entity_pos_t h, bool circular, entity_id_t id, pass_class_t passClass, bool onlyCenterPoint);
    220220
    221221    virtual void FinishAsyncRequests();
    222222
  • source/simulation2/components/ICmpObstructionManager.h

     
    9898     * @param a angle of rotation (clockwise from +Z direction)
    9999     * @param w width (size along X axis)
    100100     * @param h height (size along Z axis)
     101     * @param circular (set to true if obstruction is cicular)
    101102     * @param flags a set of EFlags values
    102103     * @param group primary control group of the shape. Must be a valid control group ID.
    103104     * @param group2 Optional; secondary control group of the shape. Defaults to INVALID_ENTITY.
     
    104105     * @return a valid tag for manipulating the shape
    105106     * @see StaticShape
    106107     */
    107     virtual tag_t AddStaticShape(entity_id_t ent, entity_pos_t x, entity_pos_t z, entity_angle_t a,
    108         entity_pos_t w, entity_pos_t h, flags_t flags, entity_id_t group, entity_id_t group2 = INVALID_ENTITY) = 0;
     108    virtual tag_t AddStaticShape(entity_id_t ent, entity_pos_t x, entity_pos_t z,
     109        entity_angle_t a, entity_pos_t w, entity_pos_t h, bool circular,
     110        flags_t flags, entity_id_t group, entity_id_t group2 = INVALID_ENTITY) = 0;
    109111
    110112    /**
    111113     * Register a unit shape.
     
    186188     */
    187189    virtual bool TestStaticShape(const IObstructionTestFilter& filter,
    188190        entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, entity_pos_t h,
    189         std::vector<entity_id_t>* out) = 0;
     191        bool circular, std::vector<entity_id_t>* out) = 0;
    190192
    191193    /**
    192194     * Collision test a unit shape against the current set of registered shapes, and optionally writes a list of the colliding
     
    226228        entity_pos_t x, z; // position of center
    227229        CFixedVector2D u, v; // 'horizontal' and 'vertical' orthogonal unit vectors, representing orientation
    228230        entity_pos_t hw, hh; // half width, half height of square
     231        bool circular; // set to true if the obstruction is circle-shaped
    229232    };
    230233
    231234    /**
     
    259262
    260263    virtual ObstructionSquare GetUnitShapeObstruction(entity_pos_t x, entity_pos_t z, entity_pos_t clearance) = 0;
    261264
    262     virtual ObstructionSquare GetStaticShapeObstruction(entity_pos_t x, entity_pos_t z, entity_angle_t a, entity_pos_t w, entity_pos_t h) = 0;
     265    virtual ObstructionSquare GetStaticShapeObstruction(entity_pos_t x, entity_pos_t z, entity_angle_t a, entity_pos_t w, entity_pos_t h, bool circular) = 0;
    263266
    264267    /**
    265268     * Set the passability to be restricted to a circular map.
  • source/simulation2/components/ICmpPathfinder.h

     
    146146     * @return ICmpObstruction::FOUNDATION_CHECK_SUCCESS if the placement is okay, else
    147147     *  a value describing the type of failure.
    148148     */
    149     virtual ICmpObstruction::EFoundationCheck CheckBuildingPlacement(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, entity_pos_t h, entity_id_t id, pass_class_t passClass) = 0;
     149    virtual ICmpObstruction::EFoundationCheck CheckBuildingPlacement(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, entity_pos_t h, bool circular, entity_id_t id, pass_class_t passClass) = 0;
    150150
    151151    /**
    152152     * Check whether a building placed here is valid and doesn't hit any obstructions
     
    155155     * @return ICmpObstruction::FOUNDATION_CHECK_SUCCESS if the placement is okay, else
    156156     *  a value describing the type of failure.
    157157     */
    158     virtual ICmpObstruction::EFoundationCheck CheckBuildingPlacement(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, entity_pos_t h, entity_id_t id, pass_class_t passClass, bool onlyCenterPoint) = 0;
     158    virtual ICmpObstruction::EFoundationCheck CheckBuildingPlacement(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, entity_pos_t h, bool circular, entity_id_t id, pass_class_t passClass, bool onlyCenterPoint) = 0;
    159159
    160160
    161161    /**
  • source/simulation2/components/tests/test_ObstructionManager.h

     
    111111        TS_ASSERT_EQUALS(ent3, out[0]);
    112112        out.clear();
    113113
    114         cmp->TestStaticShape(nullFilter, ent3x, ent3z, fixed::Zero(), fixed::FromInt(1), fixed::FromInt(1), &out);
     114        cmp->TestStaticShape(nullFilter, ent3x, ent3z, fixed::Zero(), fixed::FromInt(1), fixed::FromInt(1), false, &out);
    115115        TS_ASSERT_EQUALS(1U, out.size());
    116116        TS_ASSERT_EQUALS(ent3, out[0]);
    117117        out.clear();
     
    125125        TS_ASSERT_VECTOR_CONTAINS(out, ent2);
    126126        out.clear();
    127127
    128         cmp->TestStaticShape(nullFilter, ent2x, ent2z, fixed::Zero(), ent2c, ent2c, &out);
     128        cmp->TestStaticShape(nullFilter, ent2x, ent2z, fixed::Zero(), ent2c, ent2c, false, &out);
    129129        TS_ASSERT_EQUALS(2U, out.size());
    130130        TS_ASSERT_VECTOR_CONTAINS(out, ent1);
    131131        TS_ASSERT_VECTOR_CONTAINS(out, ent2);
     
    152152        TS_ASSERT_VECTOR_CONTAINS(out, ent3);
    153153        out.clear();
    154154
    155         cmp->TestStaticShape(nullFilter, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), &out);
     155        cmp->TestStaticShape(nullFilter, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), false, &out);
    156156        TS_ASSERT_EQUALS(3U, out.size());
    157157        TS_ASSERT_VECTOR_CONTAINS(out, ent1);
    158158        TS_ASSERT_VECTOR_CONTAINS(out, ent2);
     
    180180        TS_ASSERT_VECTOR_CONTAINS(out, ent3);
    181181        out.clear();
    182182
    183         cmp->TestStaticShape(ignoreMoving, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), &out);
     183        cmp->TestStaticShape(ignoreMoving, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), false, &out);
    184184        TS_ASSERT_EQUALS(2U, out.size());
    185185        TS_ASSERT_VECTOR_CONTAINS(out, ent2);
    186186        TS_ASSERT_VECTOR_CONTAINS(out, ent3);
     
    205205        TS_ASSERT_EQUALS(ent1, out[0]);
    206206        out.clear();
    207207
    208         cmp->TestStaticShape(ignoreShape2, ent2x, ent2z, fixed::Zero(), ent2c, ent2c, &out);
     208        cmp->TestStaticShape(ignoreShape2, ent2x, ent2z, fixed::Zero(), ent2c, ent2c, false, &out);
    209209        TS_ASSERT_EQUALS(1U, out.size());
    210210        TS_ASSERT_EQUALS(ent1, out[0]);
    211211        out.clear();
     
    230230        TS_ASSERT_EQUALS(ent3, out[0]);
    231231        out.clear();
    232232
    233         cmp->TestStaticShape(skipShape1RequireBlockMovement, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), &out);
     233        cmp->TestStaticShape(skipShape1RequireBlockMovement, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), false, &out);
    234234        TS_ASSERT_EQUALS(1U, out.size());
    235235        TS_ASSERT_EQUALS(ent3, out[0]);
    236236        out.clear();
     
    247247        TS_ASSERT_VECTOR_CONTAINS(out, ent3);
    248248        out.clear();
    249249
    250         cmp->TestStaticShape(skipShape1RequireAnyFlag, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), &out);
     250        cmp->TestStaticShape(skipShape1RequireAnyFlag, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), false, &out);
    251251        TS_ASSERT_EQUALS(2U, out.size());
    252252        TS_ASSERT_VECTOR_CONTAINS(out, ent2);
    253253        TS_ASSERT_VECTOR_CONTAINS(out, ent3);
     
    262262        TS_ASSERT_EQUALS(0U, out.size());
    263263        out.clear();
    264264
    265         cmp->TestStaticShape(skipShape1RejectAll, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), &out);
     265        cmp->TestStaticShape(skipShape1RejectAll, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), false, &out);
    266266        TS_ASSERT_EQUALS(0U, out.size());
    267267        out.clear();
    268268    }
     
    290290        TS_ASSERT_EQUALS(ent3, out[0]);
    291291        out.clear();
    292292
    293         cmp->TestStaticShape(skipGroup1ReqFoundConstr, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), &out);
     293        cmp->TestStaticShape(skipGroup1ReqFoundConstr, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), false, &out);
    294294        TS_ASSERT_EQUALS(1U, out.size());
    295295        TS_ASSERT_EQUALS(ent3, out[0]);
    296296        out.clear();
     
    306306        TS_ASSERT_EQUALS(0U, out.size());
    307307        out.clear();
    308308
    309         cmp->TestStaticShape(skipGroup1And3ReqFoundConstr, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), &out);
     309        cmp->TestStaticShape(skipGroup1And3ReqFoundConstr, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), false, &out);
    310310        TS_ASSERT_EQUALS(0U, out.size());
    311311        out.clear();
    312312
     
    323323        TS_ASSERT_VECTOR_CONTAINS(out, ent2);
    324324        out.clear();
    325325
    326         cmp->TestStaticShape(skipGroup3RequireAnyFlag, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), &out);
     326        cmp->TestStaticShape(skipGroup3RequireAnyFlag, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), false, &out);
    327327        TS_ASSERT_EQUALS(2U, out.size());
    328328        TS_ASSERT_VECTOR_CONTAINS(out, ent1);
    329329        TS_ASSERT_VECTOR_CONTAINS(out, ent2);
     
    339339        TS_ASSERT_EQUALS(0U, out.size());
    340340        out.clear();
    341341
    342         cmp->TestStaticShape(skipGroup3RequireNoFlags, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), &out);
     342        cmp->TestStaticShape(skipGroup3RequireNoFlags, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), false, &out);
    343343        TS_ASSERT_EQUALS(0U, out.size());
    344344        out.clear();
    345345
     
    378378        TS_ASSERT_VECTOR_CONTAINS(out, ent3);
    379379        out.clear();
    380380
    381         cmp->TestStaticShape(skipGroup1SecAnd4SecRequireAny, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), &out);
     381        cmp->TestStaticShape(skipGroup1SecAnd4SecRequireAny, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), false, &out);
    382382        TS_ASSERT_EQUALS(2U, out.size());
    383383        TS_ASSERT_VECTOR_CONTAINS(out, ent2);
    384384        TS_ASSERT_VECTOR_CONTAINS(out, ent3);
     
    397397        TS_ASSERT_VECTOR_CONTAINS(out, ent3);
    398398        out.clear();
    399399
    400         cmp->TestStaticShape(skipGroup1SecAnd4PrimRequireAny, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), &out);
     400        cmp->TestStaticShape(skipGroup1SecAnd4PrimRequireAny, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), false, &out);
    401401        TS_ASSERT_EQUALS(2U, out.size());
    402402        TS_ASSERT_VECTOR_CONTAINS(out, ent2);
    403403        TS_ASSERT_VECTOR_CONTAINS(out, ent3);
     
    423423                     ent4x = ent3x + ent3c + ent4w/2, // make ent4 adjacent to ent3
    424424                     ent4z = ent3z;
    425425
    426         cmp->TestStaticShape(nullFilter, ent4x, ent4z, ent4a, ent4w, ent4h, &out);
     426        cmp->TestStaticShape(nullFilter, ent4x, ent4z, ent4a, ent4w, ent4h, false, &out);
    427427        TS_ASSERT_EQUALS(1U, out.size());
    428428        TS_ASSERT_EQUALS(ent3, out[0]);
    429429        out.clear();
     
    435435
    436436        // now do the same tests, but move the shape a little bit to the right so that it doesn't touch anymore
    437437
    438         cmp->TestStaticShape(nullFilter, ent4x + fixed::FromFloat(1e-5f), ent4z, ent4a, ent4w, ent4h, &out);
     438        cmp->TestStaticShape(nullFilter, ent4x + fixed::FromFloat(1e-5f), ent4z, ent4a, ent4w, ent4h, false, &out);
    439439        TS_ASSERT_EQUALS(0U, out.size());
    440440        out.clear();
    441441
  • source/simulation2/helpers/Rasterize.cpp

     
    5656        return; // empty bounds - this shouldn't happen
    5757
    5858
    59     rasterClearance = rasterClearance.Multiply(rasterClearance);
     59    entity_pos_t rasterClearanceSq = rasterClearance.Multiply(rasterClearance);
    6060
    6161    spans.reserve(j1 - j0);
    6262   
     
    8080                continue;
    8181            }
    8282
    83             if (Geometry::DistanceToSquareSquared(CFixedVector2D(cellSize*(i+1)-shape.x, cellSize*j-shape.z),
    84                                     shape.u, shape.v, shapeHalfSize, true) > rasterClearance)
     83            CFixedVector2D diff(cellSize*(i+1)-shape.x, cellSize*j-shape.z);
     84            bool isOutShape;
     85            if (shape.circular)
     86                isOutShape = diff.CompareLength(rasterClearance + shapeHalfSize.X) > 0;
     87            else
     88                isOutShape = Geometry::DistanceToSquareSquared(diff, shape.u, shape.v, shapeHalfSize, true) > rasterClearanceSq;
     89            if (isOutShape)
    8590            {
    8691                if (previousInside)
    8792                    break;
     
    8994                continue;
    9095            }
    9196
    92             if (Geometry::DistanceToSquareSquared(CFixedVector2D(cellSize*(i+1)-shape.x, cellSize*(j+1)-shape.z),
    93                                     shape.u, shape.v, shapeHalfSize, true) > rasterClearance)
     97            diff.Y += cellSize; // one to the right
     98            if (shape.circular)
     99                isOutShape = diff.CompareLength(rasterClearance + shapeHalfSize.X) > 0;
     100            else
     101                isOutShape = Geometry::DistanceToSquareSquared(diff, shape.u, shape.v, shapeHalfSize, true) > rasterClearanceSq;
     102            if (isOutShape)
    94103            {
    95104                if (previousInside)
    96105                    break;
     
    100109
    101110            if (!previousInside)
    102111            {
    103                 if (Geometry::DistanceToSquareSquared(CFixedVector2D(cellSize*i-shape.x, cellSize*j-shape.z),
    104                                     shape.u, shape.v, shapeHalfSize, true) > rasterClearance)
     112                diff.X -= cellSize; // one step backwards
     113                if (shape.circular)
     114                    isOutShape = diff.CompareLength(rasterClearance + shapeHalfSize.X) > 0;
     115                else
     116                    isOutShape = Geometry::DistanceToSquareSquared(diff, shape.u, shape.v, shapeHalfSize, true) > rasterClearanceSq;
     117                if (isOutShape)
    105118                    continue;
    106119
    107                 if (Geometry::DistanceToSquareSquared(CFixedVector2D(cellSize*i-shape.x, cellSize*(j+1)-shape.z),
    108                                     shape.u, shape.v, shapeHalfSize, true) > rasterClearance)
     120                diff.Y -= cellSize; // one to the left
     121                if (shape.circular)
     122                    isOutShape = diff.CompareLength(rasterClearance + shapeHalfSize.X) > 0;
     123                else
     124                    isOutShape = Geometry::DistanceToSquareSquared(diff, shape.u, shape.v, shapeHalfSize, true) > rasterClearanceSq;
     125                if (isOutShape)
    109126                    continue;
    110127
    111128                previousInside = true;