📄 basic2.cpp
字号:
/////////////////////////////////////////////////////////////////////////////// Name: basic2.cpp// Purpose: Basic OGL classes (2)// Author: Julian Smart// Modified by:// Created: 12/07/98// RCS-ID: $Id: basic2.cpp,v 1.25 2005/10/06 18:17:21 ABX Exp $// Copyright: (c) Julian Smart// Licence: wxWindows licence/////////////////////////////////////////////////////////////////////////////// For compilers that support precompilation, includes "wx.h".#include "wx/wxprec.h"#ifdef __BORLANDC__#pragma hdrstop#endif#ifndef WX_PRECOMP#include "wx/wx.h"#endif#if wxUSE_PROLOGIO#include "wx/deprecated/wxexpr.h"#endif#ifdef new#undef new#endif#include <stdio.h>#include <ctype.h>#include <math.h>#include "wx/ogl/ogl.h"// Control point types// Rectangle and most other shapes#define CONTROL_POINT_VERTICAL 1#define CONTROL_POINT_HORIZONTAL 2#define CONTROL_POINT_DIAGONAL 3// Line#define CONTROL_POINT_ENDPOINT_TO 4#define CONTROL_POINT_ENDPOINT_FROM 5#define CONTROL_POINT_LINE 6// Two stage construction: need to call CreateIMPLEMENT_DYNAMIC_CLASS(wxPolygonShape, wxShape)wxPolygonShape::wxPolygonShape(){ m_points = NULL; m_originalPoints = NULL;}void wxPolygonShape::Create(wxList *the_points){ ClearPoints(); if (!the_points) { m_originalPoints = new wxList; m_points = new wxList; } else { m_originalPoints = the_points; // Duplicate the list of points m_points = new wxList; wxObjectList::compatibility_iterator node = the_points->GetFirst(); while (node) { wxRealPoint *point = (wxRealPoint *)node->GetData(); wxRealPoint *new_point = new wxRealPoint(point->x, point->y); m_points->Append((wxObject*) new_point); node = node->GetNext(); } CalculateBoundingBox(); m_originalWidth = m_boundWidth; m_originalHeight = m_boundHeight; SetDefaultRegionSize(); }}wxPolygonShape::~wxPolygonShape(){ ClearPoints();}void wxPolygonShape::ClearPoints(){ if (m_points) { wxObjectList::compatibility_iterator node = m_points->GetFirst(); while (node) { wxRealPoint *point = (wxRealPoint *)node->GetData(); delete point; m_points->Erase(node); node = m_points->GetFirst(); } delete m_points; m_points = NULL; } if (m_originalPoints) { wxObjectList::compatibility_iterator node = m_originalPoints->GetFirst(); while (node) { wxRealPoint *point = (wxRealPoint *)node->GetData(); delete point; m_originalPoints->Erase(node); node = m_originalPoints->GetFirst(); } delete m_originalPoints; m_originalPoints = NULL; }}// Width and height. Centre of object is centre of box.void wxPolygonShape::GetBoundingBoxMin(double *width, double *height){ *width = m_boundWidth; *height = m_boundHeight;}void wxPolygonShape::CalculateBoundingBox(){ // Calculate bounding box at construction (and presumably resize) time double left = 10000; double right = -10000; double top = 10000; double bottom = -10000; wxObjectList::compatibility_iterator node = m_points->GetFirst(); while (node) { wxRealPoint *point = (wxRealPoint *)node->GetData(); if (point->x < left) left = point->x; if (point->x > right) right = point->x; if (point->y < top) top = point->y; if (point->y > bottom) bottom = point->y; node = node->GetNext(); } m_boundWidth = right - left; m_boundHeight = bottom - top;}// Recalculates the centre of the polygon, and// readjusts the point offsets accordingly.// Necessary since the centre of the polygon// is expected to be the real centre of the bounding// box.void wxPolygonShape::CalculatePolygonCentre(){ double left = 10000; double right = -10000; double top = 10000; double bottom = -10000; wxObjectList::compatibility_iterator node = m_points->GetFirst(); while (node) { wxRealPoint *point = (wxRealPoint *)node->GetData(); if (point->x < left) left = point->x; if (point->x > right) right = point->x; if (point->y < top) top = point->y; if (point->y > bottom) bottom = point->y; node = node->GetNext(); } double bwidth = right - left; double bheight = bottom - top; double newCentreX = (double)(left + (bwidth/2.0)); double newCentreY = (double)(top + (bheight/2.0)); node = m_points->GetFirst(); while (node) { wxRealPoint *point = (wxRealPoint *)node->GetData(); point->x -= newCentreX; point->y -= newCentreY; node = node->GetNext(); } m_xpos += newCentreX; m_ypos += newCentreY;}bool PolylineHitTest(double n, double xvec[], double yvec[], double x1, double y1, double x2, double y2){ bool isAHit = false; int i; double lastx = xvec[0]; double lasty = yvec[0]; double min_ratio = 1.0; double line_ratio; double other_ratio; for (i = 1; i < n; i++) { oglCheckLineIntersection(x1, y1, x2, y2, lastx, lasty, xvec[i], yvec[i], &line_ratio, &other_ratio); if (line_ratio != 1.0) isAHit = true; lastx = xvec[i]; lasty = yvec[i]; if (line_ratio < min_ratio) min_ratio = line_ratio; } // Do last (implicit) line if last and first doubles are not identical if (!(xvec[0] == lastx && yvec[0] == lasty)) { oglCheckLineIntersection(x1, y1, x2, y2, lastx, lasty, xvec[0], yvec[0], &line_ratio, &other_ratio); if (line_ratio != 1.0) isAHit = true; } return isAHit;}bool wxPolygonShape::HitTest(double x, double y, int *attachment, double *distance){ // Imagine four lines radiating from this point. If all of these lines hit the polygon, // we're inside it, otherwise we're not. Obviously we'd need more radiating lines // to be sure of correct results for very strange (concave) shapes. double endPointsX[4]; double endPointsY[4]; // North endPointsX[0] = x; endPointsY[0] = (double)(y - 1000.0); // East endPointsX[1] = (double)(x + 1000.0); endPointsY[1] = y; // South endPointsX[2] = x; endPointsY[2] = (double)(y + 1000.0); // West endPointsX[3] = (double)(x - 1000.0); endPointsY[3] = y; // Store polygon points in an array int np = m_points->GetCount(); double *xpoints = new double[np]; double *ypoints = new double[np]; wxObjectList::compatibility_iterator node = m_points->GetFirst(); int i = 0; while (node) { wxRealPoint *point = (wxRealPoint *)node->GetData(); xpoints[i] = point->x + m_xpos; ypoints[i] = point->y + m_ypos; node = node->GetNext(); i ++; } // We assume it's inside the polygon UNLESS one or more // lines don't hit the outline. bool isContained = true; int noPoints = 4; for (i = 0; i < noPoints; i++) { if (!PolylineHitTest(np, xpoints, ypoints, x, y, endPointsX[i], endPointsY[i])) isContained = false; }/* if (isContained) ClipsErrorFunction("It's a hit!\n"); else ClipsErrorFunction("No hit.\n");*/ delete[] xpoints; delete[] ypoints; if (!isContained) return false; int nearest_attachment = 0; // If a hit, check the attachment points within the object. int n = GetNumberOfAttachments(); double nearest = 999999.0; for (i = 0; i < n; i++) { double xp, yp; if (GetAttachmentPositionEdge(i, &xp, &yp)) { double l = (double)sqrt(((xp - x) * (xp - x)) + ((yp - y) * (yp - y))); if (l < nearest) { nearest = l; nearest_attachment = i; } } } *attachment = nearest_attachment; *distance = nearest; return true;}// Really need to be able to reset the shape! Otherwise, if the// points ever go to zero, we've lost it, and can't resize.void wxPolygonShape::SetSize(double new_width, double new_height, bool WXUNUSED(recursive)){ SetAttachmentSize(new_width, new_height); // Multiply all points by proportion of new size to old size double x_proportion = (double)(fabs(new_width/m_originalWidth)); double y_proportion = (double)(fabs(new_height/m_originalHeight)); wxObjectList::compatibility_iterator node = m_points->GetFirst(); wxObjectList::compatibility_iterator original_node = m_originalPoints->GetFirst(); while (node && original_node) { wxRealPoint *point = (wxRealPoint *)node->GetData(); wxRealPoint *original_point = (wxRealPoint *)original_node->GetData(); point->x = (original_point->x * x_proportion); point->y = (original_point->y * y_proportion); node = node->GetNext(); original_node = original_node->GetNext(); }// CalculateBoundingBox(); m_boundWidth = (double)fabs(new_width); m_boundHeight = (double)fabs(new_height); SetDefaultRegionSize();}// Make the original points the same as the working pointsvoid wxPolygonShape::UpdateOriginalPoints(){ if (!m_originalPoints) m_originalPoints = new wxList; wxObjectList::compatibility_iterator original_node = m_originalPoints->GetFirst(); while (original_node) { wxObjectList::compatibility_iterator next_node = original_node->GetNext(); wxRealPoint *original_point = (wxRealPoint *)original_node->GetData(); delete original_point; m_originalPoints->Erase(original_node); original_node = next_node; } wxObjectList::compatibility_iterator node = m_points->GetFirst(); while (node) { wxRealPoint *point = (wxRealPoint *)node->GetData(); wxRealPoint *original_point = new wxRealPoint(point->x, point->y); m_originalPoints->Append((wxObject*) original_point); node = node->GetNext(); } CalculateBoundingBox(); m_originalWidth = m_boundWidth; m_originalHeight = m_boundHeight;}void wxPolygonShape::AddPolygonPoint(int pos){ wxObjectList::compatibility_iterator node = m_points->Item(pos); if (!node) node = m_points->GetFirst(); wxRealPoint *firstPoint = (wxRealPoint *)node->GetData(); wxObjectList::compatibility_iterator node2 = m_points->Item(pos + 1); if (!node2) node2 = m_points->GetFirst(); wxRealPoint *secondPoint = (wxRealPoint *)node2->GetData(); double x = (double)((secondPoint->x - firstPoint->x)/2.0 + firstPoint->x); double y = (double)((secondPoint->y - firstPoint->y)/2.0 + firstPoint->y); wxRealPoint *point = new wxRealPoint(x, y); if (pos >= (int) (m_points->GetCount() - 1)) m_points->Append((wxObject*) point); else m_points->Insert(node2, (wxObject*) point); UpdateOriginalPoints(); if (m_selected) { DeleteControlPoints(); MakeControlPoints(); }}void wxPolygonShape::DeletePolygonPoint(int pos){ wxObjectList::compatibility_iterator node = m_points->Item(pos); if (node) { wxRealPoint *point = (wxRealPoint *)node->GetData(); delete point; m_points->Erase(node); UpdateOriginalPoints(); if (m_selected) { DeleteControlPoints(); MakeControlPoints(); } }}// Assume (x1, y1) is centre of box (most generally, line end at box)bool wxPolygonShape::GetPerimeterPoint(double x1, double y1, double x2, double y2, double *x3, double *y3){ int n = m_points->GetCount(); // First check for situation where the line is vertical, // and we would want to connect to a point on that vertical -- // oglFindEndForPolyline can't cope with this (the arrow // gets drawn to the wrong place). if ((m_attachmentMode == ATTACHMENT_MODE_NONE) && (x1 == x2)) { // Look for the point we'd be connecting to. This is // a heuristic... wxObjectList::compatibility_iterator node = m_points->GetFirst(); while (node) { wxRealPoint *point = (wxRealPoint *)node->GetData(); if (point->x == 0.0) { if ((y2 > y1) && (point->y > 0.0)) { *x3 = point->x + m_xpos; *y3 = point->y + m_ypos; return true; } else if ((y2 < y1) && (point->y < 0.0)) { *x3 = point->x + m_xpos; *y3 = point->y + m_ypos; return true; } } node = node->GetNext(); } } double *xpoints = new double[n]; double *ypoints = new double[n]; wxObjectList::compatibility_iterator node = m_points->GetFirst(); int i = 0; while (node) { wxRealPoint *point = (wxRealPoint *)node->GetData(); xpoints[i] = point->x + m_xpos; ypoints[i] = point->y + m_ypos; node = node->GetNext(); i ++; } oglFindEndForPolyline(n, xpoints, ypoints, x1, y1, x2, y2, x3, y3);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -