You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

317 lines
7.2 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#ifndef OUTLINE_H
#define OUTLINE_H
//Qt
#include <QDebug>
#include <QColor>
#include <QPainter>
#include <QPainterPath>
#include <QPaintEvent>
#include <QVector>
#include <QPainterPathStroker>
#include <QPen>
#include <QWidget>
#include <QPaintEngine>
#include <qmath.h>
#include <QPixmap>
class Contour
{
public:
Contour(double scalex,double scaley,bool bmove,double tolerance, const QString& title){
_title = title;
_scalex = scalex;
_scaley = scaley;
_move = bmove;
_tolerance = tolerance;
}
Contour(QString title = "contour_0"){
_title = title;
_scalex = 1;
_scaley = 1;
_move = false;
_tolerance = 10;
}
void addPoint(qreal x,qreal y){
QPointF f(x,y);
_points.push_back(f);
if(polygonSelfIntersects()){
setColor(255,0,0,50);
}else{
setColor(0,0,0,150);
}
_rectPath = QPainterPath();
_rectPath.addPolygon(_points);
_rectPath.setFillRule(Qt::OddEvenFill);
}
bool polygonSelfIntersects() {
int n = _points.size();
for(int i=0;i<n;++i){
for(int j=i+1;j<n;++j){
if(lineSegmentsIntersect(_points[j],_points[(j+1)%n],_points[i],_points[(i+1)%n])){
return true;
}
}
}
return false;
}
bool lineSegmentsIntersect(const QPointF& a, const QPointF& b, const QPointF& c, const QPointF& d) {
QPointF ab = b-a;
QPointF cd = d-c;
QPointF ac = c-a;
QPointF ad = d-a;
QPointF ca = a-c;
QPointF cb = b-c;
qreal abac = ab.x()*ac.y()-ab.y()*ac.x();
qreal abad = ab.x()*ad.y()-ab.y()*ad.x();
qreal cdca = cd.x()*ca.y()-cd.y()*ca.x();
qreal cdcb = cd.x()*cb.y()-cd.y()*cb.x();
return !(abac*abad >=0 || cdca*cdcb >=0);
}
void setPoint(int i,qreal x,qreal y){
QPointF f(x,y);
_rectPath.setElementPositionAt(i,x,y);
_points[i] = f;
if(_move){
if(i==0 || i==_rectPath.elementCount()-1){
_rectPath.setElementPositionAt(0,x,y);
_rectPath.setElementPositionAt(_rectPath.elementCount()-1,x,y);
_points[i] = f;
_points[_rectPath.elementCount()-1] = f;
}
getDotline();
}
}
int pointCount(){
return _points.count();
}
int elementCount(){
return _rectPath.elementCount();
}
void setColor(int red,int green,int blue,int alpha=50){
_contourColor.setRgb(red,green,blue,alpha);
}
QColor getColor() const{
return _contourColor;
}
QString getTitle() const{
return _title;
}
void setTitle(const QString& title){
_title = title;
}
void saveData(){
// TODO
}
void setScalex(double scalex){
_scalex = scalex;
}
double getScalex() const{
return _scalex;
}
double getScaley() const{
return _scaley;
}
void setScaley(double scaley){
_scaley = scaley;
}
bool isMove() const
{
return _move;
}
void setMove(bool move)
{
_move = move;
}
QPainterPath getRectPath() const
{
return _rectPath;
}
void addRectPath(const QPainterPath &rectPath)
{
_rectPath.addPath(rectPath);
}
QVector<QPointF> Points() const
{
return _points;
}
double getTolerance() const
{
return _tolerance;
}
void setTolerance(double value)
{
_tolerance = value;
}
void clear(){
_rectPath = QPainterPath();
_dotPath = QPainterPath();
_points.clear();
}
void generate(){
_points.pop_back();
int n = _points.count();
if(_contourColor==QColor(255,0,0,50) || polygonSelfIntersects() || n < 3){
clear();
return;
}
_points.push_back(_points[0]);
_rectPath = QPainterPath();
_rectPath.addPolygon(_points);
_rectPath.closeSubpath();
_rectPath.setFillRule(Qt::OddEvenFill);
getDotline();
}
void move(QMouseEvent *event){
qreal x = event->posF().x();
qreal y = event->posF().y();
qreal tx = x - last.x();
qreal ty = y - last.y();
_rectPath.translate(tx,ty);
_dotPath.translate(tx,ty);
int n = _points.count();
for(int i=0;i<n;++i){
qreal rx = _points[i].x();
qreal ry = _points[i].y();
_points[i].setX(rx+tx);
_points[i].setY(ry+ty);
}
last = event->posF();
}
void pick(QMouseEvent* event){
QPointF f = event->posF();
if(!contains(f)){
return;
}
setMove(true);
last = f;
}
void getDotline(){
QPainterPathStroker stroker;
stroker.setCapStyle(Qt::RoundCap);
stroker.setDashPattern(Qt::DashLine);
stroker.setJoinStyle(Qt::RoundJoin);
_dotPath = stroker.createStroke(_rectPath);
}
void clearDotPath(){
_dotPath = QPainterPath();
}
bool contains(const QPointF& f){
for(int i=0;i<=_tolerance;++i){
if(_dotPath.contains(f+QPointF(i,0))||
_dotPath.contains(f+QPointF(-i,0))||
_dotPath.contains(f+QPointF(0,-i))||
_dotPath.contains(f+QPointF(0,i))){
return true;
}
}
return false;
}
int dotContains(const QPointF& f){
qreal x = f.x();
qreal y = f.y();
for(int j=0;j<_points.size();++j) {
qreal x1 = _points[j].x();
qreal y1 = _points[j].y();
for(int i=0;i<=_tolerance;++i){
if(x1 <= (x+i)&&
x1 >= (x-i)&&
y1 >= (y-i)&&
y1 <= (y+i)){
return j;
}
}
}
return -1;
}
void paint(QPixmap& w, QPaintEvent *event=nullptr){
QPainter painter;
painter.begin(&w);
painter.scale(_scalex, _scaley);
painter.setRenderHint(QPainter::Antialiasing);
pen.setColor(_contourColor);
pen.setWidth(2);
painter.setPen(pen);
painter.setBrush(_contourColor);
int n = _points.count();
if(_move){
painter.save();
for(int i=0;i<n;++i){
painter.setPen(Qt::NoPen);
painter.setBrush(_contourColor);
painter.drawEllipse(QPointF(_rectPath.elementAt(i).x,_rectPath.elementAt(i).y),5,5);
}
painter.restore();
painter.drawPath(_dotPath);
}else{
painter.drawPath(_rectPath);
}
painter.end();
}
private:
QColor _contourColor;
QPen pen;
// 记录标题比如contour_1
QString _title;
QVector<QPointF> _points;
QPointF last;
// 缩放
double _scalex;
double _scaley;
// 移动
bool _move;
// 容差
double _tolerance;
// fault的路径
QPainterPath _rectPath;
// fault的虚线框
QPainterPath _dotPath;
};
#endif // OUTLINE_H