//--------------------------------------------------------------------------- // Copyright (c) Jim Wright 2004 // // JimLine.cpp // This is a line class that combines both the math type of line stuff // such as finding the intersection of two lines, with the graphics stuff // //--------------------------------------------------------------------------- #include "StdAfx.h" #include "jimline.h" /* ** Basic constructor */ CJimLine::CJimLine(void) { m_size=1; m_color=RGB(0,0,0); } /* ** Basic copy constructor */ CJimLine::CJimLine(const CJimLine &right) : m_a(right.m_a) , m_b(right.m_b) { m_size=1; m_color=RGB(0,0,0); } /* ** Other constructors */ CJimLine::CJimLine(CJimPoint a, CJimPoint b) : m_a(a) , m_b(b) { m_size=1; m_color=RGB(0,0,0); } CJimLine::CJimLine(CJimPoint a, CJimPoint b, COLORREF color) : m_a(a) , m_b(b) { m_size=1; m_color=color; } CJimLine::CJimLine(CJimPoint a, double angle, double length) : m_a(a) { double x,y; double rad = (angle*6.283)/360; x = a.GetX() + (sin(rad)*length); y = a.GetY() + (cos(rad)*length); m_b = CJimPoint(x,y); m_size=1; m_color=RGB(0,0,0); } CJimLine::CJimLine(CJimPoint a, double angle, double length, COLORREF color) : m_a(a) { double x,y; double rad = (angle*6.283)/360; x = a.GetX() + (sin(rad)*length); y = a.GetY() + (cos(rad)*length); m_b = CJimPoint(x,y); m_size=1; m_color = color; } /* ** Basic destructor */ CJimLine::~CJimLine(void) { } /* ** This is the method that draws the item on the screen */ void CJimLine::Draw(CDC *hDC, int x, int y,double scale) { CPen myPen; myPen.CreatePen( PS_SOLID, 1, m_color ); hDC->SelectObject(myPen); hDC->MoveTo(x+(int)(m_a.GetX()*scale),y+(int)(m_a.GetY()*scale)); hDC->LineTo(x+(int)(m_b.GetX()*scale),y+(int)(m_b.GetY()*scale)); } /* ** Methods for returning the range of this object. */ double CJimLine::FindTop(void) { if(m_a.GetX() < m_b.GetX()) { return m_a.GetX(); } else { return m_b.GetX(); } } double CJimLine::FindBottom(void) { if(m_a.GetY() > m_b.GetY()) { return m_a.GetY(); } else { return m_b.GetY(); } } double CJimLine::FindLeft(void) { if(m_a.GetY() < m_b.GetY()) { return m_a.GetY(); } else { return m_b.GetY(); } } double CJimLine::FindRight(void) { if(m_a.GetX() > m_b.GetX()) { return m_a.GetX(); } else { return m_b.GetX(); } } /* ** Basic asignment operator */ CJimLine & CJimLine::operator=(const CJimLine &right) { m_a = right.m_a; m_b = right.m_b; m_size = right.m_size; m_intersectError = right.m_intersectError; m_color = right.m_color; m_slopeError = right.m_slopeError; return *this; } /* ** Returns various parts of this class. */ CJimPoint CJimLine::GetA(void) { return m_a; } CJimPoint CJimLine::GetB(void) { return m_b; } /* ** Returns the point at which two lines meet. ** This method returns the point from the lines ** if the lines extended forever. ** To find if the point lies on one of these lines ** use the PointOnLine method ** ** This method is based on the slope intersection equation ** Y = mX + b ** */ CJimPoint CJimLine::Intersect(CJimLine theirLine) { m_intersectError=false; double my_slope; double their_slope; double my_a; double their_a; double x=0,y=0; /* ** Get the slopes */ my_slope = this->Slope(); their_slope = theirLine.Slope(); if(true == m_slopeError) { x = m_a.GetX(); } if(true == theirLine.m_slopeError) { x = theirLine.GetA().GetX(); } /* ** Parallel */ if(my_slope == their_slope) { m_intersectError=true; return CJimPoint(x,y); } /* ** Get the intersect */ my_a = m_a.GetY() -(my_slope*m_a.GetX()); their_a = theirLine.GetA().GetY() -(their_slope*theirLine.GetA().GetX()); /* ** Handle horizontal line */ if(0.0 == my_slope) { y = m_a.GetY(); if(true != theirLine.m_slopeError) { x = (y-their_a)/their_slope; } return CJimPoint(x,y); } if(0.0 == their_slope) { y = theirLine.GetA().GetY(); if(true != m_slopeError) { x = (y-my_a)/my_slope; } return CJimPoint(x,y); } /* ** my line is perpendicular to y */ if(true == m_slopeError) { if(true == theirLine.m_slopeError) { m_intersectError=true; } else { y = x*their_slope+their_a; } } else { if(true == theirLine.m_slopeError) { y = x*my_slope+my_a; } else { x = -1*(my_a-their_a)/(my_slope-their_slope); y = x*my_slope+my_a; } } return CJimPoint(x,y); } double CJimLine::Slope(void) { m_slopeError=false; if(m_a.GetX() == m_b.GetX()) { m_slopeError=true; return (double)1e+10; } return m_a.Slope(m_b); } /* ** To see if a point is on the line ** */ bool CJimLine::PointOnLine(CJimPoint a) { double my_slope = Slope(); double theTestY; if(((m_a.GetY() >= a.GetY()) && (m_b.GetY() <= a.GetY())) || ((m_a.GetY() <= a.GetY()) && (m_b.GetY() >= a.GetY()))) { if(((m_a.GetX() >= a.GetX()) && (m_b.GetX() <= a.GetX())) || ((m_a.GetX() <= a.GetX()) && (m_b.GetX() >= a.GetX()))) { if(true==m_slopeError) { if(a.GetX() == m_a.GetX()) { return true; } } else { if(0.0 == my_slope) { if(a.GetY() == m_a.GetY()) { return true; } } theTestY = my_slope*(a.GetX()-m_b.GetX())+m_b.GetY(); if((a.GetY() >= theTestY-DOUBLECHECK)&&(a.GetY() <= theTestY+DOUBLECHECK)) { return true; } } } } return false; } /* ** Returns the length of this line */ double CJimLine::Length(void) { return m_a.DistanceBetween(m_b); }