Index: binaries/data/mods/public/simulation/templates/structures/brit_wonder.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/structures/brit_wonder.xml	(revision 18047)
+++ binaries/data/mods/public/simulation/templates/structures/brit_wonder.xml	(working copy)
@@ -10,7 +10,7 @@
     <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>
   </Identity>
   <Obstruction>
-    <Static width="30.0" depth="30.0"/>
+    <Static width="60.0" depth="60.0" circular="true"/>
   </Obstruction>
   <VisualActor>
     <FoundationActor>structures/fndn_theatron.xml</FoundationActor>
Index: source/simulation2/components/CCmpObstruction.cpp
===================================================================
--- source/simulation2/components/CCmpObstruction.cpp	(revision 18047)
+++ source/simulation2/components/CCmpObstruction.cpp	(working copy)
@@ -57,6 +57,7 @@
 
 	entity_pos_t m_Size0; // radius or width
 	entity_pos_t m_Size1; // radius or depth
+	bool m_Circular; // set for circular shapes
 	flags_t m_TemplateFlags;
 	entity_pos_t m_Clearance;
 
@@ -64,6 +65,7 @@
 		entity_pos_t dx, dz;
 		entity_angle_t da;	
 		entity_pos_t size0, size1;
+		bool circular;
 		flags_t flags;
 	} Shape;
 
@@ -122,6 +124,11 @@
 							"<param name='minInclusive'>1.5</param>"
 						"</data>"
 					"</attribute>"
+					"<optional>"
+						"<attribute name='circular'>"
+							"<data type='boolean'/>"
+						"</attribute>"
+					"</optional>"
 				"</element>"
 				"<element name='Unit'>"
 					"<empty/>"
@@ -140,6 +147,11 @@
 									"<data type='decimal'/>"
 								"</attribute>"
 							"</optional>"
+							"<optional>"
+								"<attribute name='circular'>"
+									"<data type='boolean'/>"
+								"</attribute>"
+							"</optional>"
 							"<attribute name='width'>"
 								"<data type='decimal'>"
 									"<param name='minInclusive'>1.5</param>"
@@ -218,6 +230,8 @@
 			m_Size1 = paramNode.GetChild("Static").GetChild("@depth").ToFixed();
 			ENSURE(m_Size0 > minObstruction);
 			ENSURE(m_Size1 > minObstruction);
+			m_Circular = paramNode.GetChild("Static").GetChild("@circular").ToBool();
+			ENSURE(!m_Circular || m_Size0 == m_Size1);
 		}
 		else
 		{
@@ -232,6 +246,8 @@
 				b.size1 = it->second.GetChild("@depth").ToFixed();
 				ENSURE(b.size0 > minObstruction);
 				ENSURE(b.size1 > minObstruction);
+				b.circular = it->second.GetChild("@circular").ToBool();
+				ENSURE(!b.circular || b.size0 == b.size1);
 				b.dx = it->second.GetChild("@x").ToFixed();
 				b.dz = it->second.GetChild("@z").ToFixed();
 				b.da = entity_angle_t::FromInt(0);
@@ -244,6 +260,7 @@
 			}
 			m_Size0 = fixed::FromInt(2).Multiply(MAX(max.X, -min.X));
 			m_Size1 = fixed::FromInt(2).Multiply(MAX(max.Y, -min.Y));
+			m_Circular = false;
 		}
 
 		m_Active = paramNode.GetChild("Active").ToBool();
@@ -335,7 +352,7 @@
 				// Need to create a new pathfinder shape:
 				if (m_Type == STATIC)
 					m_Tag = cmpObstructionManager->AddStaticShape(GetEntityId(),
-						data.x, data.z, data.a, m_Size0, m_Size1, m_Flags, m_ControlGroup, m_ControlGroup2);
+						data.x, data.z, data.a, m_Size0, m_Size1, m_Circular, m_Flags, m_ControlGroup, m_ControlGroup2);
 				else if (m_Type == UNIT)
 					m_Tag = cmpObstructionManager->AddUnitShape(GetEntityId(),
 						data.x, data.z, m_Clearance, (flags_t)(m_Flags | (m_Moving ? ICmpObstructionManager::FLAG_MOVING : 0)), m_ControlGroup);
