bool CChar::CanSeeLOS( const CObjBaseTemplate *pObj, word wFlags, bool bCombatCheck ) const { ADDTOCALLSTACK("CChar::CanSeeLOS"); // WARNING: CanSeeLOS is an expensive function (lot of calculations but most importantly it has to read the UO files, and file I/O is slow). if ( !CanSee(pObj) ) return false; pObj = pObj->GetTopLevelObj(); if ( !pObj ) return false; if ( (m_pPlayer && (g_Cfg.m_iAdvancedLos & ADVANCEDLOS_PLAYER)) || (m_pNPC && (g_Cfg.m_iAdvancedLos & ADVANCEDLOS_NPC)) ) { CPointMap pt = pObj->GetTopPoint(); const CChar *pChar = dynamic_cast<const CChar*>(pObj); if ( pChar ) { short iTotalZ = pt.m_z + pChar->GetHeightMount(true); pt.m_z = (char)minimum(iTotalZ, UO_SIZE_Z); } return CanSeeLOS_New(pt, nullptr, pObj->GetVisualRange(), wFlags, bCombatCheck); } else return CanSeeLOS(pObj->GetTopPoint(), nullptr, pObj->GetVisualRange(), wFlags, bCombatCheck); }
bool ZActor::CanAttackMelee(ZObject* pTarget, ZSkillDesc *pSkillDesc) { if (pSkillDesc == NULL) { float dist = Magnitude(pTarget->m_Position - m_Position); if (dist < m_pNPCInfo->fAttackRange) { if (CanSee(pTarget)) return true; } } else { rvector Pos = GetPosition(); rvector Dir = GetDirection(); Dir.z=0; Normalize(Dir); float fDist = Magnitude(Pos - pTarget->GetPosition()); float fColMinRange = pSkillDesc->fEffectAreaMin * 100.0f; float fColMaxRange = pSkillDesc->fEffectArea * 100.0f; if ((fDist < fColMaxRange + pTarget->GetCollRadius()) && (fDist >= fColMinRange)) { rvector vTargetDir = pTarget->GetPosition() - GetPosition(); rvector vBodyDir = GetDirection(); vBodyDir.z = vTargetDir.z = 0.0f; float angle = fabs(GetAngleOfVectors(vTargetDir, vBodyDir)); if (angle <= pSkillDesc->fEffectAngle) return true; } } return false; }
void CASW_Simple_Alien::WhatToDoNext(float delta) { if (m_iState == ASW_SIMPLE_ALIEN_ATTACKING) { if (!GetEnemy() || !CanSee(GetEnemy()) || GetEnemy()->GetHealth() <= 0) { LostEnemy(); // clears our enemy and sets us back to idling } else { // head towards enemy SetMoveTarget(GetChaseDestination(GetEnemy())); PerformMovement(delta); } SetNextThink( gpGlobals->curtime + 0.1f ); } else if (m_iState == ASW_SIMPLE_ALIEN_IDLING) { // look for a new enemy? FindNewEnemy(); if (GetEnemy()) SetNextThink( gpGlobals->curtime + 0.1f ); else SetNextThink( gpGlobals->curtime + 0.5f ); } else if (m_iState == ASW_SIMPLE_ALIEN_DEAD) { // don't need to think again } // todo: if in moving to dest state, then move towards that dest, etc. }
/** Check warnings on a specific object. * We check for ownership or hasprivs before allowing this. * \param player the enactor. * \param name name of object to check. */ void do_wcheck(dbref player, const char *name) { dbref thing; switch (thing = match_result(player, name, NOTYPE, MAT_EVERYTHING)) { case NOTHING: notify(player, T("I don't see that object.")); return; case AMBIGUOUS: notify(player, T("I don't know which one you mean.")); return; default: if (!(CanSee(player, thing) || (Owner(player) == Owner(thing)))) { notify(player, T("Permission denied.")); return; } if (IsGarbage(thing)) { notify(player, T("Why would you want to be warned about garbage?")); return; } break; } check_topology_on(player, thing); notify(player, T("@wcheck complete.")); return; }
void CASW_Sentry_Top::FindEnemy() { bool bFindNewEnemy = true; bool bHadEnemy = (m_hEnemy.IsValid() && m_hEnemy.Get()); // if have an enemy and it is alive if (m_hEnemy.IsValid() && m_hEnemy.Get() && m_hEnemy->GetHealth() > 0 ) { // check for LOS to enemy if (CanSee(m_hEnemy)) bFindNewEnemy = false; // reject if enemy is somehow invalid now CAI_BaseNPC *pNPC = dynamic_cast<CAI_BaseNPC *>(m_hEnemy.Get()); if ( pNPC && !IsValidEnemy(pNPC) ) bFindNewEnemy = true; } if (bFindNewEnemy) { if ( g_vecTargetDummies.Count() > 0 ) { m_hEnemy = g_vecTargetDummies[0]; } else { m_hEnemy = SelectOptimalEnemy(); } } // acquired a new enemy if (!bHadEnemy && m_hEnemy.IsValid() && m_hEnemy.Get()) { PlayTurnSound(); } }
CAI_BaseNPC * CASW_Sentry_Top::SelectOptimalEnemy() { // search through all npcs, any that are in LOS and have health CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ ) { if (ppAIs[i]->GetHealth() > 0 && CanSee(ppAIs[i])) { // don't shoot marines if ( !asw_sentry_friendly_target.GetBool() && (ppAIs[i]->Classify() == CLASS_ASW_MARINE || ppAIs[i]->Classify() == CLASS_ASW_COLONIST) ) continue; if ( ppAIs[i]->Classify() == CLASS_SCANNER ) continue; if ( !IsValidEnemy( ppAIs[i] ) ) continue; return ppAIs[i]; break; } } // todo: should evaluate valid targets and pick the best one? // (didn't do this for ASv1 and it was fine...) return NULL; }
void CASW_Simple_Alien::FindNewEnemy() { float dist; CBaseEntity *pNearest = UTIL_ASW_NearestMarine(GetAbsOrigin(), dist); if (CanSee(pNearest)) { SetEnemy(pNearest); } }
/** Build CUList for showing this join/part/kick */ void BuildExcept(Membership* memb, CUList& excepts) { if (IsVisible(memb)) return; const Channel::MemberMap& users = memb->chan->GetUsers(); for (Channel::MemberMap::const_iterator i = users.begin(); i != users.end(); ++i) { if (IS_LOCAL(i->first) && !CanSee(i->first, memb)) excepts.insert(i->first); } }
/** Build CUList for showing this join/part/kick */ void BuildExcept(Membership* memb, CUList& excepts) { if (IsVisible(memb)) return; const UserMembList* users = memb->chan->GetUsers(); for(UserMembCIter i = users->begin(); i != users->end(); i++) { if (IS_LOCAL(i->first) && !CanSee(i->first, memb)) excepts.insert(i->first); } }
void CChar::NPC_PetConfirmCommand(bool bSuccess, CChar *pMaster) { ADDTOCALLSTACK("CChar::NPC_PetConfirmCommand"); // I take a command from my master if ( !m_pNPC || !g_Cfg.m_sSpeechPet.IsEmpty() || !CanSee(pMaster) ) return; if ( NPC_CanSpeak() ) Speak(bSuccess ? g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_SUCCESS) : g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_FAILURE)); else SoundChar(bSuccess ? CRESND_IDLE : CRESND_NOTICE); }
// // Set visible cells in +- quadrant // void CompareGradPosNeg() { for (z = 0, z2 = 0; z2 < r2; z2 += 2 * z + 1, ++z) { for (x = 1, x2 = 1; x2 + z2 < r2; x2 += 2 * x + 1, ++x) { dx = z; dz = -x; if (maxGradMap[z][x]<=gradMapU[z][x]) { CanSee(cellX + dx, cellZ + dz, dx, dz, mapLo, maskLo, teamBits, Map::LV_LO); } } } }
void CSynAoiDimObj::PostMsgToViewee(const void* pContext) { CSynAoiDimObj* pObject; ViewObjSet_t::const_iterator iter = m_setObjInMyViewRect.begin(); ViewObjSet_t::const_iterator iter_end = m_setObjInMyViewRect.end(); while (iter != iter_end) { pObject = (*iter); if (CanSee(pObject)) { pObject->OnMsgFromViewer(pContext); } ++iter; } OnMsgToVieweeHandled(pContext); }
void CSynAoiDimObj::PostMsgToSyncer(const void *pContext) { CSynAoiDimObj* pObject; ViewObjSet_t::const_iterator iter = m_setObjInMyViewRect.begin(); ViewObjSet_t::const_iterator iter_end = m_setObjInMyViewRect.end(); while (iter != iter_end) { pObject = (*iter); if (CanSee(pObject)) { CFPos OtPos = pObject->GetPosition(); if(m_pDimScene->IsInSyncAoi(OtPos - m_Pos)) pObject->OnMsgFromSyncee(pContext); } ++iter; } OnMsgToSyncerHandled(pContext); }
/* Can we see s2 from s1 ? */ bool SquareLine::CanSee(Square s1, Square s2, Board *w) { s_cur=s1; s_goal=s2; p_lastipoint=vector2d::Invalid; board=w; sg.p0=board->GetCenterInPx(s1); sg.p1=board->GetCenterInPx(s2); #if defined(_showdebugger_) // Debugger::GetInstance().Output("from (%d,%d) to (%d,%d)\n",s_cur.x,s_cur.y,s_goal.x,s_goal.y); #endif //defined(_showdebugger_) bool t = CanSee(); #if defined(_showdebugger_) // Debugger::GetInstance().Output("\n"); #endif //defined(_showdebugger_) return t; }
void CChar::NPC_OnPetCommand( bool fSuccess, CChar * pMaster ) { ADDTOCALLSTACK("CChar::NPC_OnPetCommand"); if ( m_pPlayer ) // players don't respond return; if ( !g_Cfg.m_sSpeechPet.IsEmpty() ) return; if ( !CanSee( pMaster ) ) return; // i take a command from my master. if ( NPC_CanSpeak()) { Speak( fSuccess? g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_SUCCESS ) : g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_FAILURE ) ); } else { SoundChar( fSuccess? CRESND_RAND1 : CRESND_RAND2 ); } }
visibility_t NPC_CheckVisibility ( gentity_t *ent, int flags ) { // flags should never be 0 if ( !flags ) { return VIS_NOT; } // check PVS if ( flags & CHECK_PVS ) { if ( !gi.inPVS ( ent->currentOrigin, NPC->currentOrigin ) ) { return VIS_NOT; } } if ( !(flags & (CHECK_360|CHECK_FOV|CHECK_SHOOT)) ) { return VIS_PVS; } // check within visrange if (flags & CHECK_VISRANGE) { if( !InVisrange ( ent ) ) { return VIS_PVS; } } // check 360 degree visibility //Meaning has to be a direct line of site if ( flags & CHECK_360 ) { if ( !CanSee ( ent ) ) { return VIS_PVS; } } if ( !(flags & (CHECK_FOV|CHECK_SHOOT)) ) { return VIS_360; } // check FOV if ( flags & CHECK_FOV ) { if ( !InFOV ( ent, NPC, NPCInfo->stats.hfov, NPCInfo->stats.vfov) ) { return VIS_360; } } if ( !(flags & CHECK_SHOOT) ) { return VIS_FOV; } // check shootability if ( flags & CHECK_SHOOT ) { if ( !CanShoot ( ent, NPC ) ) { return VIS_FOV; } } return VIS_SHOOT; }
void Coloring(Model& integ) { //CalculateDistance(integ); CalculateDistance_AllVoxel(integ); cout << "CalculateNormal: " << endl; // CalculateNormal(integ); // vector<cv::Mat> UpSilhouette(ImageNum); ReadSilhouette(ImageNum, directory[1], model, pose[0], UpSilhouette); vector<cv::Mat> DownSilhouette(ImageNum); ReadSilhouette(ImageNum, directory[1], model, pose[1], DownSilhouette); vector<cv::Mat> UpImage(ImageNum); ReadColorImage(ImageNum, directory[0], model, pose[0], UpImage); vector<cv::Mat> DownImage(ImageNum); ReadColorImage(ImageNum, directory[0], model, pose[1], DownImage); cv::Point temp; int R, G, B; int step = UpImage[0].step; int width = UpSilhouette[0].cols; int height = UpSilhouette[0].rows; CColor tempColor(0.0, 0.0, 0.0); Color_hue tempColorH; vector<Color_hue> VoxColor; CVector3d Point_Image; short templum; //short thre(50); short thre(123); Color_hue tempBackColor; tempBackColor.r = integ.BackColor.r; tempBackColor.g = integ.BackColor.g; tempBackColor.b = integ.BackColor.b; tempBackColor.CalcHue(); integ.SurfColors.reserve(integ.SurfNum); // int ring1[][2] = { {0, 0}, {-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1} }; // // // integ.Voxel_colors = new CColor **[integ.num[0]]; for (int i(0); i < integ.num[0]; i++) { integ.Voxel_colors[i] = new CColor *[integ.num[1]]; for (int k(0); k < integ.num[1]; k++) integ.Voxel_colors[i][k] = new CColor[integ.num[2]]; } cout << "\nCheck visable voxels which can be seen\n" << endl; for (int x = 1; x < integ.num[0] - 1; x++) { for (int y = 1; y < integ.num[1] - 1; y++) { for (int z = 1; z < integ.num[2] - 1; z++) { // if (integ.Voxels[x][y][z].surf) { // VoxColor.clear(); for (int i = 0; i < ImageNum; i++) { CanSee(integ, x, y, z, CameraPosUp[i], "UP"); //true(UP) //UP if (integ.Flags[x][y][z].upCan) { integ.Voxels[x][y][z].line.push_back(CameraPosUp[i] - integ.Voxels[x][y][z].center); temp = integ.Voxels[x][y][z].CalcImageCoordofCenter(ART[i]); //� // for (int n = 0; n < 9; n++) { templum = (short)(UpSilhouette[i].data[width * (temp.y + ring1[n][1]) + temp.x + ring1[n][0]]); if (templum < thre) continue; //opencv tempColorH.Clear(); B = UpImage[i].data[step * (temp.y + ring1[n][1]) + (temp.x + ring1[n][0]) * 3]; G = UpImage[i].data[step * (temp.y + ring1[n][1]) + (temp.x + ring1[n][0]) * 3 + 1]; R = UpImage[i].data[step * (temp.y + ring1[n][1]) + (temp.x + ring1[n][0]) * 3 + 2]; tempColorH.b = B / 255.0; tempColorH.g = G / 255.0; tempColorH.r = R / 255.0; tempColorH.CalcHue(); tempColorH.CalcLuminance(); //if( fabs(tempBackColor.GetHue() - tempColorH.GetHue()) < HueGap_Thres ) //�w�i�F�̐F���ɋ߂��F�͎g�p���Ȃ� // continue; // //�V�}�E�}��p //if(tempColorH.luminance>0.5){ // tempColorH.Set(1.0,1.0,1.0); //} //else{ // tempColorH.Set(0.0,0.0,0.0); //} VoxColor.push_back(tempColorH); } } CanSee(integ, x, y, z, CameraPosDown[i], "DOWN"); //false(DOWN) //DOWN if (integ.Flags[x][y][z].downCan) { integ.Voxels[x][y][z].line.push_back(CameraPosDown[i] - integ.Voxels[x][y][z].center); temp = integ.Voxels[x][y][z].CalcImageCoordofCenter(ARTRTinv[i]); //� // for (int n = 0; n < 9; n++) { templum = (short)(DownSilhouette[i].data[width * (temp.y + ring1[n][1]) + temp.x + ring1[n][0]]); if (templum < thre) // continue; //opencv� tempColorH.Clear(); B = DownImage[i].data[step * (temp.y + ring1[n][1]) + (temp.x + ring1[n][0]) * 3]; G = DownImage[i].data[step * (temp.y + ring1[n][1]) + (temp.x + ring1[n][0]) * 3 + 1]; R = DownImage[i].data[step * (temp.y + ring1[n][1]) + (temp.x + ring1[n][0]) * 3 + 2]; tempColorH.b = B / 255.0; tempColorH.g = G / 255.0; tempColorH.r = R / 255.0; tempColorH.CalcHue(); tempColorH.CalcLuminance(); //if( fabs(tempBackColor.GetHue() - tempColorH.GetHue()) < HueGap_Thres ) // continue; // //if(tempColorH.luminance>0.5){ // tempColorH.Set(1.0,1.0,1.0); //} //else{ // tempColorH.Set(0.0,0.0,0.0); //} VoxColor.push_back(tempColorH); } } } if (!VoxColor.empty()) { tempColor = GetVoxelColor_hue_mode(VoxColor); //tempColor = GetVoxelColor_lumi_mode(VoxColor); //cout<<tempColor.r <<" "<<tempColor.g<<" "<<tempColor.b<<endl; integ.Voxel_colors[x][y][z] = tempColor; integ.SurfColors.push_back(tempColor); } else { integ.Voxel_colors[x][y][z] = tempColor; integ.SurfColors.push_back(tempColor); //0.0.0.0.0.0 } } } } } // UpSilhouette.clear(); UpSilhouette.shrink_to_fit(); DownSilhouette.clear(); DownSilhouette.shrink_to_fit(); UpImage.clear(); UpImage.shrink_to_fit(); DownImage.clear(); DownImage.shrink_to_fit(); }
// // New and improved sweep // void Sweep(UnitObj *u) { ASSERT(sysInit); ASSERT(u); //ASSERT(u->GetTeam()); ASSERT(u->OnMap()); START(sweepTime); r = u->GetSeeingRange(); unit = u; cellX = u->cellX; cellZ = u->cellZ; ASSERT(r < MAXR) // Get sight map and mask maskLo = u->sightMap->GetBitMask(Map::LV_LO); mapLo = u->sightMap->GetByteMap(Map::LV_LO); // Reset max radius seen u->sightMap->lastR = S16_MIN; // Set teams that this sweep will provide LOS for Team *myTeam = u->GetTeam(); teamBits = 0; if (myTeam) { for (U32 team = 0; team < Game::MAX_TEAMS; ++team) { Team *other = Team::Id2Team(team); if (other) { if ( // Other team is an ally Team::TestUnitRelation(u, other, Relation::ALLY) || // Other team is giving us line of sight myTeam->GivingSightTo(other->GetId()) ) { ASSERT(teamRemap[team] < teamCount) Game::TeamSet(teamBits, teamRemap[team]); } } } } // Dirty cells that line of sight has changed in DirtyCells(cellX - r, cellZ - r, cellX + r, cellZ + r, teamBits); // Set up viewing radius if (r > 0) { r2 = r * r; r2Inv = 1.0f / F32(r2); // Get eye position eyePos = EyePosition(u); // In the code below the row and column of cells with the // same y and x value of the unit are processed twice but // their viewing information is only updated once. Stuff // the slight inneficiency (2*r extra comparisons). This // way we require 1/4 the memory and the code is more // elegant. // scan ++ quadrant quadrantX = POS; quadrantZ = POS; FillGradMap(); FillMaxGradMapPosZ(); CompareGradPosPos(); // Scan -+ quadrant quadrantX = NEG; FillGradMapRotated(); FillMaxGradMapPosZ(); CompareGradNegPos(); // Scan -- quadrant quadrantZ = NEG; FillGradMap(); FillMaxGradMapNegZ(); CompareGradNegNeg(); // Scan +- quadrant quadrantX = POS; FillGradMapRotated(); FillMaxGradMapNegZ(); CompareGradPosNeg(); } // Can always see cell that unit is occupying CanSee(cellX, cellZ, 0, 0, mapLo, maskLo, teamBits, Map::LV_LO); // Update scan info in unit's sight map u->sightMap->lastTeam = teamBits; u->sightMap->lastR = S16(r); u->sightMap->lastX = cellX; u->sightMap->lastZ = cellZ; u->sightMap->lastAlt = eyePos; STOP(sweepTime); }
CAI_BaseNPC *CASW_Sentry_Top_Cannon::SelectOptimalEnemy() { // prioritize unfrozen aliens who are going to leave the cone soon. // prioritize aliens less the more frozen they get. CUtlVectorFixedGrowable< CAI_BaseNPC *,16 > candidates; CUtlVectorFixedGrowable< float, 16 > candidatescores; // search through all npcs, any that are in LOS and have health CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ ) { if (ppAIs[i]->GetHealth() > 0 && CanSee(ppAIs[i])) { // don't shoot marines if ( !asw_sentry_friendly_target.GetBool() && ppAIs[i]->Classify() == CLASS_ASW_MARINE ) continue; if ( ppAIs[i]->Classify() == CLASS_SCANNER ) continue; if ( !IsValidEnemy( ppAIs[i] ) ) continue; candidates.AddToTail( ppAIs[i] ); } } // bail out if we don't have anyone if ( candidates.Count() < 1 ) return NULL; else if ( candidates.Count() == 1 ) // just one candidate is an obvious result return candidates[0]; // score each of the candidates candidatescores.EnsureCount( candidates.Count() ); for ( int i = candidates.Count() - 1; i >= 0 ; --i ) { CAI_BaseNPC * RESTRICT pCandidate = candidates[i]; // is the candidate moving into or out of the cone? Vector vCandVel = GetEnemyVelocity(pCandidate); Vector vMeToTarget = pCandidate->GetAbsOrigin() - GetFiringPosition(); Vector vBaseForward = UTIL_YawToVector( m_fDeployYaw ); // crush everything to 2d for simplicity vMeToTarget.z = 0.0f; vCandVel.z = 0.0f; vBaseForward.z = 0.0f; Vector velCross = vBaseForward.Cross(vCandVel); // this encodes also some info on perpendicularity Vector vAimCross = vBaseForward.Cross(vMeToTarget); bool bTargetHeadedOutOfCone = !vCandVel.IsZero() && velCross.z * vAimCross.z >= 0; // true if same sign float flConeLeavingUrgency; if ( bTargetHeadedOutOfCone ) { flConeLeavingUrgency = fabs( velCross.z / vCandVel.Length2D() ); // just the sin; varies 0..1 where 1 means moving perpendicular to my aim } else { flConeLeavingUrgency = 0; // not at threat of leaving just yet } // the angle between my current yaw and what's needed to hit the target float flSwivelNeeded = fabs( UTIL_AngleDiff( // i wish we weren't storing euler angles UTIL_VecToYaw( vMeToTarget ), m_fDeployYaw ) ); flSwivelNeeded /= ASW_SENTRY_ANGLE; // normalize to 0..2 float fBigness = 0.0f; int nClassify = pCandidate->Classify(); switch( nClassify ) { case CLASS_ASW_SHIELDBUG: case CLASS_ASW_MORTAR_BUG: fBigness = 4.0f; break; case CLASS_ASW_HARVESTER: case CLASS_ASW_RANGER: fBigness = 2.0f; break; } candidatescores[i] = Vector( 3.0f, -1.5f, 4.0f ).Dot( Vector( flConeLeavingUrgency, flSwivelNeeded, fBigness ) ); } // find the highest scoring candidate int best = 0; for ( int i = 1 ; i < candidatescores.Count() ; ++i ) { if ( candidatescores[i] > candidatescores[best] ) best = i; } // NDebugOverlay::EntityBounds(candidates[best], 255, 255, 0, 255, 0.2f ); return candidates[best]; }
bool SquareLine::CanSee() { #if defined(_showdebugger_) // Debugger::GetInstance().Output("(%d,%d) ",s_cur.x,s_cur.y); #endif //defined(_showdebugger_) if(s_cur == s_goal) return true; if(!NotOutOfBoard(s_cur))//IsAValidRefuge can call CanSee with a square out of board. return true; //if no obstacle can hide the refuge from the borders of the map, the refuge is exposed. else if(board->GetContentAt(s_cur) == e_obstacle) return false; vector2d l_cornerspos[4]; //corners of a square board->GetSquareCornersInLogPx(s_cur,l_cornerspos); Segment sg2; int i,intersection_value ; vector2d ipoint; //foreach segment in the square, see intersection; for(i=0; i<4; i++) { if(i+1 == 4) sg2=Segment(l_cornerspos[i],l_cornerspos[0]); else sg2=Segment(l_cornerspos[i],l_cornerspos[i+1]); intersection_value = lines_intersect(sg,sg2, ipoint); ipoint.setint(); if(intersection_value == 1 && ! (ipoint== p_lastipoint) ) { if( ipoint == l_cornerspos[i] || ipoint == l_cornerspos[i+1]) { vector2d g = sg.p1-ipoint; if(g.x>0) { if(g.y>0) { s_cur=s_cur+vector2d(1,1); } else if(g.y<0) { s_cur=s_cur+vector2d(1,-1); } else assert(0); //this means that the line coincides with the x-axis. and this is not possible since the destination point is a square center. } else if(g.x<0) { if(g.y>0) { s_cur=s_cur+vector2d(-1,1); } else if(g.y<0) { s_cur=s_cur+vector2d(-1,-1); } else assert(0); //this means that the line coincides with the x-axis. and this is not possible since the destination point is a square center. } else assert(0); //this means that the line coincides with the y-axis. and this is not possible since the destination point is a square center. } else if(i==0) { s_cur=s_cur+vector2d(0,-1); } else if(i==1) { s_cur=s_cur+vector2d(1,0); } else if(i==2) { s_cur=s_cur+vector2d(0,1); } else { s_cur=s_cur+vector2d(-1,0); } p_lastipoint=ipoint; break; } } return CanSee(); }