float mglnrel::ptToBeeline2( const Point2d& a, const Point2d& b, const Point2d& pt, Point2d& ptPerp) { // 两点重合 if (a == b) { ptPerp = a; return a.distanceTo(pt); } // 竖直线 else if (mgEquals(a.x, b.x)) { ptPerp.set(a.x, pt.y); return fabsf(a.x - pt.x); } // 水平线 else if (mgEquals(a.y, b.y)) { ptPerp.set(pt.x, a.y); return fabsf(a.y - pt.y); } else { float t1 = ( b.y - a.y ) / ( b.x - a.x ); float t2 = -1.f / t1; ptPerp.x = ( pt.y - a.y + a.x * t1 - pt.x * t2 ) / ( t1 - t2 ); ptPerp.y = a.y + (ptPerp.x - a.x) * t1; return pt.distanceTo(ptPerp); } }
// http://blog.csdn.net/cyg0810/article/details/7765894 int mgcurv::crossTwoCircles(Point2d& pt1, Point2d& pt2, const Point2d& c1, float r1, const Point2d& c2, float r2) { point_t p1, p2; point_t ca(c1.x, c1.y); point_t cb(c2.x, c2.y); int n = _crossTwoCircles(p1, p2, ca, r1, cb, r2); pt1.set((float)p1.x, (float)p1.y); pt2.set((float)p2.x, (float)p2.y); return n; }
virtual bool load(MgStorage* s) { pt.set(s->readFloat("x", pt.x), s->readFloat("y", pt.y)); vec.set(s->readFloat("w", vec.x), s->readFloat("h", vec.y)); stroke = s->readBool("stroke", stroke); fill = s->readBool("fill", fill); return true; }
void Game::SpectatorsCheers(){ Point2d corner; // The cheering will last for 2 seconds if (clock() - cheer_start < 2000 && cheer_start != 0){ frames_to_cheer++; if (frames_to_cheer == FRAMES_TO_CHEER_LIMIT){ // The changes of colors for the spectators will // happen once on FRAMES_TO_CHEER_LIMIT frames, // which in our case is 10 (m_last_scored == 0)?corner.set(-21.0f, 16.5f):corner.set(-21.0f, -1.0f); RemoveSpectators(m_last_scored); DrawSpectators(corner, m_last_scored); frames_to_cheer = 0; } } }
void Game::DrawSpectators(Point2d corner, int team){ const int columns = 5; int rows = 14; Circle spectator(10, SPECTATOR_CIRCLE_RAY); float randr, randg; for(int i=0; i < columns; ++i){ corner.set(corner.x + SPECTATOR_CIRCLE_RAY*2 + 0.1f, corner.y - SPECTATOR_CIRCLE_RAY*2 + 0.43f); for(int j=0; j < rows; ++j){ if (team == 0){ randr = (float)rand()/(3*RAND_MAX); randg = (float)rand()/RAND_MAX; spectator.SetColor(RGBcolor(randr, randg, 1.0f)); } else if (team == 1){ randg = (float)rand()/RAND_MAX; spectator.SetColor(RGBcolor(1.0f, randg, 0.09f)); } spectator.DrawCircle(m_system, Point2d(corner.x, corner.y - (SPECTATOR_CIRCLE_RAY*2 + 0.1f)*j)); if (team == 0){ spectators1.push_back(spectator.GetObject()); } else { spectators2.push_back(spectator.GetObject()); } } rows--; } }
int mgcurv::crossLineCircle(Point2d& pt1, Point2d& pt2, const Point2d& a, const Point2d& b, const Point2d& c, float r) { if (a == b) { return 0; } point_t p1, p2; point_t a1(a.x - c.x, a.y - c.y); point_t b1(b.x - c.x, b.y - c.y); int n = _crossLineCircle(p1, p2, a1, b1, r); pt1.set((float)p1.x + c.x, (float)p1.y + c.y); pt2.set((float)p2.x + c.x, (float)p2.y + c.y); return n; }
/** * calculate if this line intersects with the provided Line l * Point2d * intersection output of the intersection point */ bool Line::intersect( const Line* l, Point2d & intersection ) { const Line* p, *q; /* compare length of lines and assign pointers */ if( this->length() < l->length() ) { p = l; q = this; } else { p = this; q = l; } /* p is now the line longer or the same length then q */ float ccwpa = p->ccw( q->getA() ); float ccwpb = p->ccw( q->getB() ); float ccwqa = q->ccw( p->getA() ); float ccwqb = q->ccw( p->getB() ); /* check collinearity of the two lines */ if( fabs( ccwpa ) <= FLT_EPSILON && fabs( ccwpb ) <= FLT_EPSILON ) { /* lines are collinear */ return false; /* if they are collinear, just return false. */ } /* lines are not collinear -> check for intersection or(!) contact */ if( ( ( ccwpa * ccwpb ) <= FLT_EPSILON ) && ( ( ccwqa * ccwqb ) <= FLT_EPSILON ) ) { //calculate the point float den = ( p->getA().getX() - p->getB().getX() ) * ( q->getA().getY() - q->getB().getY() ) - ( p->getA().getY() - p->getB().getY() ) * ( q->getA().getX() - q->getB().getX() ); if( fabs( den ) <= FLT_EPSILON ) return false; float x = ( ( p->getA().getX() * p->getB().getY() - p->getA().getY() * p->getB().getX() ) * ( q->getA().getX() - q->getB().getX() ) - ( p->getA().getX() - p->getB().getX() ) * ( q->getA().getX() * q->getB().getY() - q->getA().getY() * q->getB().getX() ) ) / den; float y = ( ( p->getA().getX() * p->getB().getY() - p->getA().getY() * p->getB().getX() ) * ( q->getA().getY() - q->getB().getY() ) - ( p->getA().getY() - p->getB().getY() ) * ( q->getA().getX() * q->getB().getY() - q->getA().getY() * q->getB().getX() ) ) / den; intersection.set( x, y ); return true; } return false; }
bool GiTransform::zoomScale(float viewScale, const Point2d* pxAt, bool adjust) { // 检查显示比例 if (!adjust && ScaleOutRange(viewScale, m_impl)) return false; viewScale = mgMax(viewScale, m_impl->minViewScale); viewScale = mgMin(viewScale, m_impl->maxViewScale); // 得到放缩中心点的客户区坐标 Point2d ptAt (m_impl->cxWnd * 0.5f, m_impl->cyWnd * 0.5f); if (pxAt != NULL) ptAt.set(pxAt->x, pxAt->y); // 得到放缩中心点在放缩前的世界坐标 Point2d ptAtW (ptAt * m_impl->matD2W); // 计算新显示比例下显示窗口中心的世界坐标 Point2d ptW; float w2dx = m_impl->w2dx / m_impl->viewScale * viewScale; float w2dy = m_impl->w2dy / m_impl->viewScale * viewScale; ptW.x = ptAtW.x + (m_impl->cxWnd * 0.5f - ptAt.x) / w2dx; ptW.y = ptAtW.y - (m_impl->cyWnd * 0.5f - ptAt.y) / w2dy; // 检查新显示比例下显示窗口的世界坐标范围是否在极限范围内 float halfw = m_impl->cxWnd / w2dx * 0.5f; float halfh = m_impl->cyWnd / w2dy * 0.5f; Box2d box (ptW, 2 * halfw, 2 * halfh); if (!AdjustCenterIn(adjust, box, m_impl->rectLimitsW, ptW, halfw, halfh)) { return false; } if (halfw - 3 > m_impl->rectLimitsW.width() / 2 && halfh - 3 > m_impl->rectLimitsW.height() / 2) // 显示比例太小 { viewScale *= mgMin(2 * (halfw - 3) / m_impl->rectLimitsW.width(), 2 * (halfh - 3) / m_impl->rectLimitsW.height()); viewScale = mgMin(viewScale, m_impl->maxViewScale); } return m_impl->zoomNoAdjust(ptW, viewScale); }
bool GiTransform::zoomScale(float viewScale, const Point2d* pxAt, bool adjust) { // 检查显示比例 if (!adjust && ScaleOutRange(viewScale, m_impl)) return false; viewScale = mgMax(viewScale, m_impl->minViewScale); viewScale = mgMin(viewScale, m_impl->maxViewScale); // 得到放缩中心点的客户区坐标 Point2d ptAt (m_impl->cxWnd * 0.5f, m_impl->cyWnd * 0.5f); if (pxAt != NULL) ptAt.set(pxAt->x, pxAt->y); // 得到放缩中心点在放缩前的世界坐标 Point2d ptAtW (ptAt * m_impl->matD2W); // 计算新显示比例下显示窗口中心的世界坐标 Point2d ptW; float w2dx = m_impl->w2dx / m_impl->viewScale * viewScale; float w2dy = m_impl->w2dy / m_impl->viewScale * viewScale; ptW.x = ptAtW.x + (m_impl->cxWnd * 0.5f - ptAt.x) / w2dx; ptW.y = ptAtW.y - (m_impl->cyWnd * 0.5f - ptAt.y) / w2dy; // 检查新显示比例下显示窗口的世界坐标范围是否在极限范围内 float halfw = m_impl->cxWnd / w2dx * 0.5f; float halfh = m_impl->cyWnd / w2dy * 0.5f; Box2d box (ptW, 2 * halfw, 2 * halfh); if (!m_impl->rectLimitsW.isEmpty() && !m_impl->rectLimitsW.contains(box)) { if (adjust) AdjustCenterW(ptW, halfw, halfh, m_impl->rectLimitsW); else return false; } return m_impl->zoomNoAdjust(ptW, viewScale); }
bool GiTransform::zoomTo(const Box2d& rectWorld, const RECT_2D* rcTo, bool adjust) { // 如果图形范围的宽或高接近于零,就返回 if (rectWorld.isEmpty()) return false; // 计算像素到毫米的比例 const float d2mmX = m_impl->viewScale / m_impl->w2dx; const float d2mmY = m_impl->viewScale / m_impl->w2dy; // 计算目标窗口区域(毫米) float w = 0, h = 0; Point2d ptCen; if (rcTo != NULL) { w = fabsf(static_cast<float>(rcTo->right - rcTo->left)); h = fabsf(static_cast<float>(rcTo->bottom - rcTo->top)); ptCen.x = (rcTo->left + rcTo->right) * 0.5f; ptCen.y = (rcTo->top + rcTo->bottom) * 0.5f; } if (w < 4 || h < 4) { w = (float)m_impl->cxWnd; h = (float)m_impl->cyWnd; ptCen.set(w * 0.5f, h * 0.5f); w -= 8; h -= 8; } if (w < 4 || h < 4) return false; w *= d2mmX; h *= d2mmY; ptCen.scaleBy(d2mmX, d2mmY); // 计算新显示比例 (中心不变,缩小窗口区域使得宽高比例和图形范围相同) float scale; if (h * rectWorld.width() > w * rectWorld.height()) { //h = w * rectWorld.height() / rectWorld.width(); scale = w / rectWorld.width(); } else { //w = h * rectWorld.width() / rectWorld.height(); scale = h / rectWorld.height(); } // 检查显示比例 if (!adjust && ScaleOutRange(scale, m_impl)) return false; scale = mgMax(scale, m_impl->minViewScale); scale = mgMin(scale, m_impl->maxViewScale); // 计算在新显示比例下显示窗口中心的世界坐标 Point2d ptW; ptW.x = rectWorld.center().x + (m_impl->cxWnd * d2mmX * 0.5f - ptCen.x) / scale; ptW.y = rectWorld.center().y - (m_impl->cyWnd * d2mmY * 0.5f - ptCen.y) / scale; // 检查新显示比例下显示窗口的世界坐标范围是否在极限范围内 float halfw = m_impl->cxWnd * d2mmX / scale * 0.5f; float halfh = m_impl->cyWnd * d2mmY / scale * 0.5f; Box2d box (ptW, 2 * halfw, 2 * halfh); if (!AdjustCenterIn(adjust, box, m_impl->rectLimitsW, ptW, halfw, halfh)) { return false; } return m_impl->zoomNoAdjust(ptW, scale); }
void Matrix2d::getCoordSystem(Vector2d& e0, Vector2d& e1, Point2d& origin) const { e0.set(m11, m12); e1.set(m21, m22); origin.set(dx, dy); }
virtual bool load(MgStorage* s) { pt.set(s->readFloat("x", pt.x), s->readFloat("y", pt.y)); vec.set(s->readFloat("w", vec.x), s->readFloat("h", vec.y)); return true; }
virtual bool load(MgStorage* s) { pt1.set(s->readFloat("x1", pt1.x), s->readFloat("y1", pt1.y)); pt2.set(s->readFloat("x2", pt2.x), s->readFloat("y2", pt2.y)); return true; }