// move to social comparison state if can and should. Return true if can and should and move, else return false public bool moveToSocialComparisonStateInStructureIfShould(clsGroundAtom refGroundAtom) { double socialComparisonProbability = Util.random.NextDouble(); // draw probabilistically whether to compare or not if (socialComparisonProbability <= refGroundAtom.getSocialComparisonProbability()) { // do social comparison clsGroundAtom mostSimilar = SocialComparison.findMostSimilarInStructure(refGroundAtom, Structure); // check if there is someone similar to me if (mostSimilar != null) { refGroundAtom.ChangeState(new SOCIAL_COMPARISON_IN_STRUCTURE_STATE(Structure, mostSimilar)); return(true); } // if couldn't find someone similar in vicinity do not compare } return(false); }
private void MoveInStructure(clsGroundAtom refGroundAtom, int DeltaTime) { double DeltaTimeSec = DeltaTime * 0.001; double dist = refGroundAtom.currentSpeed * DeltaTimeSec / 3600; double oldX = refGroundAtom.curr_X; double oldY = refGroundAtom.curr_Y; // YD - fixed bug where atoms in building travel way to fast than they should be. // Details: In the third line below addition of distance in meters to position in coordinates! //TerrainService.Vector vt = targetPosition - refGroundAtom.currPosition; //vt.normalize(); //TerrainService.Vector NewPosition = refGroundAtom.currPosition + (vt * dist); ////......... TerrainService.Vector vt = targetPosition - refGroundAtom.currPosition; double targetDist = TerrainService.MathEngine.CalcDistance(refGroundAtom.currPosition.x, refGroundAtom.currPosition.y, targetPosition.x, targetPosition.y); double targetAzimuth = Util.Azimuth2Points(refGroundAtom.currPosition.x, refGroundAtom.currPosition.y, targetPosition.x, targetPosition.y); TerrainService.Vector NewPosition = new TerrainService.Vector(); TerrainService.MathEngine.CalcProjectedLocationNew(refGroundAtom.currPosition.x, refGroundAtom.currPosition.y, targetAzimuth, 1000 * dist, out NewPosition.x, out NewPosition.y); // ---------------------------------------------------------------------------------------- // check if in collision clsGroundAtom collidingAtom = null; manageCollisions(refGroundAtom, NewPosition, out collidingAtom); TerrainService.GeometryHelper.Edge CrossedEdge = new TerrainService.GeometryHelper.Edge(); TerrainService.shPoint[] Pnts = Structure.Points.ToArray(); // step aside in case of collision if (!refGroundAtom.isCollision) { // draw avoidance side randomly to when collision will occur int random = Util.random.Next(2) * 2 - 1; refGroundAtom.Offset_Azimuth = 90 * random; } if (refGroundAtom.isCollision) { // choose side to step to according to social comparison theory clsGroundAtom mostSimilar = SocialComparison.findMostSimilarInStructure(refGroundAtom, Structure); if (mostSimilar != null) { TerrainService.Vector headingVector = new TerrainService.Vector(); headingVector.x = targetPosition.x - refGroundAtom.curr_X; headingVector.y = targetPosition.y - refGroundAtom.curr_Y; TerrainService.Vector vectorToMostSimilar = new TerrainService.Vector(); vectorToMostSimilar.x = mostSimilar.curr_X - refGroundAtom.curr_X; vectorToMostSimilar.y = mostSimilar.curr_Y - refGroundAtom.curr_Y; bool mostSimilarIsToTheLeft = (headingVector ^ vectorToMostSimilar).norm() > 0; if (mostSimilarIsToTheLeft) { refGroundAtom.Offset_Azimuth = 90; } else { refGroundAtom.Offset_Azimuth = -90; } } List <CollisionTime> collisions = refGroundAtom.Collisions; double azimuthToCollidingAtom = Util.Azimuth2Points(refGroundAtom.currPosition.x, refGroundAtom.currPosition.y, collidingAtom.currPosition.x, collidingAtom.currPosition.y); TerrainService.MathEngine.CalcProjectedLocationNew(refGroundAtom.currPosition.x, refGroundAtom.currPosition.y, azimuthToCollidingAtom + refGroundAtom.Offset_Azimuth, 1000 * dist, out NewPosition.x, out NewPosition.y); } bool isCross = TerrainService.GeometryHelper.GeometryMath.isPolygonBorderCross(refGroundAtom.curr_X, refGroundAtom.curr_Y, NewPosition.x, NewPosition.y, ref Pnts, ref CrossedEdge); if (isCross) { CrossedEdge.rot90(); TerrainService.Vector orig = new TerrainService.Vector(CrossedEdge.org.x, CrossedEdge.org.y, 0); TerrainService.Vector dest = new TerrainService.Vector(CrossedEdge.dest.x, CrossedEdge.dest.y, 0); TerrainService.Vector n = dest - orig; n.normalize(); TerrainService.Vector NewD = vt - 2 * (vt * n) * n; NewD.normalize(); TerrainService.Vector NewDirect = NewD * 5000; // YD: calculate new target position according to next waypoint and not randomly //targetPosition = NewDirect; targetPosition = CalculateNextWaypointPosition(refGroundAtom); // --- // YD: Bug fix for moving too fast in buildings //vt = targetPosition - refGroundAtom.currPosition; //vt.normalize(); //NewPosition = refGroundAtom.currPosition + (vt * dist); vt = targetPosition - refGroundAtom.currPosition; targetDist = TerrainService.MathEngine.CalcDistance(refGroundAtom.currPosition.x, refGroundAtom.currPosition.y, targetPosition.x, targetPosition.y) / 1000; targetAzimuth = Util.Azimuth2Points(refGroundAtom.currPosition.x, refGroundAtom.currPosition.y, targetPosition.x, targetPosition.y); TerrainService.MathEngine.CalcProjectedLocationNew(refGroundAtom.currPosition.x, refGroundAtom.currPosition.y, targetAzimuth, 1000 * dist, out NewPosition.x, out NewPosition.y); // --------------------------------------------------------------------------------- //refGroundAtom.currPosition = NewPosition; //refGroundAtom.curr_X = refGroundAtom.currPosition.x; //refGroundAtom.curr_Y = refGroundAtom.currPosition.y; // return; } refGroundAtom.currPosition = NewPosition; // YD: get current azimuth refGroundAtom.currentAzimuth = Util.Azimuth2Points(refGroundAtom.curr_X, refGroundAtom.curr_Y, NewPosition.x, NewPosition.y); refGroundAtom.curr_X = refGroundAtom.currPosition.x; refGroundAtom.curr_Y = refGroundAtom.currPosition.y; bool isIn = TerrainService.GeometryHelper.GeometryMath.isPointInPolygon(refGroundAtom.curr_X, refGroundAtom.curr_Y, ref Pnts); if (isIn == false) { System.Random Rnd = new Random(); while (true) { double vRnd = Rnd.NextDouble(); double randX = Structure.minX + (Structure.maxX - Structure.minX) * vRnd; vRnd = Rnd.NextDouble(); double randY = Structure.minY + (Structure.maxY - Structure.minY) * vRnd; bool inPolygon = TerrainService.GeometryHelper.GeometryMath.isPointInPolygon(randX, randY, ref Pnts); if (inPolygon == true) { refGroundAtom.curr_X = randX; refGroundAtom.curr_Y = randY; refGroundAtom.currPosition = new TerrainService.Vector(randX, randY, 0); // YD: calculate new target position according to next waypoint and not randomly //targetPosition = CalculateNextRandomPosition(5000, refGroundAtom.curr_X, refGroundAtom.curr_Y); targetPosition = CalculateNextWaypointPosition(refGroundAtom); // --- break; } } } // YD: since there are more than once structure, update possition according to the right structure's quadtree refGroundAtom.m_GameObject.getQuadTreeByStructure(Structure).PositionUpdate(refGroundAtom); }