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.

357 lines
8.6 KiB
C

#ifndef OUTLINE_H
#define OUTLINE_H
//
#include "basicgeometryoperator.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>
#define d(x) qDebug()<<__FUNCTION__<<(x)
class Contour
{
public:
Contour(double scalex,double scaley,bool bmove,double tolerance, QString title = "Fault_0"):_scalex(scalex),_scaley(scaley),
_move(bmove),_tolerance(tolerance){
_title = title;
_painter = new QPainter();
}
Contour(QString title = "contour_0"):_scalex(1),_scaley(1),
_move(false),_tolerance(15){
_title = title;
_painter = new QPainter();
}
~Contour(){}
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])){
qDebug()<<"intersect"<<_points[j]<<_points[(j+1)%n]<<_points[i]<<_points[(i+1)%n];
qDebug()<<j<<(j+1)%n<<i<<(i+1)%n;
return true;
}
}
}
return false;
}
bool lineSegmentsIntersect(const QPointF& a, const QPointF& b, const QPointF& c, const QPointF& d) {
qreal abx = b.x() - a.x();
qreal aby = b.y() - a.y();
qreal cdx = d.x() - c.x();
qreal cdy = d.y() - c.y();
qreal acx = c.x() - a.x();
qreal acy = c.y() - a.y();
qreal adx = d.x() - a.x();
qreal ady = d.y() - a.y();
qreal cax = a.x() - c.x();
qreal cay = a.y() - c.y();
qreal cbx = b.x() - c.x();
qreal cby = b.y() - c.y();
qreal abac = abx*acy-acx*aby;
qreal abad = abx*ady-adx*aby;
qreal cdca = cdx*cay-cdy*cax;
qreal cdcb = cdx*cby-cdy*cbx;
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;
}
setDotline();
}
}
bool isInside(const QPointF& a){
int n = _points.count();
for(int i=1;i<n-2;++i){
QPointF p1 = a - _points[i];
QPointF p2 = _points[i+1]-_points[i];
QPointF p3 = _points[i-1] - _points[i];
qreal abac = p1.x()*p2.y() - p1.y()*p2.x();
qreal abad = p1.x()*p3.y() - p1.y()*p3.x();
if(abac*abad <=0){
return true;
}
}
return false;
}
bool isInLine(const QPointF& a){
int n = _points.count();
for(int i=0;i<n-2;++i){
QPointF p1 = a - _points[i];
QPointF p2 = _points[i+1]-_points[i];
if(qAbs(p1.x()*p2.y()-p1.y()*p2.x())< 1000){
if(a.x()<=qMax(_points[i].x(),_points[i+1].x()) && a.x()>=qMin(_points[i].x(),_points[i+1].x())){
return true;
}
}
}
return false;
}
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(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> getPoints() 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);
setDotline();
}
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 setDotline(){
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(QWidget *w, QPaintEvent *event){
_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;
QPainter *_painter;
QPointF last;
// 缩放
double _scalex;
double _scaley;
// 移动
bool _move;
// 容差
double _tolerance;
// fault的路径
QPainterPath _rectPath;
// fault的虚线框
QPainterPath _dotPath;
};
#endif // OUTLINE_H