crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> QPainter: Рисование части линии, ограниченной окружностью
Snake174
  опции профиля:
сообщение 15.3.2012, 6:14
Сообщение #1


Студент
*

Группа: Участник
Сообщений: 89
Регистрация: 18.4.2011
Из: Миасс
Пользователь №: 2613

Спасибо сказали: 9 раз(а)




Репутация:   0  


Всем привет. Есть такой код:
class Widget : public QWidget
{
  Q_OBJECT

  QPoint mouseOldPos;
  QPoint mousePos;
  QImage *image;

  public:
    Widget( QWidget *parent = 0 );
    ~Widget();

  protected:
    void paintEvent( QPaintEvent *e );
    void draw( QPainter *painter );
    void mousePressEvent( QMouseEvent *e );
    void mouseReleaseEvent( QMouseEvent *e );
    void mouseMoveEvent( QMouseEvent *e );

  protected slots:
    void createImage();
};

Widget::Widget( QWidget *parent ):
  QWidget( parent ),
  image(0)
{
  setAttribute( Qt::WA_StaticContents );
  setCursor( Qt::CrossCursor );
  setMouseTracking( true );
  setFocusPolicy( Qt::WheelFocus );
  setFocus();

  setFixedSize( 800, 600 );

  QTimer::singleShot( 500, this, SLOT(createImage()) );
}
//================================================================================
=================
Widget::~Widget()
{
  if (image)
  {
    delete image;
    image = 0;
  }
}
//================================================================================
=================
void Widget::paintEvent( QPaintEvent *e )
{
  if (image)
  {
    QPainter imagePainter( image );
    imagePainter.setRenderHint( QPainter::Antialiasing, true );
    imagePainter.eraseRect( rect() );
    draw( &imagePainter );
    imagePainter.end();

    QPainter painter( this );
    QRect dirtyRect = e->rect();
    painter.drawImage( dirtyRect, (*image), dirtyRect );
  }
}
//================================================================================
=================
void Widget::draw( QPainter *painter )
{
  painter->save();
    painter->translate( width() / 2, height() / 2 );
    painter->setPen( QColor( 0, 0, 0, 255 ) );
    painter->drawEllipse( QPoint( 0, 90 ), 90, 90 );
  painter->restore();

  painter->save();
    painter->setPen( QPen( Qt::green, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) );
    painter->drawLine( QPoint( width() / 2, height() / 2 + 90 ), mousePos );
  painter->restore();
}
//================================================================================
=================
void Widget::mousePressEvent( QMouseEvent *e )
{
  if (e->buttons() & Qt::LeftButton)
  {
    mouseOldPos = e->pos();
    update();
  }
}
//================================================================================
=================
void Widget::mouseReleaseEvent( QMouseEvent *e )
{
  update();
  e->accept();
}
//================================================================================
=================
void Widget::mouseMoveEvent( QMouseEvent *e )
{
  mousePos = e->pos();
  update();
}
//================================================================================
=================
void Widget::createImage()
{
  if (!image)
  {
    image = new QImage( size(), QImage::Format_ARGB32_Premultiplied );
    image->fill( Qt::white );

    update();
  }
}

Он рисует окружность и зелёную линию от центра до указателя мыши.
Нужно чтобы рисовалась часть линии, выделенная красным цветом.
В какую сторону копать?
Image
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 15.3.2012, 6:24
Сообщение #2


фрилансер
******

Группа: Участник
Сообщений: 2941
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


уравнение окружности с центром в (x0,y0) и с радиусом r:
(x-x0)2+(y-y0)2=r2

уравнение линии, проходящей через точки (x1,y1) и (x2,y2)
(x-x1)/(x2-x1)=(y-y1)/(y2-y1)

нарисовать на бумаге, найти пересечения, вывести формулу, соединить красной линией :)

Сообщение отредактировал Алексей1153 - 15.3.2012, 6:25
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Snake174
  опции профиля:
сообщение 15.3.2012, 6:27
Сообщение #3


Студент
*

Группа: Участник
Сообщений: 89
Регистрация: 18.4.2011
Из: Миасс
Пользователь №: 2613

Спасибо сказали: 9 раз(а)




Репутация:   0  


Спасибо, сейчас попробую.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Snake174
  опции профиля:
сообщение 15.3.2012, 8:52
Сообщение #4


Студент
*

Группа: Участник
Сообщений: 89
Регистрация: 18.4.2011
Из: Миасс
Пользователь №: 2613

Спасибо сказали: 9 раз(а)




Репутация:   0  


В общем решил так:
// угол указателя мыши
float mouse_radius = getDistanceBetweenPoints( width() / 2, height() / 2 + 90, mousePos.x(), mousePos.y() );

float pX = width() / 2 + 90 * (mousePos.x() - width() / 2) / mouse_radius;
float pY = (height() / 2 + 90) + 90 * (mousePos.y() - (height() / 2 + 90)) / mouse_radius;

float pX2 = width() / 2 + 80 * (mousePos.x() - width() / 2) / mouse_radius;
float pY2 = (height() / 2 + 90) + 80 * (mousePos.y() - (height() / 2 + 90)) / mouse_radius;

painter->drawLine( int( pX2 ), int( pY2 ), int( pX ), int( pY ) );



float getVectorLength( float dx, float dy )
{
  return qSqrt( dx * dx + dy * dy );
}

float getDistanceBetweenPoints( float x1, float y1, float x2, float y2 )
{
  return getVectorLength( x2 - x1, y2 - y1 );
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 15.3.2012, 9:37
Сообщение #5


фрилансер
******

Группа: Участник
Сообщений: 2941
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


Snake174, а что за магические цифры 80 и 90 ? )
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Snake174
  опции профиля:
сообщение 15.3.2012, 10:55
Сообщение #6


Студент
*

Группа: Участник
Сообщений: 89
Регистрация: 18.4.2011
Из: Миасс
Пользователь №: 2613

Спасибо сказали: 9 раз(а)




Репутация:   0  


Цитата(Алексей1153 @ 15.3.2012, 10:37) *
Snake174, а что за магические цифры 80 и 90 ? )

QPoint( width() / 2, height() / 2 + 90 ) - центр окружности
90 - радиус
80 - радиус другой окружности.
Нашёл пересечение прямой с окружностью радиусом 80 - это первая точка, от которой будет строиться линия
Нашёл пересечение прямой с окружностью радиусом 90 - это вторая точка, до которой будет строиться линия
Вот и получилась линия длиной 10
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 16.3.2012, 8:18
Сообщение #7


фрилансер
******

Группа: Участник
Сообщений: 2941
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


делай именованные константы-это правильнее, удобнее и читабельнее :)

enum
{
   e_radius1=90,
   e_radius2=80,
};
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 27.11.2024, 3:42