@@ -392,7 +409,7 @@
 			CFixedVector2D pos = cmpPosition->GetPosition2D();
 			if (m_Type == STATIC)
 				m_Tag = cmpObstructionManager->AddStaticShape(GetEntityId(),
-					pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, m_Flags, m_ControlGroup, m_ControlGroup2);
+					pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, m_Circular, m_Flags, m_ControlGroup, m_ControlGroup2);
 			else if (m_Type == UNIT)
 				m_Tag = cmpObstructionManager->AddUnitShape(GetEntityId(),
 					pos.X, pos.Y, m_Clearance, (flags_t)(m_Flags | (m_Moving ? ICmpObstructionManager::FLAG_MOVING : 0)), m_ControlGroup);
@@ -492,7 +509,7 @@
 		if (m_Type == UNIT)
 			out = cmpObstructionManager->GetUnitShapeObstruction(pos.X, pos.Y, m_Clearance);
 		else
-			out = cmpObstructionManager->GetStaticShapeObstruction(pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1);
+			out = cmpObstructionManager->GetStaticShapeObstruction(pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, m_Circular);
 		return true;
 	}
 
@@ -508,6 +525,8 @@
 	{
 		if (m_Type == UNIT)
 			return m_Clearance;
+		else if (m_Circular)
+			return m_Size0;
 		else
 			return CFixedVector2D(m_Size0 / 2, m_Size1 / 2).Length();
 	}
@@ -562,7 +581,7 @@
 		if (m_Type == UNIT)
 			return cmpPathfinder->CheckUnitPlacement(filter, pos.X, pos.Y, m_Clearance, passClass, onlyCenterPoint);
 		else
-			return cmpPathfinder->CheckBuildingPlacement(filter, pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, GetEntityId(), passClass, onlyCenterPoint);
+			return cmpPathfinder->CheckBuildingPlacement(filter, pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, m_Circular, GetEntityId(), passClass, onlyCenterPoint);
 	}
 
 	virtual bool CheckDuplicateFoundation()
@@ -594,7 +613,7 @@
 		if (m_Type == UNIT)
 			return !cmpObstructionManager->TestUnitShape(filter, pos.X, pos.Y, m_Clearance, NULL);
 		else
-			return !cmpObstructionManager->TestStaticShape(filter, pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, NULL );
+			return !cmpObstructionManager->TestStaticShape(filter, pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, m_Circular, NULL );
 	} 
 
 	virtual std::vector<entity_id_t> GetUnitCollisions()
@@ -710,7 +729,7 @@
 			ICmpObstructionManager::FLAG_BLOCK_FOUNDATION);
 
 		std::vector<entity_id_t> collisions;
-		if (cmpObstructionManager->TestStaticShape(filter, pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, &collisions))
+		if (cmpObstructionManager->TestStaticShape(filter, pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, m_Circular, &collisions))
 		{
 			std::vector<entity_id_t> persistentEnts, normalEnts;
 
@@ -770,7 +789,7 @@
 		flags &= (flags_t)(~ICmpObstructionManager::FLAG_BLOCK_PATHFINDING);
 		
 		m_Tag = cmpObstructionManager->AddStaticShape(GetEntityId(),
-			x, z, a, m_Size0, m_Size1, flags, m_ControlGroup, m_ControlGroup2);
+			x, z, a, m_Size0, m_Size1, m_Circular, flags, m_ControlGroup, m_ControlGroup2);
 
 		fixed s, c;
 		sincos_approx(a, s, c);
@@ -779,7 +798,7 @@
 		{
 			Shape& b = m_Shapes[i];
 			tag_t tag = cmpObstructionManager->AddStaticShape(GetEntityId(),
-				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);
+				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);
 			m_ClusterTags.push_back(tag);	
 		}
 	}
Index: source/simulation2/components/CCmpObstructionManager.cpp
===================================================================
--- source/simulation2/components/CCmpObstructionManager.cpp	(revision 18047)
+++ source/simulation2/components/CCmpObstructionManager.cpp	(working copy)
@@ -67,6 +67,7 @@
 	entity_pos_t x, z; // world-space coordinates
 	CFixedVector2D u, v; // orthogonal unit vectors - axes of local coordinate space
 	entity_pos_t hw, hh; // half width/height in local coordinate space
+	bool circular;
 	ICmpObstructionManager::flags_t flags;
 	entity_id_t group;
 	entity_id_t group2;
@@ -289,7 +290,9 @@
 		return UNIT_INDEX_TO_TAG(id);
 	}
 
-	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 */)
+	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, bool circular,
+		flags_t flags, entity_id_t group, entity_id_t group2 /* = INVALID_ENTITY */)
 	{
 		fixed s, c;
 		sincos_approx(a, s, c);
@@ -296,7 +299,7 @@
 		CFixedVector2D u(c, -s);
 		CFixedVector2D v(s, c);
 
-		StaticShape shape = { ent, x, z, u, v, w/2, h/2, flags, group, group2 };
+		StaticShape shape = { ent, x, z, u, v, w/2, h/2, circular, flags, group, group2 };
 		u32 id = m_StaticShapeNext++;
 		m_StaticShapes[id] = shape;
 
@@ -317,7 +320,7 @@
 		return o;
 	}
 
-	virtual ObstructionSquare GetStaticShapeObstruction(entity_pos_t x, entity_pos_t z, entity_angle_t a, entity_pos_t w, entity_pos_t h)
+	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)
 	{
 		fixed s, c;
 		sincos_approx(a, s, c);
@@ -324,7 +327,7 @@
 		CFixedVector2D u(c, -s);
 		CFixedVector2D v(s, c);
 
-		ObstructionSquare o = { x, z, u, v, w/2, h/2 };
+		ObstructionSquare o = { x, z, u, v, w/2, h/2, circular };
 		return o;
 	}
 
@@ -460,13 +463,13 @@
 		else
 		{
 			StaticShape& shape = m_StaticShapes[TAG_TO_INDEX(tag)];
-			ObstructionSquare o = { shape.x, shape.z, shape.u, shape.v, shape.hw, shape.hh };
+			ObstructionSquare o = { shape.x, shape.z, shape.u, shape.v, shape.hw, shape.hh, shape.circular };
 			return o;
 		}
 	}
 
 	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);
-	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);
+	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);
 	virtual bool TestUnitShape(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t r, std::vector<entity_id_t>* out);
 
 	virtual void Rasterize(Grid<NavcellData>& grid, const std::vector<PathfinderPassability>& passClasses, bool fullUpdate);
@@ -711,7 +714,7 @@
 
 bool CCmpObstructionManager::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)
+	bool circular, std::vector<entity_id_t>* out)
 {
 	PROFILE("TestStaticShape");
 
@@ -746,7 +749,13 @@
 
 		CFixedVector2D center1(it->second.x, it->second.z);
 
-		if (Geometry::PointIsInSquare(center1 - center, u, v, CFixedVector2D(halfSize.X + it->second.clearance, halfSize.Y + it->second.clearance)))
+		bool isInShape;
+		if (circular)
+			isInShape = (center1 - center).CompareLength(halfSize.X) > 0;
+		else
+			isInShape = Geometry::PointIsInSquare(center1 - center, u, v, CFixedVector2D(halfSize.X + it->second.clearance, halfSize.Y + it->second.clearance));
+
+		if (isInShape)
 		{
 			if (out)
 				out->push_back(it->second.entity);
@@ -762,7 +771,13 @@
 
 		CFixedVector2D center1(it->second.x, it->second.z);
 		CFixedVector2D halfSize1(it->second.hw, it->second.hh);
-		if (Geometry::TestSquareSquare(center, u, v, halfSize, center1, it->second.u, it->second.v, halfSize1))
+		bool isInShape;
+		if (circular)
+			isInShape = Geometry::DistanceToSquare(center - center1, it->second.u, it->second.v, halfSize1, true) < halfSize.X;
+		else
+			isInShape = Geometry::TestSquareSquare(center, u, v, halfSize, center1, it->second.u, it->second.v, halfSize1);
+
+		if (isInShape)
 		{
 			if (out)
 				out->push_back(it->second.entity);
@@ -894,7 +909,7 @@
 			continue;
 
 		// TODO: it might be nice to rasterize with rounded corners for large 'expand' values.
-		ObstructionSquare square = { shape.x, shape.z, shape.u, shape.v, shape.hw, shape.hh };
+		ObstructionSquare square = { shape.x, shape.z, shape.u, shape.v, shape.hw, shape.hh, shape.circular };
 		SimRasterize::Spans spans;
 		SimRasterize::RasterizeRectWithClearance(spans, square, clearance, Pathfinding::NAVCELL_SIZE);
 		for (SimRasterize::Span& span : spans)
@@ -986,7 +1001,7 @@
 
 		// TODO: maybe we should use Geometry::GetHalfBoundingBox to be more precise?
 
-		squares.emplace_back(ObstructionSquare{ it->second.x, it->second.z, it->second.u, it->second.v, it->second.hw, it->second.hh });
+		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 });
 	}
 }
 
