<commit_before>//
// RoadMapEdit.cpp
//
// Copyright (c) 2001-2008 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

#include "wx/wxprec.h"

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

#include "RoadMapEdit.h"
#include "assert.h"
#include "NodeDlg.h"
#include "RoadDlg.h"
#include "RoadLayer.h"
#include "Builder.h"
#include "BuilderView.h"

#define NODE_RADIUS 5

wxPen LinkPen[11];
wxPen NodePen[VIT_TOTAL];
static bool g_bInitializedPens = false;

#define RP_HIGHWAY 0
// 1 through 7 are SURFT_GRAVEL through SURFT_STONE
#define RP_SELECTION 8
#define RP_DIRECTION 9
#define RP_CROSSES	10

NodeEdit::NodeEdit() : TNode()
{
	m_bSelect = false;
	m_iPathIndex = 0;
	m_pPrevPathNode = NULL;
	m_pPrevPathLink = NULL;
	m_iVisual = VIT_UNKNOWN;
}

//
// Equality operator
//
bool NodeEdit::operator==(NodeEdit &ref)
{
	if (! ((*((TNode *)this)) == ref))
		return false;

	return (m_iVisual == ref.m_iVisual);
}

void NodeEdit::Copy(NodeEdit* node)
{
	TNode::Copy(node);
	m_bSelect = node->m_bSelect;
	m_iVisual = node->m_iVisual;
}

//
// draw a node as a circle
//
bool NodeEdit::Draw(wxDC *pDC, vtScaledView *pView)
{
	pDC->SetLogicalFunction(wxCOPY);
	assert(m_iVisual >= VIT_UNKNOWN && m_iVisual <= VIT_STOPSIGN);
	pDC->SetPen(NodePen[m_iVisual]);
	pDC->SetBrush(wxBrush(wxColour(0,0,0), wxTRANSPARENT));
	wxRect box;

	int x = pView->sx(m_p.x);
	int y = pView->sy(m_p.y);
	box.x = x - NODE_RADIUS;
	box.y = y - NODE_RADIUS;
	box.width = NODE_RADIUS << 1;
	box.height = NODE_RADIUS << 1;
	pDC->DrawEllipse(box);
	if (m_bSelect)
	{
		pDC->SetLogicalFunction(wxINVERT);
		pDC->SetPen(NodePen[5]);
		pDC->DrawEllipse(box);
	}
	return true;
}

//
// bring up dialog box to edit node properties.
//
bool NodeEdit::EditProperties(vtScaledView *pView, vtRoadLayer *pLayer)
{
	NodeDlg dlg(NULL, -1, _("Node Properties"));

	dlg.SetNode(this, pLayer);

	float fScale = pView->GetScale();
	dlg.SetScale(fScale);

	return (dlg.ShowModal() == wxID_OK);
}

void NodeEdit::Translate(const DPoint2 &offset)
{
	m_p += offset;

	// update the endpoints of all the links that meet here
	for (int i = 0; i < m_iLinks; i++)
	{
		TLink *pL = m_connect[i].pLink;
		if (pL->GetNode(0) == this)
			pL->SetAt(0, m_p);
		if (pL->GetNode(1) == this)
			pL->SetAt(pL->GetSize()-1, m_p);
	}
}

void NodeEdit::DetermineVisualFromLinks()
{
	IntersectionType it;

	int nlights = 0, nstops = 0;

	for (int i = 0; i < m_iLinks; i++)
	{
		it = GetIntersectType(i);
		if (it == IT_LIGHT) nlights++;
		if (it == IT_STOPSIGN) nstops++;
	}
	if (nlights == m_iLinks)
		m_iVisual = VIT_ALLLIGHTS;
	else if (nstops == m_iLinks)
		m_iVisual = VIT_ALLSTOPS;
	else if (nlights > 0)
		m_iVisual = VIT_LIGHTS;
	else if (nstops > 0)
		m_iVisual = VIT_STOPSIGN;
	else
		m_iVisual = VIT_NONE;
}


///////////////////////////////////////////////////////////////////

LinkEdit::LinkEdit() : TLink(), Selectable()
{
	m_extent.SetRect(0,0,0,0);
	m_iPriority = 3;
	m_fLength = 0.0f;
	m_bDrawPoints = false;
	m_bSidesComputed = false;
}

//
// Equality operator
//
bool LinkEdit::operator==(LinkEdit &ref)
{
	if (! ((*((TLink *)this)) == ref))
		return false;

	return (m_iPriority == ref.m_iPriority &&
		m_fLength == ref.m_fLength);
}

void LinkEdit::ComputeExtent()
{
	int size = GetSize();

	DPoint2 p;
	p = GetAt(0);
	m_extent.SetRect(p.x, p.y, p.x, p.y);
	for (int i = 1; i < size; i++)
		m_extent.GrowToContainPoint(GetAt(i));
}

void LinkEdit::ComputeDisplayedLinkWidth(const DPoint2 &ToMeters)
{
	// also refresh the parallel left and right link edges
	m_fWidth = EstimateWidth();
	double half_width = (m_fWidth / 2);

	unsigned int size = GetSize();
	m_WidthOffset.SetSize(size);

	DPoint2 norm, prev, offset;

	for (unsigned int i = 0; i < size; i++)
	{
		prev = norm;

		DPoint2 p = GetAt(i);
		if (i < size-1)
		{
			DPoint2 vec = GetAt(i+1) - p;
			norm.x = -vec.y;
			norm.y = vec.x;
			norm.Normalize();
		}
		if (i == 0)		// first point
			offset = norm * half_width;
		else if (i > 0 && i < size-1)
		{
			// vector which bisects this point is the combination of both normals
			DPoint2 bisect = (norm + prev).Normalize();<commit_msg>check for duplicate points in ComputeDisplayedLinkWidth to avoid extraneous drawn lines on degenerate roads<commit_after>//
// RoadMapEdit.cpp
//
// Copyright (c) 2001-2008 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

#include "wx/wxprec.h"

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

#include "RoadMapEdit.h"
#include "assert.h"
#include "NodeDlg.h"
#include "RoadDlg.h"
#include "RoadLayer.h"
#include "Builder.h"
#include "BuilderView.h"

#define NODE_RADIUS 5

wxPen LinkPen[11];
wxPen NodePen[VIT_TOTAL];
static bool g_bInitializedPens = false;

#define RP_HIGHWAY 0
// 1 through 7 are SURFT_GRAVEL through SURFT_STONE
#define RP_SELECTION 8
#define RP_DIRECTION 9
#define RP_CROSSES	10

NodeEdit::NodeEdit() : TNode()
{
	m_bSelect = false;
	m_iPathIndex = 0;
	m_pPrevPathNode = NULL;
	m_pPrevPathLink = NULL;
	m_iVisual = VIT_UNKNOWN;
}

//
// Equality operator
//
bool NodeEdit::operator==(NodeEdit &ref)
{
	if (! ((*((TNode *)this)) == ref))
		return false;

	return (m_iVisual == ref.m_iVisual);
}

void NodeEdit::Copy(NodeEdit* node)
{
	TNode::Copy(node);
	m_bSelect = node->m_bSelect;
	m_iVisual = node->m_iVisual;
}

//
// draw a node as a circle
//
bool NodeEdit::Draw(wxDC *pDC, vtScaledView *pView)
{
	pDC->SetLogicalFunction(wxCOPY);
	assert(m_iVisual >= VIT_UNKNOWN && m_iVisual <= VIT_STOPSIGN);
	pDC->SetPen(NodePen[m_iVisual]);
	pDC->SetBrush(wxBrush(wxColour(0,0,0), wxTRANSPARENT));
	wxRect box;

	int x = pView->sx(m_p.x);
	int y = pView->sy(m_p.y);
	box.x = x - NODE_RADIUS;
	box.y = y - NODE_RADIUS;
	box.width = NODE_RADIUS << 1;
	box.height = NODE_RADIUS << 1;
	pDC->DrawEllipse(box);
	if (m_bSelect)
	{
		pDC->SetLogicalFunction(wxINVERT);
		pDC->SetPen(NodePen[5]);
		pDC->DrawEllipse(box);
	}
	return true;
}

//
// bring up dialog box to edit node properties.
//
bool NodeEdit::EditProperties(vtScaledView *pView, vtRoadLayer *pLayer)
{
	NodeDlg dlg(NULL, -1, _("Node Properties"));

	dlg.SetNode(this, pLayer);

	float fScale = pView->GetScale();
	dlg.SetScale(fScale);

	return (dlg.ShowModal() == wxID_OK);
}

void NodeEdit::Translate(const DPoint2 &offset)
{
	m_p += offset;

	// update the endpoints of all the links that meet here
	for (int i = 0; i < m_iLinks; i++)
	{
		TLink *pL = m_connect[i].pLink;
		if (pL->GetNode(0) == this)
			pL->SetAt(0, m_p);
		if (pL->GetNode(1) == this)
			pL->SetAt(pL->GetSize()-1, m_p);
	}
}

void NodeEdit::DetermineVisualFromLinks()
{
	IntersectionType it;

	int nlights = 0, nstops = 0;

	for (int i = 0; i < m_iLinks; i++)
	{
		it = GetIntersectType(i);
		if (it == IT_LIGHT) nlights++;
		if (it == IT_STOPSIGN) nstops++;
	}
	if (nlights == m_iLinks)
		m_iVisual = VIT_ALLLIGHTS;
	else if (nstops == m_iLinks)
		m_iVisual = VIT_ALLSTOPS;
	else if (nlights > 0)
		m_iVisual = VIT_LIGHTS;
	else if (nstops > 0)
		m_iVisual = VIT_STOPSIGN;
	else
		m_iVisual = VIT_NONE;
}


///////////////////////////////////////////////////////////////////

LinkEdit::LinkEdit() : TLink(), Selectable()
{
	m_extent.SetRect(0,0,0,0);
	m_iPriority = 3;
	m_fLength = 0.0f;
	m_bDrawPoints = false;
	m_bSidesComputed = false;
}

//
// Equality operator
//
bool LinkEdit::operator==(LinkEdit &ref)
{
	if (! ((*((TLink *)this)) == ref))
		return false;

	return (m_iPriority == ref.m_iPriority &&
		m_fLength == ref.m_fLength);
}

void LinkEdit::ComputeExtent()
{
	int size = GetSize();

	DPoint2 p;
	p = GetAt(0);
	m_extent.SetRect(p.x, p.y, p.x, p.y);
	for (int i = 1; i < size; i++)
		m_extent.GrowToContainPoint(GetAt(i));
}

void LinkEdit::ComputeDisplayedLinkWidth(const DPoint2 &ToMeters)
{
	// also refresh the parallel left and right link edges
	m_fWidth = EstimateWidth();
	double half_width = (m_fWidth / 2);

	unsigned int size = GetSize();
	m_WidthOffset.SetSize(size);

	DPoint2 norm, prev, offset;

	for (unsigned int i = 0; i < size; i++)
	{
		prev = norm;

		DPoint2 p = GetAt(i);
		if (i < size-1)
		{
			// beware duplicate points, which can cause bad normals; if we
			//  encounter them, just use the existing normal
			const DPoint2 &next = GetAt(i+1);
			if (p != next)
			{
				DPoint2 vec = next - p;
				norm.x = -vec.y;
				norm.y = vec.x;
				norm.Normalize();
			}
		}
		if (i == 0)		// first point
			offset = norm * half_width;
		else if (i > 0 && i < size-1)
		{
			// vector which bisects this point is the combination of both normals
			DPoint2 bisect = (norm + prev).Normalize();
{'fraction_non_alphanumeric': 0.1674287724234963, 'fraction_numerical': 0.013952397701958025, 'mean_word_length': 3.5934302638664515, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3852574', 'n_tokens_mistral': 3764, 'n_tokens_neox': 3534, 'n_words': 824}