⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 basic2.cpp

📁 Wxpython Implemented on Windows CE, Source code
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/////////////////////////////////////////////////////////////////////////////
// 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 Create
IMPLEMENT_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 points
void 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 + -