Index: source/simulation2/components/CCmpPathfinder.cpp
===================================================================
--- source/simulation2/components/CCmpPathfinder.cpp	(revision 18047)
+++ source/simulation2/components/CCmpPathfinder.cpp	(working copy)
@@ -826,16 +826,16 @@
 }
 
 ICmpObstruction::EFoundationCheck CCmpPathfinder::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)
+	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)
 {
-	return CCmpPathfinder::CheckBuildingPlacement(filter, x, z, a, w, h, id, passClass, false);
+	return CCmpPathfinder::CheckBuildingPlacement(filter, x, z, a, w, h, circular, id, passClass, false);
 }
 
 
 ICmpObstruction::EFoundationCheck CCmpPathfinder::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 UNUSED(onlyCenterPoint))
+	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 UNUSED(onlyCenterPoint))
 {
 	// Check unit obstruction
 	CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
@@ -842,7 +842,7 @@
 	if (!cmpObstructionManager)
 		return ICmpObstruction::FOUNDATION_CHECK_FAIL_ERROR;
 
-	if (cmpObstructionManager->TestStaticShape(filter, x, z, a, w, h, NULL))
+	if (cmpObstructionManager->TestStaticShape(filter, x, z, a, w, h, circular, NULL))
 		return ICmpObstruction::FOUNDATION_CHECK_FAIL_OBSTRUCTS_FOUNDATION;
 
 	// Test against terrain:
Index: source/simulation2/components/CCmpPathfinder_Common.h
===================================================================
--- source/simulation2/components/CCmpPathfinder_Common.h	(revision 18047)
+++ source/simulation2/components/CCmpPathfinder_Common.h	(working copy)
@@ -214,9 +214,9 @@
 
 	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);
 
-	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);
+	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);
 
-	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);
+	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);
 
 	virtual void FinishAsyncRequests();
 
Index: source/simulation2/components/ICmpObstructionManager.h
===================================================================
--- source/simulation2/components/ICmpObstructionManager.h	(revision 18047)
+++ source/simulation2/components/ICmpObstructionManager.h	(working copy)
@@ -98,6 +98,7 @@
 	 * @param a angle of rotation (clockwise from +Z direction)
 	 * @param w width (size along X axis)
 	 * @param h height (size along Z axis)
+	 * @param circular (set to true if obstruction is cicular)
 	 * @param flags a set of EFlags values
 	 * @param group primary control group of the shape. Must be a valid control group ID.
 	 * @param group2 Optional; secondary control group of the shape. Defaults to INVALID_ENTITY.
@@ -104,8 +105,9 @@
 	 * @return a valid tag for manipulating the shape
 	 * @see StaticShape
 	 */
-	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) = 0;
+	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, bool circular,
+		flags_t flags, entity_id_t group, entity_id_t group2 = INVALID_ENTITY) = 0;
 
 	/**
 	 * Register a unit shape.
@@ -186,7 +188,7 @@
 	 */
 	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) = 0;
+		bool circular, std::vector<entity_id_t>* out) = 0;
 
 	/**
 	 * Collision test a unit shape against the current set of registered shapes, and optionally writes a list of the colliding
@@ -226,6 +228,7 @@
 		entity_pos_t x, z; // position of center
 		CFixedVector2D u, v; // 'horizontal' and 'vertical' orthogonal unit vectors, representing orientation
 		entity_pos_t hw, hh; // half width, half height of square
+		bool circular; // set to true if the obstruction is circle-shaped
 	};
 
 	/**
@@ -259,7 +262,7 @@
 
 	virtual ObstructionSquare GetUnitShapeObstruction(entity_pos_t x, entity_pos_t z, entity_pos_t clearance) = 0;
 
-	virtual ObstructionSquare GetStaticShapeObstruction(entity_pos_t x, entity_pos_t z, entity_angle_t a, entity_pos_t w, entity_pos_t h) = 0;
+	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;
 
 	/**
 	 * Set the passability to be restricted to a circular map.
Index: source/simulation2/components/ICmpPathfinder.h
===================================================================
--- source/simulation2/components/ICmpPathfinder.h	(revision 18047)
+++ source/simulation2/components/ICmpPathfinder.h	(working copy)
@@ -146,7 +146,7 @@
 	 * @return ICmpObstruction::FOUNDATION_CHECK_SUCCESS if the placement is okay, else
 	 *	a value describing the type of failure.
 	 */
