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

📄 efglayout.cc

📁 Gambit 是一个游戏库理论软件
💻 CC
📖 第 1 页 / 共 2 页
字号:
//// $Source: /home/gambit/CVS/gambit/sources/gui/efglayout.cc,v $// $Date: 2002/09/14 23:24:39 $// $Revision: 1.34.2.1 $//// DESCRIPTION:// Implementation of tree layout representation//// This file is part of Gambit// Copyright (c) 2002, The Gambit Project//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.//#include <math.h>#include "wx/wxprec.h"#ifndef WX_PRECOMP#include "wx/wx.h"#endif  // WX_PRECOMP#include "math/gmath.h"#include "game/efg.h"#include "treewin.h"#include "efgshow.h"//-----------------------------------------------------------------------//                   class NodeEntry: Member functions//-----------------------------------------------------------------------NodeEntry::NodeEntry(Node *p_node)  : m_node(p_node), m_parent(0),    m_x(-1), m_y(-1), m_nextMember(0), m_inSupport(true),    m_selected(false), m_cursor(false), m_cut(false),    m_subgameRoot(false), m_subgameMarked(false), m_size(20),    m_token(NODE_TOKEN_CIRCLE),    m_branchStyle(BRANCH_STYLE_LINE), m_branchLabel(BRANCH_LABEL_HORIZONTAL),    m_branchLength(0),    m_sublevel(0), m_actionProb(0){ }int NodeEntry::GetChildNumber(void) const{  if (m_node->GetParent()) {    return m_node->GetAction()->GetNumber();  }  else {    return 0;  }}void NodeEntry::SetCursor(bool p_cursor){  m_cursor = p_cursor;  if (m_cursor) {    m_selected = true;  }}//// Draws the node token itself, as well as the incoming branch// (if not the root node)//void NodeEntry::Draw(wxDC &p_dc) const{  if (m_node->GetParent() && m_inSupport) {    DrawIncomingBranch(p_dc);  }  if (m_cut) {    p_dc.SetPen(*wxLIGHT_GREY_PEN);  }  else {    p_dc.SetPen(*wxThePenList->FindOrCreatePen(m_color, (IsSelected()) ? 4 : 2,					       wxSOLID));  }  if (m_token == NODE_TOKEN_LINE) {    p_dc.DrawLine(m_x, m_y, m_x + m_size, m_y);    if (m_branchStyle == BRANCH_STYLE_FORKTINE) {      // "classic" Gambit style: draw a small 'token' to separate      // the fork from the node      p_dc.DrawEllipse(m_x - 1, m_y - 1, 3, 3);    }  }  else if (m_token == NODE_TOKEN_BOX) {    p_dc.SetBrush(*wxWHITE_BRUSH);    p_dc.DrawRectangle(m_x, m_y - m_size / 2, m_size, m_size);  }  else if (m_token == NODE_TOKEN_DIAMOND) {    wxPoint points[4] = { wxPoint(m_x + m_size / 2, m_y - m_size / 2),			  wxPoint(m_x, m_y),			  wxPoint(m_x + m_size / 2, m_y + m_size / 2),			  wxPoint(m_x + m_size, m_y) };    p_dc.SetBrush(*wxWHITE_BRUSH);    p_dc.DrawPolygon(4, points);  }  else {    // Default: draw circles    p_dc.SetBrush(*wxWHITE_BRUSH);    p_dc.DrawEllipse(m_x, m_y - m_size / 2, m_size, m_size);   }  int textWidth, textHeight;  p_dc.SetFont(m_nodeAboveFont);  p_dc.GetTextExtent(m_nodeAboveLabel, &textWidth, &textHeight);  p_dc.DrawText(m_nodeAboveLabel,		m_x + (m_size - textWidth) / 2, m_y - textHeight - 9);  p_dc.SetFont(m_nodeBelowFont);  p_dc.GetTextExtent(m_nodeBelowLabel, &textWidth, &textHeight);  p_dc.DrawText(m_nodeBelowLabel,		m_x + (m_size - textWidth) / 2, m_y + 9);  p_dc.SetFont(m_nodeRightFont);  p_dc.GetTextExtent(m_nodeRightLabel, &textWidth, &textHeight);  p_dc.DrawText(m_nodeRightLabel,		m_x + GetSize() + 10, m_y - textHeight/2);  if (m_subgameRoot) {    if (m_subgameMarked) {      p_dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 2, wxSOLID));    }    else {      p_dc.SetPen(*wxThePenList->FindOrCreatePen(*wxLIGHT_GREY, 2, wxSOLID));    }    p_dc.DrawLine(m_x - m_size / 2, m_y,		  m_x + 2 * m_size, m_y + 2 * m_size);    p_dc.DrawLine(m_x - m_size / 2, m_y,		  m_x + 2 * m_size, m_y - 2 * m_size);  }}void NodeEntry::DrawIncomingBranch(wxDC &p_dc) const{  int xStart = m_parent->m_x + m_parent->m_size;  int xEnd = m_x;  int yStart = m_parent->m_y;  int yEnd = m_y;  if (m_parent->m_cut) {    p_dc.SetPen(*wxLIGHT_GREY_PEN);  }  else {    p_dc.SetPen(*wxThePenList->FindOrCreatePen(m_parent->m_color,					       2, wxSOLID));   }  if (m_branchStyle == BRANCH_STYLE_LINE) {    p_dc.DrawLine(xStart, yStart, xEnd, yEnd);    // Draw in the highlight indicating action probabilities    if (m_actionProb >= gNumber(0)) {      p_dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 2, wxSOLID));      p_dc.DrawLine(xStart, yStart, 		    xStart +		    (int) ((double) (xEnd - xStart) * (double) m_actionProb),		    yStart +		    (int) ((double) (yEnd - yStart) * (double) m_actionProb));    }    int textWidth, textHeight;    p_dc.SetFont(m_branchAboveFont);    p_dc.GetTextExtent(m_branchAboveLabel, &textWidth, &textHeight);    // The angle of the branch    double theta = -atan((double) (yEnd - yStart) / (double) (xEnd - xStart));    // The "centerpoint" of the branch    int xbar = (xStart + xEnd) / 2;    int ybar = (yStart + yEnd) / 2;    if (m_branchLabel == BRANCH_LABEL_HORIZONTAL) {      if (yStart >= yEnd) {	p_dc.DrawText(m_branchAboveLabel, xbar - textWidth / 2, 		      ybar - textHeight + 		      textWidth / 2 * (yEnd - yStart) / (xEnd - xStart));      }      else {	p_dc.DrawText(m_branchAboveLabel, xbar - textWidth / 2, 		      ybar - textHeight - 		      textWidth / 2 * (yEnd - yStart) / (xEnd - xStart));      }    }    else {      // Draw the text rotated appropriately      p_dc.DrawRotatedText(m_branchAboveLabel,			   (int) ((double) xbar -				  (double) textHeight * sin(theta) -				  (double) textWidth * cos(theta) / 2.0),			   (int) ((double) ybar - 				  (double) textHeight * cos(theta) +				  (double) textWidth * sin(theta) / 2.0),			   theta * 180.0 / 3.14159);    }    p_dc.SetFont(m_branchBelowFont);    p_dc.GetTextExtent(m_branchBelowLabel, &textWidth, &textHeight);    if (m_branchLabel == BRANCH_LABEL_HORIZONTAL) {      if (yStart >= yEnd) {	p_dc.DrawText(m_branchBelowLabel, xbar - textWidth / 2,		      ybar - textWidth/2 * (yEnd - yStart) / (xEnd - xStart));      }      else {	p_dc.DrawText(m_branchBelowLabel, xbar - textWidth / 2,		      ybar + textWidth/2 * (yEnd - yStart) / (xEnd - xStart));      }    }    else {      // Draw the text rotated appropriately      p_dc.DrawRotatedText(m_branchBelowLabel,			   (int) ((double) xbar -				  (double) textWidth * cos(theta) / 2.0),			   (int) ((double) ybar +				  (double) textWidth * sin(theta) / 2.0),			   theta * 180.0 / 3.14159);    }  }  else {    // Old style fork-tine     p_dc.DrawLine(xStart, yStart, xStart + m_branchLength, yEnd);    p_dc.DrawLine(xStart + m_branchLength, yEnd, xEnd, yEnd);        // Draw in the highlight indicating action probabilities    if (m_actionProb >= gNumber(0)) {      p_dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 2, wxSOLID));      p_dc.DrawLine(xStart, yStart, 		    xStart + 		    (int) ((double) m_branchLength * (double) m_actionProb),		    yStart + 		    (int) ((double) (yEnd - yStart) * (double) m_actionProb));    }    int textWidth, textHeight;    p_dc.SetFont(m_branchAboveFont);    p_dc.GetTextExtent(m_branchAboveLabel, &textWidth, &textHeight);    p_dc.DrawText(m_branchAboveLabel,		  xStart + m_branchLength + 3, yEnd - textHeight - 3);        p_dc.SetFont(m_branchBelowFont);    p_dc.GetTextExtent(m_branchBelowLabel, &textWidth, &textHeight);    p_dc.DrawText(m_branchBelowLabel,		  xStart + m_branchLength + 3, yEnd + 3);  }}bool NodeEntry::NodeHitTest(int p_x, int p_y) const{  if (p_x < m_x || p_x >= m_x + m_size) {    return false;  }  if (m_token == NODE_TOKEN_LINE) {    const int DELTA = 8;  // a fudge factor for "almost" hitting the node    return (p_y >= m_y - DELTA && p_y <= m_y + DELTA);  }  else {    return (p_y >= m_y - m_size / 2 && p_y <= m_y + m_size / 2);  }}//-----------------------------------------------------------------------//                class efgTreeLayout: Member functions//-----------------------------------------------------------------------efgTreeLayout::efgTreeLayout(efgGame &p_efg, TreeWindow *p_parent)  : m_efg(p_efg), m_parent(p_parent), m_infosetSpacing(40),    c_leftMargin(20), c_topMargin(40){ }Node *efgTreeLayout::NodeHitTest(int p_x, int p_y) const{  for (int i = 1; i <= m_nodeList.Length(); i++) {    if (m_nodeList[i]->NodeHitTest(p_x, p_y)) {      return m_nodeList[i]->GetNode();    }  }  return 0;}Node *efgTreeLayout::BranchHitTest(int p_x, int p_y) const{  for (int i = 1; i <= m_nodeList.Length(); i++) {    NodeEntry *entry = m_nodeList[i];    NodeEntry *parent_entry = GetNodeEntry(entry->GetNode()->GetParent());    if (parent_entry) {      if (p_x > (parent_entry->X() + m_parent->DrawSettings().NodeSize() + 		 parent_entry->GetSublevel() * m_infosetSpacing + 10) &&	  p_x < (parent_entry->X() + m_parent->DrawSettings().NodeSize() +		 m_parent->DrawSettings().BranchLength() +		 parent_entry->GetSublevel() * m_infosetSpacing)) {	// Good old slope/intercept method for finding a point on a line	int y0 = (parent_entry->Y() + 		  (int) (p_x - parent_entry->X() - 			 m_parent->DrawSettings().NodeSize()) *		  (entry->Y() - parent_entry->Y()) / 		  m_parent->DrawSettings().BranchLength());	if (p_y > y0-2 && p_y < y0+2) {	  return entry->GetNode();	}      }    }  }  return 0;}Node *efgTreeLayout::InfosetHitTest(int p_x, int p_y) const{  for (int i = 1; i <= m_nodeList.Length(); i++) {    NodeEntry *entry = m_nodeList[i];    if (entry->GetNextMember() && entry->GetNode()->GetInfoset()) {      if (p_x > entry->X() + entry->GetSublevel() * m_infosetSpacing - 2 &&	  p_x < entry->X() + entry->GetSublevel() * m_infosetSpacing + 2) {	if (p_y > entry->Y() && p_y < entry->GetNextMember()->Y()) {	  // next iset is below this one	  return entry->GetNode();	}	else if (p_y > entry->GetNextMember()->Y() && p_y < entry->Y()) {	  // next iset is above this one	  return entry->GetNode();	}      }    }  }  return 0;}wxString efgTreeLayout::CreateNodeAboveLabel(const NodeEntry *p_entry) const{  const Node *n = p_entry->GetNode();      switch (m_parent->DrawSettings().NodeAboveLabel()) {  case NODE_ABOVE_NOTHING:    return "";  case NODE_ABOVE_LABEL:    return (const char *) n->GetName();  case NODE_ABOVE_PLAYER:    return ((const char *) 	    ((n->GetPlayer()) ? n->GetPlayer()->GetName() : gText("")));  case NODE_ABOVE_ISETLABEL:    return ((const char *)	    ((n->GetInfoset()) ? n->GetInfoset()->GetName() : gText("")));  case NODE_ABOVE_ISETID:    return ((const char *)	    ((n->GetInfoset()) ?	     ("(" + ToText(n->GetPlayer()->GetNumber()) +	      "," + ToText(n->GetInfoset()->GetNumber()) + ")") : gText("")));  case NODE_ABOVE_OUTCOME:    return (const char *) m_parent->OutcomeAsString(n);  case NODE_ABOVE_REALIZPROB:    return (const char *) m_parent->Parent()->GetRealizProb(n);  case NODE_ABOVE_BELIEFPROB:    return (const char *) m_parent->Parent()->GetBeliefProb(n);  case NODE_ABOVE_VALUE:    return (const char *) m_parent->Parent()->GetNodeValue(n);  default:    return "";  }}    wxString efgTreeLayout::CreateNodeBelowLabel(const NodeEntry *p_entry) const{  const Node *n = p_entry->GetNode();  switch (m_parent->DrawSettings().NodeBelowLabel()) {   case NODE_BELOW_NOTHING:    return "";  case NODE_BELOW_LABEL:    return (const char *) n->GetName();  case NODE_BELOW_PLAYER:    return ((const char *)	    ((n->GetPlayer()) ? n->GetPlayer()->GetName() : gText("")));  case NODE_BELOW_ISETLABEL:    return ((const char *)	    ((n->GetInfoset()) ? n->GetInfoset()->GetName() : gText("")));  case NODE_BELOW_ISETID:    return ((const char *)	    ((n->GetInfoset()) ?	     ("(" + ToText(n->GetPlayer()->GetNumber()) +	      "," + ToText(n->GetInfoset()->GetNumber()) + ")") : gText("")));  case NODE_BELOW_OUTCOME:    return (const char *) m_parent->OutcomeAsString(n);  case NODE_BELOW_REALIZPROB:    return (const char *) m_parent->Parent()->GetRealizProb(n);  case NODE_BELOW_BELIEFPROB:    return (const char *) m_parent->Parent()->GetBeliefProb(n);  case NODE_BELOW_VALUE:    return (const char *) m_parent->Parent()->GetNodeValue(n);  default:    return "";  }}wxString efgTreeLayout::CreateNodeRightLabel(const NodeEntry *p_entry) const{      const Node *node = p_entry->GetNode();  switch (m_parent->DrawSettings().NodeRightLabel()) {   case NODE_RIGHT_NOTHING:    return "";  case NODE_RIGHT_OUTCOME:    return (const char *) m_parent->OutcomeAsString(node);  case NODE_RIGHT_NAME:    if (node->Game()->GetOutcome(node)) {      return (const char *) m_efg.GetOutcomeName(node->Game()->GetOutcome(node));    }    else {      return "";    }  default:    return "";  }}wxString efgTreeLayout::CreateBranchAboveLabel(const NodeEntry *p_entry) const{  const Node *parent = p_entry->GetParent()->GetNode();  switch (m_parent->DrawSettings().BranchAboveLabel()) {  case BRANCH_ABOVE_NOTHING:    return "";  case BRANCH_ABOVE_LABEL:    return (const char *) parent->GetInfoset()->GetActionName(p_entry->GetChildNumber());  case BRANCH_ABOVE_PROBS:    return (const char *) m_parent->Parent()->GetActionProb(parent,							    p_entry->GetChildNumber());  case BRANCH_ABOVE_VALUE:    return (const char *) m_parent->Parent()->GetActionValue(parent,							     p_entry->GetChildNumber());  default:    return "";  }}wxString efgTreeLayout::CreateBranchBelowLabel(const NodeEntry *p_entry) const{  const Node *parent = p_entry->GetParent()->GetNode();  switch (m_parent->DrawSettings().BranchBelowLabel()) {  case BRANCH_BELOW_NOTHING:    return "";  case BRANCH_BELOW_LABEL:    return (const char *) parent->GetInfoset()->GetActionName(p_entry->GetChildNumber());  case BRANCH_BELOW_PROBS:    return (const char *) m_parent->Parent()->GetActionProb(parent,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -