//check if the line through the congestion area, BOOL CCongestionAreaManager::CheckAndHandleCongestion(Person* pPerson, ElapsedTime eventTime, BOOL bAreaCong) { //check the data TerminalMobElementBehavior* spTerminalBehavior = pPerson->getTerminalBehavior(); Point ptStart; pPerson->getTerminalPoint(ptStart); int nFloor = (int)ptStart.getZ() / 100; if( !m_vGrid[nFloor]->IsValidCongestionArea() ) return FALSE; Point ptEnd; pPerson->getTerminalDest(ptEnd); if(SAMEPOINT(ptStart, ptEnd) || !SAMEFLOAT(ptStart.getZ(), ptEnd.getZ()) ) return FALSE; CCongestionAreaCell* pCell = NULL; Point ptDest = Point(0.0, 0.0, 0.0); //the line between start and end, //then get the intersect point between the line and the congestion area Point ptIntersect = Point(0.0, 0.0, ptStart.getZ()); BOOL bExist = m_vGrid[nFloor]->GetInterSectPoint(ptStart, ptEnd, ptIntersect); if (!bExist) return FALSE; // pCell = m_vGrid[nFloor]->GetCell(ptIntersect); // if(pCell == NULL) // return FALSE; if(pCell = m_vGrid[nFloor]->GetCell(ptStart)) pCell->EnterCell(pPerson->GetAdminGroupSize());//start cell if (pCell) { ptIntersect = m_vGrid[nFloor]->GetNearestPoint(ptStart,ptEnd); } ptDest = ptIntersect; //save the old destination point, old speed and old location if (spTerminalBehavior) { spTerminalBehavior->SetOldDestPoint(ptEnd); spTerminalBehavior->SetOldSpeed(pPerson->getSpeed()); spTerminalBehavior->SetOldLocation(ptStart); spTerminalBehavior->processBillboard(eventTime); //set the new destination pPerson->setTerminalDestination(ptDest); //calculate the time and add event ElapsedTime time = eventTime + pPerson->moveTime(); CongestionAreaEvent* event = new CongestionAreaEvent; event->init(pPerson, time,false); event->addEvent(); } return TRUE; }
LWPOLY * lwpoly_grid(LWPOLY *poly, gridspec *grid) { LWPOLY *opoly; int ri; POINTARRAY **newrings = NULL; int nrings = 0; double minvisiblearea; /* * TODO: control this assertion * it is assumed that, since the grid size will be a pixel, * a visible ring should show at least a white pixel inside, * thus, for a square, that would be grid_xsize*grid_ysize */ minvisiblearea = grid->xsize * grid->ysize; nrings = 0; POSTGIS_DEBUGF(3, "grid_polygon3d: applying grid to polygon with %d rings", poly->nrings); for (ri=0; ri<poly->nrings; ri++) { POINTARRAY *ring = poly->rings[ri]; POINTARRAY *newring; #if POSTGIS_DEBUG_LEVEL >= 4 POINT2D p1, p2; getPoint2d_p(ring, 0, &p1); getPoint2d_p(ring, ring->npoints-1, &p2); if ( ! SAMEPOINT(&p1, &p2) ) POSTGIS_DEBUG(4, "Before gridding: first point != last point"); #endif newring = ptarray_grid(ring, grid); /* Skip ring if not composed by at least 4 pts (3 segments) */ if ( newring->npoints < 4 ) { pfree(newring); POSTGIS_DEBUGF(3, "grid_polygon3d: ring%d skipped ( <4 pts )", ri); if ( ri ) continue; else break; /* this is the external ring, no need to work on holes */ } #if POSTGIS_DEBUG_LEVEL >= 4 getPoint2d_p(newring, 0, &p1); getPoint2d_p(newring, newring->npoints-1, &p2); if ( ! SAMEPOINT(&p1, &p2) ) POSTGIS_DEBUG(4, "After gridding: first point != last point"); #endif POSTGIS_DEBUGF(3, "grid_polygon3d: ring%d simplified from %d to %d points", ri, ring->npoints, newring->npoints); /* * Add ring to simplified ring array * (TODO: dinamic allocation of pts_per_ring) */ if ( ! nrings ) { newrings = palloc(sizeof(POINTARRAY *)); } else { newrings = repalloc(newrings, sizeof(POINTARRAY *)*(nrings+1)); } if ( ! newrings ) { elog(ERROR, "Out of virtual memory"); return NULL; } newrings[nrings++] = newring; } POSTGIS_DEBUGF(3, "grid_polygon3d: simplified polygon with %d rings", nrings); if ( ! nrings ) return NULL; opoly = lwpoly_construct(poly->srid, NULL, nrings, newrings); return opoly; }
//process congestion event and generate the next event int CCongestionAreaManager::ProcessCongestionEvent(CongestionAreaEvent* pEvent, ElapsedTime eventTime) { Person* pPerson = (Person*)pEvent->GetMobileElement(); if(pPerson == NULL) return 0; // step1. Leave Cell TerminalMobElementBehavior* spTerminalBehavior = pPerson->getTerminalBehavior(); if (spTerminalBehavior == NULL) { return 0; } Point floorpt; pPerson->getTerminalPoint(floorpt); int nFloor = int(floorpt.getZ()) / 100; CCongestionAreaCell* pCell = m_vGrid[nFloor]->GetCell(spTerminalBehavior->GetOldLocation()); if(pCell != NULL)// && pPerson->GetOldLocation() != pPerson->GetOldStartPoint() { if(pCell->GetPersonsCount()==0) { CString str; str.Format("1-%d", pPerson->getID()); AfxMessageBox(str); } pCell->LeaveCell(pPerson->GetAdminGroupSize()); } // step2. Enter Cell Point ptDest; pPerson->getTerminalDest(ptDest); pCell = m_vGrid[nFloor]->GetCell(ptDest); // ASSERT(pCell != NULL);//if the cell is null, last time has already exit if(pCell != NULL) pCell->EnterCell(pPerson->GetAdminGroupSize()); // setp3. save the current point as old location spTerminalBehavior->SetOldLocation(ptDest); // setp4. Write log pPerson->writeLogEntry(eventTime, false,false); // step5. Next event. //calculate the next event destination; Point pt; pPerson->getTerminalPoint(pt); const Point& ptOld = spTerminalBehavior->GetOldDestPoint(); Point ptNext = /*pt.GetDistancePoint(ptOld, STEPDIST)*/m_vGrid[nFloor]->GetNearestPoint(pt,ptOld); //if get null, leaving the congestion area, reset the old destionation and speed; //if the ptNext equal ptOld, the person arrived at the end next processor pCell = m_vGrid[nFloor]->GetCell(ptNext); if(pCell == NULL //the end point not in the congestion area || SAMEPOINT(ptNext, ptOld) ) //the end point in the congestion area,but get the end { //if the person leaving the congestion area, leave the current cell, CCongestionAreaCell* pPreCell = m_vGrid[nFloor]->GetCell(spTerminalBehavior->GetOldLocation()); if(pPreCell != NULL) { if(pPreCell->GetPersonsCount()==0) { CString str; str.Format("2-%d", pPerson->getID()); AfxMessageBox(str); } pPreCell->LeaveCell(pPerson->GetAdminGroupSize()); } pPerson->setTerminalDestination(spTerminalBehavior->GetOldDestPoint()); pPerson->setSpeed(spTerminalBehavior->GetOldSpeed()); if(pCell == NULL && pPerson->getState() != WalkOnPipe) { //pPerson->setLocation(ptNext); if(CheckAndHandleCongestion(pPerson, eventTime, TRUE)) return 1; else spTerminalBehavior->processGeneralMovementHelp(eventTime); } else spTerminalBehavior->processGeneralMovementHelp(eventTime); return 0; } //reset the new speed to calculate the next event time; int nCount = pCell->GetPersonsCount(); DistanceUnit dSpeed = GetNewSpeed(pPerson, nCount); pPerson->setSpeed(dSpeed); pPerson->setTerminalDestination(ptNext); //Add the next event to the event list; ElapsedTime time = eventTime + pPerson->moveTime(); CongestionAreaEvent* event = new CongestionAreaEvent; event->init(pPerson, time,false); event->addEvent(); return 1; }