-	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;
+	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;
 
 	/**
 	 * Check whether a building placed here is valid and doesn't hit any obstructions
@@ -155,7 +155,7 @@
 	 * @return ICmpObstruction::FOUNDATION_CHECK_SUCCESS if the placement is okay, else
 	 *	a value describing the type of failure.
 	 */
-	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;
+	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;
 
 
 	/**
Index: source/simulation2/components/tests/test_ObstructionManager.h
===================================================================
--- source/simulation2/components/tests/test_ObstructionManager.h	(revision 18047)
+++ source/simulation2/components/tests/test_ObstructionManager.h	(working copy)
@@ -111,7 +111,7 @@
 		TS_ASSERT_EQUALS(ent3, out[0]);
 		out.clear();
 
-		cmp->TestStaticShape(nullFilter, ent3x, ent3z, fixed::Zero(), fixed::FromInt(1), fixed::FromInt(1), &out);
+		cmp->TestStaticShape(nullFilter, ent3x, ent3z, fixed::Zero(), fixed::FromInt(1), fixed::FromInt(1), false, &out);
 		TS_ASSERT_EQUALS(1U, out.size());
 		TS_ASSERT_EQUALS(ent3, out[0]);
 		out.clear();
@@ -125,7 +125,7 @@
 		TS_ASSERT_VECTOR_CONTAINS(out, ent2);
 		out.clear();
 
-		cmp->TestStaticShape(nullFilter, ent2x, ent2z, fixed::Zero(), ent2c, ent2c, &out);
+		cmp->TestStaticShape(nullFilter, ent2x, ent2z, fixed::Zero(), ent2c, ent2c, false, &out);
 		TS_ASSERT_EQUALS(2U, out.size());
 		TS_ASSERT_VECTOR_CONTAINS(out, ent1);
 		TS_ASSERT_VECTOR_CONTAINS(out, ent2);
@@ -152,7 +152,7 @@
 		TS_ASSERT_VECTOR_CONTAINS(out, ent3);
 		out.clear();
 
-		cmp->TestStaticShape(nullFilter, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), &out);
+		cmp->TestStaticShape(nullFilter, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), false, &out);
 		TS_ASSERT_EQUALS(3U, out.size());
 		TS_ASSERT_VECTOR_CONTAINS(out, ent1);
 		TS_ASSERT_VECTOR_CONTAINS(out, ent2);
@@ -180,7 +180,7 @@
 		TS_ASSERT_VECTOR_CONTAINS(out, ent3);
 		out.clear();
 
-		cmp->TestStaticShape(ignoreMoving, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), &out);
+		cmp->TestStaticShape(ignoreMoving, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), false, &out);
 		TS_ASSERT_EQUALS(2U, out.size());
 		TS_ASSERT_VECTOR_CONTAINS(out, ent2);
 		TS_ASSERT_VECTOR_CONTAINS(out, ent3);
@@ -205,7 +205,7 @@
 		TS_ASSERT_EQUALS(ent1, out[0]);
 		out.clear();
 
-		cmp->TestStaticShape(ignoreShape2, ent2x, ent2z, fixed::Zero(), ent2c, ent2c, &out);
+		cmp->TestStaticShape(ignoreShape2, ent2x, ent2z, fixed::Zero(), ent2c, ent2c, false, &out);
 		TS_ASSERT_EQUALS(1U, out.size());
 		TS_ASSERT_EQUALS(ent1, out[0]);
 		out.clear();
@@ -230,7 +230,7 @@
 		TS_ASSERT_EQUALS(ent3, out[0]);
 		out.clear();
 
-		cmp->TestStaticShape(skipShape1RequireBlockMovement, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), &out);
+		cmp->TestStaticShape(skipShape1RequireBlockMovement, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), false, &out);
 		TS_ASSERT_EQUALS(1U, out.size());
 		TS_ASSERT_EQUALS(ent3, out[0]);
 		out.clear();
@@ -247,7 +247,7 @@
 		TS_ASSERT_VECTOR_CONTAINS(out, ent3);
 		out.clear();
 
-		cmp->TestStaticShape(skipShape1RequireAnyFlag, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), &out);
+		cmp->TestStaticShape(skipShape1RequireAnyFlag, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), false, &out);
 		TS_ASSERT_EQUALS(2U, out.size());
 		TS_ASSERT_VECTOR_CONTAINS(out, ent2);
 		TS_ASSERT_VECTOR_CONTAINS(out, ent3);
@@ -262,7 +262,7 @@
 		TS_ASSERT_EQUALS(0U, out.size());
 		out.clear();
 
-		cmp->TestStaticShape(skipShape1RejectAll, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), &out);
+		cmp->TestStaticShape(skipShape1RejectAll, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), false, &out);
 		TS_ASSERT_EQUALS(0U, out.size());
 		out.clear();
 	}
@@ -290,7 +290,7 @@
 		TS_ASSERT_EQUALS(ent3, out[0]);
 		out.clear();
 
-		cmp->TestStaticShape(skipGroup1ReqFoundConstr, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), &out);
+		cmp->TestStaticShape(skipGroup1ReqFoundConstr, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), false, &out);
 		TS_ASSERT_EQUALS(1U, out.size());
 		TS_ASSERT_EQUALS(ent3, out[0]);
 		out.clear();
@@ -306,7 +306,7 @@
 		TS_ASSERT_EQUALS(0U, out.size());
 		out.clear();
 
-		cmp->TestStaticShape(skipGroup1And3ReqFoundConstr, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), &out);
+		cmp->TestStaticShape(skipGroup1And3ReqFoundConstr, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), false, &out);
 		TS_ASSERT_EQUALS(0U, out.size());
 		out.clear();
 
@@ -323,7 +323,7 @@
 		TS_ASSERT_VECTOR_CONTAINS(out, ent2);
 		out.clear();
 
-		cmp->TestStaticShape(skipGroup3RequireAnyFlag, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), &out);
+		cmp->TestStaticShape(skipGroup3RequireAnyFlag, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), false, &out);
 		TS_ASSERT_EQUALS(2U, out.size());
 		TS_ASSERT_VECTOR_CONTAINS(out, ent1);
 		TS_ASSERT_VECTOR_CONTAINS(out, ent2);
@@ -339,7 +339,7 @@
 		TS_ASSERT_EQUALS(0U, out.size());
 		out.clear();
 
-		cmp->TestStaticShape(skipGroup3RequireNoFlags, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), &out);
+		cmp->TestStaticShape(skipGroup3RequireNoFlags, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), false, &out);
 		TS_ASSERT_EQUALS(0U, out.size());
 		out.clear();
 
@@ -378,7 +378,7 @@
 		TS_ASSERT_VECTOR_CONTAINS(out, ent3);
 		out.clear();
 
-		cmp->TestStaticShape(skipGroup1SecAnd4SecRequireAny, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), &out);
+		cmp->TestStaticShape(skipGroup1SecAnd4SecRequireAny, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), false, &out);
 		TS_ASSERT_EQUALS(2U, out.size());
 		TS_ASSERT_VECTOR_CONTAINS(out, ent2);
 		TS_ASSERT_VECTOR_CONTAINS(out, ent3);
@@ -397,7 +397,7 @@
 		TS_ASSERT_VECTOR_CONTAINS(out, ent3);
 		out.clear();
 
-		cmp->TestStaticShape(skipGroup1SecAnd4PrimRequireAny, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), &out);
+		cmp->TestStaticShape(skipGroup1SecAnd4PrimRequireAny, ent1x, ent1z, fixed::Zero(), fixed::FromInt(10), fixed::FromInt(10), false, &out);
 		TS_ASSERT_EQUALS(2U, out.size());
 		TS_ASSERT_VECTOR_CONTAINS(out, ent2);
 		TS_ASSERT_VECTOR_CONTAINS(out, ent3);
@@ -423,7 +423,7 @@
 		             ent4x = ent3x + ent3c + ent4w/2, // make ent4 adjacent to ent3
 		             ent4z = ent3z;
 
-		cmp->TestStaticShape(nullFilter, ent4x, ent4z, ent4a, ent4w, ent4h, &out);
+		cmp->TestStaticShape(nullFilter, ent4x, ent4z, ent4a, ent4w, ent4h, false, &out);
 		TS_ASSERT_EQUALS(1U, out.size());
 		TS_ASSERT_EQUALS(ent3, out[0]);
 		out.clear();
@@ -435,7 +435,7 @@
 
 		// now do the same tests, but move the shape a little bit to the right so that it doesn't touch anymore
 
-		cmp->TestStaticShape(nullFilter, ent4x + fixed::FromFloat(1e-5f), ent4z, ent4a, ent4w, ent4h, &out);
+		cmp->TestStaticShape(nullFilter, ent4x + fixed::FromFloat(1e-5f), ent4z, ent4a, ent4w, ent4h, false, &out);
 		TS_ASSERT_EQUALS(0U, out.size());
 		out.clear();
 
Index: source/simulation2/helpers/Rasterize.cpp
===================================================================
--- source/simulation2/helpers/Rasterize.cpp	(revision 18047)
+++ source/simulation2/helpers/Rasterize.cpp	(working copy)
@@ -56,7 +56,7 @@
 		return; // empty bounds - this shouldn't happen
 
 
-	rasterClearance = rasterClearance.Multiply(rasterClearance);
+	entity_pos_t rasterClearanceSq = rasterClearance.Multiply(rasterClearance);
 
 	spans.reserve(j1 - j0);
 	
@@ -80,8 +80,13 @@
 				continue;
 			}
 
-			if (Geometry::DistanceToSquareSquared(CFixedVector2D(cellSize*(i+1)-shape.x, cellSize*j-shape.z),
-									shape.u, shape.v, shapeHalfSize, true) > rasterClearance)
+			CFixedVector2D diff(cellSize*(i+1)-shape.x, cellSize*j-shape.z);
+			bool isOutShape;
+			if (shape.circular)
+				isOutShape = diff.CompareLength(rasterClearance + shapeHalfSize.X) > 0;
+			else
+				isOutShape = Geometry::DistanceToSquareSquared(diff, shape.u, shape.v, shapeHalfSize, true) > rasterClearanceSq;
+			if (isOutShape)
 			{
 				if (previousInside)
 					break;
@@ -89,8 +94,12 @@
 				continue;
 			}
 
-			if (Geometry::DistanceToSquareSquared(CFixedVector2D(cellSize*(i+1)-shape.x, cellSize*(j+1)-shape.z),
-									shape.u, shape.v, shapeHalfSize, true) > rasterClearance)
+			diff.Y += cellSize; // one to the right
+			if (shape.circular)
+				isOutShape = diff.CompareLength(rasterClearance + shapeHalfSize.X) > 0;
+			else
+				isOutShape = Geometry::DistanceToSquareSquared(diff, shape.u, shape.v, shapeHalfSize, true) > rasterClearanceSq;
+			if (isOutShape)
 			{
 				if (previousInside)
 					break;
@@ -100,12 +109,20 @@
 
 			if (!previousInside)
 			{
-				if (Geometry::DistanceToSquareSquared(CFixedVector2D(cellSize*i-shape.x, cellSize*j-shape.z),
-									shape.u, shape.v, shapeHalfSize, true) > rasterClearance)
+				diff.X -= cellSize; // one step backwards
+				if (shape.circular)
+					isOutShape = diff.CompareLength(rasterClearance + shapeHalfSize.X) > 0;
+				else
+					isOutShape = Geometry::DistanceToSquareSquared(diff, shape.u, shape.v, shapeHalfSize, true) > rasterClearanceSq;
+				if (isOutShape)
 					continue;
 
-				if (Geometry::DistanceToSquareSquared(CFixedVector2D(cellSize*i-shape.x, cellSize*(j+1)-shape.z),
-									shape.u, shape.v, shapeHalfSize, true) > rasterClearance)
+				diff.Y -= cellSize; // one to the left
+				if (shape.circular)
+					isOutShape = diff.CompareLength(rasterClearance + shapeHalfSize.X) > 0;
+				else
+					isOutShape = Geometry::DistanceToSquareSquared(diff, shape.u, shape.v, shapeHalfSize, true) > rasterClearanceSq;
+				if (isOutShape)
 					continue;
 
 				previousInside = true;
