diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8a30d25
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,398 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.tlog
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
diff --git a/BuildProcessTemplates/DefaultTemplate.11.1.xaml b/BuildProcessTemplates/DefaultTemplate.11.1.xaml
deleted file mode 100644
index 60eac4b..0000000
--- a/BuildProcessTemplates/DefaultTemplate.11.1.xaml
+++ /dev/null
@@ -1,543 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [New Microsoft.TeamFoundation.Build.Workflow.Activities.BuildSettings()]
- [False]
- [New Microsoft.TeamFoundation.Build.Workflow.Activities.TestSpecList(New Microsoft.TeamFoundation.Build.Workflow.Activities.AgileTestPlatformSpec("**\*test*.dll"))]
- ["$(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.r)"]
- [False]
- [True]
- [True]
- [Microsoft.TeamFoundation.Build.Workflow.Activities.CleanWorkspaceOption.All]
-
-
-
- [Microsoft.TeamFoundation.Build.Workflow.Activities.CodeAnalysisOption.AsConfigured]
- [True]
- [Microsoft.TeamFoundation.Build.Workflow.Activities.ToolPlatform.Auto]
- [True]
- [New Microsoft.TeamFoundation.Build.Workflow.Activities.SourceAndSymbolServerSettings(True, Nothing)]
- [True]
-
-
-
- [New Microsoft.TeamFoundation.Build.Workflow.Activities.AgentSettings() With {.MaxWaitTime = New System.TimeSpan(4, 0, 0), .MaxExecutionTime = New System.TimeSpan(0, 0, 0), .TagComparison = Microsoft.TeamFoundation.Build.Workflow.Activities.TagComparison.MatchExactly }]
- [Microsoft.TeamFoundation.Build.Workflow.BuildVerbosity.Normal]
-
-
-
-
-
-
- All
- 11.0
- Assembly references and imported namespaces serialized as XML namespaces
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/BuildProcessTemplates/LabDefaultTemplate.11.xaml b/BuildProcessTemplates/LabDefaultTemplate.11.xaml
deleted file mode 100644
index 542717f..0000000
--- a/BuildProcessTemplates/LabDefaultTemplate.11.xaml
+++ /dev/null
@@ -1,208 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 11.0
-
-
-
-
-
- 920,3702
- Assembly references and imported namespaces serialized as XML namespaces
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- True
-
-
-
-
-
-
- [LabWorkflowParameters.BuildDetails.BuildUri]
-
-
- [ChildBuildDetail.Uri]
-
-
-
-
-
-
-
-
-
-
-
- [BuildLocation]
-
-
- [If(LabWorkflowParameters.BuildDetails.Configuration Is Nothing, BuildLocation, If(LabWorkflowParameters.BuildDetails.Configuration.IsEmpty Or (SelectedBuildDetail.Information.GetNodesByType(Microsoft.TeamFoundation.Build.Common.InformationTypes.ConfigurationSummary, True)).Count = 1, BuildLocation, If(LabWorkflowParameters.BuildDetails.Configuration.IsPlatformEmptyOrAnyCpu, BuildLocation + "\" + LabWorkflowParameters.BuildDetails.Configuration.Configuration, BuildLocation + "\" + LabWorkflowParameters.BuildDetails.Configuration.Platform + "\" + LabWorkflowParameters.BuildDetails.Configuration.Configuration)))]
-
-
-
-
-
-
-
-
-
-
-
- [LabEnvironmentUri]
-
-
- [LabWorkflowParameters.EnvironmentDetails.LabEnvironmentUri.ToString()]
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [PostDeploymentSnapshotName]
-
-
- [If(LabWorkflowParameters.BuildDetails.IsTeamSystemBuild = True,String.Format("{0}_{1}_{2}", LabWorkflowParameters.DeploymentDetails.PostDeploymentSnapshotName, BuildNumber,BuildDetail.BuildNumber),String.Format("{0}_{1}", LabWorkflowParameters.DeploymentDetails.PostDeploymentSnapshotName, BuildDetail.BuildNumber))]
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [BuildStatus]
-
-
- [Microsoft.TeamFoundation.Build.Client.BuildStatus.PartiallySucceeded]
-
-
-
-
-
-
- [BuildStatus]
-
-
- [Microsoft.TeamFoundation.Build.Client.BuildStatus.Failed]
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/BuildProcessTemplates/UpgradeTemplate.xaml b/BuildProcessTemplates/UpgradeTemplate.xaml
deleted file mode 100644
index 8ae6923..0000000
--- a/BuildProcessTemplates/UpgradeTemplate.xaml
+++ /dev/null
@@ -1,76 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [New Microsoft.TeamFoundation.Build.Workflow.Activities.AgentSettings() With {.MaxWaitTime = New System.TimeSpan(4, 0, 0), .MaxExecutionTime = New System.TimeSpan(0, 0, 0), .TagComparison = Microsoft.TeamFoundation.Build.Workflow.Activities.TagComparison.MatchExactly }]
-
-
-
- [Microsoft.TeamFoundation.Build.Workflow.Activities.ToolPlatform.Auto]
- [False]
- [False]
-
-
-
-
-
-
-
-
-
- [Microsoft.TeamFoundation.VersionControl.Client.RecursionType.OneLevel]
- [Microsoft.TeamFoundation.Build.Workflow.BuildVerbosity.Normal]
-
-
-
- All
- Assembly references and imported namespaces serialized as XML namespaces
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/README.md b/README.md
index 5d1259f..0932436 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,23 @@
-# **Triangle.NET** (beta 4) by Christian Woltering
+# Triangle.NET
-Triangle.NET generates 2D (constrained) Delaunay triangulations and high-quality meshes of point sets or planar straight line graphs. It is a C# port of Jonathan Shewchuk's [Triangle](http://www.cs.cmu.edu/~quake/triangle.html) software.
+Triangle.NET generates 2D (constrained) Delaunay triangulations and high-quality meshes of point sets or planar straight line graphs. It is a C# port of Jonathan Shewchuk's [Triangle](https://www.cs.cmu.edu/~quake/triangle.html) software.
-## Attribution
+## Features
-This C# libray is created and maintained by Christian Woltering. This repository is a fork of the original [**Triangle.NET** repository at CodePlex](https://triangle.codeplex.com).
+* Constrained Delaunay triangulation of planar straight line graphs
+* Incremental, sweepline and divide & conquer Delaunay triangulation algorithms
+* High-quality triangular meshes with minimum/maximum angle constraints
+* Mesh refinement
+* Mesh smoothing using centroidal Voronoi tessellation (CVT)
+* Node renumbering (Cuthill-McKee)
+* Read and write Triangle format files (.node, .poly, .ele)
+
+## Usage
+
+Please refer to the [Examples](https://github.com/wo80/Triangle.NET/tree/master/src/Triangle.Examples) project. [Geri Borbás](https://github.com/Geri-Borbas) has prepared a "Release" branch containing the main project source only for submodule usage.
## License
-> Licensed under the [**MIT License**](https://en.wikipedia.org/wiki/MIT_License).
\ No newline at end of file
+The original C code published by Jonathan Shewchuk comes with a proprietary license (see [Triangle README](https://github.com/wo80/Triangle/blob/master/src/Triangle/README)) which, unfortunately, isn't very clear about how a derived work like Triangle.NET should be handled. Though Triangle.NET was published on Codeplex (https://triangle.codeplex.com, no longer available) under the MIT license in 2012, I recommend not using this code in a commercial context. Due to the unclear licensing situation, there will also be no Nuget package release.
+
+For further discussion, please refer to the open issue [License Confusion](https://github.com/wo80/Triangle.NET/issues/6).
diff --git a/Triangle.NET/TestApp/Mesh Explorer.csproj b/Triangle.NET/TestApp/Mesh Explorer.csproj
deleted file mode 100644
index ce945f7..0000000
--- a/Triangle.NET/TestApp/Mesh Explorer.csproj
+++ /dev/null
@@ -1,198 +0,0 @@
-
-
-
- Debug
- x86
- 8.0.30703
- 2.0
- {336AAF8A-5316-4303-9E73-5E38BD0B28AF}
- WinExe
- Properties
- MeshExplorer
- Mesh Explorer
- v4.0
- Client
- 512
- SAK
- SAK
- SAK
- SAK
-
-
- x86
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- x86
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
- Component
-
-
- Component
-
-
- Component
-
-
- Component
-
-
- Component
-
-
- Component
-
-
- Component
-
-
-
- Form
-
-
- Form
-
-
- FormExport.cs
-
-
- Form
-
-
- FormGenerator.cs
-
-
- Form
-
-
- FormLog.cs
-
-
- Form
-
-
- FormMain.cs
-
-
- Form
-
-
- FormTopology.cs
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- UserControl
-
-
- TopologyControlView.cs
-
-
- Component
-
-
-
-
- UserControl
-
-
- AboutView.cs
-
-
-
- UserControl
-
-
- MeshControlView.cs
-
-
- UserControl
-
-
- StatisticView.cs
-
-
- FormExport.cs
-
-
- FormGenerator.cs
-
-
- FormLog.cs
-
-
- FormMain.cs
-
-
- FormTopology.cs
-
-
- TopologyControlView.cs
-
-
- AboutView.cs
-
-
- MeshControlView.cs
-
-
- StatisticView.cs
-
-
-
-
- {41022e0e-bd0f-439e-bc3a-aabb1b43471b}
- Triangle.Rendering
-
-
- {F7907A0A-B75F-400B-9E78-BFAD00DB4D6B}
- Triangle
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Triangle.NET/TestApp/Mesh Explorer.csproj.vspscc b/Triangle.NET/TestApp/Mesh Explorer.csproj.vspscc
deleted file mode 100644
index feffdec..0000000
--- a/Triangle.NET/TestApp/Mesh Explorer.csproj.vspscc
+++ /dev/null
@@ -1,10 +0,0 @@
-""
-{
-"FILE_VERSION" = "9237"
-"ENLISTMENT_CHOICE" = "NEVER"
-"PROJECT_FILE_RELATIVE_PATH" = ""
-"NUMBER_OF_EXCLUDED_FILES" = "0"
-"ORIGINAL_PROJECT_FILE_PATH" = ""
-"NUMBER_OF_NESTED_PROJECTS" = "0"
-"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
-}
diff --git a/Triangle.NET/TestApp/Properties/AssemblyInfo.cs b/Triangle.NET/TestApp/Properties/AssemblyInfo.cs
deleted file mode 100644
index d240e61..0000000
--- a/Triangle.NET/TestApp/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("Mesh Explorer")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Mesh Explorer")]
-[assembly: AssemblyCopyright("Copyright © 2012")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("7368d676-5415-47a5-b1a7-3d517e418b21")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Triangle.NET/TestApp/Views/AboutView.resx b/Triangle.NET/TestApp/Views/AboutView.resx
deleted file mode 100644
index 29dcb1b..0000000
--- a/Triangle.NET/TestApp/Views/AboutView.resx
+++ /dev/null
@@ -1,120 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
\ No newline at end of file
diff --git a/Triangle.NET/Triangle.Rendering/BoundingBox.cs b/Triangle.NET/Triangle.Rendering/BoundingBox.cs
deleted file mode 100644
index 73a4ae5..0000000
--- a/Triangle.NET/Triangle.Rendering/BoundingBox.cs
+++ /dev/null
@@ -1,68 +0,0 @@
-
-namespace TriangleNet.Rendering
-{
- using System.Drawing;
-
- public class BoundingBox
- {
- public float Left;
- public float Right;
- public float Bottom;
- public float Top;
-
- public float Width
- {
- get { return this.Right - this.Left; }
- }
-
- public float Height
- {
- get { return this.Top - this.Bottom; }
- }
-
- public BoundingBox()
- {
- Reset();
- }
-
- public BoundingBox(float left, float right, float bottom, float top)
- {
- this.Left = left;
- this.Right = right;
- this.Bottom = bottom;
- this.Top = top;
- }
-
- public void Update(Point pt)
- {
- this.Update(pt.X, pt.Y);
- }
-
- public void Update(PointF pt)
- {
- this.Update(pt.X, pt.Y);
- }
-
- public void Update(double x, double y)
- {
- Update((float)x, (float)y);
- }
-
- public void Update(float x, float y)
- {
- // Update bounding box
- if (this.Left > x) this.Left = x;
- if (this.Right < x) this.Right = x;
- if (this.Bottom > y) this.Bottom = y;
- if (this.Top < y) this.Top = y;
- }
-
- public void Reset()
- {
- this.Left = float.MaxValue;
- this.Right = -float.MaxValue;
- this.Bottom = float.MaxValue;
- this.Top = -float.MaxValue;
- }
- }
-}
diff --git a/Triangle.NET/Triangle.Rendering/Buffer/BufferBase.cs b/Triangle.NET/Triangle.Rendering/Buffer/BufferBase.cs
deleted file mode 100644
index 27e9974..0000000
--- a/Triangle.NET/Triangle.Rendering/Buffer/BufferBase.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-
-namespace TriangleNet.Rendering.Buffer
-{
- public abstract class BufferBase : IBuffer where T : struct
- {
- protected T[] data;
- protected int size;
-
- public BufferBase(int capacity, int size)
- {
- this.data = new T[capacity];
- this.size = size;
- }
-
- public BufferBase(T[] data, int size)
- {
- this.data = data;
- this.size = size;
- }
-
- public T[] Data
- {
- get { return data; }
- }
-
- public int Count
- {
- get { return data == null ? 0 : data.Length; }
- }
-
- public abstract int Size
- {
- get;
- }
-
- public abstract BufferTarget Target
- {
- get;
- }
- }
-}
diff --git a/Triangle.NET/Triangle.Rendering/Buffer/ColorBuffer.cs b/Triangle.NET/Triangle.Rendering/Buffer/ColorBuffer.cs
deleted file mode 100644
index 6ae7643..0000000
--- a/Triangle.NET/Triangle.Rendering/Buffer/ColorBuffer.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-
-namespace TriangleNet.Rendering.Buffer
-{
- using System;
- using System.Drawing;
-
- public class ColorBuffer : BufferBase
- {
- public ColorBuffer(int capacity, int size)
- : base(capacity, size)
- {
- }
-
- public ColorBuffer(Color[] data, int size)
- : base(data, size)
- {
- }
-
- public override int Size
- {
- get { return 1; }
- }
-
- public override BufferTarget Target
- {
- get { return BufferTarget.ColorBuffer; }
- }
- }
-}
diff --git a/Triangle.NET/Triangle.Rendering/Buffer/IndexBuffer.cs b/Triangle.NET/Triangle.Rendering/Buffer/IndexBuffer.cs
deleted file mode 100644
index a98526f..0000000
--- a/Triangle.NET/Triangle.Rendering/Buffer/IndexBuffer.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-
-namespace TriangleNet.Rendering.Buffer
-{
- public class IndexBuffer : BufferBase
- {
- public IndexBuffer(int capacity, int size)
- : base(capacity, size)
- {
- }
-
- public IndexBuffer(int[] data, int size)
- : base(data, size)
- {
- }
-
- ///
- /// Gets the number of indices for one element (i.e. 2 for segments
- /// or 3 for triangles).
- ///
- public override int Size
- {
- get { return size; }
- }
-
- public override BufferTarget Target
- {
- get { return BufferTarget.IndexBuffer; }
- }
- }
-}
diff --git a/Triangle.NET/Triangle.Rendering/Buffer/VertexBuffer.cs b/Triangle.NET/Triangle.Rendering/Buffer/VertexBuffer.cs
deleted file mode 100644
index fb8ec45..0000000
--- a/Triangle.NET/Triangle.Rendering/Buffer/VertexBuffer.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-
-namespace TriangleNet.Rendering.Buffer
-{
- public class VertexBuffer : BufferBase
- {
- public VertexBuffer(int capacity, int size = 2)
- : base(capacity, size)
- {
- }
-
- public VertexBuffer(float[] data, int size = 2)
- : base(data, size)
- {
- }
-
- ///
- /// Gets the number of coordinates of one vertex in the buffer (i.e. 2 for
- /// 2D points or 3D points).
- ///
- public override int Size
- {
- get { return size; }
- }
-
- public override BufferTarget Target
- {
- get { return BufferTarget.VertexBuffer; }
- }
- }
-}
diff --git a/Triangle.NET/Triangle.Rendering/ColorManager.cs b/Triangle.NET/Triangle.Rendering/ColorManager.cs
deleted file mode 100644
index b3d2b20..0000000
--- a/Triangle.NET/Triangle.Rendering/ColorManager.cs
+++ /dev/null
@@ -1,181 +0,0 @@
-
-namespace TriangleNet.Rendering
-{
- using System.Collections.Generic;
- using System.Drawing;
- using TriangleNet.Rendering.Util;
-
- public class ColorManager
- {
- Color background;
- SolidBrush point;
- SolidBrush steinerPoint;
- Pen line;
- Pen segment;
- Pen voronoiLine;
-
- #region Public properties
-
- ///
- /// Gets or sets the background color.
- ///
- public Color Background
- {
- get { return background; }
- set { background = value; }
- }
-
- ///
- /// Gets or sets the brush used for points.
- ///
- public SolidBrush Point
- {
- get { return point; }
- set
- {
- if (point != null) point.Dispose();
- point = value;
- }
- }
-
- ///
- /// Gets or sets the brush used for steiner points.
- ///
- public SolidBrush SteinerPoint
- {
- get { return steinerPoint; }
- set
- {
- if (steinerPoint != null) steinerPoint.Dispose();
- steinerPoint = value;
- }
- }
-
- ///
- /// Gets or sets the pen used for mesh edges.
- ///
- public Pen Line
- {
- get { return line; }
- set
- {
- if (line != null) line.Dispose();
- line = value;
- }
- }
-
- ///
- /// Gets or sets the pen used for mesh segments.
- ///
- public Pen Segment
- {
- get { return segment; }
- set
- {
- if (segment != null) segment.Dispose();
- segment = value;
- }
- }
-
- ///
- /// Gets or sets the pen used for Voronoi edges.
- ///
- public Pen VoronoiLine
- {
- get { return voronoiLine; }
- set
- {
- if (voronoiLine != null) voronoiLine.Dispose();
- voronoiLine = value;
- }
- }
-
- #endregion
-
- ///
- /// Gets or sets a dictionary which maps region ids (or partition indices) to a color.
- ///
- public Dictionary ColorDictionary { get; set; }
-
- ///
- /// Gets or sets a colormap which is used for function plotting.
- ///
- public ColorMap ColorMap { get; set; }
-
- ///
- /// Creates an instance of the class with default (dark) color scheme.
- ///
- public static ColorManager Default()
- {
- var colors = new ColorManager();
-
- colors.Background = Color.FromArgb(0, 0, 0);
- colors.Point = new SolidBrush(Color.Green);
- colors.SteinerPoint = new SolidBrush(Color.Peru);
- colors.Line = new Pen(Color.FromArgb(30, 30, 30));
- colors.Segment = new Pen(Color.DarkBlue);
- colors.VoronoiLine = new Pen(Color.FromArgb(40, 50, 60));
-
- return colors;
- }
-
- public void CreateColorDictionary(int length)
- {
- var keys = new int[length];
-
- for (int i = 0; i < length; i++)
- {
- keys[i] = i;
- }
-
- CreateColorDictionary(keys, length);
- }
-
- public void CreateColorDictionary(IEnumerable keys, int length)
- {
- this.ColorDictionary = new Dictionary();
-
- int i = 0, n = regionColors.Length;
-
- foreach (var key in keys)
- {
- this.ColorDictionary.Add(key, regionColors[i]);
-
- i = (i + 1) % n;
- }
- }
-
- internal void Dispose(Dictionary brushes)
- {
- foreach (var brush in brushes.Values)
- {
- brush.Dispose();
- }
- }
-
- internal Dictionary GetBrushDictionary()
- {
- var brushes = new Dictionary();
-
- foreach (var item in ColorDictionary)
- {
- brushes.Add(item.Key, new SolidBrush(item.Value));
- }
-
- return brushes;
- }
-
- // Change or add as many colors as you like...
- private static Color[] regionColors = {
- Color.Transparent,
- Color.FromArgb(200, 0, 255, 0),
- Color.FromArgb(200, 255, 0, 0),
- Color.FromArgb(200, 0, 0, 255),
- Color.FromArgb(200, 0, 255, 255),
- Color.FromArgb(200, 255, 255, 0),
- Color.FromArgb(200, 255, 0, 255),
- Color.FromArgb(200, 127, 0, 255),
- Color.FromArgb(200, 0, 127, 255)
- };
- }
-}
diff --git a/Triangle.NET/Triangle.Rendering/GDI/ImageRenderer.cs b/Triangle.NET/Triangle.Rendering/GDI/ImageRenderer.cs
deleted file mode 100644
index e499521..0000000
--- a/Triangle.NET/Triangle.Rendering/GDI/ImageRenderer.cs
+++ /dev/null
@@ -1,154 +0,0 @@
-
-namespace TriangleNet.Rendering.GDI
-{
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Drawing.Imaging;
- using System.IO;
- using TriangleNet.Meshing;
-
- ///
- /// Enables rendering of polygons or meshes to a bitmap.
- ///
- public class ImageRenderer
- {
- ColorManager colors = LightScheme();
-
- public ColorManager ColorScheme
- {
- get { return colors; }
- set { colors = value; }
- }
-
- public bool EnableRegions { get; set; }
-
- public bool EnablePoints { get; set; }
-
- ///
- /// Export the mesh to PNG format.
- ///
- /// The current mesh.
- /// The desired width (pixel) of the image.
- /// The PNG filename.
- /// Enable rendering of regions.
- /// Enable rendering of points.
- public static void Save(IMesh mesh, string file = null, int width = 800,
- bool regions = false, bool points = true)
- {
- // Check file name
- if (string.IsNullOrWhiteSpace(file))
- {
- file = string.Format("mesh-{0}.png", DateTime.Now.ToString("yyyy-M-d-hh-mm-ss"));
- }
-
- // Ensure .png extension.
- if (!file.EndsWith(".png", StringComparison.OrdinalIgnoreCase))
- {
- Path.ChangeExtension(file, ".png");
- }
-
- var renderer = new ImageRenderer();
-
- renderer.EnableRegions = regions;
- renderer.EnablePoints = points;
-
- var bitmap = renderer.Render(mesh, width);
-
- bitmap.Save(file, ImageFormat.Png);
- }
-
- ///
- /// Renders the mesh to a bitmap.
- ///
- /// The current mesh.
- /// The desired width (pixel) of the image.
- /// The bitmap.
- ///
- /// The width has to be at least 2 * sqrt(n), n the number of vertices.
- /// Otherwise, an empty bitmap
- ///
- public Bitmap Render(IMesh mesh, int width = 800)
- {
- Bitmap bitmap;
-
- // Check if the specified width is reasonable
- if (width < 2 * Math.Sqrt(mesh.Vertices.Count))
- {
- return new Bitmap(1, 1);
- }
-
- var bounds = mesh.Bounds;
-
- // World margin on each side
- float margin = (float)bounds.Height * 0.05f;
- float scale = width / ((float)bounds.Width + 2 * margin);
-
- var target = new Rectangle(0, 0, width, (int)((bounds.Height + 2 * margin) * scale));
-
- bitmap = new Bitmap(width, target.Height, PixelFormat.Format32bppPArgb);
-
- using (var g = Graphics.FromImage(bitmap))
- {
- g.Clear(colors.Background);
- g.SmoothingMode = SmoothingMode.HighQuality;
-
- var context = new RenderContext(new Projection(target), colors);
- context.Add(mesh, true);
-
- if (EnableRegions)
- {
- context.Add(GetRegions(mesh));
- }
-
- if (!EnablePoints)
- {
- context.Enable(3, false);
- }
-
- var renderer = new LayerRenderer();
- renderer.Context = context;
- renderer.RenderTarget = g;
- renderer.Render();
- }
-
- return bitmap;
- }
-
- private int[] GetRegions(IMesh mesh)
- {
- mesh.Renumber();
-
- var labels = new int[mesh.Triangles.Count];
- var regions = new SortedSet();
-
- foreach (var t in mesh.Triangles)
- {
- labels[t.ID] = t.Label;
- regions.Add(t.Label);
- }
-
- if (colors.ColorDictionary == null)
- {
- colors.CreateColorDictionary(regions, regions.Count);
- }
-
- return labels;
- }
-
- public static ColorManager LightScheme()
- {
- var colors = new ColorManager();
-
- colors.Background = Color.White;
- colors.Point = new SolidBrush(Color.FromArgb(60, 80, 120));
- colors.SteinerPoint = new SolidBrush(Color.DarkGreen);
- colors.Line = new Pen(Color.FromArgb(200, 200, 200));
- colors.Segment = new Pen(Color.SteelBlue);
- colors.VoronoiLine = new Pen(Color.FromArgb(160, 170, 180));
-
- return colors;
- }
- }
-}
diff --git a/Triangle.NET/Triangle.Rendering/IRenderContext.cs b/Triangle.NET/Triangle.Rendering/IRenderContext.cs
deleted file mode 100644
index 6b1b638..0000000
--- a/Triangle.NET/Triangle.Rendering/IRenderContext.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-
-namespace TriangleNet.Rendering
-{
- using System.Collections.Generic;
- using TriangleNet.Geometry;
- using TriangleNet.Meshing;
- using TriangleNet.Voronoi.Legacy;
-
- public interface IRenderContext
- {
- ColorManager ColorManager { get; }
-
- BoundingBox Bounds { get; }
-
- IList RenderLayers { get; }
-
- Projection Zoom { get; }
-
- IMesh Mesh { get; }
-
- bool HasData { get; }
-
- void Add(IPolygon data);
- void Add(IMesh data, bool reset);
- void Add(ICollection points, IEnumerable edges, bool reset);
-
- void Add(float[] values);
- void Add(int[] partition);
-
- void Enable(int layer, bool enabled);
- }
-}
diff --git a/Triangle.NET/Triangle.Rendering/IRenderLayer.cs b/Triangle.NET/Triangle.Rendering/IRenderLayer.cs
deleted file mode 100644
index 4367a17..0000000
--- a/Triangle.NET/Triangle.Rendering/IRenderLayer.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-
-namespace TriangleNet.Rendering
-{
- using System.Collections.Generic;
- using TriangleNet.Geometry;
- using TriangleNet.Meshing;
- using TriangleNet.Rendering.Buffer;
- using TriangleNet.Rendering.Util;
-
- using Color = System.Drawing.Color;
-
- public interface IRenderLayer
- {
- int Count { get; }
-
- // Points can be set, because layers may share vertices.
- IBuffer Points { get; }
- IBuffer Indices { get; }
-
- bool IsEnabled { get; set; }
-
- bool IsEmpty();
-
- void Reset(bool clear);
-
- // TODO: add boolean: reset
- BoundingBox SetPoints(IBuffer buffer);
- BoundingBox SetPoints(IPolygon poly);
- BoundingBox SetPoints(IMesh mesh);
- BoundingBox SetPoints(ICollection points);
- void SetPolygon(IPolygon poly);
- void SetPolygon(IMesh mesh);
- void SetMesh(IMesh mesh, bool elements);
- void SetMesh(IEnumerable edges);
-
-
- // TODO: better put these into a subclass.
- IBuffer Partition { get; }
- IBuffer Colors { get; }
-
- void AttachLayerData(float[] values, ColorMap colormap);
- void AttachLayerData(int[] partition);
- }
-}
diff --git a/Triangle.NET/Triangle.Rendering/Projection.cs b/Triangle.NET/Triangle.Rendering/Projection.cs
deleted file mode 100644
index 6dd8118..0000000
--- a/Triangle.NET/Triangle.Rendering/Projection.cs
+++ /dev/null
@@ -1,271 +0,0 @@
-// -----------------------------------------------------------------------
-//
-// TODO: Update copyright text.
-//
-// -----------------------------------------------------------------------
-
-namespace TriangleNet.Rendering
-{
- using System;
- using System.Drawing;
-
- ///
- /// Manages a world to screen transformation (2D orthographic projection).
- ///
- public class Projection
- {
- // The screen.
- Rectangle screen;
-
- // The complete mesh.
- RectangleF world;
-
- ///
- /// Gets or sets the current viewport (visible mesh).
- ///
- public RectangleF Viewport { get; set; }
-
- ///
- /// Gets the current scale.
- ///
- public float Scale
- {
- get { return screen.Width / Viewport.Width; }
- }
-
- ///
- /// Gets the zoom level.
- ///
- public int Level { get; private set; }
-
- ///
- /// Gets or sets a clip margin (default is 5% of viewport width on each side).
- ///
- public float ClipMargin { get; set; }
-
- // The y-direction of windows screen coordinates is upside down,
- // so inverY must be set to true.
- bool invertY = false;
-
- int maxZoomLevel = 100;
-
- public Projection(Rectangle screen, bool invertY = true)
- {
- this.screen = screen;
- this.world = screen;
- this.Viewport = screen;
-
- this.Level = 1;
-
- this.ClipMargin = this.Viewport.Width * 0.05f;
-
- this.invertY = invertY;
- }
-
- ///
- /// Inititialize the projection.
- ///
- /// The world that should be transformed to screen coordinates.
- public void Initialize(BoundingBox world)
- {
- this.Level = 1;
-
- // Add a margin so there's some space around the border
- float worldMargin = (world.Width < world.Height) ? world.Height * 0.05f : world.Width * 0.05f;
-
- // Get the initial viewport (complete mesh centered on the screen)
- float screenRatio = screen.Width / (float)screen.Height;
- float worldRatio = world.Width / world.Height;
-
- float scale = (world.Width + worldMargin) / screen.Width;
-
- if (screenRatio > worldRatio)
- {
- scale = (world.Height + worldMargin) / screen.Height;
- }
-
- float centerX = world.Left + world.Width / 2;
- float centerY = world.Bottom + world.Height / 2;
-
- // TODO: Add initial margin
- this.Viewport = new RectangleF(centerX - screen.Width * scale / 2,
- centerY - screen.Height * scale / 2,
- screen.Width * scale,
- screen.Height * scale);
-
- this.ClipMargin = this.Viewport.Width * 0.05f;
-
- this.world = this.Viewport;
- }
-
- ///
- /// Handle resize of the screen.
- ///
- /// The new screen dimensions.
- public void Resize(Rectangle newScreen)
- {
- // The viewport has to be updated, but we want to keep
- // the scaling and the center.
-
- // Get the screen scaling.
- float scaleX = newScreen.Width / (float)screen.Width;
- float scaleY = newScreen.Height / (float)screen.Height;
-
- this.screen = newScreen;
-
- var view = this.Viewport;
-
- // Center of the viewport
- float centerX = (view.Left + view.Right) / 2;
- float centerY = (view.Bottom + view.Top) / 2;
-
- // The new viewport dimensions.
- float width = view.Width * scaleX;
- float height = view.Height * scaleY;
-
- this.Viewport = new RectangleF(
- centerX - width / 2,
- centerY - height / 2,
- width, height);
-
- // Do the same for the world:
- centerX = (world.Left + world.Right) / 2;
- centerY = (world.Bottom + world.Top) / 2;
-
- width = world.Width * scaleX;
- height = world.Height * scaleY;
-
- this.world = new RectangleF(
- centerX - width / 2,
- centerY - height / 2,
- width, height);
- }
-
- public bool Translate(int dx, int dy)
- {
- if (Level == 1)
- {
- return false;
- }
-
- var view = this.Viewport;
-
- float x = view.X + dx * view.Width / 4;
- float y = view.Y + dy * view.Height / 4;
-
- this.Viewport = new RectangleF(x, y, view.Width, view.Height);
-
- return true;
- }
-
- ///
- /// Zoom in or out of the viewport.
- ///
- /// Zoom amount
- /// Relative x point position
- /// Relative y point position
- public bool Zoom(int amount, float focusX, float focusY)
- {
- float width, height;
-
- if (invertY)
- {
- focusY = 1 - focusY;
- }
-
- if (amount > 0) // Zoom in
- {
- this.Level++;
-
- if (this.Level > maxZoomLevel)
- {
- this.Level = maxZoomLevel;
- return false;
- }
-
- width = Viewport.Width / 1.1f;
- height = Viewport.Height / 1.1f;
- }
- else
- {
- this.Level--;
-
- if (this.Level < 1)
- {
- this.Level = 1;
- this.Viewport = this.world;
- return false;
- }
-
- width = Viewport.Width * 1.1f;
- height = Viewport.Height * 1.1f;
- }
-
- // Current focus on viewport
- float x = Viewport.X + Viewport.Width * focusX;
- float y = Viewport.Y + Viewport.Height * focusY;
-
- // New left and top positions
- x = x - width * focusX;
- y = y - height * focusY;
-
- // Check if outside of world
- if (x < world.X)
- {
- x = world.X;
- }
- else if (x + width > world.Right)
- {
- x = world.Right - width;
- }
-
- if (y < world.Y)
- {
- y = world.Y;
- }
- else if (y + height > world.Bottom)
- {
- y = world.Bottom - height;
- }
-
- // Set new viewport
- this.Viewport = new RectangleF(x, y, width, height);
-
- this.ClipMargin = this.Viewport.Width * 0.05f;
-
- return true;
- }
-
- public void Reset()
- {
- this.Viewport = this.world;
- this.Level = 1;
- }
-
- public void WorldToScreen(ref PointF pt)
- {
- pt.X = (pt.X - Viewport.X) / Viewport.Width * screen.Width;
- pt.Y = (1 - (pt.Y - Viewport.Y) / Viewport.Height) * screen.Height;
- }
-
- public void ScreenToWorld(ref PointF pt)
- {
- pt.X = Viewport.X + Viewport.Width * pt.X;
- pt.Y = Viewport.Y + Viewport.Height * (1 - pt.Y);
- }
-
- [Obsolete]
- public PointF WorldToScreen(float x, float y)
- {
- return new PointF((x - Viewport.X) / Viewport.Width * screen.Width,
- (1 - (y - Viewport.Y) / Viewport.Height) * screen.Height);
- }
-
- [Obsolete]
- public PointF ScreenToWorld(float x, float y)
- {
- return new PointF(Viewport.X + Viewport.Width * x,
- Viewport.Y + Viewport.Height * (1 - y));
- }
- }
-}
diff --git a/Triangle.NET/Triangle.Rendering/Properties/AssemblyInfo.cs b/Triangle.NET/Triangle.Rendering/Properties/AssemblyInfo.cs
deleted file mode 100644
index 2c12083..0000000
--- a/Triangle.NET/Triangle.Rendering/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("Triangle.Rendering")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Triangle.Rendering")]
-[assembly: AssemblyCopyright("Copyright © 2014")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("14f2491b-ee62-41e4-ab93-206540302ece")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Triangle.NET/Triangle.Rendering/RenderLayer.cs b/Triangle.NET/Triangle.Rendering/RenderLayer.cs
deleted file mode 100644
index 4b1b1e9..0000000
--- a/Triangle.NET/Triangle.Rendering/RenderLayer.cs
+++ /dev/null
@@ -1,188 +0,0 @@
-
-namespace TriangleNet.Rendering
-{
- using System.Collections.Generic;
- using TriangleNet.Geometry;
- using TriangleNet.Meshing;
- using TriangleNet.Rendering.Buffer;
- using TriangleNet.Rendering.Util;
-
- using Color = System.Drawing.Color;
-
- public class RenderLayer : IRenderLayer
- {
- int count;
-
- protected IBuffer points;
- protected IBuffer indices;
-
- protected IBuffer partition;
- protected IBuffer colors;
-
- public RenderLayer()
- {
- this.IsEnabled = false;
- }
-
- public int Count
- {
- get { return count; }
- }
-
- public IBuffer Points
- {
- get { return points; }
- set { points = value; }
- }
-
- public IBuffer Indices
- {
- get { return indices; }
- }
-
- public IBuffer Partition
- {
- get { return partition; }
- }
-
- public IBuffer Colors
- {
- get { return colors; }
- }
-
- public bool IsEnabled { get; set; }
-
- public bool IsEmpty()
- {
- return (points == null || points.Count == 0);
- }
-
- public void Reset(bool clear)
- {
- if (clear)
- {
- count = 0;
- points = null;
- }
-
- indices = null;
- partition = null;
- colors = null;
- }
-
- public BoundingBox SetPoints(IBuffer buffer)
- {
- BoundingBox bounds = new BoundingBox();
-
- if (points != null && points.Count < buffer.Count)
- {
- count = points.Count / points.Size;
- }
- else
- {
- count = buffer.Count / buffer.Size;
- }
-
- this.points = buffer;
-
- return bounds;
- }
-
- public BoundingBox SetPoints(IPolygon poly)
- {
- BoundingBox bounds = new BoundingBox();
-
- points = BufferHelper.CreateVertexBuffer(poly.Points, ref bounds);
- count = points.Count / points.Size;
-
- return bounds;
- }
-
- public BoundingBox SetPoints(IMesh mesh)
- {
- BoundingBox bounds = new BoundingBox();
-
- points = BufferHelper.CreateVertexBuffer(mesh.Vertices, ref bounds);
- count = points.Count / points.Size;
-
- return bounds;
- }
-
- public BoundingBox SetPoints(ICollection vertices)
- {
- BoundingBox bounds = new BoundingBox();
-
- points = BufferHelper.CreateVertexBuffer(vertices, ref bounds);
- count = points.Count / points.Size;
-
- return bounds;
- }
-
- public void SetPolygon(IPolygon poly)
- {
- indices = BufferHelper.CreateIndexBuffer(poly.Segments, 2);
- }
-
- public void SetPolygon(IMesh mesh)
- {
- indices = BufferHelper.CreateIndexBuffer(mesh.Segments, 2);
- }
-
- public void SetMesh(IEnumerable edges)
- {
- indices = BufferHelper.CreateIndexBuffer(edges, 2);
- }
-
- public void SetMesh(IMesh mesh, bool elements)
- {
- mesh.Renumber();
-
- if (!elements)
- {
- indices = BufferHelper.CreateIndexBuffer(mesh.Edges, 2);
- }
-
- if (elements || indices.Count == 0)
- {
- indices = BufferHelper.CreateIndexBuffer(mesh.Triangles, 3);
- }
- }
-
- // TODO: remove colormap argument
- public void AttachLayerData(float[] values, ColorMap colormap)
- {
- int length = values.Length;
-
- Color[] data = new Color[length];
-
- double min = double.MaxValue;
- double max = double.MinValue;
-
- // Find min and max of given values.
- for (int i = 0; i < length; i++)
- {
- if (values[i] < min)
- {
- min = values[i];
- }
-
- if (values[i] > max)
- {
- max = values[i];
- }
- }
-
- for (int i = 0; i < length; i++)
- {
- data[i] = colormap.GetColor(values[i], min, max);
- }
-
- colors = new ColorBuffer(data, 1);
- }
-
- public void AttachLayerData(int[] partition)
- {
- this.partition = new IndexBuffer(partition, 1);
- }
- }
-}
diff --git a/Triangle.NET/Triangle.Rendering/Text/EdgeIterator.cs b/Triangle.NET/Triangle.Rendering/Text/EdgeIterator.cs
deleted file mode 100644
index cb02260..0000000
--- a/Triangle.NET/Triangle.Rendering/Text/EdgeIterator.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-
-namespace TriangleNet.Rendering.Text
-{
- using System.Collections.Generic;
- using TriangleNet.Geometry;
-
- static class EdgeIterator
- {
- ///
- /// Enumerate the edges of the mesh.
- ///
- ///
- ///
- ///
- ///
- /// In contrast to the this
- /// method will return objects that include the vertex information (and not only the
- /// indices).
- ///
- public static IEnumerable EnumerateEdges(Mesh mesh, bool skipSegments = true)
- {
- foreach (var t in mesh.Triangles)
- {
- for (int i = 0; i < 3; i++)
- {
- int nid = t.GetNeighborID(i);
-
- if ((t.ID < nid) || (nid < 0))
- {
- var s = t.GetSegment(i);
-
- if (skipSegments && s == null)
- {
- // Since segments will be processed separately, don't
- // include them in the enumeration.
- yield return new Segment(
- t.GetVertex((i + 1) % 3),
- t.GetVertex((i + 2) % 3));
- }
- else
- {
- if (s == null)
- {
- yield return new Segment(
- t.GetVertex((i + 1) % 3),
- t.GetVertex((i + 2) % 3));
- }
- else
- {
- yield return s;
- }
- }
- }
- }
- }
- }
- }
-}
diff --git a/Triangle.NET/Triangle.Rendering/Triangle.Rendering.csproj b/Triangle.NET/Triangle.Rendering/Triangle.Rendering.csproj
deleted file mode 100644
index 7df27fb..0000000
--- a/Triangle.NET/Triangle.Rendering/Triangle.Rendering.csproj
+++ /dev/null
@@ -1,98 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {41022E0E-BD0F-439E-BC3A-AABB1B43471B}
- Library
- Properties
- TriangleNet.Rendering
- Triangle.Rendering
- v4.0
- 512
- SAK
- SAK
- SAK
- SAK
- Client
-
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Component
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {f7907a0a-b75f-400b-9e78-bfad00db4d6b}
- Triangle
-
-
-
-
-
\ No newline at end of file
diff --git a/Triangle.NET/Triangle.Rendering/Triangle.Rendering.csproj.vspscc b/Triangle.NET/Triangle.Rendering/Triangle.Rendering.csproj.vspscc
deleted file mode 100644
index feffdec..0000000
--- a/Triangle.NET/Triangle.Rendering/Triangle.Rendering.csproj.vspscc
+++ /dev/null
@@ -1,10 +0,0 @@
-""
-{
-"FILE_VERSION" = "9237"
-"ENLISTMENT_CHOICE" = "NEVER"
-"PROJECT_FILE_RELATIVE_PATH" = ""
-"NUMBER_OF_EXCLUDED_FILES" = "0"
-"ORIGINAL_PROJECT_FILE_PATH" = ""
-"NUMBER_OF_NESTED_PROJECTS" = "0"
-"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
-}
diff --git a/Triangle.NET/Triangle.Rendering/Util/BufferHelper.cs b/Triangle.NET/Triangle.Rendering/Util/BufferHelper.cs
deleted file mode 100644
index 7919293..0000000
--- a/Triangle.NET/Triangle.Rendering/Util/BufferHelper.cs
+++ /dev/null
@@ -1,142 +0,0 @@
-
-namespace TriangleNet.Rendering.Util
-{
- using System.Collections.Generic;
- using TriangleNet.Topology;
- using TriangleNet.Geometry;
- using TriangleNet.Rendering.Buffer;
-
- internal static class BufferHelper
- {
- public static IBuffer CreateVertexBuffer(double[] points, ref BoundingBox bounds)
- {
- int length = points.Length;
-
- var buffer = new VertexBuffer(length);
-
- bounds.Reset();
-
- var data = buffer.Data;
-
- float x, y;
-
- length = length >> 1;
-
- for (int i = 0; i < length; i++)
- {
- x = (float)points[2 * i];
- y = (float)points[2 * i + 1];
-
- data[2 * i] = x;
- data[2 * i + 1] = y;
-
- bounds.Update(x, y);
- }
-
- return buffer as IBuffer;
- }
-
- public static IBuffer CreateVertexBuffer(ICollection points, ref BoundingBox bounds)
- {
- var buffer = new VertexBuffer(2 * points.Count);
-
- bounds.Reset();
-
- var data = buffer.Data;
-
- float x, y;
-
- int i = 0;
-
- foreach (var p in points)
- {
- x = (float)p.X;
- y = (float)p.Y;
-
- data[2 * i] = x;
- data[2 * i + 1] = y;
-
- bounds.Update(x, y);
-
- i++;
- }
-
- return buffer as IBuffer;
- }
-
- public static IBuffer CreateVertexBuffer(ICollection points, ref BoundingBox bounds)
- {
- var buffer = new VertexBuffer(2 * points.Count);
-
- bounds.Reset();
-
- var data = buffer.Data;
-
- int i = 0;
-
- foreach (var p in points)
- {
- data[2 * i] = (float)p.X;
- data[2 * i + 1] = (float)p.Y;
-
- bounds.Update(p.X, p.Y);
-
- i++;
- }
-
- return buffer as IBuffer;
- }
-
- public static IBuffer CreateIndexBuffer(IList segments, int size)
- {
- var buffer = new IndexBuffer(size * segments.Count, size);
-
- var data = buffer.Data;
-
- int i = 0;
-
- foreach (var e in segments)
- {
- data[size * i + 0] = e.P0;
- data[size * i + 1] = e.P1;
-
- i++;
- }
-
- return buffer as IBuffer;
- }
-
- public static IBuffer CreateIndexBuffer(IEnumerable edges, int size)
- {
- var data = new List();
-
- foreach (var e in edges)
- {
- data.Add(e.P0);
- data.Add(e.P1);
- }
-
- return new IndexBuffer(data.ToArray(), size) as IBuffer;
- }
-
- public static IBuffer CreateIndexBuffer(ICollection elements, int size)
- {
- var buffer = new IndexBuffer(size * elements.Count, size);
-
- var data = buffer.Data;
-
- int i = 0;
-
- foreach (var e in elements)
- {
- data[size * i + 0] = e.GetVertexID(0);
- data[size * i + 1] = e.GetVertexID(1);
- data[size * i + 2] = e.GetVertexID(2);
-
- i++;
- }
-
- return buffer as IBuffer;
- }
- }
-}
diff --git a/Triangle.NET/Triangle.sln b/Triangle.NET/Triangle.sln
deleted file mode 100644
index 745beda..0000000
--- a/Triangle.NET/Triangle.sln
+++ /dev/null
@@ -1,69 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2012
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Triangle", "Triangle\Triangle.csproj", "{F7907A0A-B75F-400B-9E78-BFAD00DB4D6B}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mesh Explorer", "TestApp\Mesh Explorer.csproj", "{336AAF8A-5316-4303-9E73-5E38BD0B28AF}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Triangle.Rendering", "Triangle.Rendering\Triangle.Rendering.csproj", "{41022E0E-BD0F-439E-BC3A-AABB1B43471B}"
-EndProject
-Global
- GlobalSection(TeamFoundationVersionControl) = preSolution
- SccNumberOfProjects = 4
- SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C}
- SccTeamFoundationServer = https://tfs.codeplex.com/tfs/tfs06
- SccLocalPath0 = .
- SccProjectUniqueName1 = Triangle\\Triangle.csproj
- SccProjectName1 = Triangle
- SccLocalPath1 = Triangle
- SccProjectUniqueName2 = TestApp\\Mesh\u0020Explorer.csproj
- SccProjectName2 = TestApp
- SccLocalPath2 = TestApp
- SccProjectUniqueName3 = Triangle.Rendering\\Triangle.Rendering.csproj
- SccProjectName3 = Triangle.Rendering
- SccLocalPath3 = Triangle.Rendering
- EndGlobalSection
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Debug|Mixed Platforms = Debug|Mixed Platforms
- Debug|x86 = Debug|x86
- Release|Any CPU = Release|Any CPU
- Release|Mixed Platforms = Release|Mixed Platforms
- Release|x86 = Release|x86
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {F7907A0A-B75F-400B-9E78-BFAD00DB4D6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {F7907A0A-B75F-400B-9E78-BFAD00DB4D6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {F7907A0A-B75F-400B-9E78-BFAD00DB4D6B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {F7907A0A-B75F-400B-9E78-BFAD00DB4D6B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {F7907A0A-B75F-400B-9E78-BFAD00DB4D6B}.Debug|x86.ActiveCfg = Debug|Any CPU
- {F7907A0A-B75F-400B-9E78-BFAD00DB4D6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {F7907A0A-B75F-400B-9E78-BFAD00DB4D6B}.Release|Any CPU.Build.0 = Release|Any CPU
- {F7907A0A-B75F-400B-9E78-BFAD00DB4D6B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {F7907A0A-B75F-400B-9E78-BFAD00DB4D6B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {F7907A0A-B75F-400B-9E78-BFAD00DB4D6B}.Release|x86.ActiveCfg = Release|Any CPU
- {336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Debug|Any CPU.ActiveCfg = Debug|x86
- {336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
- {336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Debug|Mixed Platforms.Build.0 = Debug|x86
- {336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Debug|x86.ActiveCfg = Debug|x86
- {336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Debug|x86.Build.0 = Debug|x86
- {336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Release|Any CPU.ActiveCfg = Release|x86
- {336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Release|Mixed Platforms.ActiveCfg = Release|x86
- {336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Release|Mixed Platforms.Build.0 = Release|x86
- {336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Release|x86.ActiveCfg = Release|x86
- {336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Release|x86.Build.0 = Release|x86
- {41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Debug|x86.ActiveCfg = Debug|Any CPU
- {41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Release|Any CPU.Build.0 = Release|Any CPU
- {41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Release|x86.ActiveCfg = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
diff --git a/Triangle.NET/Triangle.vssscc b/Triangle.NET/Triangle.vssscc
deleted file mode 100644
index 794f014..0000000
--- a/Triangle.NET/Triangle.vssscc
+++ /dev/null
@@ -1,10 +0,0 @@
-""
-{
-"FILE_VERSION" = "9237"
-"ENLISTMENT_CHOICE" = "NEVER"
-"PROJECT_FILE_RELATIVE_PATH" = ""
-"NUMBER_OF_EXCLUDED_FILES" = "0"
-"ORIGINAL_PROJECT_FILE_PATH" = ""
-"NUMBER_OF_NESTED_PROJECTS" = "0"
-"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROJECT"
-}
diff --git a/Triangle.NET/Triangle/Geometry/Polygon.cs b/Triangle.NET/Triangle/Geometry/Polygon.cs
deleted file mode 100644
index 96d7106..0000000
--- a/Triangle.NET/Triangle/Geometry/Polygon.cs
+++ /dev/null
@@ -1,183 +0,0 @@
-// -----------------------------------------------------------------------
-//
-// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace TriangleNet.Geometry
-{
- using System;
- using System.Collections.Generic;
-
- ///
- /// A polygon represented as a planar straight line graph.
- ///
- public class Polygon : IPolygon
- {
- List points;
- List holes;
- List regions;
-
- List segments;
-
- ///
- public List Points
- {
- get { return points; }
- }
-
- ///
- public List Holes
- {
- get { return holes; }
- }
-
- ///
- public List Regions
- {
- get { return regions; }
- }
-
- ///
- public List Segments
- {
- get { return segments; }
- }
-
- ///
- public bool HasPointMarkers { get; set; }
-
- ///
- public bool HasSegmentMarkers { get; set; }
-
- ///
- public int Count
- {
- get { return points.Count; }
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- public Polygon()
- : this(3, false)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The default capacity for the points list.
- public Polygon(int capacity)
- : this(3, false)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The default capacity for the points list.
- /// Use point and segment markers.
- public Polygon(int capacity, bool markers)
- {
- points = new List(capacity);
- holes = new List();
- regions = new List();
-
- segments = new List();
-
- HasPointMarkers = markers;
- HasSegmentMarkers = markers;
- }
-
- [Obsolete("Use polygon.Add(contour) method instead.")]
- public void AddContour(IEnumerable points, int marker = 0,
- bool hole = false, bool convex = false)
- {
- this.Add(new Contour(points, marker, convex), hole);
- }
-
- [Obsolete("Use polygon.Add(contour) method instead.")]
- public void AddContour(IEnumerable points, int marker, Point hole)
- {
- this.Add(new Contour(points, marker), hole);
- }
-
- ///
- public Rectangle Bounds()
- {
- var bounds = new Rectangle();
- bounds.Expand(this.points);
-
- return bounds;
- }
-
- ///
- /// Add a vertex to the polygon.
- ///
- /// The vertex to insert.
- public void Add(Vertex vertex)
- {
- this.points.Add(vertex);
- }
-
- ///
- /// Add a segment to the polygon.
- ///
- /// The segment to insert.
- /// If true, both endpoints will be added to the points list.
- public void Add(ISegment segment, bool insert = false)
- {
- this.segments.Add(segment);
-
- if (insert)
- {
- this.points.Add(segment.GetVertex(0));
- this.points.Add(segment.GetVertex(1));
- }
- }
-
- ///
- /// Add a segment to the polygon.
- ///
- /// The segment to insert.
- /// The index of the segment endpoint to add to the points list (must be 0 or 1).
- public void Add(ISegment segment, int index)
- {
- this.segments.Add(segment);
-
- this.points.Add(segment.GetVertex(index));
- }
-
- ///
- /// Add a contour to the polygon.
- ///
- /// The contour to insert.
- /// Treat contour as a hole.
- public void Add(Contour contour, bool hole = false)
- {
- if (hole)
- {
- this.Add(contour, contour.FindInteriorPoint());
- }
- else
- {
- this.points.AddRange(contour.Points);
- this.segments.AddRange(contour.GetSegments());
- }
- }
-
- ///
- /// Add a contour to the polygon.
- ///
- /// The contour to insert.
- /// Point inside the contour, making it a hole.
- public void Add(Contour contour, Point hole)
- {
- this.points.AddRange(contour.Points);
- this.segments.AddRange(contour.GetSegments());
-
- this.holes.Add(hole);
- }
- }
-}
diff --git a/Triangle.NET/Triangle/Log.cs b/Triangle.NET/Triangle/Log.cs
deleted file mode 100644
index b5e577b..0000000
--- a/Triangle.NET/Triangle/Log.cs
+++ /dev/null
@@ -1,84 +0,0 @@
-// -----------------------------------------------------------------------
-//
-// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace TriangleNet
-{
- using System.Collections.Generic;
- using TriangleNet.Logging;
-
- ///
- /// A simple logger, which logs messages to a List.
- ///
- /// Using singleton pattern as proposed by Jon Skeet.
- /// http://csharpindepth.com/Articles/General/Singleton.aspx
- ///
- public sealed class Log : ILog
- {
- ///
- /// Log detailed information.
- ///
- public static bool Verbose { get; set; }
-
- private List log = new List();
-
- private LogLevel level = LogLevel.Info;
-
- #region Singleton pattern
-
- private static readonly Log instance = new Log();
-
- // Explicit static constructor to tell C# compiler
- // not to mark type as beforefieldinit
- static Log() { }
-
- private Log() { }
-
- public static ILog Instance
- {
- get
- {
- return instance;
- }
- }
-
- #endregion
-
- public void Add(LogItem item)
- {
- log.Add(item);
- }
-
- public void Clear()
- {
- log.Clear();
- }
-
- public void Info(string message)
- {
- log.Add(new LogItem(LogLevel.Info, message));
- }
-
- public void Warning(string message, string location)
- {
- log.Add(new LogItem(LogLevel.Warning, message, location));
- }
-
- public void Error(string message, string location)
- {
- log.Add(new LogItem(LogLevel.Error, message, location));
- }
-
- public IList Data
- {
- get { return log; }
- }
-
- public LogLevel Level
- {
- get { return level; }
- }
- }
-}
diff --git a/Triangle.NET/Triangle/Logging/ILog.cs b/Triangle.NET/Triangle/Logging/ILog.cs
deleted file mode 100644
index f0184a9..0000000
--- a/Triangle.NET/Triangle/Logging/ILog.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-// -----------------------------------------------------------------------
-//
-// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace TriangleNet.Logging
-{
- using System.Collections.Generic;
-
- public enum LogLevel
- {
- Info = 0,
- Warning = 1,
- Error = 2
- }
-
- ///
- /// A basic log interface.
- ///
- public interface ILog where T : ILogItem
- {
- void Add(T item);
- void Clear();
-
- void Info(string message);
- void Error(string message, string info);
- void Warning(string message, string info);
-
- IList Data { get; }
-
- LogLevel Level { get; }
- }
-}
diff --git a/Triangle.NET/Triangle/Logging/ILogItem.cs b/Triangle.NET/Triangle/Logging/ILogItem.cs
deleted file mode 100644
index 7ed0761..0000000
--- a/Triangle.NET/Triangle/Logging/ILogItem.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-// -----------------------------------------------------------------------
-//
-// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace TriangleNet.Logging
-{
- using System;
-
- ///
- /// A basic log item interface.
- ///
- public interface ILogItem
- {
- DateTime Time { get; }
- LogLevel Level { get; }
- string Message { get; }
- string Info { get; }
- }
-}
diff --git a/Triangle.NET/Triangle/Logging/LogItem.cs b/Triangle.NET/Triangle/Logging/LogItem.cs
deleted file mode 100644
index 1be74bc..0000000
--- a/Triangle.NET/Triangle/Logging/LogItem.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-// -----------------------------------------------------------------------
-//
-// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace TriangleNet.Logging
-{
- using System;
-
- ///
- /// Represents an item stored in the log.
- ///
- public class LogItem : ILogItem
- {
- DateTime time;
- LogLevel level;
- string message;
- string info;
-
- public DateTime Time
- {
- get { return time; }
- }
-
- public LogLevel Level
- {
- get { return level; }
- }
-
- public string Message
- {
- get { return message; }
- }
-
- public string Info
- {
- get { return info; }
- }
-
- public LogItem(LogLevel level, string message)
- : this(level, message, "")
- { }
-
- public LogItem(LogLevel level, string message, string info)
- {
- this.time = DateTime.Now;
- this.level = level;
- this.message = message;
- this.info = info;
- }
- }
-}
diff --git a/Triangle.NET/Triangle/Meshing/Iterators/EdgeIterator.cs b/Triangle.NET/Triangle/Meshing/Iterators/EdgeIterator.cs
deleted file mode 100644
index 1b247f4..0000000
--- a/Triangle.NET/Triangle/Meshing/Iterators/EdgeIterator.cs
+++ /dev/null
@@ -1,101 +0,0 @@
-// -----------------------------------------------------------------------
-//
-// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace TriangleNet.Meshing.Iterators
-{
- using System.Collections.Generic;
- using TriangleNet.Topology;
- using TriangleNet.Geometry;
-
- ///
- /// Enumerates the edges of a triangulation.
- ///
- public class EdgeIterator : IEnumerator
- {
- IEnumerator triangles;
- Otri tri = default(Otri);
- Otri neighbor = default(Otri);
- Osub sub = default(Osub);
- Edge current;
- Vertex p1, p2;
-
- ///
- /// Initializes a new instance of the class.
- ///
- public EdgeIterator(Mesh mesh)
- {
- triangles = mesh.triangles.GetEnumerator();
- triangles.MoveNext();
-
- tri.tri = triangles.Current;
- tri.orient = 0;
- }
-
- public Edge Current
- {
- get { return current; }
- }
-
- public void Dispose()
- {
- this.triangles.Dispose();
- }
-
- object System.Collections.IEnumerator.Current
- {
- get { return current; }
- }
-
- public bool MoveNext()
- {
- if (tri.tri == null)
- {
- return false;
- }
-
- current = null;
-
- while (current == null)
- {
- if (tri.orient == 3)
- {
- if (triangles.MoveNext())
- {
- tri.tri = triangles.Current;
- tri.orient = 0;
- }
- else
- {
- // Finally no more triangles
- return false;
- }
- }
-
- tri.Sym(ref neighbor);
-
- if ((tri.tri.id < neighbor.tri.id) || (neighbor.tri.id == Mesh.DUMMY))
- {
- p1 = tri.Org();
- p2 = tri.Dest();
-
- tri.Pivot(ref sub);
-
- // Boundary mark of dummysub is 0, so we don't need to worry about that.
- current = new Edge(p1.id, p2.id, sub.seg.boundary);
- }
-
- tri.orient++;
- }
-
- return true;
- }
-
- public void Reset()
- {
- this.triangles.Reset();
- }
- }
-}
diff --git a/Triangle.NET/Triangle/Properties/AssemblyInfo.cs b/Triangle.NET/Triangle/Properties/AssemblyInfo.cs
deleted file mode 100644
index 330e970..0000000
--- a/Triangle.NET/Triangle/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("Triangle")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Triangle")]
-[assembly: AssemblyCopyright("Copyright © 2012")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("96a540d0-1772-4bed-8d25-ef5fa23cd1bc")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Triangle.NET/Triangle/Smoothing/ISmoother.cs b/Triangle.NET/Triangle/Smoothing/ISmoother.cs
deleted file mode 100644
index 621a2c5..0000000
--- a/Triangle.NET/Triangle/Smoothing/ISmoother.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-// -----------------------------------------------------------------------
-//
-// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace TriangleNet.Smoothing
-{
- using TriangleNet.Meshing;
-
- ///
- /// Interface for mesh smoothers.
- ///
- public interface ISmoother
- {
- void Smooth(IMesh mesh);
- void Smooth(IMesh mesh, int limit);
- }
-}
\ No newline at end of file
diff --git a/Triangle.NET/Triangle/Tools/Interpolation.cs b/Triangle.NET/Triangle/Tools/Interpolation.cs
deleted file mode 100644
index f315b03..0000000
--- a/Triangle.NET/Triangle/Tools/Interpolation.cs
+++ /dev/null
@@ -1,105 +0,0 @@
-
-namespace TriangleNet.Tools
-{
- using TriangleNet.Geometry;
-
- public static class Interpolation
- {
-#if USE_ATTRIBS
- ///
- /// Linear interpolation of vertex attributes.
- ///
- /// The interpolation vertex.
- /// The triangle containing the vertex.
- /// The number of vertex attributes.
- ///
- /// The vertex is expected to lie inside the triangle.
- ///
- public static void InterpolateAttributes(Vertex vertex, ITriangle triangle, int n)
- {
- Vertex org = triangle.GetVertex(0);
- Vertex dest = triangle.GetVertex(1);
- Vertex apex = triangle.GetVertex(2);
-
- double xdo, ydo, xao, yao;
- double denominator;
- double dx, dy;
- double xi, eta;
-
- // Compute the circumcenter of the triangle.
- xdo = dest.x - org.x;
- ydo = dest.y - org.y;
- xao = apex.x - org.x;
- yao = apex.y - org.y;
-
- denominator = 0.5 / (xdo * yao - xao * ydo);
-
- //dx = (yao * dodist - ydo * aodist) * denominator;
- //dy = (xdo * aodist - xao * dodist) * denominator;
-
- dx = vertex.x - org.x;
- dy = vertex.y - org.y;
-
- // To interpolate vertex attributes for the new vertex, define a
- // coordinate system with a xi-axis directed from the triangle's
- // origin to its destination, and an eta-axis, directed from its
- // origin to its apex.
- xi = (yao * dx - xao * dy) * (2.0 * denominator);
- eta = (xdo * dy - ydo * dx) * (2.0 * denominator);
-
- for (int i = 0; i < n; i++)
- {
- // Interpolate the vertex attributes.
- vertex.attributes[i] = org.attributes[i]
- + xi * (dest.attributes[i] - org.attributes[i])
- + eta * (apex.attributes[i] - org.attributes[i]);
- }
- }
-#endif
-
-#if USE_Z
- ///
- /// Linear interpolation of a scalar value.
- ///
- /// The interpolation point.
- /// The triangle containing the point.
- ///
- /// The point is expected to lie inside the triangle.
- ///
- public static void InterpolateZ(Point p, ITriangle triangle)
- {
- Vertex org = triangle.GetVertex(0);
- Vertex dest = triangle.GetVertex(1);
- Vertex apex = triangle.GetVertex(2);
-
- double xdo, ydo, xao, yao;
- double denominator;
- double dx, dy;
- double xi, eta;
-
- // Compute the circumcenter of the triangle.
- xdo = dest.x - org.x;
- ydo = dest.y - org.y;
- xao = apex.x - org.x;
- yao = apex.y - org.y;
-
- denominator = 0.5 / (xdo * yao - xao * ydo);
-
- //dx = (yao * dodist - ydo * aodist) * denominator;
- //dy = (xdo * aodist - xao * dodist) * denominator;
-
- dx = p.x - org.x;
- dy = p.y - org.y;
-
- // To interpolate z value for the given point inserted, define a
- // coordinate system with a xi-axis, directed from the triangle's
- // origin to its destination, and an eta-axis, directed from its
- // origin to its apex.
- xi = (yao * dx - xao * dy) * (2.0 * denominator);
- eta = (xdo * dy - ydo * dx) * (2.0 * denominator);
-
- p.z = org.z + xi * (dest.z - org.z) + eta * (apex.z - org.z);
- }
-#endif
- }
-}
diff --git a/Triangle.NET/Triangle/Triangle.csproj b/Triangle.NET/Triangle/Triangle.csproj
deleted file mode 100644
index d0a8638..0000000
--- a/Triangle.NET/Triangle/Triangle.csproj
+++ /dev/null
@@ -1,139 +0,0 @@
-
-
-
- Debug
- AnyCPU
- 8.0.30703
- 2.0
- {F7907A0A-B75F-400B-9E78-BFAD00DB4D6B}
- Library
- Properties
- TriangleNet
- Triangle
- v4.0
- 512
- Client
- SAK
- SAK
- SAK
- SAK
-
-
- true
- full
- false
- bin\Debug\
- TRACE;DEBUG;USE_ATTRIBS
- prompt
- 4
-
-
- pdbonly
- true
- bin\Release\
- TRACE;USE_ATTRIBS
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Triangle.NET/Triangle/Triangle.csproj.vspscc b/Triangle.NET/Triangle/Triangle.csproj.vspscc
deleted file mode 100644
index feffdec..0000000
--- a/Triangle.NET/Triangle/Triangle.csproj.vspscc
+++ /dev/null
@@ -1,10 +0,0 @@
-""
-{
-"FILE_VERSION" = "9237"
-"ENLISTMENT_CHOICE" = "NEVER"
-"PROJECT_FILE_RELATIVE_PATH" = ""
-"NUMBER_OF_EXCLUDED_FILES" = "0"
-"ORIGINAL_PROJECT_FILE_PATH" = ""
-"NUMBER_OF_NESTED_PROJECTS" = "0"
-"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
-}
diff --git a/src/Triangle.Examples/Examples/Example1.cs b/src/Triangle.Examples/Examples/Example1.cs
new file mode 100644
index 0000000..82d09d5
--- /dev/null
+++ b/src/Triangle.Examples/Examples/Example1.cs
@@ -0,0 +1,33 @@
+
+namespace TriangleNet.Examples
+{
+ using TriangleNet.Geometry;
+ using TriangleNet.Meshing;
+ using TriangleNet.Meshing.Algorithm;
+ using TriangleNet.Rendering.Text;
+
+ ///
+ /// Simple point set triangulation.
+ ///
+ public class Example1
+ {
+ public static bool Run(bool print = false)
+ {
+ // Generate points.
+ var points = Generate.RandomPoints(50, new Rectangle(0, 0, 100, 100));
+
+ // Choose triangulator: Incremental, SweepLine or Dwyer.
+ var triangulator = new Dwyer();
+
+ // Generate a default mesher.
+ var mesher = new GenericMesher(triangulator);
+
+ // Generate mesh.
+ var mesh = mesher.Triangulate(points);
+
+ if (print) SvgImage.Save(mesh, "example-1.svg", 500);
+
+ return mesh.Triangles.Count > 0;
+ }
+ }
+}
diff --git a/src/Triangle.Examples/Examples/Example10.cs b/src/Triangle.Examples/Examples/Example10.cs
new file mode 100644
index 0000000..ff13379
--- /dev/null
+++ b/src/Triangle.Examples/Examples/Example10.cs
@@ -0,0 +1,125 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using TriangleNet.Geometry;
+using TriangleNet.Meshing;
+using TriangleNet.Meshing.Algorithm;
+using TriangleNet.Rendering.Text;
+using TriangleNet.Tools;
+
+namespace TriangleNet.Examples
+{
+ ///
+ /// Scattered data interpolation without USE_Z or USE_ATTRIBS.
+ ///
+ internal class Example10
+ {
+ // The function we are sampling.
+ private static readonly Func F = p => Math.Sin(p.X) * Math.Cos(p.Y);
+
+ public static bool Run(bool print = false)
+ {
+ // The input domain.
+ var r = new Rectangle(0d, 0d, 10d, 10d);
+
+ var mesh = GetScatteredDataMesh(r, out double[] data);
+ //var mesh = GetStructuredDataMesh(r, out double[] data);
+
+ if (print) SvgImage.Save(mesh, "example-10.svg", 500);
+
+ // The points to interpolate.
+ var xy = Generate.RandomPoints(50, r);
+
+ var xyData = InterpolateData((Mesh)mesh, data, xy);
+
+ double error = xy.Max(p => Math.Abs(xyData[p.ID] - F(p)));
+
+ // L2 error
+ // double error = Math.Sqrt(xy.Sum(p => Math.Pow(xyData[p.ID] - F(p), 2)));
+
+ return error < 0.5;
+ }
+
+ private static IMesh GetStructuredDataMesh(Rectangle domain, out double[] data)
+ {
+ var mesh = GenericMesher.StructuredMesh(domain, 20, 20);
+
+ mesh.Renumber();
+
+ // Generate function values for mesh points.
+ data = new double[mesh.Vertices.Count];
+
+ foreach (var item in mesh.Vertices)
+ {
+ data[item.ID] = F(item);
+ }
+
+ return mesh;
+ }
+
+ private static IMesh GetScatteredDataMesh(Rectangle domain, out double[] data)
+ {
+ var r = new Rectangle(domain);
+
+ double h = domain.Width / 20;
+
+ // Generate a rectangle boundary point set (20 points on each side).
+ var input = Generate.Rectangle(r, 0.5);
+
+ // Making sure we add some margin to the boundary.
+ h = -h / 2;
+ r.Resize(h, h);
+
+ // Add more input points (more sampling points, better interpolation).
+ input.Points.AddRange(Generate.RandomPoints(350, r));
+
+ var mesher = new GenericMesher(new Dwyer());
+
+ // Generate mesh.
+ var mesh = mesher.Triangulate(input.Points);
+
+ mesh.Renumber();
+
+ // Generate function values for mesh points.
+ data = new double[mesh.Vertices.Count];
+
+ foreach (var item in mesh.Vertices)
+ {
+ data[item.ID] = F(item);
+ }
+
+ return mesh;
+ }
+
+ private static double[] InterpolateData(Mesh mesh, double[] data, IEnumerable xy)
+ {
+ // The interpolated values.
+ var values = new double[xy.Count()];
+
+ var qtree = new TriangleQuadTree(mesh);
+
+ int i = 0;
+
+ foreach (var p in xy)
+ {
+ var tri = qtree.Query(p.X, p.Y);
+
+ // For easy access of the interpolated values.
+ p.ID = i;
+
+ if (tri == null)
+ {
+ values[i] = float.NaN;
+ }
+ else
+ {
+ values[i] = Interpolation.InterpolatePoint(tri, p, data);
+ }
+
+ i++;
+ }
+
+ return values;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Triangle.Examples/Examples/Example2.cs b/src/Triangle.Examples/Examples/Example2.cs
new file mode 100644
index 0000000..c497ccf
--- /dev/null
+++ b/src/Triangle.Examples/Examples/Example2.cs
@@ -0,0 +1,48 @@
+namespace TriangleNet.Examples
+{
+ using TriangleNet.Geometry;
+ using TriangleNet.Meshing;
+ using TriangleNet.Rendering.Text;
+
+ ///
+ /// Triangulate a polygon with hole and set minimum angle constraint.
+ ///
+ public static class Example2
+ {
+ public static bool Run(bool print = false)
+ {
+ // Generate the input geometry.
+ var poly = CreatePolygon();
+
+ // Set minimum angle quality option.
+ var quality = new QualityOptions() { MinimumAngle = 30.0 };
+
+ // Generate mesh using the polygons Triangulate extension method.
+ var mesh = poly.Triangulate(quality);
+
+ if (print) SvgImage.Save(mesh, "example-2.svg", 500);
+
+ return mesh.Triangles.Count > 0;
+ }
+
+ public static IPolygon CreatePolygon(double h = 0.2)
+ {
+ // Generate the input geometry.
+ var poly = new Polygon();
+
+ // Center point.
+ var center = new Point(0, 0);
+
+ // Inner contour (hole).
+ poly.Add(Generate.Circle(1.0, center, h, 1), center);
+
+ // Internal contour.
+ poly.Add(Generate.Circle(2.0, center, h, 2));
+
+ // Outer contour.
+ poly.Add(Generate.Circle(3.0, center, h, 3));
+
+ return poly;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Triangle.Examples/Examples/Example3.cs b/src/Triangle.Examples/Examples/Example3.cs
new file mode 100644
index 0000000..7e0182d
--- /dev/null
+++ b/src/Triangle.Examples/Examples/Example3.cs
@@ -0,0 +1,54 @@
+
+namespace TriangleNet.Examples
+{
+ using System;
+ using TriangleNet.Geometry;
+ using TriangleNet.Meshing;
+ using TriangleNet.Rendering.Text;
+ using TriangleNet.Smoothing;
+
+ ///
+ /// Triangulate a polygon with hole with maximum area constraint, followed by mesh smoothing.
+ ///
+ public class Example3
+ {
+ public static bool Run(bool print = false)
+ {
+ // Generate mesh.
+ var mesh = CreateMesh();
+
+ if (print) SvgImage.Save(mesh, "example-3.svg", 500);
+
+ return mesh.Triangles.Count > 0;
+ }
+
+ public static IMesh CreateMesh()
+ {
+ // Generate the input geometry.
+ var poly = Example2.CreatePolygon();
+
+ // Since we want to do CVT smoothing, ensure that the mesh
+ // is conforming Delaunay.
+ var options = new ConstraintOptions() { ConformingDelaunay = true };
+
+ // Set maximum area quality option (we don't need to set a minimum
+ // angle, since smoothing will improve the triangle shapes).
+ var quality = new QualityOptions()
+ {
+ // The boundary segments have a length of 0.2, so we set a
+ // maximum area constraint assuming equilateral triangles.
+ MaximumArea = (Math.Sqrt(3) / 4 * 0.2 * 0.2) * 1.45
+ };
+
+ // Generate mesh using the polygons Triangulate extension method.
+ var mesh = poly.Triangulate(options, quality);
+
+ var smoother = new SimpleSmoother();
+
+ // Smooth mesh.
+ smoother.Smooth(mesh, 25);
+
+ return mesh;
+ }
+ }
+}
diff --git a/src/Triangle.Examples/Examples/Example4.cs b/src/Triangle.Examples/Examples/Example4.cs
new file mode 100644
index 0000000..d3c122a
--- /dev/null
+++ b/src/Triangle.Examples/Examples/Example4.cs
@@ -0,0 +1,71 @@
+
+namespace TriangleNet.Examples
+{
+ using TriangleNet;
+ using TriangleNet.Geometry;
+ using TriangleNet.Meshing;
+ using TriangleNet.Rendering.Text;
+ using TriangleNet.Smoothing;
+
+ ///
+ /// Refine only a part of a polygon mesh by using region pointers and an area constraint.
+ ///
+ public class Example4
+ {
+ public static bool Run(bool print = false)
+ {
+ // Generate the input geometry.
+ var poly = CreatePolygon();
+
+ // Define regions (first one defines the area constraint).
+ poly.Regions.Add(new RegionPointer(1.5, 0.0, 1, 0.01));
+ poly.Regions.Add(new RegionPointer(2.5, 0.0, 2));
+
+ // Set quality and constraint options.
+ var options = new ConstraintOptions()
+ {
+ ConformingDelaunay = true
+ };
+
+ var quality = new QualityOptions()
+ {
+ MinimumAngle = 25.0,
+ VariableArea = true
+ };
+
+ //quality.UserTest = (t, area) => t.Label == 1 && area > 0.01;
+
+ var mesh = poly.Triangulate(options, quality);
+
+ var smoother = new SimpleSmoother();
+
+ smoother.Smooth(mesh, 5);
+
+ if (print) SvgImage.Save(mesh, "example-4.svg", 500);
+
+ return mesh.Triangles.Count > 0;
+ }
+
+ public static IPolygon CreatePolygon()
+ {
+ // Generate three concentric circles.
+ var poly = new Polygon();
+
+ // Center point.
+ var center = new Point(0, 0);
+
+ // Inner contour (hole).
+ poly.Add(Generate.Circle(1.0, center, 0.1, 1), center);
+
+ // Internal contour.
+ poly.Add(Generate.Circle(2.0, center, 0.1, 2));
+
+ // Outer contour.
+ poly.Add(Generate.Circle(3.0, center, 0.3, 3));
+
+ // Note that the outer contour has a larger segment size!
+
+ return poly;
+ }
+ }
+}
diff --git a/src/Triangle.Examples/Examples/Example5.cs b/src/Triangle.Examples/Examples/Example5.cs
new file mode 100644
index 0000000..17540af
--- /dev/null
+++ b/src/Triangle.Examples/Examples/Example5.cs
@@ -0,0 +1,98 @@
+
+namespace TriangleNet.Examples
+{
+ using System.Collections.Generic;
+ using TriangleNet;
+ using TriangleNet.Geometry;
+ using TriangleNet.Meshing;
+ using TriangleNet.Meshing.Iterators;
+ using TriangleNet.Rendering.Text;
+
+ ///
+ /// Two ways finding boundary triangles.
+ ///
+ public static class Example5
+ {
+ public static bool Run(bool print = false)
+ {
+ var mesh = Example3.CreateMesh();
+
+ FindBoundary1(mesh);
+
+ if (print) SvgImage.Save(mesh, "example-5-1.svg", 500, true, false);
+
+ FindBoundary2(mesh);
+
+ if (print) SvgImage.Save(mesh, "example-5-2.svg", 500, true, false);
+
+ return mesh.Triangles.Count > 0;
+ }
+
+ ///
+ /// Find boundary triangles using segments.
+ ///
+ private static void FindBoundary1(IMesh mesh, bool neigbours = true)
+ {
+ mesh.Renumber();
+
+ var cache = new List(mesh.Segments.Count + 1);
+
+ var circulator = new VertexCirculator((Mesh)mesh);
+
+ foreach (var s in mesh.Segments)
+ {
+ int label = s.Label;
+
+ for (int i = 0; i < 2; i++)
+ {
+ var vertex = s.GetVertex(i);
+
+ // Check the vertex ID to see if it was processed already.
+ if (vertex.ID >= 0)
+ {
+ var star = circulator.EnumerateTriangles(vertex);
+
+ foreach (var triangle in star)
+ {
+ triangle.Label = label;
+ }
+
+ // Mark the vertex as "processed".
+ vertex.ID = -vertex.ID;
+
+ cache.Add(vertex);
+ }
+ }
+ }
+
+ // Undo the vertex ID changes.
+ foreach (var vertex in cache)
+ {
+ vertex.ID = -vertex.ID;
+ }
+ }
+
+ ///
+ /// Find boundary triangles using vertices.
+ ///
+ private static void FindBoundary2(IMesh mesh)
+ {
+ var circulator = new VertexCirculator((Mesh)mesh);
+
+ foreach (var vertex in mesh.Vertices)
+ {
+ int label = vertex.Label;
+
+ if (label > 0)
+ {
+ var star = circulator.EnumerateTriangles(vertex);
+
+ foreach (var triangle in star)
+ {
+ triangle.Label = label;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/Triangle.Examples/Examples/Example6.cs b/src/Triangle.Examples/Examples/Example6.cs
new file mode 100644
index 0000000..0ed1b2c
--- /dev/null
+++ b/src/Triangle.Examples/Examples/Example6.cs
@@ -0,0 +1,56 @@
+namespace TriangleNet.Examples
+{
+ using System.Linq;
+ using TriangleNet;
+ using TriangleNet.Geometry;
+ using TriangleNet.Meshing.Iterators;
+ using TriangleNet.Rendering.Text;
+ using TriangleNet.Tools;
+ using TriangleNet.Topology;
+
+ ///
+ /// Boolean operations on mesh regions (intersection, difference, xor).
+ ///
+ public static class Example6
+ {
+ public static bool Run(bool print = true)
+ {
+ // Generate the input geometry.
+ var polygon = new Polygon(8, true);
+
+ // Two intersecting rectangles.
+ var A = Generate.Rectangle(0d, 0d, 4d, 4d, label: 1);
+ var B = Generate.Rectangle(1d, 1d, 4d, 4d, label: 2);
+
+ polygon.Add(A);
+ polygon.Add(B);
+
+ // Generate mesh.
+ var mesh = (Mesh)polygon.Triangulate();
+
+ if (print) SvgImage.Save(mesh, "example-6.svg", 500);
+
+ // Find a seeding triangle (in this case, the point (2, 2) lies in
+ // both rectangles).
+ var seed = (new TriangleQuadTree(mesh)).Query(2.0, 2.0) as Triangle;
+
+ var iterator = new RegionIterator(mesh);
+
+ iterator.Process(seed, t => t.Label ^= 1, 1);
+ iterator.Process(seed, t => t.Label ^= 2, 2);
+
+ // At this point, all triangles will have label 1, 2 or 3 (= 1 xor 2).
+
+ // The intersection of A and B.
+ var intersection = mesh.Triangles.Where(t => t.Label == 3);
+
+ // The difference A \ B.
+ var difference = mesh.Triangles.Where(t => t.Label == 1);
+
+ // The xor of A and B.
+ var xor = mesh.Triangles.Where(t => t.Label == 1 || t.Label == 2);
+
+ return intersection.Any() && difference.Any() && xor.Any();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Triangle.Examples/Examples/Example7.cs b/src/Triangle.Examples/Examples/Example7.cs
new file mode 100644
index 0000000..cdc2f8f
--- /dev/null
+++ b/src/Triangle.Examples/Examples/Example7.cs
@@ -0,0 +1,73 @@
+
+namespace TriangleNet.Examples
+{
+ using System;
+ using TriangleNet.Geometry;
+ using TriangleNet.Meshing;
+ using TriangleNet.Meshing.Iterators;
+ using TriangleNet.Rendering.Text;
+
+ ///
+ /// Using a user test function to define a maximum edge length constraint.
+ ///
+ public static class Example7
+ {
+ const double MAX_EDGE_LENGTH = 0.2;
+
+ public static bool Run(bool print = false)
+ {
+ var poly = new Polygon();
+
+ // Generate the input geometry.
+ poly.Add(Generate.Rectangle(0.0, 0.0, 1.0, 1.0));
+
+ // Set minimum angle quality option, ignoring holes.
+ var quality = new QualityOptions()
+ {
+ UserTest = MaxEdgeLength
+ };
+
+ // Generate mesh using the polygons Triangulate extension method.
+ var mesh = (Mesh)poly.Triangulate(quality);
+
+ // Validate.
+ foreach (var e in EdgeIterator.EnumerateEdges(mesh))
+ {
+ double length = Math.Sqrt(DistSqr(e.GetVertex(0), e.GetVertex(1)));
+
+ if (length > MAX_EDGE_LENGTH)
+ {
+ return false;
+ }
+ }
+
+ if (print) SvgImage.Save(mesh, "example-7.svg", 500);
+
+ return true;
+ }
+
+ static bool MaxEdgeLength(ITriangle tri, double area)
+ {
+ var p0 = tri.GetVertex(0);
+ var p1 = tri.GetVertex(1);
+ var p2 = tri.GetVertex(2);
+
+ var s1 = DistSqr(p0, p1);
+ var s2 = DistSqr(p1, p2);
+ var s3 = DistSqr(p2, p0);
+
+ // Comparing against squared max leg length.
+ var maxlen = MAX_EDGE_LENGTH * MAX_EDGE_LENGTH;
+
+ return s1 > maxlen || s2 > maxlen || s3 > maxlen;
+ }
+
+ static double DistSqr(Vertex a, Vertex b)
+ {
+ var dx = a.X - b.X;
+ var dy = a.Y - b.Y;
+
+ return dx * dx + dy * dy;
+ }
+ }
+}
diff --git a/src/Triangle.Examples/Examples/Example8.cs b/src/Triangle.Examples/Examples/Example8.cs
new file mode 100644
index 0000000..f0a16a5
--- /dev/null
+++ b/src/Triangle.Examples/Examples/Example8.cs
@@ -0,0 +1,84 @@
+
+namespace TriangleNet.Examples
+{
+ using System;
+ using System.Collections.Generic;
+ using TriangleNet;
+ using TriangleNet.Meshing.Iterators;
+ using TriangleNet.Tools;
+
+ ///
+ /// Compute the adjacency matrix of the mesh vertices.
+ ///
+ public class Example8
+ {
+ public static bool Run()
+ {
+ var mesh = (Mesh)Example3.CreateMesh();
+
+ return FindAdjacencyMatrix(mesh);
+ }
+
+ private static bool FindAdjacencyMatrix(Mesh mesh)
+ {
+ mesh.Renumber();
+
+ var ap = new List(mesh.Vertices.Count); // Column pointers.
+ var ai = new List(4 * mesh.Vertices.Count); // Row indices.
+
+ var circulator = new VertexCirculator(mesh);
+
+ int k = 0;
+
+ foreach (var vertex in mesh.Vertices)
+ {
+ var star = circulator.EnumerateVertices(vertex);
+
+ ap.Add(k);
+
+ // Each vertex is adjacent to itself.
+ ai.Add(vertex.ID);
+ k++;
+
+ foreach (var item in star)
+ {
+ ai.Add(item.ID);
+ k++;
+ }
+ }
+
+ ap.Add(k);
+
+ var matrix1 = new AdjacencyMatrix(ap.ToArray(), ai.ToArray());
+ var matrix2 = new AdjacencyMatrix(mesh);
+
+ // Column pointers should be exactly the same.
+ if (!CompareArray(matrix1.ColumnPointers, matrix2.ColumnPointers))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ private static bool CompareArray(int[] a, int[] b)
+ {
+ int length = a.Length;
+
+ if (b.Length != length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i < length; i++)
+ {
+ if (a[i] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/src/Triangle.Examples/Examples/Example9.cs b/src/Triangle.Examples/Examples/Example9.cs
new file mode 100644
index 0000000..a02664b
--- /dev/null
+++ b/src/Triangle.Examples/Examples/Example9.cs
@@ -0,0 +1,89 @@
+
+namespace TriangleNet.Examples
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using TriangleNet.Geometry;
+
+ ///
+ /// Troubleshooting: finding degenerate boundary triangles.
+ ///
+ public class Example9
+ {
+ public static bool Run(bool print = false)
+ {
+ var pts = new List
+ {
+ // The 4 corners of the rectangle.
+ new Vertex(1.5, 1.0),
+ new Vertex(1.5, -1.0),
+ new Vertex(-1.5, -1.0),
+ new Vertex(-1.5, 1.0),
+
+ // The edge midpoints.
+ new Vertex(0.0, 1.0),
+ new Vertex(0.0, -1.0),
+ new Vertex(1.5, 0.0),
+ new Vertex(-1.5, 0.0)
+ };
+
+ var r = new Random(78403);
+
+ // The original rectangle.
+ var poly = Rotate(pts, 0);
+
+ for (int i = 0; i < 10; i++)
+ {
+ var mesh = poly.Triangulate();
+
+ var list = MeshValidator.GetDegenerateBoundaryTriangles(mesh);
+
+ if (print && list.Any())
+ {
+ Console.WriteLine("Iteration {0}: found {1} degenerate triangle(s) of {2}.",
+ i, list.Count(), mesh.Triangles.Count);
+
+ foreach (var t in list)
+ {
+ Console.WriteLine(" [{0} {1} {2}]",
+ t.GetVertexID(0),
+ t.GetVertexID(1),
+ t.GetVertexID(2));
+ }
+ }
+
+ // Random rotation.
+ poly = Rotate(pts, Math.PI * r.NextDouble());
+ }
+
+ return true;
+ }
+
+ ///
+ /// Rotate given point set around the origin.
+ ///
+ private static IPolygon Rotate(List points, double radians)
+ {
+ var poly = new Polygon(points.Count);
+
+ int id = 0;
+
+ foreach (var p in points)
+ {
+ double x = p.X;
+ double y = p.Y;
+
+ double s = Math.Sin(radians);
+ double c = Math.Cos(radians);
+
+ double xr = c * x - s * y;
+ double yr = s * x + c * y;
+
+ poly.Points.Add(new Vertex(xr, yr) { ID = id++ });
+ }
+
+ return poly;
+ }
+ }
+}
diff --git a/src/Triangle.Examples/Examples/ExamplePar.cs b/src/Triangle.Examples/Examples/ExamplePar.cs
new file mode 100644
index 0000000..e53cf39
--- /dev/null
+++ b/src/Triangle.Examples/Examples/ExamplePar.cs
@@ -0,0 +1,98 @@
+
+namespace TriangleNet.Examples
+{
+ using System;
+ using System.Collections.Concurrent;
+ using System.IO;
+ using System.Linq;
+ using System.Threading.Tasks;
+ using TriangleNet;
+ using TriangleNet.IO;
+ using TriangleNet.Meshing;
+
+ ///
+ /// Processing meshes in parallel.
+ ///
+ public class ExamplePar
+ {
+ ///
+ /// Reads all .poly files from given directory and processes them in parallel.
+ ///
+ public static bool Run(string dir)
+ {
+ var files = Directory.EnumerateFiles(dir, "*.poly", SearchOption.AllDirectories);
+
+ var queue = new ConcurrentQueue(files);
+
+ int concurrencyLevel = Environment.ProcessorCount / 2;
+
+ var tasks = new Task[concurrencyLevel];
+
+ for (int i = 0; i < concurrencyLevel; i++)
+ {
+ tasks[i] = Task.Run(() =>
+ {
+ // Each task has it's own triangle pool and predicates instance.
+ var pool = new TrianglePool();
+ var predicates = new RobustPredicates();
+
+ // The factory methods return the above instances.
+ var config = new Configuration()
+ {
+ Predicates = () => predicates,
+ TrianglePool = () => pool.Restart()
+ };
+
+ var mesher = new GenericMesher(config);
+ var result = new MeshResult();
+
+ while (queue.Count > 0)
+ {
+ if (queue.TryDequeue(out var file))
+ {
+ var poly = FileProcessor.Read(file);
+
+ var mesh = mesher.Triangulate(poly);
+
+ ProcessMesh(mesh, result);
+ }
+ }
+
+ pool.Clear();
+
+ return result;
+ });
+ }
+
+ Task.WaitAll(tasks);
+
+ int numberOfTriangles = tasks.Sum(t => t.Result.NumberOfTriangles);
+ int invalid = tasks.Sum(t => t.Result.Invalid);
+
+ Console.WriteLine("Total number of triangles processed: {0}", numberOfTriangles);
+
+ if (invalid > 0)
+ {
+ Console.WriteLine(" Number of invalid triangulations: {0}", invalid);
+ }
+
+ return true;
+ }
+
+ private static void ProcessMesh(IMesh mesh, MeshResult result)
+ {
+ result.NumberOfTriangles += mesh.Triangles.Count;
+
+ if (!MeshValidator.IsConsistent((Mesh)mesh))
+ {
+ result.Invalid += 1;
+ }
+ }
+
+ class MeshResult
+ {
+ public int NumberOfTriangles;
+ public int Invalid;
+ }
+ }
+}
diff --git a/src/Triangle.Examples/Generate.cs b/src/Triangle.Examples/Generate.cs
new file mode 100644
index 0000000..e3864af
--- /dev/null
+++ b/src/Triangle.Examples/Generate.cs
@@ -0,0 +1,123 @@
+
+namespace TriangleNet
+{
+ using System;
+ using System.Collections.Generic;
+ using TriangleNet.Geometry;
+
+ static class Generate
+ {
+ private static readonly Random random = new Random(63841);
+
+ public static List RandomPoints(int n, Rectangle bounds)
+ {
+ var points = new List(n);
+
+ var xmin = bounds.Left;
+ var ymin = bounds.Bottom;
+
+ var width = bounds.Width;
+ var height = bounds.Height;
+
+ for (int i = 0; i < n; i++)
+ {
+ double x = random.NextDouble();
+ double y = random.NextDouble();
+ points.Add(new Vertex(xmin + x * width, ymin + y * height));
+ }
+
+ return points;
+ }
+
+ ///
+ /// Creates a rectangle contour.
+ ///
+ public static Contour Rectangle(Rectangle rect, double size = 0d, int label = 0)
+ {
+ return Rectangle(rect.X, rect.Y, rect.Width, rect.Height, size, label);
+ }
+
+ ///
+ /// Creates a rectangle contour.
+ ///
+ public static Contour Rectangle(double x, double y, double width, double height,
+ double size = 0d, int label = 0)
+ {
+ // Horizontal and vertical step sizes.
+ double stepH = 0d;
+ double stepV = 0d;
+
+ int nH = 1;
+ int nV = 1;
+
+ if (size > 0d)
+ {
+ size = Math.Min(size, Math.Min(width, height));
+
+ nH = (int)Math.Ceiling(width / size);
+ nV = (int)Math.Ceiling(height / size);
+
+ stepH = width / nH;
+ stepV = height / nV;
+ }
+
+ var points = new List(2 * nH + 2 * nV);
+
+ double right = x + width;
+ double top = y + height;
+
+ // Left box boundary points
+ for (int i = 0; i < nV; i++)
+ {
+ points.Add(new Vertex(x, y + i * stepV, label));
+ }
+
+ // Top box boundary points
+ for (int i = 0; i < nH; i++)
+ {
+ points.Add(new Vertex(x + i * stepH, top, label));
+ }
+
+ // Right box boundary points
+ for (int i = 0; i < nV; i++)
+ {
+ points.Add(new Vertex(right, top - i * stepV, label));
+ }
+
+ // Bottom box boundary points
+ for (int i = 0; i < nH; i++)
+ {
+ points.Add(new Vertex(right - i * stepH, y, label));
+ }
+
+ return new Contour(points, label, true);
+ }
+
+ ///
+ /// Create a circular contour.
+ ///
+ /// The radius.
+ /// The center point.
+ /// The desired segment length.
+ /// The boundary label.
+ /// A circular contour.
+ public static Contour Circle(double r, Point center, double h, int label = 0)
+ {
+ int n = (int)(2 * Math.PI * r / h);
+
+ var points = new List(n);
+
+ double x, y, dphi = 2 * Math.PI / n;
+
+ for (int i = 0; i < n; i++)
+ {
+ x = center.X + r * Math.Cos(i * dphi);
+ y = center.Y + r * Math.Sin(i * dphi);
+
+ points.Add(new Vertex(x, y, label));
+ }
+
+ return new Contour(points, label, true);
+ }
+ }
+}
diff --git a/src/Triangle.Examples/Program.cs b/src/Triangle.Examples/Program.cs
new file mode 100644
index 0000000..05269a1
--- /dev/null
+++ b/src/Triangle.Examples/Program.cs
@@ -0,0 +1,33 @@
+
+namespace TriangleNet
+{
+ using System;
+ using TriangleNet.Examples;
+
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ Check("Example 1", Example1.Run());
+ Check("Example 2", Example2.Run());
+ Check("Example 3", Example3.Run());
+ Check("Example 4", Example4.Run());
+ Check("Example 5", Example5.Run());
+ Check("Example 6", Example6.Run());
+ Check("Example 7", Example7.Run());
+ Check("Example 8", Example8.Run());
+ Check("Example 9", Example9.Run());
+ Check("Example 10", Example10.Run());
+ }
+
+ static void Check(string item, bool success)
+ {
+ var color = Console.ForegroundColor;
+
+ Console.Write(item + " ");
+ Console.ForegroundColor = success ? ConsoleColor.DarkGreen : ConsoleColor.DarkRed;
+ Console.WriteLine(success ? "OK" : "Failed");
+ Console.ForegroundColor = color;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Triangle.Examples/Triangle.Examples.csproj b/src/Triangle.Examples/Triangle.Examples.csproj
new file mode 100644
index 0000000..e5cf28f
--- /dev/null
+++ b/src/Triangle.Examples/Triangle.Examples.csproj
@@ -0,0 +1,14 @@
+
+
+
+ Exe
+ net6.0
+ TriangleNet
+
+
+
+
+
+
+
+
diff --git a/Triangle.NET/Triangle.Rendering/ExtensionMethods.cs b/src/Triangle.Rendering.GDI/ExtensionMethods.cs
similarity index 96%
rename from Triangle.NET/Triangle.Rendering/ExtensionMethods.cs
rename to src/Triangle.Rendering.GDI/ExtensionMethods.cs
index 175d185..6f3b9c8 100644
--- a/Triangle.NET/Triangle.Rendering/ExtensionMethods.cs
+++ b/src/Triangle.Rendering.GDI/ExtensionMethods.cs
@@ -1,26 +1,26 @@
-
-namespace TriangleNet.Rendering
-{
- using System.Drawing;
-
- internal static class ExtensionMethods
- {
- ///
- /// Check if segment (a, b) intersects rectangle.
- ///
- public static bool Intersects(this RectangleF rect, PointF a, PointF b)
- {
- // TODO: implement intersection.
- return rect.Contains(a) || rect.Contains(b);
- }
-
- ///
- /// Check if triangle (a, b, c) intersects rectangle.
- ///
- public static bool Intersects(this RectangleF rect, PointF a, PointF b, PointF c)
- {
- // TODO: implement intersection.
- return rect.Contains(a) || rect.Contains(b) || rect.Contains(c);
- }
- }
-}
+
+namespace TriangleNet.Rendering
+{
+ using System.Drawing;
+
+ internal static class ExtensionMethods
+ {
+ ///
+ /// Check if segment (a, b) intersects rectangle.
+ ///
+ public static bool Intersects(this RectangleF rect, PointF a, PointF b)
+ {
+ // TODO: implement intersection.
+ return rect.Contains(a) || rect.Contains(b);
+ }
+
+ ///
+ /// Check if triangle (a, b, c) intersects rectangle.
+ ///
+ public static bool Intersects(this RectangleF rect, PointF a, PointF b, PointF c)
+ {
+ // TODO: implement intersection.
+ return rect.Contains(a) || rect.Contains(b) || rect.Contains(c);
+ }
+ }
+}
diff --git a/Triangle.NET/Triangle.Rendering/GDI/FunctionRenderer.cs b/src/Triangle.Rendering.GDI/FunctionRenderer.cs
similarity index 93%
rename from Triangle.NET/Triangle.Rendering/GDI/FunctionRenderer.cs
rename to src/Triangle.Rendering.GDI/FunctionRenderer.cs
index 7320b29..2af4cac 100644
--- a/Triangle.NET/Triangle.Rendering/GDI/FunctionRenderer.cs
+++ b/src/Triangle.Rendering.GDI/FunctionRenderer.cs
@@ -1,101 +1,101 @@
-
-namespace TriangleNet.Rendering.GDI
-{
- using System;
- using System.Drawing;
- using TriangleNet.Rendering.GDI.Native;
-
- public class FunctionRenderer
- {
- TriVertex[] points;
- GradientTriangle[] elements;
-
- public Graphics RenderTarget { get; set; }
-
- public IRenderContext Context { get; set; }
-
- public void Render(IRenderLayer layer)
- {
- Create(layer);
-
- var hdc = RenderTarget.GetHdc();
-
- NativeMethods.GradientFill(hdc,
- points, (uint)points.Length, elements, (uint)elements.Length,
- GradientFillMode.GRADIENT_FILL_TRIANGLE);
-
- RenderTarget.ReleaseHdc(hdc);
- }
-
- private void Create(IRenderLayer layer)
- {
- var zoom = Context.Zoom;
- var colors = layer.Colors.Data;
-
- int length = colors.Length;
-
- int size = layer.Points.Size;
- var data = layer.Points.Data;
-
- if (length != data.Length / size)
- {
- throw new Exception();
- }
-
- this.points = new TriVertex[length];
-
- TriVertex vertex;
- Color color;
- PointF p = new PointF((float)data[0], (float)data[1]);
-
- zoom.WorldToScreen(ref p);
-
- // Get correction distance
- float dx = (p.X - (int)p.X) * 2.0f;
- float dy = (p.Y - (int)p.Y) * 2.0f;
-
- // Create vertices.
- for (int i = 0; i < length; i++)
- {
- p.X = (float)data[size * i];
- p.Y = (float)data[size * i + 1];
-
- zoom.WorldToScreen(ref p);
-
- color = colors[i];
-
- vertex = new TriVertex();
-
- vertex.x = (int)(p.X + dx);
- vertex.y = (int)(p.Y + dy);
-
- vertex.Red = (ushort)(color.R << 8);
- vertex.Green = (ushort)(color.G << 8);
- vertex.Blue = (ushort)(color.B << 8);
- vertex.Alpha = (ushort)(color.A << 8);
-
- this.points[i] = vertex;
- }
-
- var triangles = layer.Indices.Data;
-
- length = triangles.Length / 3;
-
- this.elements = new GradientTriangle[length];
-
- GradientTriangle e;
-
- // Create triangles.
- for (int i = 0; i < length; i++)
- {
- e = new GradientTriangle();
-
- e.Vertex1 = (uint)triangles[3 * i];
- e.Vertex2 = (uint)triangles[3 * i + 1];
- e.Vertex3 = (uint)triangles[3 * i + 2];
-
- this.elements[i] = e;
- }
- }
- }
-}
+
+namespace TriangleNet.Rendering.GDI
+{
+ using System;
+ using System.Drawing;
+ using TriangleNet.Rendering.GDI.Native;
+
+ public class FunctionRenderer
+ {
+ TriVertex[] points;
+ GradientTriangle[] elements;
+
+ public Graphics RenderTarget { get; set; }
+
+ public IRenderContext Context { get; set; }
+
+ public void Render(IRenderLayer layer)
+ {
+ Create(layer);
+
+ var hdc = RenderTarget.GetHdc();
+
+ NativeMethods.GradientFill(hdc,
+ points, (uint)points.Length, elements, (uint)elements.Length,
+ GradientFillMode.GRADIENT_FILL_TRIANGLE);
+
+ RenderTarget.ReleaseHdc(hdc);
+ }
+
+ private void Create(IRenderLayer layer)
+ {
+ var zoom = Context.Zoom;
+ var colors = layer.Colors.Data;
+
+ int length = colors.Length;
+
+ int size = layer.Points.Size;
+ var data = layer.Points.Data;
+
+ if (length != data.Length / size)
+ {
+ throw new Exception();
+ }
+
+ this.points = new TriVertex[length];
+
+ TriVertex vertex;
+ Color color;
+ PointF p = new PointF((float)data[0], (float)data[1]);
+
+ zoom.NdcToScreen(ref p);
+
+ // Get correction distance
+ float dx = (p.X - (int)p.X) * 2.0f;
+ float dy = (p.Y - (int)p.Y) * 2.0f;
+
+ // Create vertices.
+ for (int i = 0; i < length; i++)
+ {
+ p.X = (float)data[size * i];
+ p.Y = (float)data[size * i + 1];
+
+ zoom.NdcToScreen(ref p);
+
+ color = colors[i];
+
+ vertex = new TriVertex();
+
+ vertex.x = (int)(p.X + dx);
+ vertex.y = (int)(p.Y + dy);
+
+ vertex.Red = (ushort)(color.R << 8);
+ vertex.Green = (ushort)(color.G << 8);
+ vertex.Blue = (ushort)(color.B << 8);
+ vertex.Alpha = (ushort)(color.A << 8);
+
+ this.points[i] = vertex;
+ }
+
+ var triangles = layer.Indices.Data;
+
+ length = triangles.Length / 3;
+
+ this.elements = new GradientTriangle[length];
+
+ GradientTriangle e;
+
+ // Create triangles.
+ for (int i = 0; i < length; i++)
+ {
+ e = new GradientTriangle();
+
+ e.Vertex1 = (uint)triangles[3 * i];
+ e.Vertex2 = (uint)triangles[3 * i + 1];
+ e.Vertex3 = (uint)triangles[3 * i + 2];
+
+ this.elements[i] = e;
+ }
+ }
+ }
+}
diff --git a/src/Triangle.Rendering.GDI/Helper.cs b/src/Triangle.Rendering.GDI/Helper.cs
new file mode 100644
index 0000000..81f71cd
--- /dev/null
+++ b/src/Triangle.Rendering.GDI/Helper.cs
@@ -0,0 +1,28 @@
+using System.Collections.Generic;
+using System.Drawing;
+
+namespace TriangleNet.Rendering.GDI
+{
+ internal class Helper
+ {
+ public static void Dispose(Dictionary brushes)
+ {
+ foreach (var brush in brushes.Values)
+ {
+ brush.Dispose();
+ }
+ }
+
+ public static Dictionary GetBrushDictionary(Dictionary ColorDictionary)
+ {
+ var brushes = new Dictionary();
+
+ foreach (var item in ColorDictionary)
+ {
+ brushes.Add(item.Key, new SolidBrush(item.Value));
+ }
+
+ return brushes;
+ }
+ }
+}
diff --git a/src/Triangle.Rendering.GDI/ImageRenderer.cs b/src/Triangle.Rendering.GDI/ImageRenderer.cs
new file mode 100644
index 0000000..3011273
--- /dev/null
+++ b/src/Triangle.Rendering.GDI/ImageRenderer.cs
@@ -0,0 +1,287 @@
+
+namespace TriangleNet.Rendering.GDI
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Drawing;
+ using System.Drawing.Drawing2D;
+ using System.Drawing.Imaging;
+ using System.IO;
+ using TriangleNet.Meshing;
+
+ ///
+ /// Enables rendering of polygons or meshes to a bitmap.
+ ///
+ public class ImageRenderer
+ {
+ ColorManager colors = LightScheme();
+
+ public ColorManager ColorScheme
+ {
+ get { return colors; }
+ set { colors = value; }
+ }
+
+ public bool EnableRegions { get; set; }
+
+ public bool EnablePoints { get; set; }
+
+ ///
+ /// Exports a polygon to PNG format.
+ ///
+ /// The polygon.
+ /// The desired width (pixel) of the image.
+ /// The PNG filename.
+ /// Enable rendering of regions.
+ /// Enable rendering of points.
+ public static void Save(Geometry.IPolygon poly, string file = null, int width = 800,
+ bool points = true)
+ {
+ // Check file name
+ if (string.IsNullOrWhiteSpace(file))
+ {
+ file = string.Format("poly-{0}.png", DateTime.Now.ToString("yyyy-M-d-hh-mm-ss"));
+ }
+
+ // Ensure .png extension.
+ if (file.EndsWith(".png", StringComparison.OrdinalIgnoreCase))
+ {
+ Path.ChangeExtension(file, ".png");
+ }
+
+ var renderer = new ImageRenderer();
+
+ renderer.EnableRegions = false;
+ renderer.EnablePoints = points;
+
+ var bitmap = renderer.Render(poly, width);
+
+ bitmap.Save(file, ImageFormat.Png);
+ }
+
+ ///
+ /// Exports a mesh to PNG format.
+ ///
+ /// The mesh.
+ /// The desired width (pixel) of the image.
+ /// The PNG filename.
+ /// Enable rendering of regions.
+ /// Enable rendering of points.
+ public static void Save(IMesh mesh, string file = null, int width = 800,
+ bool regions = false, bool points = true)
+ {
+ // Check file name
+ if (string.IsNullOrWhiteSpace(file))
+ {
+ file = string.Format("mesh-{0}.png", DateTime.Now.ToString("yyyy-M-d-hh-mm-ss"));
+ }
+
+ // Ensure .png extension.
+ if (!file.EndsWith(".png", StringComparison.OrdinalIgnoreCase))
+ {
+ Path.ChangeExtension(file, ".png");
+ }
+
+ var renderer = new ImageRenderer();
+
+ renderer.EnableRegions = regions;
+ renderer.EnablePoints = points;
+
+ var bitmap = renderer.Render(mesh, width);
+
+ bitmap.Save(file, ImageFormat.Png);
+ }
+
+ ///
+ /// Renders the polygon to a bitmap.
+ ///
+ /// The polygon.
+ /// The desired width (pixel) of the image.
+ /// The bitmap.
+ ///
+ /// The width has to be at least 2 * sqrt(n), n the number of vertices.
+ /// Otherwise, an empty bitmap
+ ///
+ public Bitmap Render(Geometry.IPolygon poly, int width = 800)
+ {
+ Bitmap bitmap;
+
+ // Check if the specified width is reasonable
+ if (width < 2 * Math.Sqrt(poly.Points.Count))
+ {
+ return new Bitmap(1, 1);
+ }
+
+ var bounds = poly.Bounds();
+
+ // World margin on each side
+ float margin = (float)bounds.Height * 0.05f;
+ float scale = width / ((float)bounds.Width + 2 * margin);
+
+ var target = new Rectangle(0, 0, width, (int)((bounds.Height + 2 * margin) * scale));
+
+ bitmap = new Bitmap(width, target.Height, PixelFormat.Format32bppPArgb);
+
+ using (var g = Graphics.FromImage(bitmap))
+ {
+ g.Clear(colors.Background);
+ g.SmoothingMode = SmoothingMode.HighQuality;
+
+ var context = new RenderContext(new Projection(target), colors);
+ context.Add(poly);
+
+ if (!EnablePoints)
+ {
+ context.Enable(3, false);
+ }
+
+ var renderer = new LayerRenderer();
+ renderer.Context = context;
+ renderer.RenderTarget = g;
+ renderer.Render();
+ }
+
+ return bitmap;
+ }
+
+ ///
+ /// Renders the mesh to a bitmap.
+ ///
+ /// The current mesh.
+ /// The desired width (pixel) of the image.
+ /// The bitmap.
+ ///
+ /// The width has to be at least 2 * sqrt(n), n the number of vertices.
+ /// Otherwise, an empty bitmap
+ ///
+ public Bitmap Render(IMesh mesh, int width = 800)
+ {
+ Bitmap bitmap;
+
+ // Check if the specified width is reasonable
+ if (width < 2 * Math.Sqrt(mesh.Vertices.Count))
+ {
+ return new Bitmap(1, 1);
+ }
+
+ var bounds = mesh.Bounds;
+
+ // World margin on each side
+ float margin = (float)bounds.Height * 0.05f;
+ float scale = width / ((float)bounds.Width + 2 * margin);
+
+ var target = new Rectangle(0, 0, width, (int)((bounds.Height + 2 * margin) * scale));
+
+ bitmap = new Bitmap(width, target.Height, PixelFormat.Format32bppPArgb);
+
+ using (var g = Graphics.FromImage(bitmap))
+ {
+ g.Clear(colors.Background);
+ g.SmoothingMode = SmoothingMode.HighQuality;
+
+ var context = new RenderContext(new Projection(target), colors);
+ context.Add(mesh, true);
+
+ if (EnableRegions)
+ {
+ context.Add(GetRegions(mesh));
+ }
+
+ if (!EnablePoints)
+ {
+ context.Enable(3, false);
+ }
+
+ var renderer = new LayerRenderer();
+ renderer.Context = context;
+ renderer.RenderTarget = g;
+ renderer.Render();
+ }
+
+ return bitmap;
+ }
+
+ public Bitmap Render(IMesh mesh, Topology.DCEL.DcelMesh dcel, int width = 800)
+ {
+ Bitmap bitmap;
+
+ // Check if the specified width is reasonable
+ if (width < 2 * Math.Sqrt(mesh.Vertices.Count))
+ {
+ return new Bitmap(1, 1);
+ }
+
+ var bounds = mesh.Bounds;
+
+ // World margin on each side
+ float margin = (float)bounds.Height * 0.05f;
+ float scale = width / ((float)bounds.Width + 2 * margin);
+
+ var target = new Rectangle(0, 0, width, (int)((bounds.Height + 2 * margin) * scale));
+
+ bitmap = new Bitmap(width, target.Height, PixelFormat.Format32bppPArgb);
+
+ using (var g = Graphics.FromImage(bitmap))
+ {
+ g.Clear(colors.Background);
+ g.SmoothingMode = SmoothingMode.HighQuality;
+
+ var context = new RenderContext(new Projection(target), colors);
+ context.Add(mesh, true);
+ context.Add(dcel.Vertices.ToArray(), dcel.Edges, false);
+
+ if (EnableRegions)
+ {
+ context.Add(GetRegions(mesh));
+ }
+
+ if (!EnablePoints)
+ {
+ context.Enable(3, false);
+ }
+
+ var renderer = new LayerRenderer();
+ renderer.Context = context;
+ renderer.RenderTarget = g;
+ renderer.Render();
+ }
+
+ return bitmap;
+ }
+
+ private int[] GetRegions(IMesh mesh)
+ {
+ mesh.Renumber();
+
+ var labels = new int[mesh.Triangles.Count];
+ var regions = new SortedSet();
+
+ foreach (var t in mesh.Triangles)
+ {
+ labels[t.ID] = t.Label;
+ regions.Add(t.Label);
+ }
+
+ if (colors.ColorDictionary == null)
+ {
+ colors.CreateColorDictionary(regions);
+ }
+
+ return labels;
+ }
+
+ public static ColorManager LightScheme()
+ {
+ var colors = new ColorManager();
+
+ colors.Background = Color.White;
+ colors.Point = Color.FromArgb(60, 80, 120);
+ colors.SteinerPoint = Color.DarkGreen;
+ colors.Line = Color.FromArgb(200, 200, 200);
+ colors.Segment = Color.SteelBlue;
+ colors.VoronoiLine = Color.FromArgb(160, 170, 180);
+
+ return colors;
+ }
+ }
+}
diff --git a/Triangle.NET/Triangle.Rendering/GDI/LayerRenderer.cs b/src/Triangle.Rendering.GDI/LayerRenderer.cs
similarity index 92%
rename from Triangle.NET/Triangle.Rendering/GDI/LayerRenderer.cs
rename to src/Triangle.Rendering.GDI/LayerRenderer.cs
index b70dda2..6a9aa78 100644
--- a/Triangle.NET/Triangle.Rendering/GDI/LayerRenderer.cs
+++ b/src/Triangle.Rendering.GDI/LayerRenderer.cs
@@ -1,118 +1,124 @@
-
-namespace TriangleNet.Rendering.GDI
-{
- using System.Drawing;
-
- public class LayerRenderer : IRenderer
- {
- MeshRenderer meshRenderer;
- FunctionRenderer functionRenderer;
-
- public IRenderContext Context { get; set; }
-
- public Graphics RenderTarget { get; set; }
-
- public LayerRenderer()
- {
- meshRenderer = new MeshRenderer();
- functionRenderer = new FunctionRenderer();
- }
-
- public void Render()
- {
- meshRenderer.Context = Context;
- meshRenderer.RenderTarget = RenderTarget;
-
- functionRenderer.Context = Context;
- functionRenderer.RenderTarget = RenderTarget;
-
- // 0 = mesh (filled)
- // 1 = mesh (wireframe)
- // 2 = polygon
- // 3 = points
- // 4 = voronoi overlay
- // 5 = vector field
- // 6 = contour lines
-
- int i = 0;
-
- foreach (var layer in this.Context.RenderLayers)
- {
- if (!layer.IsEmpty() && layer.IsEnabled)
- {
- switch (i)
- {
- case 0:
- RenderFilledMesh(layer);
- break;
- case 1:
- RenderMesh(layer);
- break;
- case 2:
- RenderPolygon(layer);
- break;
- case 3:
- RenderPoints(layer);
- break;
- case 4:
- RenderVoronoi(layer);
- break;
- case 5:
- case 6:
- default:
- break;
- }
- }
-
- i++;
- }
- }
-
- private void RenderFilledMesh(IRenderLayer layer)
- {
- if (layer.Partition != null)
- {
- meshRenderer.RenderElements(layer.Points.Data, layer.Indices.Data, 3, layer.Partition.Data);
- }
- else if (layer.Colors != null)
- {
- functionRenderer.Render(layer);
- }
- }
-
- private void RenderMesh(IRenderLayer layer)
- {
- if (layer.Indices.Size == 3)
- {
- meshRenderer.RenderElements(layer.Points.Data, layer.Indices.Data, 3, null);
- }
- else
- {
- meshRenderer.RenderEdges(layer.Points.Data, layer.Indices.Data, Context.ColorManager.Line);
- }
- }
-
- private void RenderPolygon(IRenderLayer layer)
- {
- meshRenderer.RenderSegments(layer.Points.Data, layer.Indices.Data, Context.ColorManager.Segment);
- }
-
- private void RenderPoints(IRenderLayer layer)
- {
- meshRenderer.RenderPoints(layer.Points.Data, layer.Points.Size, layer.Count);
- }
-
- private void RenderVoronoi(IRenderLayer layer)
- {
- if (RenderManager.VORONOI_DEBUG)
- {
- meshRenderer.RenderEdges(layer.Points.Data, layer.Indices.Data, Pens.Purple);
- meshRenderer.RenderPoints(layer.Points.Data, layer.Points.Size, 0, layer.Count, Brushes.Red);
- }
- else
- {
- meshRenderer.RenderEdges(layer.Points.Data, layer.Indices.Data, Context.ColorManager.VoronoiLine);
- }
- }
- }
-}
+
+namespace TriangleNet.Rendering.GDI
+{
+ using System.Drawing;
+
+ public class LayerRenderer : IRenderer
+ {
+ MeshRenderer meshRenderer;
+ FunctionRenderer functionRenderer;
+
+ public IRenderContext Context { get; set; }
+
+ public Graphics RenderTarget { get; set; }
+
+ public LayerRenderer()
+ {
+ meshRenderer = new MeshRenderer();
+ functionRenderer = new FunctionRenderer();
+ }
+
+ public void Render()
+ {
+ meshRenderer.Context = Context;
+ meshRenderer.RenderTarget = RenderTarget;
+
+ functionRenderer.Context = Context;
+ functionRenderer.RenderTarget = RenderTarget;
+
+ // 0 = mesh (filled)
+ // 1 = mesh (wireframe)
+ // 2 = polygon
+ // 3 = points
+ // 4 = voronoi overlay
+ // 5 = vector field
+ // 6 = contour lines
+
+ int i = 0;
+
+ foreach (var layer in this.Context.RenderLayers)
+ {
+ if (!layer.IsEmpty() && layer.IsEnabled)
+ {
+ switch (i)
+ {
+ case 0:
+ RenderFilledMesh(layer);
+ break;
+ case 1:
+ RenderMesh(layer);
+ break;
+ case 2:
+ RenderPolygon(layer);
+ break;
+ case 3:
+ RenderPoints(layer);
+ break;
+ case 4:
+ RenderVoronoi(layer);
+ break;
+ case 5:
+ case 6:
+ default:
+ break;
+ }
+ }
+
+ i++;
+ }
+ }
+
+ private void RenderFilledMesh(IRenderLayer layer)
+ {
+ if (layer.Partition != null)
+ {
+ meshRenderer.RenderElements(layer.Points.Data, layer.Indices.Data, 3, layer.Partition.Data);
+ }
+ else if (layer.Colors != null)
+ {
+ functionRenderer.Render(layer);
+ }
+ }
+
+ private void RenderMesh(IRenderLayer layer)
+ {
+ if (layer.Indices.Size == 3)
+ {
+ meshRenderer.RenderElements(layer.Points.Data, layer.Indices.Data, 3, null);
+ }
+ else
+ {
+ using var pen = new Pen(Context.ColorManager.Line);
+
+ meshRenderer.RenderEdges(layer.Points.Data, layer.Indices.Data, pen);
+ }
+ }
+
+ private void RenderPolygon(IRenderLayer layer)
+ {
+ using var pen = new Pen(Context.ColorManager.Segment);
+
+ meshRenderer.RenderSegments(layer.Points.Data, layer.Indices.Data, pen);
+ }
+
+ private void RenderPoints(IRenderLayer layer)
+ {
+ meshRenderer.RenderPoints(layer.Points.Data, layer.Points.Size, layer.Count);
+ }
+
+ private void RenderVoronoi(IRenderLayer layer)
+ {
+ if (RenderManager.VORONOI_DEBUG)
+ {
+ meshRenderer.RenderEdges(layer.Points.Data, layer.Indices.Data, Pens.Purple);
+ meshRenderer.RenderPoints(layer.Points.Data, layer.Points.Size, 0, layer.Count, Brushes.Red);
+ }
+ else
+ {
+ using var pen = new Pen(Context.ColorManager.VoronoiLine);
+
+ meshRenderer.RenderEdges(layer.Points.Data, layer.Indices.Data, pen);
+ }
+ }
+ }
+}
diff --git a/Triangle.NET/Triangle.Rendering/GDI/MeshRenderer.cs b/src/Triangle.Rendering.GDI/MeshRenderer.cs
similarity index 83%
rename from Triangle.NET/Triangle.Rendering/GDI/MeshRenderer.cs
rename to src/Triangle.Rendering.GDI/MeshRenderer.cs
index 38c3614..71e9d48 100644
--- a/Triangle.NET/Triangle.Rendering/GDI/MeshRenderer.cs
+++ b/src/Triangle.Rendering.GDI/MeshRenderer.cs
@@ -1,173 +1,175 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace TriangleNet.Rendering.GDI
-{
- using System.Drawing;
- using TriangleNet.Rendering.GDI.Native;
-
- ///
- /// Renders a mesh.
- ///
- public class MeshRenderer
- {
- ///
- /// Initializes a new instance of the class.
- ///
- public MeshRenderer()
- {
- }
-
- public Graphics RenderTarget { get; set; }
-
- public IRenderContext Context { get; set; }
-
- public void RenderPoints(float[] points, int size, int limit = 0)
- {
- int n = points.Length / size;
- int m = limit > 0 ? limit : n;
-
- // Draw unchanged points
- RenderPoints(points, size, 0, m, Context.ColorManager.Point);
-
- // Draw new (Steiner) points
- if (limit > 0)
- {
- RenderPoints(points, size, m, n, Context.ColorManager.SteinerPoint);
- }
- }
-
- public void RenderPoints(float[] points, int size, int start, int end, Brush brush)
- {
- var g = this.RenderTarget;
- var zoom = this.Context.Zoom;
-
- int i, k, n = points.Length / size;
- PointF p = new PointF();
-
- // Render points
- for (i = start; i < end; i++)
- {
- k = size * i;
-
- p.X = points[k];
- p.Y = points[k + 1];
-
- if (zoom.Viewport.Contains(p))
- {
- zoom.WorldToScreen(ref p);
- g.FillEllipse(brush, p.X - 1.5f, p.Y - 1.5f, 3, 3);
- }
- }
- }
-
- public void RenderSegments(float[] points, int[] indices, Pen pen)
- {
- RenderLines(points, indices, pen);
- }
-
- public void RenderEdges(float[] points, int[] indices, Pen pen)
- {
- RenderLines(points, indices, pen);
- }
-
- public void RenderElements(float[] points, int[] indices, int size, int[] partition)
- {
- var g = this.RenderTarget;
- var zoom = this.Context.Zoom;
-
- int n = indices.Length / size;
- int k0, k1, k2;
-
- var tri = new PointF[size];
-
- bool filled = partition != null;
-
- var brushes = filled ? Context.ColorManager.GetBrushDictionary() : null;
-
- // TODO: remove hardcoded color
- var pen = new Pen(Color.FromArgb(20, 20, 20));
-
- // Draw triangles
- for (int i = 0; i < n; i++)
- {
- k0 = 2 * indices[3 * i];
- k1 = 2 * indices[3 * i + 1];
- k2 = 2 * indices[3 * i + 2];
-
- tri[0].X = points[k0];
- tri[0].Y = points[k0 + 1];
-
- tri[1].X = points[k1];
- tri[1].Y = points[k1 + 1];
-
- tri[2].X = points[k2];
- tri[2].Y = points[k2 + 1];
-
- if (zoom.Viewport.Intersects(tri[0], tri[1], tri[2]))
- {
- zoom.WorldToScreen(ref tri[0]);
- zoom.WorldToScreen(ref tri[1]);
- zoom.WorldToScreen(ref tri[2]);
-
- if (filled)
- {
- var b = brushes[partition[i]];
-
- if (b.Color.A > 0)
- {
- g.FillPolygon(b, tri);
- }
- }
- else
- {
- g.DrawPolygon(pen, tri);
- }
- }
- }
-
- pen.Dispose();
-
- if (filled)
- {
- Context.ColorManager.Dispose(brushes);
- }
- }
-
- public void RenderLines(float[] points, int[] indices, Pen pen)
- {
- var g = this.RenderTarget;
- var zoom = this.Context.Zoom;
-
- int n = indices.Length / 2;
- int k0, k1;
-
- PointF p0 = new PointF();
- PointF p1 = new PointF();
-
- // Draw edges
- for (int i = 0; i < n; i++)
- {
- k0 = 2 * indices[2 * i];
- k1 = 2 * indices[2 * i + 1];
-
- p0.X = points[k0];
- p0.Y = points[k0 + 1];
-
- p1.X = points[k1];
- p1.Y = points[k1 + 1];
-
- if (zoom.Viewport.Intersects(p0, p1))
- {
- zoom.WorldToScreen(ref p0);
- zoom.WorldToScreen(ref p1);
-
- g.DrawLine(pen, p0, p1);
- }
- }
- }
- }
-}
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+//
+// -----------------------------------------------------------------------
+
+namespace TriangleNet.Rendering.GDI
+{
+ using System.Drawing;
+
+ ///
+ /// Renders a mesh.
+ ///
+ public class MeshRenderer
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public MeshRenderer()
+ {
+ }
+
+ public Graphics RenderTarget { get; set; }
+
+ public IRenderContext Context { get; set; }
+
+ public void RenderPoints(float[] points, int size, int limit = 0)
+ {
+ int n = points.Length / size;
+ int m = limit > 0 ? limit : n;
+
+ using var Point = new SolidBrush(Context.ColorManager.Point);
+ using var SteinerPoint = new SolidBrush(Context.ColorManager.SteinerPoint);
+
+ // Draw unchanged points
+ RenderPoints(points, size, 0, m, Point);
+
+ // Draw new (Steiner) points
+ if (limit > 0)
+ {
+ RenderPoints(points, size, m, n, SteinerPoint);
+ }
+ }
+
+ public void RenderPoints(float[] points, int size, int start, int end, Brush brush)
+ {
+ var g = this.RenderTarget;
+ var zoom = this.Context.Zoom;
+
+ int i, k, n = points.Length / size;
+ PointF p = new PointF();
+
+ // Render points
+ for (i = start; i < end; i++)
+ {
+ k = size * i;
+
+ p.X = points[k];
+ p.Y = points[k + 1];
+
+ if (zoom.Viewport.Contains(p))
+ {
+ zoom.NdcToScreen(ref p);
+ g.FillEllipse(brush, p.X - 1.5f, p.Y - 1.5f, 3, 3);
+ }
+ }
+ }
+
+ public void RenderSegments(float[] points, int[] indices, Pen pen)
+ {
+ RenderLines(points, indices, pen);
+ }
+
+ public void RenderEdges(float[] points, int[] indices, Pen pen)
+ {
+ RenderLines(points, indices, pen);
+ }
+
+ public void RenderElements(float[] points, int[] indices, int size, int[] partition)
+ {
+ var g = this.RenderTarget;
+ var zoom = this.Context.Zoom;
+
+ int n = indices.Length / size;
+ int k0, k1, k2;
+
+ var tri = new PointF[size];
+
+ bool filled = partition != null;
+
+ var brushes = filled ? Helper.GetBrushDictionary(Context.ColorManager.ColorDictionary) : null;
+
+ // TODO: remove hard-coded color
+ var pen = new Pen(Color.FromArgb(20, 20, 20));
+
+ // Draw triangles
+ for (int i = 0; i < n; i++)
+ {
+ k0 = 2 * indices[3 * i];
+ k1 = 2 * indices[3 * i + 1];
+ k2 = 2 * indices[3 * i + 2];
+
+ tri[0].X = points[k0];
+ tri[0].Y = points[k0 + 1];
+
+ tri[1].X = points[k1];
+ tri[1].Y = points[k1 + 1];
+
+ tri[2].X = points[k2];
+ tri[2].Y = points[k2 + 1];
+
+ if (zoom.Viewport.Intersects(tri[0], tri[1], tri[2]))
+ {
+ zoom.NdcToScreen(ref tri[0]);
+ zoom.NdcToScreen(ref tri[1]);
+ zoom.NdcToScreen(ref tri[2]);
+
+ if (filled)
+ {
+ var b = brushes[partition[i]];
+
+ if (b.Color.A > 0)
+ {
+ g.FillPolygon(b, tri);
+ }
+ }
+ else
+ {
+ g.DrawPolygon(pen, tri);
+ }
+ }
+ }
+
+ pen.Dispose();
+
+ if (filled)
+ {
+ Helper.Dispose(brushes);
+ }
+ }
+
+ public void RenderLines(float[] points, int[] indices, Pen pen)
+ {
+ var g = this.RenderTarget;
+ var zoom = this.Context.Zoom;
+
+ int n = indices.Length / 2;
+ int k0, k1;
+
+ PointF p0 = new PointF();
+ PointF p1 = new PointF();
+
+ // Draw edges
+ for (int i = 0; i < n; i++)
+ {
+ k0 = 2 * indices[2 * i];
+ k1 = 2 * indices[2 * i + 1];
+
+ p0.X = points[k0];
+ p0.Y = points[k0 + 1];
+
+ p1.X = points[k1];
+ p1.Y = points[k1 + 1];
+
+ if (zoom.Viewport.Intersects(p0, p1))
+ {
+ zoom.NdcToScreen(ref p0);
+ zoom.NdcToScreen(ref p1);
+
+ g.DrawLine(pen, p0, p1);
+ }
+ }
+ }
+ }
+}
diff --git a/Triangle.NET/Triangle.Rendering/GDI/Native/GradientFillMode.cs b/src/Triangle.Rendering.GDI/Native/GradientFillMode.cs
similarity index 97%
rename from Triangle.NET/Triangle.Rendering/GDI/Native/GradientFillMode.cs
rename to src/Triangle.Rendering.GDI/Native/GradientFillMode.cs
index 7b6ba25..9db4ac9 100644
--- a/Triangle.NET/Triangle.Rendering/GDI/Native/GradientFillMode.cs
+++ b/src/Triangle.Rendering.GDI/Native/GradientFillMode.cs
@@ -1,35 +1,35 @@
-
-namespace TriangleNet.Rendering.GDI.Native
-{
- using System;
-
- ///
- /// Specifies gradient fill mode
- ///
- [Flags]
- internal enum GradientFillMode : uint
- {
- ///
- /// In this mode, two endpoints describe a rectangle. The rectangle is defined
- /// to have a constant color (specified by the TRIVERTEX structure) for the
- /// left and right edges. GDI interpolates the color from the left to right
- /// edge and fills the interior
- ///
- GRADIENT_FILL_RECT_H = 0,
- ///
- /// In this mode, two endpoints describe a rectangle. The rectangle is
- /// defined to have a constant color (specified by the TRIVERTEX structure)
- /// for the top and bottom edges. GDI interpolates the color from the top
- /// to bottom edge and fills the interior
- ///
- GRADIENT_FILL_RECT_V = 1,
- ///
- /// In this mode, an array of TRIVERTEX structures is passed to GDI
- /// along with a list of array indexes that describe separate triangles.
- /// GDI performs linear interpolation between triangle vertices and fills
- /// the interior. Drawing is done directly in 24- and 32-bpp modes.
- /// Dithering is performed in 16-, 8-, 4-, and 1-bpp mode
- ///
- GRADIENT_FILL_TRIANGLE = 2
- }
-}
+
+namespace TriangleNet.Rendering.GDI.Native
+{
+ using System;
+
+ ///
+ /// Specifies gradient fill mode
+ ///
+ [Flags]
+ internal enum GradientFillMode : uint
+ {
+ ///
+ /// In this mode, two endpoints describe a rectangle. The rectangle is defined
+ /// to have a constant color (specified by the TRIVERTEX structure) for the
+ /// left and right edges. GDI interpolates the color from the left to right
+ /// edge and fills the interior
+ ///
+ GRADIENT_FILL_RECT_H = 0,
+ ///
+ /// In this mode, two endpoints describe a rectangle. The rectangle is
+ /// defined to have a constant color (specified by the TRIVERTEX structure)
+ /// for the top and bottom edges. GDI interpolates the color from the top
+ /// to bottom edge and fills the interior
+ ///
+ GRADIENT_FILL_RECT_V = 1,
+ ///
+ /// In this mode, an array of TRIVERTEX structures is passed to GDI
+ /// along with a list of array indexes that describe separate triangles.
+ /// GDI performs linear interpolation between triangle vertices and fills
+ /// the interior. Drawing is done directly in 24- and 32-bpp modes.
+ /// Dithering is performed in 16-, 8-, 4-, and 1-bpp mode
+ ///
+ GRADIENT_FILL_TRIANGLE = 2
+ }
+}
diff --git a/Triangle.NET/Triangle.Rendering/GDI/Native/GradientRect.cs b/src/Triangle.Rendering.GDI/Native/GradientRect.cs
similarity index 96%
rename from Triangle.NET/Triangle.Rendering/GDI/Native/GradientRect.cs
rename to src/Triangle.Rendering.GDI/Native/GradientRect.cs
index f617645..9511c00 100644
--- a/Triangle.NET/Triangle.Rendering/GDI/Native/GradientRect.cs
+++ b/src/Triangle.Rendering.GDI/Native/GradientRect.cs
@@ -1,28 +1,28 @@
-
-namespace TriangleNet.Rendering.GDI.Native
-{
- using System.Runtime.InteropServices;
-
- ///
- /// The GRADIENT_RECT structure specifies the index of two vertices in the
- /// pVertex array in the GradientFill function. These two vertices form the
- /// upper-left and lower-right boundaries of a rectangle.
- ///
- ///
- /// http://msdn.microsoft.com/en-us/library/windows/desktop/dd144958.aspx
- ///
- [StructLayout(LayoutKind.Sequential)]
- internal struct GradientRect
- {
- ///
- /// The upper-left corner of a rectangle.
- ///
- public uint UpperLeft;
-
- ///
- /// The lower-right corner of a rectangle.
- ///
- public uint LowerRight;
- }
-
-}
+
+namespace TriangleNet.Rendering.GDI.Native
+{
+ using System.Runtime.InteropServices;
+
+ ///
+ /// The GRADIENT_RECT structure specifies the index of two vertices in the
+ /// pVertex array in the GradientFill function. These two vertices form the
+ /// upper-left and lower-right boundaries of a rectangle.
+ ///
+ ///
+ /// http://msdn.microsoft.com/en-us/library/windows/desktop/dd144958.aspx
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct GradientRect
+ {
+ ///
+ /// The upper-left corner of a rectangle.
+ ///
+ public uint UpperLeft;
+
+ ///
+ /// The lower-right corner of a rectangle.
+ ///
+ public uint LowerRight;
+ }
+
+}
diff --git a/Triangle.NET/Triangle.Rendering/GDI/Native/GradientTriangle.cs b/src/Triangle.Rendering.GDI/Native/GradientTriangle.cs
similarity index 96%
rename from Triangle.NET/Triangle.Rendering/GDI/Native/GradientTriangle.cs
rename to src/Triangle.Rendering.GDI/Native/GradientTriangle.cs
index dd64867..f6ae91b 100644
--- a/Triangle.NET/Triangle.Rendering/GDI/Native/GradientTriangle.cs
+++ b/src/Triangle.Rendering.GDI/Native/GradientTriangle.cs
@@ -1,32 +1,32 @@
-
-namespace TriangleNet.Rendering.GDI.Native
-{
- using System.Runtime.InteropServices;
-
- ///
- /// The GRADIENT_TRIANGLE structure specifies the index of three
- /// vertices in the pVertex array in the GradientFill function.
- /// These three vertices form one triangle
- ///
- ///
- /// http://msdn.microsoft.com/en-us/library/windows/desktop/dd144959.aspx
- ///
- [StructLayout(LayoutKind.Sequential)]
- internal struct GradientTriangle
- {
- ///
- /// The first point of the triangle where sides intersect.
- ///
- public uint Vertex1;
-
- ///
- /// The second point of the triangle where sides intersect.
- ///
- public uint Vertex2;
-
- ///
- /// The third point of the triangle where sides intersect.
- ///
- public uint Vertex3;
- }
-}
+
+namespace TriangleNet.Rendering.GDI.Native
+{
+ using System.Runtime.InteropServices;
+
+ ///
+ /// The GRADIENT_TRIANGLE structure specifies the index of three
+ /// vertices in the pVertex array in the GradientFill function.
+ /// These three vertices form one triangle
+ ///
+ ///
+ /// http://msdn.microsoft.com/en-us/library/windows/desktop/dd144959.aspx
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct GradientTriangle
+ {
+ ///
+ /// The first point of the triangle where sides intersect.
+ ///
+ public uint Vertex1;
+
+ ///
+ /// The second point of the triangle where sides intersect.
+ ///
+ public uint Vertex2;
+
+ ///
+ /// The third point of the triangle where sides intersect.
+ ///
+ public uint Vertex3;
+ }
+}
diff --git a/Triangle.NET/Triangle.Rendering/GDI/Native/NativeMethods.cs b/src/Triangle.Rendering.GDI/Native/NativeMethods.cs
similarity index 97%
rename from Triangle.NET/Triangle.Rendering/GDI/Native/NativeMethods.cs
rename to src/Triangle.Rendering.GDI/Native/NativeMethods.cs
index 2a625f4..46e4dea 100644
--- a/Triangle.NET/Triangle.Rendering/GDI/Native/NativeMethods.cs
+++ b/src/Triangle.Rendering.GDI/Native/NativeMethods.cs
@@ -1,90 +1,90 @@
-
-namespace TriangleNet.Rendering.GDI.Native
-{
- using System;
- using System.Runtime.InteropServices;
-
- ///
- /// PInvoke signatures for GradientFill methods.
- ///
- ///
- /// Minimum requirements: Windows 2000 Professional
- ///
- /// http://msdn.microsoft.com/en-us/library/windows/desktop/dd144957.aspx
- ///
- internal static class NativeMethods
- {
- ///
- /// The GradientFill function fills rectangle and triangle structures
- ///
- /// Handle to the destination device contex
- /// Array of TRIVERTEX structures that each define a triangle vertex
- /// The number of vertices in pVertex
- /// Array of elements
- /// The number of elements in pMesh
- /// Specifies gradient fill mode
- /// If the function succeeds, the return value is true, false
- public static bool GradientFill([In] IntPtr hdc, TriVertex[] pVertex, uint nVertex, uint[] pMesh, uint nMesh,
- GradientFillMode ulMode)
- {
- return Native.GradientFill(hdc, pVertex, nVertex, pMesh, nMesh, ulMode);
- }
-
- ///
- /// The GradientFill function fills rectangle and triangle structures
- ///
- /// Handle to the destination device contex
- /// Array of TRIVERTEX structures that each define a triangle vertex
- /// The number of vertices in pVertex
- /// Array of GRADIENT_TRIANGLE structures in triangle mode
- /// The number of elements in pMesh
- /// Specifies gradient fill mode
- /// If the function succeeds, the return value is true, false
- public static bool GradientFill([In] IntPtr hdc, TriVertex[] pVertex, uint nVertex, GradientTriangle[] pMesh,
- uint nMesh, GradientFillMode ulMode)
- {
- return Native.GradientFill(hdc, pVertex, nVertex, pMesh, nMesh, ulMode);
- }
-
- ///
- /// The GradientFill function fills rectangle and triangle structures
- ///
- /// Handle to the destination device contex
- /// Array of TRIVERTEX structures that each define a triangle vertex
- /// The number of vertices in pVertex
- /// an array of GRADIENT_RECT structures in rectangle mode
- /// The number of elements in pMesh
- /// Specifies gradient fill mode
- /// If the function succeeds, the return value is true, false
- public static bool GradientFill([In] IntPtr hdc, TriVertex[] pVertex, uint nVertex, GradientRect[] pMesh,
- uint nMesh, GradientFillMode ulMode)
- {
- return Native.GradientFill(hdc, pVertex, nVertex, pMesh, nMesh, ulMode);
- }
-
- #region Nested type: Native
-
- internal class Native
- {
- [DllImport("msimg32.dll", EntryPoint = "GradientFill", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool GradientFill([In] IntPtr hdc,
- [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Struct, SizeParamIndex = 2)] TriVertex[] pVertex,
- uint nVertex, uint[] pMesh, uint nMesh, GradientFillMode ulMode);
-
- [DllImport("msimg32.dll", EntryPoint = "GradientFill", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool GradientFill([In] IntPtr hdc,
- [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Struct, SizeParamIndex = 2)] TriVertex[] pVertex,
- uint nVertex, GradientRect[] pMesh, uint nMesh, GradientFillMode ulMode);
-
- [DllImport("msimg32.dll", EntryPoint = "GradientFill", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool GradientFill([In] IntPtr hdc,
- [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Struct, SizeParamIndex = 2)] TriVertex[] pVertex,
- uint nVertex, GradientTriangle[] pMesh, uint nMesh, GradientFillMode ulMode);
- }
-
- #endregion
- }
+
+namespace TriangleNet.Rendering.GDI.Native
+{
+ using System;
+ using System.Runtime.InteropServices;
+
+ ///
+ /// PInvoke signatures for GradientFill methods.
+ ///
+ ///
+ /// Minimum requirements: Windows 2000 Professional
+ ///
+ /// http://msdn.microsoft.com/en-us/library/windows/desktop/dd144957.aspx
+ ///
+ internal static class NativeMethods
+ {
+ ///
+ /// The GradientFill function fills rectangle and triangle structures
+ ///
+ /// Handle to the destination device context
+ /// Array of TRIVERTEX structures that each define a triangle vertex
+ /// The number of vertices in pVertex
+ /// Array of elements
+ /// The number of elements in pMesh
+ /// Specifies gradient fill mode
+ /// If the function succeeds, the return value is true, false
+ public static bool GradientFill([In] IntPtr hdc, TriVertex[] pVertex, uint nVertex, uint[] pMesh, uint nMesh,
+ GradientFillMode ulMode)
+ {
+ return Native.GradientFill(hdc, pVertex, nVertex, pMesh, nMesh, ulMode);
+ }
+
+ ///
+ /// The GradientFill function fills rectangle and triangle structures
+ ///
+ /// Handle to the destination device context
+ /// Array of TRIVERTEX structures that each define a triangle vertex
+ /// The number of vertices in pVertex
+ /// Array of GRADIENT_TRIANGLE structures in triangle mode
+ /// The number of elements in pMesh
+ /// Specifies gradient fill mode
+ /// If the function succeeds, the return value is true, false
+ public static bool GradientFill([In] IntPtr hdc, TriVertex[] pVertex, uint nVertex, GradientTriangle[] pMesh,
+ uint nMesh, GradientFillMode ulMode)
+ {
+ return Native.GradientFill(hdc, pVertex, nVertex, pMesh, nMesh, ulMode);
+ }
+
+ ///
+ /// The GradientFill function fills rectangle and triangle structures
+ ///
+ /// Handle to the destination device context
+ /// Array of TRIVERTEX structures that each define a triangle vertex
+ /// The number of vertices in pVertex
+ /// an array of GRADIENT_RECT structures in rectangle mode
+ /// The number of elements in pMesh
+ /// Specifies gradient fill mode
+ /// If the function succeeds, the return value is true, false
+ public static bool GradientFill([In] IntPtr hdc, TriVertex[] pVertex, uint nVertex, GradientRect[] pMesh,
+ uint nMesh, GradientFillMode ulMode)
+ {
+ return Native.GradientFill(hdc, pVertex, nVertex, pMesh, nMesh, ulMode);
+ }
+
+ #region Nested type: Native
+
+ internal class Native
+ {
+ [DllImport("msimg32.dll", EntryPoint = "GradientFill", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool GradientFill([In] IntPtr hdc,
+ [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Struct, SizeParamIndex = 2)] TriVertex[] pVertex,
+ uint nVertex, uint[] pMesh, uint nMesh, GradientFillMode ulMode);
+
+ [DllImport("msimg32.dll", EntryPoint = "GradientFill", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool GradientFill([In] IntPtr hdc,
+ [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Struct, SizeParamIndex = 2)] TriVertex[] pVertex,
+ uint nVertex, GradientRect[] pMesh, uint nMesh, GradientFillMode ulMode);
+
+ [DllImport("msimg32.dll", EntryPoint = "GradientFill", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool GradientFill([In] IntPtr hdc,
+ [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Struct, SizeParamIndex = 2)] TriVertex[] pVertex,
+ uint nVertex, GradientTriangle[] pMesh, uint nMesh, GradientFillMode ulMode);
+ }
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/Triangle.NET/Triangle.Rendering/GDI/Native/TriVertex.cs b/src/Triangle.Rendering.GDI/Native/TriVertex.cs
similarity index 96%
rename from Triangle.NET/Triangle.Rendering/GDI/Native/TriVertex.cs
rename to src/Triangle.Rendering.GDI/Native/TriVertex.cs
index 0279447..121c637 100644
--- a/Triangle.NET/Triangle.Rendering/GDI/Native/TriVertex.cs
+++ b/src/Triangle.Rendering.GDI/Native/TriVertex.cs
@@ -1,45 +1,45 @@
-
-namespace TriangleNet.Rendering.GDI.Native
-{
- using System.Runtime.InteropServices;
-
- ///
- /// The TRIVERTEX structure contains color information and position information.
- ///
- ///
- /// http://msdn.microsoft.com/en-us/library/windows/desktop/dd145142.aspx
- ///
- [StructLayout(LayoutKind.Sequential)]
- internal struct TriVertex
- {
- ///
- /// The x-coordinate, in logical units, of the upper-left corner of the rectangle
- ///
- public int x;
-
- ///
- /// The y-coordinate, in logical units, of the upper-left corner of the rectangle
- ///
- public int y;
-
- ///
- /// The color information at the point of x, y
- ///
- public ushort Red;
-
- ///
- /// The color information at the point of x, y
- ///
- public ushort Green;
-
- ///
- /// The color information at the point of x, y
- ///
- public ushort Blue;
-
- ///
- /// The color information at the point of x, y
- ///
- public ushort Alpha;
- }
-}
+
+namespace TriangleNet.Rendering.GDI.Native
+{
+ using System.Runtime.InteropServices;
+
+ ///
+ /// The TRIVERTEX structure contains color information and position information.
+ ///
+ ///
+ /// http://msdn.microsoft.com/en-us/library/windows/desktop/dd145142.aspx
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct TriVertex
+ {
+ ///
+ /// The x-coordinate, in logical units, of the upper-left corner of the rectangle
+ ///
+ public int x;
+
+ ///
+ /// The y-coordinate, in logical units, of the upper-left corner of the rectangle
+ ///
+ public int y;
+
+ ///
+ /// The color information at the point of x, y
+ ///
+ public ushort Red;
+
+ ///
+ /// The color information at the point of x, y
+ ///
+ public ushort Green;
+
+ ///
+ /// The color information at the point of x, y
+ ///
+ public ushort Blue;
+
+ ///
+ /// The color information at the point of x, y
+ ///
+ public ushort Alpha;
+ }
+}
diff --git a/Triangle.NET/Triangle.Rendering/GDI/RenderControl.cs b/src/Triangle.Rendering.GDI/RenderControl.cs
similarity index 90%
rename from Triangle.NET/Triangle.Rendering/GDI/RenderControl.cs
rename to src/Triangle.Rendering.GDI/RenderControl.cs
index 2dfda4a..c85e680 100644
--- a/Triangle.NET/Triangle.Rendering/GDI/RenderControl.cs
+++ b/src/Triangle.Rendering.GDI/RenderControl.cs
@@ -1,252 +1,251 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace TriangleNet.Rendering.GDI
-{
- using System;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Drawing.Text;
- using System.Globalization;
- using System.Windows.Forms;
-
- ///
- /// Renders a mesh using GDI.
- ///
- public class RenderControl : Control, IRenderControl
- {
- // Rendering stuff
- private BufferedGraphics buffer;
- private BufferedGraphicsContext context;
-
- //ColorManager renderColors;
-
- bool initialized = false;
-
- string coordinate = String.Empty;
-
- Timer timer;
-
- ///
- /// Initializes a new instance of the class.
- ///
- public RenderControl()
- {
- //this.SetStyle(ControlStyles.UserPaint, true);
- //this.SetStyle(ControlStyles.OptimizedDoubleBuffer, false);
- //this.SetStyle(ControlStyles.Selectable, true);
- this.SetStyle(ControlStyles.ResizeRedraw, true);
-
- //renderColors = ColorManager.Default();
-
- this.BackColor = Color.Black;
-
- context = BufferedGraphicsManager.Current;// new BufferedGraphicsContext();
-
- timer = new Timer();
- timer.Interval = 3000;
- timer.Tick += (sender, e) =>
- {
- timer.Stop();
- coordinate = String.Empty;
- this.Invalidate();
- };
- }
-
- public IRenderer Renderer { get; set; }
-
- ///
- /// Initialize the graphics buffer (should be called in the forms load event).
- ///
- public void Initialize()
- {
- //zoom.Initialize(this.ClientRectangle);
- InitializeBuffer();
-
- initialized = true;
-
- this.Invalidate();
- }
-
- public override void Refresh()
- {
- this.Render();
- }
-
- ///
- /// Update graphics buffer and zoom after a resize.
- ///
- public void HandleResize()
- {
- var zoom = this.Renderer.Context.Zoom;
-
- zoom.Resize(this.ClientRectangle);
- InitializeBuffer();
- }
-
- private void InitializeBuffer()
- {
- if (this.Width > 0 && this.Height > 0)
- {
- if (buffer != null)
- {
- if (this.ClientRectangle == buffer.Graphics.VisibleClipBounds)
- {
- this.Invalidate();
-
- // Bounds didn't change. Probably we just restored the
- // window from minimized state.
- return;
- }
-
- buffer.Dispose();
- }
-
- //buffer = context.Allocate(Graphics.FromHwnd(this.Handle), this.ClientRectangle);
- buffer = context.Allocate(this.CreateGraphics(), this.ClientRectangle);
-
- if (initialized)
- {
- this.Render();
- }
- }
- }
-
- private void Render()
- {
- coordinate = String.Empty;
-
- if (buffer == null)
- {
- return;
- }
-
- var g = buffer.Graphics;
- var renderer = this.Renderer as LayerRenderer;
-
- g.Clear(renderer.Context.ColorManager.Background);
-
- if (!initialized || renderer == null)
- {
- return;
- }
-
- g.SmoothingMode = SmoothingMode.AntiAlias;
-
- renderer.RenderTarget = g;
- renderer.Render();
-
- this.Invalidate();
- }
-
- #region Protected overrides
-
- protected override void OnPaint(PaintEventArgs e)
- {
- if (!initialized)
- {
- base.OnPaint(e);
- return;
- }
-
- buffer.Render();
-
- if (!String.IsNullOrEmpty(coordinate) && Renderer.Context.HasData)
- {
- Graphics g = e.Graphics;
- g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
- g.DrawString(coordinate, this.Font, Brushes.White, 10, 10);
- }
- }
-
- protected override void OnPaintBackground(PaintEventArgs pevent)
- {
- // Do nothing
- if (!initialized)
- {
- base.OnPaintBackground(pevent);
- }
- }
-
- protected override void OnMouseWheel(MouseEventArgs e)
- {
- if (!initialized) return;
-
- var zoom = this.Renderer.Context.Zoom;
-
- if (zoom.Zoom(e.Delta, (float)e.X / Width, (float)e.Y / Height))
- {
- // Redraw
- this.Render();
- }
- }
-
- protected override void OnMouseClick(MouseEventArgs e)
- {
- // We need to manually set the focus to get proper handling of
- // the KeyUp and MouseWheel events.
- this.Focus();
-
- if (!initialized) return;
-
- var zoom = this.Renderer.Context.Zoom;
-
- if (e.Button == MouseButtons.Middle)
- {
- zoom.Reset();
- this.Render();
- }
- else if (e.Button == MouseButtons.Left)
- {
- timer.Stop();
-
- PointF c = new PointF((float)e.X / Width, (float)e.Y / Height);
- zoom.ScreenToWorld(ref c);
- coordinate = String.Format(NumberFormatInfo.InvariantInfo,
- "X:{0} Y:{1}", c.X, c.Y);
-
- this.Invalidate();
-
- timer.Start();
- }
- }
-
- protected override void OnKeyUp(KeyEventArgs e)
- {
- if (!initialized) return;
-
- var zoom = this.Renderer.Context.Zoom;
-
- bool redraw = false;
-
- if (e.KeyCode == Keys.Up)
- {
- redraw = zoom.Translate(0, 1);
- }
- else if (e.KeyCode == Keys.Down)
- {
- redraw = zoom.Translate(0, -1);
- }
- else if (e.KeyCode == Keys.Left)
- {
- redraw = zoom.Translate(-1, 0);
- }
- else if (e.KeyCode == Keys.Right)
- {
- redraw = zoom.Translate(1, 0);
- }
-
- if (redraw)
- {
- this.Render();
- }
-
- e.Handled = true;
- }
-
- #endregion
- }
-}
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+//
+// -----------------------------------------------------------------------
+
+namespace TriangleNet.Rendering.GDI
+{
+ using System.Drawing;
+ using System.Drawing.Drawing2D;
+ using System.Drawing.Text;
+ using System.Globalization;
+ using System.Windows.Forms;
+
+ ///
+ /// Renders a mesh using GDI.
+ ///
+ public class RenderControl : Control, IRenderControl
+ {
+ // Rendering stuff
+ private BufferedGraphics buffer;
+ private BufferedGraphicsContext context;
+
+ //ColorManager renderColors;
+
+ bool initialized = false;
+
+ string coordinate = string.Empty;
+
+ Timer timer;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public RenderControl()
+ {
+ //this.SetStyle(ControlStyles.UserPaint, true);
+ //this.SetStyle(ControlStyles.OptimizedDoubleBuffer, false);
+ //this.SetStyle(ControlStyles.Selectable, true);
+ this.SetStyle(ControlStyles.ResizeRedraw, true);
+
+ //renderColors = ColorManager.Default();
+
+ this.BackColor = Color.Black;
+
+ context = BufferedGraphicsManager.Current;// new BufferedGraphicsContext();
+
+ timer = new Timer();
+ timer.Interval = 3000;
+ timer.Tick += (sender, e) =>
+ {
+ timer.Stop();
+ coordinate = string.Empty;
+ this.Invalidate();
+ };
+ }
+
+ public IRenderer Renderer { get; set; }
+
+ ///
+ /// Initialize the graphics buffer (should be called in the forms load event).
+ ///
+ public void Initialize()
+ {
+ //zoom.Initialize(this.ClientRectangle);
+ InitializeBuffer();
+
+ initialized = true;
+
+ this.Invalidate();
+ }
+
+ public override void Refresh()
+ {
+ this.Render();
+ }
+
+ ///
+ /// Update graphics buffer and zoom after a resize.
+ ///
+ public void HandleResize()
+ {
+ var zoom = this.Renderer.Context.Zoom;
+
+ zoom.Resize(this.ClientRectangle);
+ InitializeBuffer();
+ }
+
+ private void InitializeBuffer()
+ {
+ if (this.Width > 0 && this.Height > 0)
+ {
+ if (buffer != null)
+ {
+ if (this.ClientRectangle == buffer.Graphics.VisibleClipBounds)
+ {
+ this.Invalidate();
+
+ // Bounds didn't change. Probably we just restored the
+ // window from minimized state.
+ return;
+ }
+
+ buffer.Dispose();
+ }
+
+ //buffer = context.Allocate(Graphics.FromHwnd(this.Handle), this.ClientRectangle);
+ buffer = context.Allocate(this.CreateGraphics(), this.ClientRectangle);
+
+ if (initialized)
+ {
+ this.Render();
+ }
+ }
+ }
+
+ private void Render()
+ {
+ coordinate = string.Empty;
+
+ if (buffer == null)
+ {
+ return;
+ }
+
+ var g = buffer.Graphics;
+ var renderer = this.Renderer as LayerRenderer;
+
+ g.Clear(renderer.Context.ColorManager.Background);
+
+ if (!initialized || renderer == null)
+ {
+ return;
+ }
+
+ g.SmoothingMode = SmoothingMode.AntiAlias;
+
+ renderer.RenderTarget = g;
+ renderer.Render();
+
+ this.Invalidate();
+ }
+
+ #region Protected overrides
+
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ if (!initialized)
+ {
+ base.OnPaint(e);
+ return;
+ }
+
+ buffer.Render();
+
+ if (!string.IsNullOrEmpty(coordinate) && Renderer.Context.HasData)
+ {
+ Graphics g = e.Graphics;
+ g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
+ TextRenderer.DrawText(g, coordinate, Font, new Point(10, 10), Color.White);
+ }
+ }
+
+ protected override void OnPaintBackground(PaintEventArgs pevent)
+ {
+ // Do nothing
+ if (!initialized)
+ {
+ base.OnPaintBackground(pevent);
+ }
+ }
+
+ protected override void OnMouseWheel(MouseEventArgs e)
+ {
+ if (!initialized) return;
+
+ var zoom = this.Renderer.Context.Zoom;
+
+ if (zoom.Zoom(e.Delta, (float)e.X / Width, (float)e.Y / Height))
+ {
+ // Redraw
+ this.Render();
+ }
+ }
+
+ protected override void OnMouseClick(MouseEventArgs e)
+ {
+ // We need to manually set the focus to get proper handling of
+ // the KeyUp and MouseWheel events.
+ this.Focus();
+
+ if (!initialized) return;
+
+ var zoom = this.Renderer.Context.Zoom;
+
+ if (e.Button == MouseButtons.Middle)
+ {
+ zoom.Reset();
+ this.Render();
+ }
+ else if (e.Button == MouseButtons.Left)
+ {
+ timer.Stop();
+
+ PointF c = new PointF((float)e.X / Width, (float)e.Y / Height);
+ zoom.ScreenToWorld(c, out double x, out double y);
+ coordinate = string.Format(NumberFormatInfo.InvariantInfo,
+ "X:{0} Y:{1}", x, y);
+
+ this.Invalidate();
+
+ timer.Start();
+ }
+ }
+
+ protected override void OnKeyUp(KeyEventArgs e)
+ {
+ if (!initialized) return;
+
+ var zoom = this.Renderer.Context.Zoom;
+
+ bool redraw = false;
+
+ if (e.KeyCode == Keys.Up)
+ {
+ redraw = zoom.Translate(0, 1);
+ }
+ else if (e.KeyCode == Keys.Down)
+ {
+ redraw = zoom.Translate(0, -1);
+ }
+ else if (e.KeyCode == Keys.Left)
+ {
+ redraw = zoom.Translate(-1, 0);
+ }
+ else if (e.KeyCode == Keys.Right)
+ {
+ redraw = zoom.Translate(1, 0);
+ }
+
+ if (redraw)
+ {
+ this.Render();
+ }
+
+ e.Handled = true;
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Triangle.Rendering.GDI/Triangle.Rendering.GDI.csproj b/src/Triangle.Rendering.GDI/Triangle.Rendering.GDI.csproj
new file mode 100644
index 0000000..d1db388
--- /dev/null
+++ b/src/Triangle.Rendering.GDI/Triangle.Rendering.GDI.csproj
@@ -0,0 +1,17 @@
+
+
+
+ Library
+ net6.0-windows
+ true
+ TriangleNet.Rendering.GDI
+ Triangle.Rendering.GDI
+ AnyCPU;x64
+
+
+
+
+
+
+
+
diff --git a/src/Triangle.Rendering/Buffer/BufferBase.cs b/src/Triangle.Rendering/Buffer/BufferBase.cs
new file mode 100644
index 0000000..fe14212
--- /dev/null
+++ b/src/Triangle.Rendering/Buffer/BufferBase.cs
@@ -0,0 +1,32 @@
+
+namespace TriangleNet.Rendering.Buffer
+{
+ public abstract class BufferBase : IBuffer where T : struct
+ {
+ protected T[] data;
+ protected int size;
+
+ public BufferBase(int capacity, int size)
+ : this(new T[capacity], size)
+ {
+ }
+
+ public BufferBase(T[] data, int size)
+ {
+ this.data = data;
+ this.size = size;
+ }
+
+ ///
+ public T[] Data => data;
+
+ ///
+ public int Count => data == null ? 0 : data.Length;
+
+ ///
+ public abstract int Size { get; }
+
+ ///
+ public abstract BufferTarget Target { get; }
+ }
+}
diff --git a/src/Triangle.Rendering/Buffer/ColorBuffer.cs b/src/Triangle.Rendering/Buffer/ColorBuffer.cs
new file mode 100644
index 0000000..e074f1e
--- /dev/null
+++ b/src/Triangle.Rendering/Buffer/ColorBuffer.cs
@@ -0,0 +1,34 @@
+
+namespace TriangleNet.Rendering.Buffer
+{
+ using System.Drawing;
+
+ public class ColorBuffer : BufferBase
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The buffer capacity.
+ /// The size of one element in the buffer (i.e. 2 for 2D points)
+ public ColorBuffer(int capacity, int size)
+ : base(capacity, size)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The buffer data.
+ /// The size of one element in the buffer (i.e. 2 for 2D points)
+ public ColorBuffer(Color[] data, int size)
+ : base(data, size)
+ {
+ }
+
+ ///
+ public override int Size => 1;
+
+ ///
+ public override BufferTarget Target => BufferTarget.ColorBuffer;
+ }
+}
diff --git a/Triangle.NET/Triangle.Rendering/Buffer/IBuffer.cs b/src/Triangle.Rendering/Buffer/IBuffer.cs
similarity index 95%
rename from Triangle.NET/Triangle.Rendering/Buffer/IBuffer.cs
rename to src/Triangle.Rendering/Buffer/IBuffer.cs
index a39ab3e..06caeb3 100644
--- a/Triangle.NET/Triangle.Rendering/Buffer/IBuffer.cs
+++ b/src/Triangle.Rendering/Buffer/IBuffer.cs
@@ -1,34 +1,34 @@
-
-namespace TriangleNet.Rendering.Buffer
-{
- public enum BufferTarget : byte
- {
- ColorBuffer,
- IndexBuffer,
- VertexBuffer
- }
-
- public interface IBuffer where T : struct
- {
- ///
- /// Gets the contents of the buffer.
- ///
- T[] Data { get; }
-
- ///
- /// Gets the size of the buffer.
- ///
- int Count { get; }
-
- ///
- /// Gets the size of one element in the buffer (i.e. 2 for 2D points
- /// or 3 for triangles).
- ///
- int Size { get; }
-
- ///
- /// Gets the buffer target (vertices or indices).
- ///
- BufferTarget Target { get; }
- }
-}
+
+namespace TriangleNet.Rendering.Buffer
+{
+ public enum BufferTarget : byte
+ {
+ ColorBuffer,
+ IndexBuffer,
+ VertexBuffer
+ }
+
+ public interface IBuffer where T : struct
+ {
+ ///
+ /// Gets the contents of the buffer.
+ ///
+ T[] Data { get; }
+
+ ///
+ /// Gets the size of the buffer.
+ ///
+ int Count { get; }
+
+ ///
+ /// Gets the size of one element in the buffer (i.e. 2 for 2D points
+ /// or 3 for triangles).
+ ///
+ int Size { get; }
+
+ ///
+ /// Gets the buffer target (vertices or indices).
+ ///
+ BufferTarget Target { get; }
+ }
+}
diff --git a/src/Triangle.Rendering/Buffer/IndexBuffer.cs b/src/Triangle.Rendering/Buffer/IndexBuffer.cs
new file mode 100644
index 0000000..a9a2152
--- /dev/null
+++ b/src/Triangle.Rendering/Buffer/IndexBuffer.cs
@@ -0,0 +1,80 @@
+
+using System.Collections.Generic;
+using System.Linq;
+using TriangleNet.Geometry;
+using TriangleNet.Topology;
+
+namespace TriangleNet.Rendering.Buffer
+{
+ public class IndexBuffer : BufferBase
+ {
+ #region Static methods
+
+ public static IBuffer Create(IEnumerable edges, int size)
+ {
+ var buffer = new IndexBuffer(size * edges.Count(), size);
+
+ var data = buffer.Data;
+
+ int i = 0;
+
+ foreach (var e in edges)
+ {
+ data[size * i + 0] = e.P0;
+ data[size * i + 1] = e.P1;
+
+ i++;
+ }
+
+ return buffer;
+ }
+
+ public static IBuffer Create(ICollection elements, int size)
+ {
+ var buffer = new IndexBuffer(size * elements.Count, size);
+
+ var data = buffer.Data;
+
+ int i = 0;
+
+ foreach (var e in elements)
+ {
+ data[size * i + 0] = e.GetVertexID(0);
+ data[size * i + 1] = e.GetVertexID(1);
+ data[size * i + 2] = e.GetVertexID(2);
+
+ i++;
+ }
+
+ return buffer;
+ }
+
+ #endregion
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The buffer capacity.
+ /// The size of one element in the buffer (i.e. 2 for 2D points)
+ public IndexBuffer(int capacity, int size)
+ : base(capacity, size)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The buffer data.
+ /// The size of one element in the buffer (i.e. 2 for 2D points)
+ public IndexBuffer(int[] data, int size)
+ : base(data, size)
+ {
+ }
+
+ ///
+ public override int Size => size;
+
+ ///
+ public override BufferTarget Target => BufferTarget.IndexBuffer;
+ }
+}
diff --git a/src/Triangle.Rendering/Buffer/VertexBuffer.cs b/src/Triangle.Rendering/Buffer/VertexBuffer.cs
new file mode 100644
index 0000000..b8b8815
--- /dev/null
+++ b/src/Triangle.Rendering/Buffer/VertexBuffer.cs
@@ -0,0 +1,130 @@
+
+using System;
+using System.Collections.Generic;
+using TriangleNet.Geometry;
+
+namespace TriangleNet.Rendering.Buffer
+{
+ public class VertexBuffer : BufferBase
+ {
+ #region Static methods
+
+ ///
+ /// Create a vertex buffer from given point collection.
+ ///
+ /// The points to render.
+ /// Returns the vertex buffer.
+ public static IBuffer Create(ICollection points)
+ {
+ return Create(points, new Rectangle(0d, 0d, 1d, 1d));
+ }
+
+ ///
+ /// Create a normalized vertex buffer from given point collection.
+ ///
+ /// The points to render.
+ /// The bounding box used for normalization.
+ /// Returns a buffer of normalized coordinates.
+ public static IBuffer Create(ICollection points, Rectangle bounds)
+ {
+ var buffer = new VertexBuffer(2 * points.Count);
+
+ var data = buffer.Data;
+
+ double dx = bounds.X;
+ double dy = bounds.Y;
+
+ double scale = 1.0 / Math.Max(bounds.Width, bounds.Height);
+
+ int i = 0;
+
+ double x, y;
+
+ foreach (var p in points)
+ {
+ x = (p.X - dx) * scale;
+ y = (p.Y - dy) * scale;
+
+ data[2 * i] = (float)x;
+ data[2 * i + 1] = (float)y;
+
+ i++;
+ }
+
+ return buffer;
+ }
+
+ ///
+ /// Create a vertex buffer from given point collection.
+ ///
+ /// The points to render.
+ /// Returns the vertex buffer.
+ public static IBuffer Create(ICollection points)
+ {
+ return Create(points, new Rectangle(0d, 0d, 1d, 1d));
+ }
+
+ ///
+ /// Create a normalized vertex buffer from given vertex collection.
+ ///
+ /// The vertices to render.
+ /// The bounding box used for normalization.
+ /// Returns a buffer of normalized coordinates.
+ public static IBuffer Create(ICollection points, Rectangle bounds)
+ {
+ var buffer = new VertexBuffer(2 * points.Count);
+
+ var data = buffer.Data;
+
+ double dx = bounds.X;
+ double dy = bounds.Y;
+
+ double scale = 1.0 / Math.Max(bounds.Width, bounds.Height);
+
+ int i = 0;
+
+ double x, y;
+
+ foreach (var p in points)
+ {
+ x = (p.X - dx) * scale;
+ y = (p.Y - dy) * scale;
+
+ data[2 * i] = (float)x;
+ data[2 * i + 1] = (float)y;
+
+ i++;
+ }
+
+ return buffer;
+ }
+
+ #endregion
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The buffer capacity.
+ /// The size of one element in the buffer (i.e. 2 for 2D points)
+ public VertexBuffer(int capacity, int size = 2)
+ : base(capacity, size)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The buffer data.
+ /// The size of one element in the buffer (i.e. 2 for 2D points)
+ public VertexBuffer(float[] data, int size = 2)
+ : base(data, size)
+ {
+ }
+
+ ///
+ public override int Size => size;
+
+ ///
+ public override BufferTarget Target => BufferTarget.VertexBuffer;
+ }
+}
diff --git a/src/Triangle.Rendering/ColorManager.cs b/src/Triangle.Rendering/ColorManager.cs
new file mode 100644
index 0000000..bee0b2c
--- /dev/null
+++ b/src/Triangle.Rendering/ColorManager.cs
@@ -0,0 +1,110 @@
+
+namespace TriangleNet.Rendering
+{
+ using System.Collections.Generic;
+ using System.Drawing;
+ using TriangleNet.Rendering.Util;
+
+ public class ColorManager
+ {
+ #region Public properties
+
+ ///
+ /// Gets or sets the background color.
+ ///
+ public Color Background { get; set; }
+
+ ///
+ /// Gets or sets the brush used for points.
+ ///
+ public Color Point { get; set; }
+
+ ///
+ /// Gets or sets the brush used for steiner points.
+ ///
+ public Color SteinerPoint { get; set; }
+
+ ///
+ /// Gets or sets the pen used for mesh edges.
+ ///
+ public Color Line { get; set; }
+
+ ///
+ /// Gets or sets the pen used for mesh segments.
+ ///
+ public Color Segment { get; set; }
+
+ ///
+ /// Gets or sets the pen used for Voronoi edges.
+ ///
+ public Color VoronoiLine { get; set; }
+
+ #endregion
+
+ ///
+ /// Gets or sets a dictionary which maps region ids (or partition indices) to a color.
+ ///
+ public Dictionary ColorDictionary { get; set; }
+
+ ///
+ /// Gets or sets a color map used for function plotting.
+ ///
+ public ColorMap ColorMap { get; set; }
+
+ ///
+ /// Creates an instance of the class with default (dark) color scheme.
+ ///
+ public static ColorManager Default()
+ {
+ var colors = new ColorManager();
+
+ colors.Background = Color.FromArgb(0, 0, 0);
+ colors.Point = Color.Green;
+ colors.SteinerPoint = Color.Peru;
+ colors.Line = Color.FromArgb(30, 30, 30);
+ colors.Segment = Color.DarkBlue;
+ colors.VoronoiLine = Color.FromArgb(40, 50, 60);
+
+ return colors;
+ }
+
+ public void CreateColorDictionary(int length)
+ {
+ var keys = new int[length];
+
+ for (int i = 0; i < length; i++)
+ {
+ keys[i] = i;
+ }
+
+ CreateColorDictionary(keys);
+ }
+
+ public void CreateColorDictionary(IEnumerable keys)
+ {
+ this.ColorDictionary = new Dictionary();
+
+ int i = 0, n = regionColors.Length;
+
+ foreach (var key in keys)
+ {
+ this.ColorDictionary.Add(key, regionColors[i]);
+
+ i = (i + 1) % n;
+ }
+ }
+
+ // Change or add as many colors as you like...
+ private static Color[] regionColors = {
+ Color.Transparent,
+ Color.FromArgb(200, 0, 255, 0),
+ Color.FromArgb(200, 255, 0, 0),
+ Color.FromArgb(200, 0, 0, 255),
+ Color.FromArgb(200, 0, 255, 255),
+ Color.FromArgb(200, 255, 255, 0),
+ Color.FromArgb(200, 255, 0, 255),
+ Color.FromArgb(200, 127, 0, 255),
+ Color.FromArgb(200, 0, 127, 255)
+ };
+ }
+}
diff --git a/src/Triangle.Rendering/IRenderContext.cs b/src/Triangle.Rendering/IRenderContext.cs
new file mode 100644
index 0000000..c8c8b82
--- /dev/null
+++ b/src/Triangle.Rendering/IRenderContext.cs
@@ -0,0 +1,89 @@
+
+namespace TriangleNet.Rendering
+{
+ using System.Collections.Generic;
+ using TriangleNet.Geometry;
+ using TriangleNet.Meshing;
+
+ public interface IRenderContext
+ {
+ ///
+ /// Gets the color manager.
+ ///
+ ColorManager ColorManager { get; }
+
+ ///
+ /// Gets the list of s.
+ ///
+ IList RenderLayers { get; }
+
+ ///
+ /// Gets the .
+ ///
+ Projection Zoom { get; }
+
+ ///
+ /// Gets the .
+ ///
+ IMesh Mesh { get; }
+
+ ///
+ /// Gets a value indicating whether the context has data to render.
+ ///
+ bool HasData { get; }
+
+ ///
+ /// Add polygon data.
+ ///
+ ///
+ void Add(IPolygon data);
+
+ ///
+ /// Add mesh data.
+ ///
+ ///
+ ///
+ void Add(IMesh data, bool reset);
+
+ ///
+ /// Add edge data (used for Voronoi).
+ ///
+ ///
+ ///
+ ///
+ void Add(ICollection points, IEnumerable edges, bool reset);
+
+ ///
+ /// Add mesh function values z=f(x,y).
+ ///
+ ///
+ void Add(float[] values);
+
+ ///
+ /// Add mesh partitioning data.
+ ///
+ ///
+ void Add(int[] partition);
+
+ ///
+ /// Enable or disable a layer for rendering.
+ ///
+ /// The layer index.
+ /// If true, enable layer, otherwise disable.
+ ///
+ /// 0 = mesh (filled)
+ /// 1 = mesh (wireframe)
+ /// 2 = polygon
+ /// 3 = points
+ /// 4 = voronoi overlay
+ /// 5 = vector field
+ /// 6 = contour lines
+ ///
+ void Enable(int layer, bool enabled);
+
+ ///
+ /// Clear data from all layers.
+ ///
+ void Clear();
+ }
+}
diff --git a/Triangle.NET/Triangle.Rendering/IRenderControl.cs b/src/Triangle.Rendering/IRenderControl.cs
similarity index 88%
rename from Triangle.NET/Triangle.Rendering/IRenderControl.cs
rename to src/Triangle.Rendering/IRenderControl.cs
index da85e8e..477ee70 100644
--- a/Triangle.NET/Triangle.Rendering/IRenderControl.cs
+++ b/src/Triangle.Rendering/IRenderControl.cs
@@ -1,26 +1,26 @@
-// -----------------------------------------------------------------------
-//
-// TODO: Update copyright text.
-//
-// -----------------------------------------------------------------------
-
-namespace TriangleNet.Rendering
-{
- using System;
- using System.Windows.Forms;
- using System.Drawing;
-
- ///
- /// TODO: Update summary.
- ///
- public interface IRenderControl
- {
- IRenderer Renderer { get; set; }
- Rectangle ClientRectangle { get; }
-
- void Initialize();
- void Refresh();
-
- void HandleResize();
- }
-}
+// -----------------------------------------------------------------------
+//
+// TODO: Update copyright text.
+//
+// -----------------------------------------------------------------------
+
+namespace TriangleNet.Rendering
+{
+ using System.Drawing;
+
+ ///
+ /// TODO: Update summary.
+ ///
+ public interface IRenderControl
+ {
+ IRenderer Renderer { get; set; }
+
+ Rectangle ClientRectangle { get; }
+
+ void Initialize();
+
+ void Refresh();
+
+ void HandleResize();
+ }
+}
diff --git a/src/Triangle.Rendering/IRenderLayer.cs b/src/Triangle.Rendering/IRenderLayer.cs
new file mode 100644
index 0000000..b83e457
--- /dev/null
+++ b/src/Triangle.Rendering/IRenderLayer.cs
@@ -0,0 +1,83 @@
+
+namespace TriangleNet.Rendering
+{
+ using TriangleNet.Rendering.Buffer;
+ using TriangleNet.Rendering.Util;
+
+ using Color = System.Drawing.Color;
+
+ ///
+ /// Interface for managing the data of a render layer.
+ ///
+ public interface IRenderLayer
+ {
+ ///
+ /// Gets the number of points in the point buffer.
+ ///
+ int Count { get; }
+
+ ///
+ /// Gets the points buffer.
+ ///
+ IBuffer Points { get; }
+
+ ///
+ /// Gets the indices buffer.
+ ///
+ IBuffer Indices { get; }
+
+ ///
+ /// Gets or sets a value indicating whether the layer is enabled.
+ ///
+ bool IsEnabled { get; set; }
+
+ ///
+ /// Indicates whether this layer contains data to render.
+ ///
+ /// Returns true, if the points buffer contains data.
+ bool IsEmpty();
+
+ ///
+ /// Resets this layer to an empty state.
+ ///
+ /// If true, all buffers will be set to null.
+ void Reset(bool clear);
+
+ void SetPoints(IBuffer buffer, bool reset = true);
+
+ void SetIndices(IBuffer buffer);
+
+ #region Attached data (mesh partitioning and heat map rendering)
+
+ // TODO: better put attached data into a subclass?
+
+ ///
+ /// Gets the mesh partition.
+ ///
+ ///
+ /// Triangle i given by indices [3 * i, 3 * i + 1, 3 * i + 2]
+ /// belongs to Partition[i].
+ ///
+ IBuffer Partition { get; }
+
+ ///
+ /// Gets the color attached to a point in the points buffer.
+ ///
+ IBuffer Colors { get; }
+
+ ///
+ /// Attach function values z=f(x,y) for all points (x,y) in the point buffer.
+ ///
+ /// The function values.
+ /// The color map.
+ void AttachLayerData(float[] values, ColorMap colormap);
+
+ ///
+ /// Attach partitioning data to each triangle in the index buffer.
+ ///
+ /// The mesh partition.
+ void AttachLayerData(int[] partition);
+
+ #endregion
+ }
+}
diff --git a/Triangle.NET/Triangle.Rendering/IRenderer.cs b/src/Triangle.Rendering/IRenderer.cs
similarity index 93%
rename from Triangle.NET/Triangle.Rendering/IRenderer.cs
rename to src/Triangle.Rendering/IRenderer.cs
index a77c7c5..6c78a2a 100644
--- a/Triangle.NET/Triangle.Rendering/IRenderer.cs
+++ b/src/Triangle.Rendering/IRenderer.cs
@@ -1,10 +1,10 @@
-
-namespace TriangleNet.Rendering
-{
- public interface IRenderer
- {
- IRenderContext Context { get; set; }
-
- void Render();
- }
-}
+
+namespace TriangleNet.Rendering
+{
+ public interface IRenderer
+ {
+ IRenderContext Context { get; set; }
+
+ void Render();
+ }
+}
diff --git a/src/Triangle.Rendering/Projection.cs b/src/Triangle.Rendering/Projection.cs
new file mode 100644
index 0000000..6741b14
--- /dev/null
+++ b/src/Triangle.Rendering/Projection.cs
@@ -0,0 +1,282 @@
+// -----------------------------------------------------------------------
+//
+// Triangle.NET Copyright (c) 2012-2022 Christian Woltering
+//
+// -----------------------------------------------------------------------
+
+namespace TriangleNet.Rendering
+{
+ using System;
+ using System.Drawing;
+
+ using TRectangle = Geometry.Rectangle;
+
+ ///
+ /// Manages a world to screen transformation (2D orthographic projection).
+ ///
+ ///
+ ///
+ /// The projection implementation is actually not world-to-screen, but NDC-to-screen
+ /// (Normalized-Device-Coordinates). NDC here is - in contrast for example to OpenGL, the
+ /// transformation of world coordinates to a unit rectangle with origin (0,0) and a max
+ /// side length 1 (the width/height ratio is preserved). It's a simple translate-scale
+ /// transform, which is automatically applied in VertexBuffer.Create(points, bounds).
+ ///
+ ///
+ /// Since the upper-left corner of the display is usually the screen coordinate origin
+ /// (0,0), the projection will automatically invert the y-axis.
+ ///
+ ///
+ public class Projection
+ {
+ // The original mesh bounds (needed for screen-to-world projection).
+ TRectangle world_;
+
+ // Precomputed scaling factor for normalized coordinates.
+ double scale_;
+
+ // The screen dimensions.
+ Rectangle screen;
+
+ // The original mesh and the viewport in normalized coordinates.
+ RectangleF world, viewport;
+
+ ///
+ /// Gets or sets the current viewport (normalized coordinates).
+ ///
+ public RectangleF Viewport => viewport;
+
+ ///
+ /// Gets the zoom level.
+ ///
+ public int Level { get; private set; }
+
+ private const int MAX_ZOOM = 100;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The current screen (viewport) dimensions.
+ public Projection(Rectangle screen)
+ {
+ this.screen = screen;
+
+ world = viewport = new RectangleF(screen.X, screen.Y, screen.Width, screen.Height);
+
+ world_ = new TRectangle();
+ scale_ = 0;
+
+ Level = 1;
+ }
+
+ ///
+ /// Initialize the projection.
+ ///
+ /// The world that should be transformed to screen coordinates.
+ public void Initialize(TRectangle world)
+ {
+ Level = 1;
+
+ // Bounding box of original (non-normalized) coordinates.
+ world_ = world;
+
+ // Scaling factor for normalized coordinates.
+ scale_ = Math.Max(world.Width, world.Height);
+
+ // Dimensions in normalized coordinates.
+ float ww = (float)(world.Width / scale_);
+ float wh = (float)(world.Height / scale_);
+
+ // Add a margin so there's some space around the screen borders.
+ float margin = (ww < wh) ? wh * 0.05f : ww * 0.05f;
+
+ int sw = screen.Width;
+ int sh = screen.Height;
+
+ float wRatio = ww / wh;
+ float sRatio = sw / (float)sh;
+
+ float scale = (sRatio < wRatio) ? (ww + margin) / sw : (wh + margin) / sh;
+
+ // Center in normalized coordinates (left = bottom = 0)
+ float centerX = ww / 2;
+ float centerY = wh / 2;
+
+ // Get the initial viewport (complete mesh centered on the screen)
+ this.world = viewport = new RectangleF(
+ centerX - sw * scale / 2,
+ centerY - sh * scale / 2,
+ sw * scale,
+ sh * scale);
+ }
+
+ ///
+ /// Handle resize of the screen (viewport).
+ ///
+ /// The new screen (viewport) dimensions.
+ public void Resize(Rectangle newScreen)
+ {
+ // The viewport has to be updated, but we want to keep
+ // the scaling and the center.
+
+ // Get the screen scaling.
+ float scaleX = newScreen.Width / (float)screen.Width;
+ float scaleY = newScreen.Height / (float)screen.Height;
+
+ screen = newScreen;
+
+ var view = viewport;
+
+ // Center of the viewport
+ float centerX = (view.Left + view.Right) / 2;
+ float centerY = (view.Bottom + view.Top) / 2;
+
+ // The new viewport dimensions.
+ float width = view.Width * scaleX;
+ float height = view.Height * scaleY;
+
+ viewport = new RectangleF(
+ centerX - width / 2,
+ centerY - height / 2,
+ width, height);
+
+ // Do the same for the world:
+ centerX = (world.Left + world.Right) / 2;
+ centerY = (world.Bottom + world.Top) / 2;
+
+ width = world.Width * scaleX;
+ height = world.Height * scaleY;
+
+ world = new RectangleF(
+ centerX - width / 2,
+ centerY - height / 2,
+ width, height);
+ }
+
+ public bool Translate(int dx, int dy)
+ {
+ if (Level == 1)
+ {
+ return false;
+ }
+
+ var view = viewport;
+
+ float x = view.X + dx * view.Width / 4;
+ float y = view.Y + dy * view.Height / 4;
+
+ viewport = new RectangleF(x, y, view.Width, view.Height);
+
+ return true;
+ }
+
+ ///
+ /// Zoom in or out of the viewport.
+ ///
+ /// Zoom amount.
+ /// Relative x point position (in [0..1] range).
+ /// Relative y point position (in [0..1] range).
+ public bool Zoom(int amount, float focusX, float focusY)
+ {
+ float width, height;
+
+ // Invert y coordinate.
+ focusY = 1 - focusY;
+
+ if (amount > 0) // Zoom in
+ {
+ Level++;
+
+ if (Level > MAX_ZOOM)
+ {
+ Level = MAX_ZOOM;
+ return false;
+ }
+
+ width = viewport.Width / 1.1f;
+ height = viewport.Height / 1.1f;
+ }
+ else
+ {
+ Level--;
+
+ if (Level < 1)
+ {
+ Reset();
+ return false;
+ }
+
+ width = viewport.Width * 1.1f;
+ height = viewport.Height * 1.1f;
+ }
+
+ // Current focus on viewport
+ float x = viewport.X + viewport.Width * focusX;
+ float y = viewport.Y + viewport.Height * focusY;
+
+ // New left and top positions
+ x = x - width * focusX;
+ y = y - height * focusY;
+
+ // Check if outside of world
+ if (x < world.X)
+ {
+ x = world.X;
+ }
+ else if (x + width > world.Right)
+ {
+ x = world.Right - width;
+ }
+
+ if (y < world.Y)
+ {
+ y = world.Y;
+ }
+ else if (y + height > world.Bottom)
+ {
+ y = world.Bottom - height;
+ }
+
+ // Set new viewport
+ viewport = new RectangleF(x, y, width, height);
+
+ return true;
+ }
+
+ ///
+ /// Reset the zoom to initial state.
+ ///
+ public void Reset()
+ {
+ viewport = world;
+ Level = 1;
+ }
+
+ ///
+ /// Project a normalized device coordinate to screen coordinates.
+ ///
+ /// Input normalized device coordinate, output screen coordinate.
+ public void NdcToScreen(ref PointF pt)
+ {
+ pt.X = (pt.X - viewport.X) / viewport.Width * screen.Width;
+ pt.Y = (1 - (pt.Y - viewport.Y) / viewport.Height) * screen.Height;
+ }
+
+ ///
+ /// Project a screen coordinate to world coordinates.
+ ///
+ /// Normalized position on screen (both coordinates in [0..1] range).
+ /// The world x-coordinate.
+ /// The world y-coordinate.
+ public void ScreenToWorld(PointF pt, out double x, out double y)
+ {
+ // Position in normalized coordinates.
+ var nx = viewport.X + viewport.Width * pt.X;
+ var ny = viewport.Y + viewport.Height * (1 - pt.Y);
+
+ // Translate and scale to world coordinates.
+ x = world_.X + nx * scale_;
+ y = world_.Y + ny * scale_;
+ }
+ }
+}
diff --git a/Triangle.NET/Triangle.Rendering/RenderContext.cs b/src/Triangle.Rendering/RenderContext.cs
similarity index 63%
rename from Triangle.NET/Triangle.Rendering/RenderContext.cs
rename to src/Triangle.Rendering/RenderContext.cs
index 66e3ede..703af06 100644
--- a/Triangle.NET/Triangle.Rendering/RenderContext.cs
+++ b/src/Triangle.Rendering/RenderContext.cs
@@ -1,162 +1,160 @@
-
-namespace TriangleNet.Rendering
-{
- using System.Collections.Generic;
- using System.Linq;
- using TriangleNet.Geometry;
- using TriangleNet.Meshing;
- using TriangleNet.Voronoi.Legacy;
-
- ///
- /// The RenderContext class brings all the rendering parts together.
- ///
- public class RenderContext : IRenderContext
- {
- private ColorManager colorManager;
- private BoundingBox bounds;
- private Projection zoom;
- private IMesh mesh;
-
- private List renderLayers;
-
- public RenderContext(Projection zoom, ColorManager colorManager)
- {
- bounds = new BoundingBox();
-
- renderLayers = new List(6);
-
- renderLayers.Add(new RenderLayer()); // 0 = mesh (filled)
- renderLayers.Add(new RenderLayer()); // 1 = mesh (wireframe)
- renderLayers.Add(new RenderLayer()); // 2 = polygon
- renderLayers.Add(new RenderLayer()); // 3 = points
- renderLayers.Add(new RenderLayer()); // 4 = voronoi overlay
- renderLayers.Add(new RenderLayer()); // 5 = vector field
- renderLayers.Add(new RenderLayer()); // 6 = contour lines
-
- RenderLayers[1].IsEnabled = true;
- RenderLayers[2].IsEnabled = true;
- RenderLayers[3].IsEnabled = true;
-
- this.zoom = zoom;
- this.colorManager = colorManager;
- }
-
- public ColorManager ColorManager
- {
- get { return colorManager; }
- }
-
- public BoundingBox Bounds
- {
- get { return bounds; }
- }
-
- public IList RenderLayers
- {
- get { return renderLayers; }
- }
-
- public Projection Zoom
- {
- get { return zoom; }
- }
-
- public IMesh Mesh
- {
- get { return mesh; }
- }
-
- public bool HasData
- {
- get
- {
- return renderLayers.Any(layer => !layer.IsEmpty());
- }
- }
-
- public void Add(IPolygon data)
- {
- foreach (var layer in RenderLayers)
- {
- layer.Reset(true);
- }
-
- // Always clear voronoi layer.
- RenderLayers[4].Reset(true);
-
- int i = 0;
-
- // Ensure linear numbering of polygon vertices.
- foreach (var p in data.Points)
- {
- p.ID = i++;
- }
-
- this.bounds = RenderLayers[2].SetPoints(data);
- this.zoom.Initialize(bounds);
-
- RenderLayers[2].SetPolygon(data);
- RenderLayers[3].SetPoints(RenderLayers[2].Points);
- }
-
- public void Add(IMesh data, bool reset)
- {
- foreach (var layer in RenderLayers)
- {
- layer.Reset(reset);
- }
-
- // Always clear voronoi layer.
- RenderLayers[4].Reset(true);
-
- // Save reference to mesh.
- this.mesh = data;
-
- this.bounds = RenderLayers[1].SetPoints(data);
- this.zoom.Initialize(bounds);
-
- RenderLayers[1].SetMesh(data, false);
-
- RenderLayers[2].SetPoints(RenderLayers[1].Points);
- RenderLayers[2].SetPolygon(data);
-
- RenderLayers[3].SetPoints(RenderLayers[1].Points);
- }
-
- public void Add(ICollection points, IEnumerable edges, bool reset)
- {
- RenderLayers[4].SetPoints(points);
- RenderLayers[4].SetMesh(edges);
- RenderLayers[4].IsEnabled = true;
- }
-
- public void Add(float[] data)
- {
- // Add function values for filled mesh.
- RenderLayers[0].SetPoints(RenderLayers[1].Points);
- RenderLayers[0].SetMesh(this.mesh, true);
- RenderLayers[0].AttachLayerData(data, colorManager.ColorMap);
-
- RenderLayers[0].IsEnabled = true;
- }
-
- public void Add(int[] data)
- {
- // Add partition data for filled mesh.
- RenderLayers[0].SetPoints(RenderLayers[1].Points);
- RenderLayers[0].SetMesh(this.mesh, true);
- RenderLayers[0].AttachLayerData(data);
-
- RenderLayers[0].IsEnabled = true;
- }
-
- public void Enable(int layer, bool enabled)
- {
- renderLayers[layer].IsEnabled = enabled;
- }
-
- public void Clear()
- {
- }
- }
-}
+
+namespace TriangleNet.Rendering
+{
+ using System.Collections.Generic;
+ using System.Linq;
+ using TriangleNet.Geometry;
+ using TriangleNet.Meshing;
+ using TriangleNet.Rendering.Buffer;
+
+ ///
+ /// The RenderContext class brings all the rendering parts together.
+ ///
+ public class RenderContext : IRenderContext
+ {
+ private ColorManager colorManager;
+ private Projection zoom;
+ private Rectangle bounds;
+ private IMesh mesh;
+
+ private List renderLayers;
+
+ public RenderContext(Projection zoom, ColorManager colorManager)
+ {
+ renderLayers = new List(6);
+
+ renderLayers.Add(new RenderLayer()); // 0 = mesh (filled)
+ renderLayers.Add(new RenderLayer()); // 1 = mesh (wireframe)
+ renderLayers.Add(new RenderLayer()); // 2 = polygon
+ renderLayers.Add(new RenderLayer()); // 3 = points
+ renderLayers.Add(new RenderLayer()); // 4 = voronoi overlay
+ renderLayers.Add(new RenderLayer()); // 5 = vector field
+ renderLayers.Add(new RenderLayer()); // 6 = contour lines
+
+ RenderLayers[1].IsEnabled = true;
+ RenderLayers[2].IsEnabled = true;
+ RenderLayers[3].IsEnabled = true;
+
+ this.zoom = zoom;
+ this.colorManager = colorManager;
+ }
+
+ ///
+ public ColorManager ColorManager => colorManager;
+
+ ///
+ public IList RenderLayers => renderLayers;
+
+ ///
+ public Projection Zoom => zoom;
+
+ ///
+ public IMesh Mesh => mesh;
+
+ ///
+ public bool HasData => renderLayers.Any(layer => !layer.IsEmpty());
+
+ ///
+ public void Add(IPolygon data)
+ {
+ foreach (var layer in RenderLayers)
+ {
+ layer.Reset(true);
+ }
+
+ // Always clear Voronoi layer.
+ RenderLayers[4].Reset(true);
+
+ int i = 0;
+
+ // Ensure linear numbering of polygon vertices.
+ foreach (var p in data.Points)
+ {
+ p.ID = i++;
+ }
+
+ bounds = data.Bounds();
+
+ zoom.Initialize(bounds);
+
+ RenderLayers[2].SetPoints(VertexBuffer.Create(data.Points, bounds));
+ RenderLayers[2].SetIndices(IndexBuffer.Create(data.Segments, 2));
+
+ RenderLayers[3].SetPoints(RenderLayers[2].Points);
+ }
+
+ ///
+ public void Add(IMesh data, bool reset)
+ {
+ foreach (var layer in RenderLayers)
+ {
+ layer.Reset(reset);
+ }
+
+ // Always clear voronoi layer.
+ RenderLayers[4].Reset(true);
+
+ // Save reference to mesh.
+ mesh = data;
+ bounds = data.Bounds;
+
+ // Ensure linear numbering of vertices.
+ mesh.Renumber();
+
+ zoom.Initialize(bounds);
+
+ RenderLayers[1].SetPoints(VertexBuffer.Create(data.Vertices, bounds));
+ RenderLayers[1].SetIndices(IndexBuffer.Create(data.Edges, 2));
+
+ RenderLayers[2].SetPoints(RenderLayers[1].Points);
+ RenderLayers[2].SetIndices(IndexBuffer.Create(data.Segments, 2));
+
+ RenderLayers[3].SetPoints(RenderLayers[1].Points, false);
+ }
+
+ ///
+ public void Add(ICollection points, IEnumerable edges, bool reset)
+ {
+ RenderLayers[4].SetPoints(VertexBuffer.Create(points, bounds));
+ RenderLayers[4].SetIndices(IndexBuffer.Create(edges, 2));
+ RenderLayers[4].IsEnabled = true;
+ }
+
+ ///
+ public void Add(float[] data)
+ {
+ // Add function values for filled mesh.
+ RenderLayers[0].SetPoints(RenderLayers[1].Points);
+ RenderLayers[0].SetIndices(IndexBuffer.Create(mesh.Triangles, 3));
+ RenderLayers[0].AttachLayerData(data, colorManager.ColorMap);
+
+ RenderLayers[0].IsEnabled = true;
+ }
+
+ ///
+ public void Add(int[] data)
+ {
+ // Add partition data for filled mesh.
+ RenderLayers[0].SetPoints(RenderLayers[1].Points);
+ RenderLayers[0].SetIndices(IndexBuffer.Create(mesh.Triangles, 3));
+ RenderLayers[0].AttachLayerData(data);
+
+ RenderLayers[0].IsEnabled = true;
+ }
+
+ ///
+ public void Enable(int layer, bool enabled)
+ {
+ renderLayers[layer].IsEnabled = enabled;
+ }
+
+ ///
+ public void Clear()
+ {
+ foreach (var layer in RenderLayers)
+ {
+ layer.Reset(true);
+ }
+ }
+ }
+}
diff --git a/src/Triangle.Rendering/RenderLayer.cs b/src/Triangle.Rendering/RenderLayer.cs
new file mode 100644
index 0000000..a590db6
--- /dev/null
+++ b/src/Triangle.Rendering/RenderLayer.cs
@@ -0,0 +1,126 @@
+
+namespace TriangleNet.Rendering
+{
+ using System.Collections.Generic;
+ using TriangleNet.Geometry;
+ using TriangleNet.Meshing;
+ using TriangleNet.Rendering.Buffer;
+ using TriangleNet.Rendering.Util;
+
+ using Color = System.Drawing.Color;
+
+ public class RenderLayer : IRenderLayer
+ {
+ int count;
+
+ protected IBuffer points;
+ protected IBuffer indices;
+
+ protected IBuffer partition;
+ protected IBuffer colors;
+
+ public RenderLayer()
+ {
+ this.IsEnabled = false;
+ }
+
+ ///
+ public int Count => count;
+
+ ///
+ public IBuffer Points => points;
+
+ ///
+ public IBuffer Indices => indices;
+
+ ///
+ public IBuffer Partition => partition;
+
+ ///
+ public IBuffer Colors => colors;
+
+ ///
+ public bool IsEnabled { get; set; }
+
+ ///
+ public bool IsEmpty()
+ {
+ return (points == null || points.Count == 0);
+ }
+
+ ///
+ public void Reset(bool clear)
+ {
+ if (clear)
+ {
+ count = 0;
+ points = null;
+ }
+
+ indices = null;
+ partition = null;
+ colors = null;
+ }
+
+ ///
+ public void SetPoints(IBuffer buffer, bool reset = true)
+ {
+ if (!reset && points != null && points.Count < buffer.Count)
+ {
+ // NOTE: we keep the old size to be able to render new Steiner
+ // points in a different color than existing points.
+ count = points.Count / points.Size;
+ }
+ else
+ {
+ count = buffer.Count / buffer.Size;
+ }
+
+ points = buffer;
+ }
+
+ ///
+ public void SetIndices(IBuffer buffer)
+ {
+ indices = buffer;
+ }
+
+ ///
+ public void AttachLayerData(float[] values, ColorMap colormap)
+ {
+ int length = values.Length;
+
+ double min = double.MaxValue;
+ double max = double.MinValue;
+
+ // Find min and max of given values.
+ for (int i = 0; i < length; i++)
+ {
+ if (values[i] < min)
+ {
+ min = values[i];
+ }
+
+ if (values[i] > max)
+ {
+ max = values[i];
+ }
+ }
+
+ var colorData = new Color[length];
+
+ for (int i = 0; i < length; i++)
+ {
+ colorData[i] = colormap.GetColor(values[i], min, max);
+ }
+
+ colors = new ColorBuffer(colorData, 1);
+ }
+
+ ///
+ public void AttachLayerData(int[] partition)
+ {
+ this.partition = new IndexBuffer(partition, 1);
+ }
+ }
+}
diff --git a/Triangle.NET/Triangle.Rendering/RenderManager.cs b/src/Triangle.Rendering/RenderManager.cs
similarity index 75%
rename from Triangle.NET/Triangle.Rendering/RenderManager.cs
rename to src/Triangle.Rendering/RenderManager.cs
index 1337185..86a07b6 100644
--- a/Triangle.NET/Triangle.Rendering/RenderManager.cs
+++ b/src/Triangle.Rendering/RenderManager.cs
@@ -1,132 +1,115 @@
-
-namespace TriangleNet.Rendering
-{
- using System.Collections.Generic;
- using System.Windows.Forms;
- using TriangleNet.Geometry;
- using TriangleNet.Meshing;
- using TriangleNet.Rendering.GDI;
- using TriangleNet.Rendering.Util;
-
- public class RenderManager
- {
- // TODO: delete
- public static bool VORONOI_DEBUG = false;
-
- IRenderControl control;
- IRenderContext context;
- IRenderer renderer;
- Projection zoom;
-
- public IRenderControl Control
- {
- get { return control; }
- }
-
- public IRenderContext Context
- {
- get { return context; }
- }
-
- public RenderManager()
- {
- }
-
- public RenderManager(IRenderControl control)
- {
- Initialize(control);
- }
-
- public RenderManager(IRenderControl control, IRenderer renderer)
- {
- Initialize(control, renderer);
- }
-
- public void Initialize(IRenderControl control)
- {
- Initialize(control, new LayerRenderer());
- }
-
- public void Initialize(IRenderControl control, IRenderer renderer)
- {
- this.zoom = new Projection(control.ClientRectangle);
-
- this.context = new RenderContext(zoom, ColorManager.Default());
-
- this.renderer = renderer;
- this.renderer.Context = context;
-
- this.control = control;
- this.control.Initialize();
- this.control.Renderer = renderer;
- }
-
- public bool TryCreateControl(string assemblyName, IEnumerable dependencies,
- out IRenderControl control)
- {
- if (!ReflectionHelper.TryCreateControl(assemblyName, dependencies, out control))
- {
- return false;
- }
-
- return control is Control;
- }
-
- public void Resize()
- {
- control.HandleResize();
- }
-
- public void Enable(int layer, bool enabled)
- {
- context.Enable(layer, enabled);
-
- control.Refresh();
- }
-
- public void Set(IPolygon data, bool refresh = true)
- {
- context.Add(data);
-
- if (refresh)
- {
- control.Refresh();
- }
- }
-
- public void Set(IMesh data, bool reset, bool refresh = true)
- {
- context.Add(data, reset);
-
- if (refresh)
- {
- control.Refresh();
- }
- }
-
- ///
- /// Set data for Voronoi layer.
- ///
- public void Set(ICollection points, IEnumerable edges, bool reset, bool refresh = true)
- {
- context.Add(points, edges, reset);
-
- if (refresh)
- {
- control.Refresh();
- }
- }
-
- public void Update(float[] values)
- {
- context.Add(values);
- control.Refresh();
- }
-
- public void Update(int[] partition)
- {
- context.Add(partition);
- control.Refresh();
- }
- }
-}
+
+namespace TriangleNet.Rendering
+{
+ using System.Collections.Generic;
+ using TriangleNet.Geometry;
+ using TriangleNet.Meshing;
+ using TriangleNet.Rendering.Util;
+
+ public class RenderManager
+ {
+ // TODO: delete
+ public static bool VORONOI_DEBUG = false;
+
+ IRenderControl control;
+ IRenderContext context;
+ IRenderer renderer;
+ Projection zoom;
+
+ public IRenderControl Control => control;
+
+ public IRenderContext Context => context;
+
+ public RenderManager()
+ {
+ }
+
+ public RenderManager(IRenderControl control, IRenderer renderer)
+ {
+ Initialize(control, renderer);
+ }
+
+ public void Initialize(IRenderControl control, IRenderer renderer)
+ {
+ this.zoom = new Projection(control.ClientRectangle);
+
+ this.context = new RenderContext(zoom, ColorManager.Default());
+
+ this.renderer = renderer;
+ this.renderer.Context = context;
+
+ this.control = control;
+ this.control.Initialize();
+ this.control.Renderer = renderer;
+ }
+
+ public bool TryCreateControl(string assemblyName, IEnumerable dependencies,
+ out IRenderControl control)
+ {
+ return ReflectionHelper.TryCreateControl(assemblyName, dependencies, out control);
+ }
+
+ public void Resize()
+ {
+ control.HandleResize();
+ }
+
+ public void Clear()
+ {
+ context.Clear();
+ control.Refresh();
+ }
+
+ public void Enable(int layer, bool enabled)
+ {
+ context.Enable(layer, enabled);
+
+ control.Refresh();
+ }
+
+ public void Set(IPolygon data, bool refresh = true)
+ {
+ context.Add(data);
+
+ if (refresh)
+ {
+ control.Refresh();
+ }
+ }
+
+ public void Set(IMesh data, bool reset, bool refresh = true)
+ {
+ context.Add(data, reset);
+
+ if (refresh)
+ {
+ control.Refresh();
+ }
+ }
+
+ ///
+ /// Set data for Voronoi layer.
+ ///
+ public void Set(ICollection points, IEnumerable edges, bool reset, bool refresh = true)
+ {
+ context.Add(points, edges, reset);
+
+ if (refresh)
+ {
+ control.Refresh();
+ }
+ }
+
+ public void Update(float[] values)
+ {
+ context.Add(values);
+ control.Refresh();
+ }
+
+ public void Update(int[] partition)
+ {
+ context.Add(partition);
+ control.Refresh();
+ }
+ }
+}
diff --git a/Triangle.NET/Triangle.Rendering/Text/EpsDocument.cs b/src/Triangle.Rendering/Text/EpsDocument.cs
similarity index 96%
rename from Triangle.NET/Triangle.Rendering/Text/EpsDocument.cs
rename to src/Triangle.Rendering/Text/EpsDocument.cs
index 3db8888..94bd5a8 100644
--- a/Triangle.NET/Triangle.Rendering/Text/EpsDocument.cs
+++ b/src/Triangle.Rendering/Text/EpsDocument.cs
@@ -1,208 +1,208 @@
-
-namespace TriangleNet.Rendering.Text
-{
- using System;
- using System.Drawing;
- using System.IO;
-
- public class EpsDocument : IDisposable
- {
- // Constant to convert from millimeters to PostScript units (1/72th inch).
- private const double UNITS_PER_MM = 72.0 / 25.4;
-
- private FormattingStreamWriter _w;
- private PageSize _size;
-
- ///
- /// Gets or sets the document name.
- ///
- public string Name { get; set; }
-
- ///
- /// Gets or sets the default point size (default = 1).
- ///
- public int DefaultPointSize { get; set; }
-
- public EpsDocument(string filename, PageSize pageSize)
- : this(File.Create(filename), pageSize)
- {
- Name = Path.GetFileName(filename);
- }
-
- public EpsDocument(Stream stream, PageSize pageSize)
- {
- _w = new FormattingStreamWriter(stream);
- _w.NewLine = "\n";
-
- _size = pageSize;
-
- DefaultPointSize = 1;
- }
-
- public void AddComment(string comment, int line = 1)
- {
- for (int i = 0; i < line; i++)
- {
- _w.WriteLine("%");
- }
-
- var t = comment.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries );
-
- for (int i = 0; i < t.Length; i++)
- {
- _w.WriteLine("% " + t[i]);
- }
-
- for (int i = 0; i < line; i++)
- {
- _w.WriteLine("%");
- }
- }
-
- public void DrawPoint(Point p)
- {
- _w.WriteLine("{0} {1} P", p.X, p.Y);
- }
-
- public void DrawLine(Point p1, Point p2)
- {
- _w.WriteLine("{0} {1} {2} {3} L", p1.X, p1.Y, p2.X, p2.Y);
- }
-
- public void DrawRectangle(Rectangle rect)
- {
- _w.WriteLine("newpath");
- _w.WriteLine(" {0} {1} moveto", rect.X, rect.Y);
- _w.WriteLine(" {0} {1} lineto", rect.Right, rect.Y);
- _w.WriteLine(" {0} {1} lineto", rect.Right, rect.Bottom);
- _w.WriteLine(" {0} {1} lineto", rect.X, rect.Bottom);
- _w.WriteLine(" {0} {1} lineto", rect.X, rect.Y);
- _w.WriteLine("stroke");
-
- }
-
- public void SetClip(Rectangle rect)
- {
- _w.WriteLine("newpath");
- _w.WriteLine(" {0} {1} moveto", rect.X, rect.Y);
- _w.WriteLine(" {0} {1} lineto", rect.Right, rect.Y);
- _w.WriteLine(" {0} {1} lineto", rect.Right, rect.Bottom);
- _w.WriteLine(" {0} {1} lineto", rect.X, rect.Bottom);
- _w.WriteLine(" {0} {1} lineto", rect.X, rect.Y);
- _w.WriteLine("clip newpath");
- }
-
- public void SetColor(Color color)
- {
- _w.WriteLine("{0:0.###} {1:0.###} {2:0.###} setrgbcolor",
- ((float)color.R) / 255f,
- ((float)color.G) / 255f,
- ((float)color.B) / 255f);
- }
-
- public void SetStroke(float width)
- {
- _w.WriteLine("{0:0.###} setlinewidth", width);
- }
-
- public void SetStroke(float width, Color color)
- {
- SetColor(color);
- SetStroke(width);
- }
-
- public void WriteHeader()
- {
- var x = _size.X; // * UNITS_PER_MM
- var y = _size.Y;
- var right = _size.Right;
- var bottom = _size.Bottom;
-
- // Write document header.
-
- _w.WriteLine("%!PS-Adobe-3.0 EPSF-3.0");
- _w.WriteLine("%%Creator: Triangle.NET");
- _w.WriteLine("%%Title: {0}", Name);
- _w.WriteLine("%%Pages: 1");
- _w.WriteLine("%%BoundingBox: {0} {1} {2} {3}", (int)x, (int)y, (int)right, (int)bottom);
- _w.WriteLine("%%HiResBoundingBox: {0:0.#####} {1:0.#####} {2:0.#####} {3:0.#####}", x, y, right, bottom);
- _w.WriteLine("%%Document-Fonts: Times-Roman");
- _w.WriteLine("%%LanguageLevel: 3");
- _w.WriteLine("%%EndComments");
- _w.WriteLine("%%Page: 1 1");
- _w.WriteLine("save");
-
- // Define points.
- _w.WriteLine("% Define points.");
- _w.WriteLine("/P {");
- _w.WriteLine("2 dict begin");
- _w.WriteLine("/y exch def");
- _w.WriteLine("/x exch def");
- _w.WriteLine("gsave");
- _w.WriteLine("newpath x y {0} 0 360 arc fill", DefaultPointSize);
- _w.WriteLine("grestore");
- _w.WriteLine("end");
- _w.WriteLine("} def");
-
- // Define lines.
- _w.WriteLine("% Define lines.");
- _w.WriteLine("/L {");
- _w.WriteLine("2 dict begin");
- _w.WriteLine("/y2 exch def");
- _w.WriteLine("/x2 exch def");
- _w.WriteLine("/y1 exch def");
- _w.WriteLine("/x1 exch def");
- _w.WriteLine("gsave");
- _w.WriteLine("newpath x1 y1 moveto x2 y2 lineto stroke");
- _w.WriteLine("grestore");
- _w.WriteLine("end");
- _w.WriteLine("} def");
- }
-
- private void Close()
- {
- _w.WriteLine("%");
- _w.WriteLine("restore showpage");
- _w.WriteLine("%%Trailer");
- _w.WriteLine("%%EOF");
- }
-
- #region IDisposable implementation
-
- // Has Dispose already been called?
- bool disposed = false;
-
- // Public implementation of Dispose pattern callable by consumers.
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- // Protected implementation of Dispose pattern.
- protected virtual void Dispose(bool disposing)
- {
- if (disposed)
- return;
-
- Close();
-
- if (disposing)
- {
- _w.Dispose();
- _w = null;
- }
-
- // Free any unmanaged objects here.
- //
- disposed = true;
- }
-
- ~EpsDocument()
- {
- Dispose(false);
- }
-
- #endregion
- }
-}
+
+namespace TriangleNet.Rendering.Text
+{
+ using System;
+ using System.Drawing;
+ using System.IO;
+
+ public class EpsDocument : IDisposable
+ {
+ // Constant to convert from millimeters to PostScript units (1/72th inch).
+ private const double UNITS_PER_MM = 72.0 / 25.4;
+
+ private FormattingStreamWriter _w;
+ private PageSize _size;
+
+ ///
+ /// Gets or sets the document name.
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// Gets or sets the default point size (default = 1).
+ ///
+ public int DefaultPointSize { get; set; }
+
+ public EpsDocument(string filename, PageSize pageSize)
+ : this(File.Create(filename), pageSize)
+ {
+ Name = Path.GetFileName(filename);
+ }
+
+ public EpsDocument(Stream stream, PageSize pageSize)
+ {
+ _w = new FormattingStreamWriter(stream);
+ _w.NewLine = "\n";
+
+ _size = pageSize;
+
+ DefaultPointSize = 1;
+ }
+
+ public void AddComment(string comment, int line = 1)
+ {
+ for (int i = 0; i < line; i++)
+ {
+ _w.WriteLine("%");
+ }
+
+ var t = comment.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries );
+
+ for (int i = 0; i < t.Length; i++)
+ {
+ _w.WriteLine("% " + t[i]);
+ }
+
+ for (int i = 0; i < line; i++)
+ {
+ _w.WriteLine("%");
+ }
+ }
+
+ public void DrawPoint(Point p)
+ {
+ _w.WriteLine("{0} {1} P", p.X, p.Y);
+ }
+
+ public void DrawLine(Point p1, Point p2)
+ {
+ _w.WriteLine("{0} {1} {2} {3} L", p1.X, p1.Y, p2.X, p2.Y);
+ }
+
+ public void DrawRectangle(Rectangle rect)
+ {
+ _w.WriteLine("newpath");
+ _w.WriteLine(" {0} {1} moveto", rect.X, rect.Y);
+ _w.WriteLine(" {0} {1} lineto", rect.Right, rect.Y);
+ _w.WriteLine(" {0} {1} lineto", rect.Right, rect.Bottom);
+ _w.WriteLine(" {0} {1} lineto", rect.X, rect.Bottom);
+ _w.WriteLine(" {0} {1} lineto", rect.X, rect.Y);
+ _w.WriteLine("stroke");
+
+ }
+
+ public void SetClip(Rectangle rect)
+ {
+ _w.WriteLine("newpath");
+ _w.WriteLine(" {0} {1} moveto", rect.X, rect.Y);
+ _w.WriteLine(" {0} {1} lineto", rect.Right, rect.Y);
+ _w.WriteLine(" {0} {1} lineto", rect.Right, rect.Bottom);
+ _w.WriteLine(" {0} {1} lineto", rect.X, rect.Bottom);
+ _w.WriteLine(" {0} {1} lineto", rect.X, rect.Y);
+ _w.WriteLine("clip newpath");
+ }
+
+ public void SetColor(Color color)
+ {
+ _w.WriteLine("{0:0.###} {1:0.###} {2:0.###} setrgbcolor",
+ ((float)color.R) / 255f,
+ ((float)color.G) / 255f,
+ ((float)color.B) / 255f);
+ }
+
+ public void SetStroke(float width)
+ {
+ _w.WriteLine("{0:0.###} setlinewidth", width);
+ }
+
+ public void SetStroke(float width, Color color)
+ {
+ SetColor(color);
+ SetStroke(width);
+ }
+
+ public void WriteHeader()
+ {
+ var x = _size.X; // * UNITS_PER_MM
+ var y = _size.Y;
+ var right = _size.Right;
+ var bottom = _size.Bottom;
+
+ // Write document header.
+
+ _w.WriteLine("%!PS-Adobe-3.0 EPSF-3.0");
+ _w.WriteLine("%%Creator: Triangle.NET");
+ _w.WriteLine("%%Title: {0}", Name);
+ _w.WriteLine("%%Pages: 1");
+ _w.WriteLine("%%BoundingBox: {0} {1} {2} {3}", (int)x, (int)y, (int)right, (int)bottom);
+ _w.WriteLine("%%HiResBoundingBox: {0:0.#####} {1:0.#####} {2:0.#####} {3:0.#####}", x, y, right, bottom);
+ _w.WriteLine("%%Document-Fonts: Times-Roman");
+ _w.WriteLine("%%LanguageLevel: 3");
+ _w.WriteLine("%%EndComments");
+ _w.WriteLine("%%Page: 1 1");
+ _w.WriteLine("save");
+
+ // Define points.
+ _w.WriteLine("% Define points.");
+ _w.WriteLine("/P {");
+ _w.WriteLine("2 dict begin");
+ _w.WriteLine("/y exch def");
+ _w.WriteLine("/x exch def");
+ _w.WriteLine("gsave");
+ _w.WriteLine("newpath x y {0} 0 360 arc fill", DefaultPointSize);
+ _w.WriteLine("grestore");
+ _w.WriteLine("end");
+ _w.WriteLine("} def");
+
+ // Define lines.
+ _w.WriteLine("% Define lines.");
+ _w.WriteLine("/L {");
+ _w.WriteLine("2 dict begin");
+ _w.WriteLine("/y2 exch def");
+ _w.WriteLine("/x2 exch def");
+ _w.WriteLine("/y1 exch def");
+ _w.WriteLine("/x1 exch def");
+ _w.WriteLine("gsave");
+ _w.WriteLine("newpath x1 y1 moveto x2 y2 lineto stroke");
+ _w.WriteLine("grestore");
+ _w.WriteLine("end");
+ _w.WriteLine("} def");
+ }
+
+ private void Close()
+ {
+ _w.WriteLine("%");
+ _w.WriteLine("restore showpage");
+ _w.WriteLine("%%Trailer");
+ _w.WriteLine("%%EOF");
+ }
+
+ #region IDisposable implementation
+
+ // Has Dispose already been called?
+ bool disposed = false;
+
+ // Public implementation of Dispose pattern callable by consumers.
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ // Protected implementation of Dispose pattern.
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposed)
+ return;
+
+ Close();
+
+ if (disposing)
+ {
+ _w.Dispose();
+ _w = null;
+ }
+
+ // Free any unmanaged objects here.
+ //
+ disposed = true;
+ }
+
+ ~EpsDocument()
+ {
+ Dispose(false);
+ }
+
+ #endregion
+ }
+}
diff --git a/Triangle.NET/Triangle.Rendering/Text/EpsImage.cs b/src/Triangle.Rendering/Text/EpsImage.cs
similarity index 97%
rename from Triangle.NET/Triangle.Rendering/Text/EpsImage.cs
rename to src/Triangle.Rendering/Text/EpsImage.cs
index aeb1f3c..5de9176 100644
--- a/Triangle.NET/Triangle.Rendering/Text/EpsImage.cs
+++ b/src/Triangle.Rendering/Text/EpsImage.cs
@@ -1,157 +1,157 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-// Original Matlab code by John Burkardt, Florida State University
-//
-// -----------------------------------------------------------------------
-
-namespace TriangleNet.Rendering.Text
-{
- using System;
- using System.IO;
- using TriangleNet;
- using TriangleNet.Geometry;
-
- using Color = System.Drawing.Color;
- using IntPoint = System.Drawing.Point;
- using IntRectangle = System.Drawing.Rectangle;
-
- ///
- /// Writes a mesh to an EPS file.
- ///
- public class EpsImage
- {
- // EPS page metrics
- PageSize ps = new PageSize(36, 126, 576, 666);
- PageSize clip = new PageSize(18, 108, 594, 684);
-
- // Mesh metrics
- double x_max, x_min;
- double y_max, y_min;
-
- // TODO: use color manager
- private static Color ColorPoints = Color.FromArgb(0, 100, 0);
- private static Color ColorLines = Color.FromArgb(150, 150, 150);
- private static Color ColorSegments = Color.FromArgb(70, 130, 180);
- private static Color ColorBorder = Color.FromArgb(230, 230, 230);
-
- ///
- /// Export the mesh to EPS format.
- ///
- /// The current mesh.
- /// The EPS filename.
- /// The desired width of the image (currently ignored).
- public void Export(Mesh mesh, string filename, int width)
- {
- // Check file name
- if (String.IsNullOrWhiteSpace(filename))
- {
- filename = String.Format("mesh-{0}.eps", DateTime.Now.ToString("yyyy-M-d-hh-mm-ss"));
- }
-
- if (!filename.EndsWith(".eps"))
- {
- filename = Path.ChangeExtension(filename, ".eps");
- }
-
- UpdateMetrics(mesh.Bounds);
-
- using (var eps = new EpsDocument(filename, ps))
- {
- int n = mesh.Vertices.Count;
-
- // Size of the points.
- eps.DefaultPointSize = (n < 100) ? 3 : ((n < 500) ? 2 : 1);
-
- eps.WriteHeader();
-
- // Draw a gray border around the page.
- eps.SetColor(ColorBorder);
- eps.DrawRectangle(GetRectangle(ps));
-
- // Define a clipping polygon.
- eps.SetClip(GetRectangle(clip));
-
- // Draw edges.
- eps.AddComment("Draw edges.");
- eps.SetStroke(0.4f, ColorLines);
-
- foreach (var e in EdgeIterator.EnumerateEdges(mesh))
- {
- eps.DrawLine(Transform(e.GetVertex(0)), Transform(e.GetVertex(1)));
- }
-
- // Draw Segments.
- eps.AddComment("Draw Segments.");
- eps.SetStroke(0.8f, ColorSegments);
-
- foreach (var s in mesh.Segments)
- {
- eps.DrawLine(Transform(s.GetVertex(0)), Transform(s.GetVertex(1)));
- }
-
- // Draw points.
- eps.AddComment("Draw points.");
- eps.SetColor(ColorPoints);
-
- foreach (var node in mesh.Vertices)
- {
- eps.DrawPoint(Transform(node));
- }
- }
- }
-
- private IntRectangle GetRectangle(PageSize size)
- {
- return new IntRectangle((int)size.X, (int)size.Y, (int)size.Width, (int)size.Height);
- }
-
- private IntPoint Transform(Point p)
- {
- return Transform(p.X, p.Y);
- }
-
- private IntPoint Transform(double x, double y)
- {
- return new IntPoint(
- (int)Math.Floor(((x_max - x) * ps.X + (x - x_min) * ps.Right) / (x_max - x_min)),
- (int)Math.Floor(((y_max - y) * ps.Y + (y - y_min) * ps.Bottom) / (y_max - y_min))
- );
- }
-
- private void UpdateMetrics(Rectangle bounds)
- {
- x_max = bounds.Right;
- x_min = bounds.Left;
- y_max = bounds.Top;
- y_min = bounds.Bottom;
-
- // Enlarge width 5% on each side
- double x_scale = x_max - x_min;
- x_max = x_max + 0.05 * x_scale;
- x_min = x_min - 0.05 * x_scale;
- x_scale = x_max - x_min;
-
- // Enlarge height 5% on each side
- double y_scale = y_max - y_min;
- y_max = y_max + 0.05 * y_scale;
- y_min = y_min - 0.05 * y_scale;
- y_scale = y_max - y_min;
-
- if (x_scale < y_scale)
- {
- int delta = (int)Math.Round((ps.Right - ps.X) * (y_scale - x_scale) / (2.0 * y_scale));
-
- ps.Expand(-delta, 0);
- clip.Expand(-delta, 0);
- }
- else
- {
- int delta = (int)Math.Round((ps.Bottom - ps.Y) * (x_scale - y_scale) / (2.0 * x_scale));
-
- ps.Expand(0, -delta);
- clip.Expand(0, -delta);
- }
- }
- }
-}
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+// Original Matlab code by John Burkardt, Florida State University
+//
+// -----------------------------------------------------------------------
+
+namespace TriangleNet.Rendering.Text
+{
+ using System;
+ using System.IO;
+ using TriangleNet;
+ using TriangleNet.Geometry;
+ using TriangleNet.Meshing.Iterators;
+ using Color = System.Drawing.Color;
+ using IntPoint = System.Drawing.Point;
+ using IntRectangle = System.Drawing.Rectangle;
+
+ ///
+ /// Writes a mesh to an EPS file.
+ ///
+ public class EpsImage
+ {
+ // EPS page metrics
+ PageSize ps = new PageSize(36, 126, 576, 666);
+ PageSize clip = new PageSize(18, 108, 594, 684);
+
+ // Mesh metrics
+ double x_max, x_min;
+ double y_max, y_min;
+
+ // TODO: use color manager
+ private static Color ColorPoints = Color.FromArgb(0, 100, 0);
+ private static Color ColorLines = Color.FromArgb(150, 150, 150);
+ private static Color ColorSegments = Color.FromArgb(70, 130, 180);
+ private static Color ColorBorder = Color.FromArgb(230, 230, 230);
+
+ ///
+ /// Export the mesh to EPS format.
+ ///
+ /// The current mesh.
+ /// The EPS filename.
+ /// The desired width of the image (currently ignored).
+ public void Export(Mesh mesh, string filename, int width)
+ {
+ // Check file name
+ if (String.IsNullOrWhiteSpace(filename))
+ {
+ filename = String.Format("mesh-{0}.eps", DateTime.Now.ToString("yyyy-M-d-hh-mm-ss"));
+ }
+
+ if (!filename.EndsWith(".eps"))
+ {
+ filename = Path.ChangeExtension(filename, ".eps");
+ }
+
+ UpdateMetrics(mesh.Bounds);
+
+ using (var eps = new EpsDocument(filename, ps))
+ {
+ int n = mesh.Vertices.Count;
+
+ // Size of the points.
+ eps.DefaultPointSize = (n < 100) ? 3 : ((n < 500) ? 2 : 1);
+
+ eps.WriteHeader();
+
+ // Draw a gray border around the page.
+ eps.SetColor(ColorBorder);
+ eps.DrawRectangle(GetRectangle(ps));
+
+ // Define a clipping polygon.
+ eps.SetClip(GetRectangle(clip));
+
+ // Draw edges.
+ eps.AddComment("Draw edges.");
+ eps.SetStroke(0.4f, ColorLines);
+
+ foreach (var e in EdgeIterator.EnumerateEdges(mesh))
+ {
+ eps.DrawLine(Transform(e.GetVertex(0)), Transform(e.GetVertex(1)));
+ }
+
+ // Draw Segments.
+ eps.AddComment("Draw Segments.");
+ eps.SetStroke(0.8f, ColorSegments);
+
+ foreach (var s in mesh.Segments)
+ {
+ eps.DrawLine(Transform(s.GetVertex(0)), Transform(s.GetVertex(1)));
+ }
+
+ // Draw points.
+ eps.AddComment("Draw points.");
+ eps.SetColor(ColorPoints);
+
+ foreach (var node in mesh.Vertices)
+ {
+ eps.DrawPoint(Transform(node));
+ }
+ }
+ }
+
+ private IntRectangle GetRectangle(PageSize size)
+ {
+ return new IntRectangle((int)size.X, (int)size.Y, (int)size.Width, (int)size.Height);
+ }
+
+ private IntPoint Transform(Point p)
+ {
+ return Transform(p.X, p.Y);
+ }
+
+ private IntPoint Transform(double x, double y)
+ {
+ return new IntPoint(
+ (int)Math.Floor(((x_max - x) * ps.X + (x - x_min) * ps.Right) / (x_max - x_min)),
+ (int)Math.Floor(((y_max - y) * ps.Y + (y - y_min) * ps.Bottom) / (y_max - y_min))
+ );
+ }
+
+ private void UpdateMetrics(Rectangle bounds)
+ {
+ x_max = bounds.Right;
+ x_min = bounds.Left;
+ y_max = bounds.Top;
+ y_min = bounds.Bottom;
+
+ // Enlarge width 5% on each side
+ double x_scale = x_max - x_min;
+ x_max = x_max + 0.05 * x_scale;
+ x_min = x_min - 0.05 * x_scale;
+ x_scale = x_max - x_min;
+
+ // Enlarge height 5% on each side
+ double y_scale = y_max - y_min;
+ y_max = y_max + 0.05 * y_scale;
+ y_min = y_min - 0.05 * y_scale;
+ y_scale = y_max - y_min;
+
+ if (x_scale < y_scale)
+ {
+ int delta = (int)Math.Round((ps.Right - ps.X) * (y_scale - x_scale) / (2.0 * y_scale));
+
+ ps.Expand(-delta, 0);
+ clip.Expand(-delta, 0);
+ }
+ else
+ {
+ int delta = (int)Math.Round((ps.Bottom - ps.Y) * (x_scale - y_scale) / (2.0 * x_scale));
+
+ ps.Expand(0, -delta);
+ clip.Expand(0, -delta);
+ }
+ }
+ }
+}
diff --git a/Triangle.NET/Triangle.Rendering/Text/FormattingStreamWriter.cs b/src/Triangle.Rendering/Text/FormattingStreamWriter.cs
similarity index 90%
rename from Triangle.NET/Triangle.Rendering/Text/FormattingStreamWriter.cs
rename to src/Triangle.Rendering/Text/FormattingStreamWriter.cs
index b3cdd1d..e134a7c 100644
--- a/Triangle.NET/Triangle.Rendering/Text/FormattingStreamWriter.cs
+++ b/src/Triangle.Rendering/Text/FormattingStreamWriter.cs
@@ -1,73 +1,67 @@
-
-namespace TriangleNet.Rendering.Text
-{
- using System;
- using System.Globalization;
- using System.IO;
-
- ///
- ///
- ///
- ///
- /// From http://stackoverflow.com/questions/12011789/streamwriter-and-iformatprovider
- ///
- public class FormattingStreamWriter : StreamWriter
- {
- private readonly IFormatProvider formatProvider;
-
- ///
- /// Initializes a new instance of the StreamWriter class for the specified file
- /// by using the default encoding and buffer size.
- ///
- /// The complete file path to write to.
- public FormattingStreamWriter(string path)
- : this(path, CultureInfo.InvariantCulture)
- {
- }
-
- ///
- /// Initializes a new instance of the StreamWriter class for the specified stream
- /// by using UTF-8 encoding and the default buffer size.
- ///
- /// The stream to write to.
- public FormattingStreamWriter(Stream stream)
- : this(stream, CultureInfo.InvariantCulture)
- {
- }
-
- ///
- /// Initializes a new instance of the StreamWriter class for the specified file
- /// by using the default encoding and buffer size.
- ///
- /// The complete file path to write to.
- /// The format provider.
- public FormattingStreamWriter(string path, IFormatProvider formatProvider)
- : base(path)
- {
- this.formatProvider = formatProvider;
- }
-
- ///
- /// Initializes a new instance of the StreamWriter class for the specified stream
- /// by using UTF-8 encoding and the default buffer size.
- ///
- /// The stream to write to.
- /// The format provider.
- public FormattingStreamWriter(Stream stream, IFormatProvider formatProvider)
- : base(stream)
- {
- this.formatProvider = formatProvider;
- }
-
- ///
- /// Gets an object that controls formatting.
- ///
- public override IFormatProvider FormatProvider
- {
- get
- {
- return this.formatProvider;
- }
- }
- }
-}
+
+namespace TriangleNet.Rendering.Text
+{
+ using System;
+ using System.Globalization;
+ using System.IO;
+
+ ///
+ /// A class allowing to specify the .
+ ///
+ ///
+ /// From http://stackoverflow.com/questions/12011789/streamwriter-and-iformatprovider
+ ///
+ public class FormattingStreamWriter : StreamWriter
+ {
+ private readonly IFormatProvider formatProvider;
+
+ ///
+ /// Initializes a new instance of the StreamWriter class for the specified file
+ /// by using the default encoding and buffer size.
+ ///
+ /// The complete file path to write to.
+ public FormattingStreamWriter(string path)
+ : this(path, CultureInfo.InvariantCulture)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the StreamWriter class for the specified stream
+ /// by using UTF-8 encoding and the default buffer size.
+ ///
+ /// The stream to write to.
+ public FormattingStreamWriter(Stream stream)
+ : this(stream, CultureInfo.InvariantCulture)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the StreamWriter class for the specified file
+ /// by using the default encoding and buffer size.
+ ///
+ /// The complete file path to write to.
+ /// The format provider.
+ public FormattingStreamWriter(string path, IFormatProvider formatProvider)
+ : base(path)
+ {
+ this.formatProvider = formatProvider;
+ }
+
+ ///
+ /// Initializes a new instance of the StreamWriter class for the specified stream
+ /// by using UTF-8 encoding and the default buffer size.
+ ///
+ /// The stream to write to.
+ /// The format provider.
+ public FormattingStreamWriter(Stream stream, IFormatProvider formatProvider)
+ : base(stream)
+ {
+ this.formatProvider = formatProvider;
+ }
+
+ ///
+ /// Gets an object that controls formatting.
+ ///
+ public override IFormatProvider FormatProvider => formatProvider;
+ }
+}
diff --git a/Triangle.NET/Triangle.Rendering/Text/PageSize.cs b/src/Triangle.Rendering/Text/PageSize.cs
similarity index 95%
rename from Triangle.NET/Triangle.Rendering/Text/PageSize.cs
rename to src/Triangle.Rendering/Text/PageSize.cs
index 9d2f5c9..594235b 100644
--- a/Triangle.NET/Triangle.Rendering/Text/PageSize.cs
+++ b/src/Triangle.Rendering/Text/PageSize.cs
@@ -1,81 +1,81 @@
-
-namespace TriangleNet.Rendering.Text
-{
- using System.Drawing;
-
- ///
- /// Page size in millimeters.
- ///
- public struct PageSize
- {
- private const float MM_PER_INCH = 2.54f;
-
- public static readonly PageSize A3 = new PageSize(297.0f, 420.0f);
- public static readonly PageSize A4 = new PageSize(210.0f, 297.0f);
- public static readonly PageSize A5 = new PageSize(148.0f, 210.0f);
- public static readonly PageSize LETTER = new PageSize(8.5f * MM_PER_INCH, 11.0f * MM_PER_INCH);
- public static readonly PageSize LEGAL = new PageSize(8.5f * MM_PER_INCH, 14.0f * MM_PER_INCH);
-
- private float left;
- private float top;
- private float right;
- private float bottom;
-
- public float X
- {
- get { return left; }
- }
-
- public float Y
- {
- get { return top; }
- }
-
- public float Width
- {
- get { return right - left; }
- }
-
- public float Height
- {
- get { return bottom - top; }
- }
-
- public float Right
- {
- get { return right; }
- }
-
- public float Bottom
- {
- get { return bottom; }
- }
-
- public PageSize(float left, float top, float right, float bottom)
- {
- this.left = left;
- this.top = top;
- this.right = right;
- this.bottom = bottom;
- }
-
- public PageSize(float width, float height)
- : this(0.0f, 0.0f, width, height)
- {
- }
-
- public PageSize(Rectangle size)
- : this(size.Left, size.Right, size.Top, size.Bottom)
- {
- }
-
- public void Expand(float dx, float dy)
- {
- left -= dx;
- top -= dy;
-
- right += dx;
- bottom += dy;
- }
- }
-}
+
+namespace TriangleNet.Rendering.Text
+{
+ using System.Drawing;
+
+ ///
+ /// Page size in millimeters.
+ ///
+ public struct PageSize
+ {
+ private const float MM_PER_INCH = 2.54f;
+
+ public static readonly PageSize A3 = new PageSize(297.0f, 420.0f);
+ public static readonly PageSize A4 = new PageSize(210.0f, 297.0f);
+ public static readonly PageSize A5 = new PageSize(148.0f, 210.0f);
+ public static readonly PageSize LETTER = new PageSize(8.5f * MM_PER_INCH, 11.0f * MM_PER_INCH);
+ public static readonly PageSize LEGAL = new PageSize(8.5f * MM_PER_INCH, 14.0f * MM_PER_INCH);
+
+ private float left;
+ private float top;
+ private float right;
+ private float bottom;
+
+ public float X
+ {
+ get { return left; }
+ }
+
+ public float Y
+ {
+ get { return top; }
+ }
+
+ public float Width
+ {
+ get { return right - left; }
+ }
+
+ public float Height
+ {
+ get { return bottom - top; }
+ }
+
+ public float Right
+ {
+ get { return right; }
+ }
+
+ public float Bottom
+ {
+ get { return bottom; }
+ }
+
+ public PageSize(float left, float top, float right, float bottom)
+ {
+ this.left = left;
+ this.top = top;
+ this.right = right;
+ this.bottom = bottom;
+ }
+
+ public PageSize(float width, float height)
+ : this(0.0f, 0.0f, width, height)
+ {
+ }
+
+ public PageSize(Rectangle size)
+ : this(size.Left, size.Right, size.Top, size.Bottom)
+ {
+ }
+
+ public void Expand(float dx, float dy)
+ {
+ left -= dx;
+ top -= dy;
+
+ right += dx;
+ bottom += dy;
+ }
+ }
+}
diff --git a/Triangle.NET/Triangle.Rendering/Text/SvgImage.cs b/src/Triangle.Rendering/Text/SvgImage.cs
similarity index 83%
rename from Triangle.NET/Triangle.Rendering/Text/SvgImage.cs
rename to src/Triangle.Rendering/Text/SvgImage.cs
index d1e2ce4..5b63777 100644
--- a/Triangle.NET/Triangle.Rendering/Text/SvgImage.cs
+++ b/src/Triangle.Rendering/Text/SvgImage.cs
@@ -1,254 +1,266 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace TriangleNet.Rendering.Text
-{
- using System;
- using System.IO;
- using System.Text;
- using TriangleNet;
- using TriangleNet.Geometry;
-
- ///
- /// Writes a mesh to an SVG file.
- ///
- public class SvgImage
- {
- // Iterations to insert a linebreak in SVG path.
- private const int LINEBREAK_COUNT = 10;
-
- float scale = 1f;
-
- ///
- /// Export the mesh to SVG format.
- ///
- /// The current mesh.
- /// The SVG filename.
- /// The desired width of the image.
- public void Export(Mesh mesh, string filename, int width)
- {
- // Check file name
- if (String.IsNullOrWhiteSpace(filename))
- {
- filename = String.Format("mesh-{0}.svg", DateTime.Now.ToString("yyyy-M-d-hh-mm-ss"));
- }
-
- if (!filename.EndsWith(".svg"))
- {
- filename = Path.ChangeExtension(filename, ".svg");
- }
-
- if (width < 200)
- {
- width = 200;
- }
-
- var bounds = mesh.Bounds;
-
- float margin = 0.05f * (float)bounds.Width;
-
- scale = width / ((float)bounds.Width + 2 * margin);
-
- int x_offset = -(int)((bounds.Left - margin) * scale);
- int y_offset = (int)((bounds.Top + margin) * scale);
-
- int height = (int)((bounds.Height + 2 * margin) * scale);
-
- using (var svg = new FormattingStreamWriter(filename))
- {
- svg.WriteLine("");
- }
- }
-
- private void DrawTriangles(StreamWriter svg, Mesh mesh, bool label)
- {
- svg.Write("\t{2}",
- xa, ya, tri.ID);
- labels.AppendLine();
- }
- }
-
- svg.WriteLine("\" style=\"stroke:#c2c2c2; fill:none; stroke-linejoin:bevel;\"/>");
-
- // Label the triangles.
- if (label)
- {
- svg.WriteLine("\t");
- svg.Write(labels.ToString());
- svg.WriteLine("\t");
- }
- }
-
- private void DrawEdges(StreamWriter svg, Mesh mesh)
- {
- svg.Write("\t");
- }
-
- private void DrawSegments(StreamWriter svg, Mesh mesh)
- {
- svg.Write("\t");
- }
-
- private void DrawPoints(StreamWriter svg, Mesh mesh, bool label)
- {
- int n = mesh.Vertices.Count;
-
- float circle_size = 1.5f;
-
- if (n < 100)
- {
- circle_size = 3;
- }
- else if (n < 500)
- {
- circle_size = 2;
- }
-
- svg.WriteLine("\t");
-
- double x, y;
-
- StringBuilder labels = new StringBuilder();
-
- foreach (var node in mesh.Vertices)
- {
- x = scale * node.X;
- y = scale * node.Y;
-
- svg.WriteLine("\t\t",
- x, y, circle_size);
-
- if (label)
- {
- labels.AppendFormat("{2}",
- x, y, node.ID);
- labels.AppendLine();
- }
- }
-
- svg.WriteLine("\t");
-
- // Label the nodes.
- if (label)
- {
- svg.WriteLine("\t");
- svg.Write(labels.ToString());
- svg.WriteLine("\t");
- }
- }
- }
-}
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+//
+// -----------------------------------------------------------------------
+
+namespace TriangleNet.Rendering.Text
+{
+ using System;
+ using System.IO;
+ using System.Text;
+ using TriangleNet;
+ using TriangleNet.Geometry;
+ using TriangleNet.Meshing;
+ using TriangleNet.Meshing.Iterators;
+
+ ///
+ /// Writes a mesh to an SVG file.
+ ///
+ public class SvgImage
+ {
+ // Iterations to insert a linebreak in SVG path.
+ private const int LINEBREAK_COUNT = 10;
+
+ float scale = 1f;
+
+ ///
+ /// Exports a mesh to SVG format.
+ ///
+ /// The mesh.
+ /// The SVG filename.
+ /// The desired width (pixel) of the image.
+ /// Enable rendering of regions.
+ /// Enable rendering of points.
+ public static void Save(IMesh mesh, string file = null, int width = 800,
+ bool regions = false, bool points = true)
+ {
+ new SvgImage().Export(mesh, file, width);
+ }
+
+ ///
+ /// Export a mesh to SVG format.
+ ///
+ /// The current mesh.
+ /// The SVG filename.
+ /// The desired width of the image.
+ public void Export(IMesh mesh, string filename, int width)
+ {
+ // Check file name
+ if (string.IsNullOrWhiteSpace(filename))
+ {
+ filename = string.Format("mesh-{0}.svg", DateTime.Now.ToString("yyyy-M-d-hh-mm-ss"));
+ }
+
+ if (!filename.EndsWith(".svg"))
+ {
+ filename = Path.ChangeExtension(filename, ".svg");
+ }
+
+ if (width < 200)
+ {
+ width = 200;
+ }
+
+ var bounds = mesh.Bounds;
+
+ float margin = 0.05f * (float)bounds.Width;
+
+ scale = width / ((float)bounds.Width + 2 * margin);
+
+ int x_offset = -(int)((bounds.Left - margin) * scale);
+ int y_offset = (int)((bounds.Top + margin) * scale);
+
+ int height = (int)((bounds.Height + 2 * margin) * scale);
+
+ using (var svg = new FormattingStreamWriter(filename))
+ {
+ svg.WriteLine("");
+ }
+ }
+
+ private void DrawTriangles(StreamWriter svg, IMesh mesh, bool label)
+ {
+ svg.Write("\t{2}",
+ xa, ya, tri.ID);
+ labels.AppendLine();
+ }
+ }
+
+ svg.WriteLine("\" style=\"stroke:#c2c2c2; fill:none; stroke-linejoin:bevel;\"/>");
+
+ // Label the triangles.
+ if (label)
+ {
+ svg.WriteLine("\t");
+ svg.Write(labels.ToString());
+ svg.WriteLine("\t");
+ }
+ }
+
+ private void DrawEdges(StreamWriter svg, IMesh mesh)
+ {
+ svg.Write("\t");
+ }
+
+ private void DrawSegments(StreamWriter svg, IMesh mesh)
+ {
+ svg.Write("\t");
+ }
+
+ private void DrawPoints(StreamWriter svg, IMesh mesh, bool label)
+ {
+ int n = mesh.Vertices.Count;
+
+ float circle_size = 1.5f;
+
+ if (n < 100)
+ {
+ circle_size = 3;
+ }
+ else if (n < 500)
+ {
+ circle_size = 2;
+ }
+
+ svg.WriteLine("\t");
+
+ double x, y;
+
+ var labels = new StringBuilder();
+
+ foreach (var node in mesh.Vertices)
+ {
+ x = scale * node.X;
+ y = scale * node.Y;
+
+ svg.WriteLine("\t\t",
+ x, y, circle_size);
+
+ if (label)
+ {
+ labels.AppendFormat("{2}",
+ x, y, node.ID);
+ labels.AppendLine();
+ }
+ }
+
+ svg.WriteLine("\t");
+
+ // Label the nodes.
+ if (label)
+ {
+ svg.WriteLine("\t");
+ svg.Write(labels.ToString());
+ svg.WriteLine("\t");
+ }
+ }
+ }
+}
diff --git a/src/Triangle.Rendering/Triangle.Rendering.csproj b/src/Triangle.Rendering/Triangle.Rendering.csproj
new file mode 100644
index 0000000..9618430
--- /dev/null
+++ b/src/Triangle.Rendering/Triangle.Rendering.csproj
@@ -0,0 +1,15 @@
+
+
+
+ Library
+ net6.0
+ TriangleNet.Rendering
+ Triangle.Rendering
+ AnyCPU;x64
+
+
+
+
+
+
+
diff --git a/Triangle.NET/Triangle.Rendering/Util/ColorMap.cs b/src/Triangle.Rendering/Util/ColorMap.cs
similarity index 95%
rename from Triangle.NET/Triangle.Rendering/Util/ColorMap.cs
rename to src/Triangle.Rendering/Util/ColorMap.cs
index ca53def..37adde3 100644
--- a/Triangle.NET/Triangle.Rendering/Util/ColorMap.cs
+++ b/src/Triangle.Rendering/Util/ColorMap.cs
@@ -1,112 +1,112 @@
-
-namespace TriangleNet.Rendering.Util
-{
- using System;
- using System.Drawing;
-
- public class ColorMap
- {
- #region Colormap definitions
-
- public static ColorMap Jet(int size)
- {
- ColorMap map = new ColorMap(size);
- float v, step = 1.0f / (size - 1);
- float[] rgb = new float[3];
-
- for (int i = 0; i < size; i += 1)
- {
- v = 4 * i * step;
-
- rgb[0] = Math.Min(v - 1.5f, 4.5f - v);
- rgb[1] = Math.Min(v - 0.5f, 3.5f - v);
- rgb[2] = Math.Min(v + 0.5f, 2.5f - v);
-
- Clamp(rgb, 0.0f, 1.0f);
-
- map.colors[size - i - 1] = ColorFromRgb(rgb[0], rgb[1], rgb[2]);
- }
-
- return map;
- }
-
- public static ColorMap Hot(int size)
- {
- ColorMap map = new ColorMap(size);
- float v, step = 1.0f / (size - 1);
- float[] rgb = new float[3];
-
- for (int i = 0; i < size; i += 1)
- {
- v = 2.5f * i * step;
-
- rgb[0] = v;
- rgb[1] = v - 1;
- rgb[2] = 2 * v - 4;
-
- Clamp(rgb, 0.0f, 1.0f);
-
- map.colors[i] = ColorFromRgb(rgb[0], rgb[1], rgb[2]);
- }
-
- return map;
- }
-
- #endregion
-
- #region Helper
-
- private static Color ColorFromRgb(float r, float g, float b)
- {
- byte max = byte.MaxValue;
-
- return Color.FromArgb((byte)(r * max), (byte)(g * max), (byte)(b * max));
- }
-
- private static void Clamp(float[] values, float min, float max)
- {
- int n = values.Length;
-
- for (int i = 0; i < n; i += 1)
- {
- values[i] = Math.Min(max, Math.Max(min, values[i]));
- }
- }
-
- private static int Clamp(int index, int max)
- {
- if (index < 0)
- {
- index = 0;
- }
- else if (index > max)
- {
- index = max;
- }
-
- return index;
- }
-
- #endregion
-
- private Color[] colors;
-
- private ColorMap(int size)
- {
- this.colors = new Color[size];
- }
-
- public ColorMap(Color[] colors)
- {
- this.colors = colors;
- }
-
- public Color GetColor(double value, double min, double max)
- {
- int n = this.colors.Length;
- int i = (int)Math.Floor(n * (max - value) / (max - min));
-
- return this.colors[Clamp(i, n - 1)];
- }
- }
-}
+
+namespace TriangleNet.Rendering.Util
+{
+ using System;
+ using System.Drawing;
+
+ public class ColorMap
+ {
+ #region Colormap definitions
+
+ public static ColorMap Jet(int size)
+ {
+ ColorMap map = new ColorMap(size);
+ float v, step = 1.0f / (size - 1);
+ float[] rgb = new float[3];
+
+ for (int i = 0; i < size; i += 1)
+ {
+ v = 4 * i * step;
+
+ rgb[0] = Math.Min(v - 1.5f, 4.5f - v);
+ rgb[1] = Math.Min(v - 0.5f, 3.5f - v);
+ rgb[2] = Math.Min(v + 0.5f, 2.5f - v);
+
+ Clamp(rgb, 0.0f, 1.0f);
+
+ map.colors[size - i - 1] = ColorFromRgb(rgb[0], rgb[1], rgb[2]);
+ }
+
+ return map;
+ }
+
+ public static ColorMap Hot(int size)
+ {
+ ColorMap map = new ColorMap(size);
+ float v, step = 1.0f / (size - 1);
+ float[] rgb = new float[3];
+
+ for (int i = 0; i < size; i += 1)
+ {
+ v = 2.5f * i * step;
+
+ rgb[0] = v;
+ rgb[1] = v - 1;
+ rgb[2] = 2 * v - 4;
+
+ Clamp(rgb, 0.0f, 1.0f);
+
+ map.colors[i] = ColorFromRgb(rgb[0], rgb[1], rgb[2]);
+ }
+
+ return map;
+ }
+
+ #endregion
+
+ #region Helper
+
+ private static Color ColorFromRgb(float r, float g, float b)
+ {
+ byte max = byte.MaxValue;
+
+ return Color.FromArgb((byte)(r * max), (byte)(g * max), (byte)(b * max));
+ }
+
+ private static void Clamp(float[] values, float min, float max)
+ {
+ int n = values.Length;
+
+ for (int i = 0; i < n; i += 1)
+ {
+ values[i] = Math.Min(max, Math.Max(min, values[i]));
+ }
+ }
+
+ private static int Clamp(int index, int max)
+ {
+ if (index < 0)
+ {
+ index = 0;
+ }
+ else if (index > max)
+ {
+ index = max;
+ }
+
+ return index;
+ }
+
+ #endregion
+
+ private Color[] colors;
+
+ private ColorMap(int size)
+ {
+ this.colors = new Color[size];
+ }
+
+ public ColorMap(Color[] colors)
+ {
+ this.colors = colors;
+ }
+
+ public Color GetColor(double value, double min, double max)
+ {
+ int n = this.colors.Length;
+ int i = (int)Math.Floor(n * (max - value) / (max - min));
+
+ return this.colors[Clamp(i, n - 1)];
+ }
+ }
+}
diff --git a/Triangle.NET/Triangle.Rendering/Util/ReflectionHelper.cs b/src/Triangle.Rendering/Util/ReflectionHelper.cs
similarity index 96%
rename from Triangle.NET/Triangle.Rendering/Util/ReflectionHelper.cs
rename to src/Triangle.Rendering/Util/ReflectionHelper.cs
index 528fea3..6ed1a65 100644
--- a/Triangle.NET/Triangle.Rendering/Util/ReflectionHelper.cs
+++ b/src/Triangle.Rendering/Util/ReflectionHelper.cs
@@ -1,81 +1,81 @@
-
-namespace TriangleNet.Rendering.Util
-{
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Reflection;
-
- internal static class ReflectionHelper
- {
- public static bool TryCreateControl(string assemblyName, IEnumerable dependencies,
- out IRenderControl control)
- {
- return TryCreateControl(assemblyName, dependencies, null, out control);
- }
-
- public static bool TryCreateControl(string assemblyName, IEnumerable dependencies,
- string className, out IRenderControl control)
- {
- control = null;
-
- if (!FilesExist(assemblyName, dependencies))
- {
- return false;
- }
-
- assemblyName = Path.GetFileNameWithoutExtension(assemblyName);
-
- // Try create render control instance.
- try
- {
- // Load the assembly into the current application domain.
- var assembly = Assembly.Load(assemblyName);
-
- // Get all types implementing the IRenderControl interface.
- var type = typeof(IRenderControl);
- var matches = assembly.GetTypes().Where(s => type.IsAssignableFrom(s));
-
- var match = string.IsNullOrEmpty(className) ? matches.FirstOrDefault()
- : matches.Where(s => s.Name == className).FirstOrDefault();
-
- if (match != null)
- {
- // Create an instance.
- control = (IRenderControl)Activator.CreateInstance(match);
- }
- }
- catch (Exception)
- {
- return false;
- }
-
- // Return true if render control was successfully created.
- return (control != null);
- }
-
- private static bool FilesExist(string assemblyName, IEnumerable dependencies)
- {
- // Check if assembly exists
- if (!File.Exists(assemblyName))
- {
- return false;
- }
-
- // Check if dependencies exists
- if (dependencies != null)
- {
- foreach (var item in dependencies)
- {
- if (!File.Exists(item))
- {
- return false;
- }
- }
- }
-
- return true;
- }
- }
-}
+
+namespace TriangleNet.Rendering.Util
+{
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Linq;
+ using System.Reflection;
+
+ internal static class ReflectionHelper
+ {
+ public static bool TryCreateControl(string assemblyName, IEnumerable dependencies,
+ out IRenderControl control)
+ {
+ return TryCreateControl(assemblyName, dependencies, null, out control);
+ }
+
+ public static bool TryCreateControl(string assemblyName, IEnumerable dependencies,
+ string className, out IRenderControl control)
+ {
+ control = null;
+
+ if (!FilesExist(assemblyName, dependencies))
+ {
+ return false;
+ }
+
+ assemblyName = Path.GetFileNameWithoutExtension(assemblyName);
+
+ // Try create render control instance.
+ try
+ {
+ // Load the assembly into the current application domain.
+ var assembly = Assembly.Load(assemblyName);
+
+ // Get all types implementing the IRenderControl interface.
+ var type = typeof(IRenderControl);
+ var matches = assembly.GetTypes().Where(s => type.IsAssignableFrom(s));
+
+ var match = string.IsNullOrEmpty(className) ? matches.FirstOrDefault()
+ : matches.Where(s => s.Name == className).FirstOrDefault();
+
+ if (match != null)
+ {
+ // Create an instance.
+ control = (IRenderControl)Activator.CreateInstance(match);
+ }
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+
+ // Return true if render control was successfully created.
+ return (control != null);
+ }
+
+ private static bool FilesExist(string assemblyName, IEnumerable dependencies)
+ {
+ // Check if assembly exists
+ if (!File.Exists(assemblyName))
+ {
+ return false;
+ }
+
+ // Check if dependencies exists
+ if (dependencies != null)
+ {
+ foreach (var item in dependencies)
+ {
+ if (!File.Exists(item))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/src/Triangle.Tests/Geomerty/ContourTest.cs b/src/Triangle.Tests/Geomerty/ContourTest.cs
new file mode 100644
index 0000000..087c23f
--- /dev/null
+++ b/src/Triangle.Tests/Geomerty/ContourTest.cs
@@ -0,0 +1,86 @@
+using NUnit.Framework;
+using TriangleNet.Geometry;
+using System;
+using System.Collections.Generic;
+
+namespace TriangleNet.Tests.Geometry
+{
+ public class ContourTest
+ {
+ [Test]
+ public void TestFindInteriorPoint()
+ {
+ // The vertices that define the contour (have to be in order, obviously).
+ var vertices = new Vertex[]
+ {
+ new Vertex(0d, 0d),
+ new Vertex(1d ,0d),
+ new Vertex(1d, 1d),
+ new Vertex(0d, 1d),
+ };
+
+ var contour = new Contour(vertices);
+
+ var p = contour.FindInteriorPoint();
+
+ Assert.IsTrue(p.X > 0d && p.X < 1d && p.Y > 0d && p.Y < 1d);
+ }
+
+ [Test]
+ public void TestFindInteriorPointL()
+ {
+ // L-shaped contour (FindPointInPolygon() produces a test candidate
+ // which lies exactly on a segment where IsPointInPolygon() returns
+ // true, so IsPointOnSegment() is actually needed here).
+ var points = new List()
+ {
+ new Vertex(3, 1),
+ new Vertex(1, 1),
+ new Vertex(1, 3),
+ new Vertex(2, 3),
+ new Vertex(2, 2),
+ new Vertex(3, 2)
+ };
+
+ var contour = new Contour(points);
+
+ var poly = new Polygon(6);
+
+ poly.Add(contour, true);
+
+ var h = poly.Holes[0];
+ var p = RobustPredicates.Default;
+
+ int count = points.Count;
+ int i = count - 1;
+
+ for (int j = 0; j < count; j++)
+ {
+ double ccw = p.CounterClockwise(points[i], h, points[j]);
+
+ Assert.Greater(Math.Abs(ccw), 1e-12);
+
+ i = j;
+ }
+ }
+
+ [Test]
+ public void TestFindInteriorPointDup()
+ {
+ // Rectangle contour with duplicate point.
+ var points = new List()
+ {
+ new Vertex(0.0, 0.0),
+ new Vertex(0.0, 1.0),
+ new Vertex(2.0, 1.0),
+ new Vertex(2.0, 0.5),
+ new Vertex(2.0, 0.5), // duplicate
+ new Vertex(2.0, 0.0)
+ };
+
+ var contour = new Contour(points);
+
+ Assert.DoesNotThrow(() => contour.FindInteriorPoint());
+ }
+ }
+}
diff --git a/src/Triangle.Tests/Helper.cs b/src/Triangle.Tests/Helper.cs
new file mode 100644
index 0000000..23c675f
--- /dev/null
+++ b/src/Triangle.Tests/Helper.cs
@@ -0,0 +1,35 @@
+
+namespace TriangleNet.Tests
+{
+ using System.Collections.Generic;
+ using TriangleNet.Geometry;
+ using TriangleNet.Topology;
+
+ static class Helper
+ {
+ public static Contour Rectangle(double left, double top,
+ double right, double bottom, int mark = 0)
+ {
+ var points = new List(4);
+
+ points.Add(new Vertex(left, top, mark));
+ points.Add(new Vertex(right, top, mark));
+ points.Add(new Vertex(right, bottom, mark));
+ points.Add(new Vertex(left, bottom, mark));
+
+ return new Contour(points, mark, true);
+ }
+
+ public static Triangle CreateTriangle(int id, Vertex org, Vertex dest, Vertex apex)
+ {
+ var t = new Triangle() { id = id, hash = id };
+
+ // Node ordering 'plus 1 mod 3'.
+ t.vertices[0] = apex;
+ t.vertices[1] = org;
+ t.vertices[2] = dest;
+
+ return t;
+ }
+ }
+}
diff --git a/src/Triangle.Tests/Meshing/Algorithm/TriangulatorTest.cs b/src/Triangle.Tests/Meshing/Algorithm/TriangulatorTest.cs
new file mode 100644
index 0000000..fa7f762
--- /dev/null
+++ b/src/Triangle.Tests/Meshing/Algorithm/TriangulatorTest.cs
@@ -0,0 +1,72 @@
+using NUnit.Framework;
+using System.Collections.Generic;
+using System.Linq;
+using TriangleNet.Geometry;
+using TriangleNet.Meshing.Algorithm;
+
+namespace TriangleNet.Tests.Meshing.Algorithm
+{
+ public class TriangulatorTest
+ {
+ [Test]
+ public void TestTriangulateIncremental()
+ {
+ var t = new Incremental();
+
+ var vertices = GetVertices();
+
+ var mesh = t.Triangulate(vertices, new Configuration());
+
+ Assert.AreEqual(6, vertices.Count);
+ Assert.AreEqual(6, mesh.Vertices.Count);
+ Assert.AreEqual(1, mesh.Vertices
+ .Where(v => v.Type == VertexType.UndeadVertex)
+ .Count());
+ }
+
+ [Test]
+ public void TestTriangulateSweepLine()
+ {
+ var t = new SweepLine();
+
+ var vertices = GetVertices();
+
+ var mesh = t.Triangulate(vertices, new Configuration());
+
+ Assert.AreEqual(6, vertices.Count);
+ Assert.AreEqual(6, mesh.Vertices.Count);
+ Assert.AreEqual(1, mesh.Vertices
+ .Where(v => v.Type == VertexType.UndeadVertex)
+ .Count());
+ }
+
+ [Test]
+ public void TestTriangulateDwyer()
+ {
+ var t = new Dwyer();
+
+ var vertices = GetVertices();
+
+ var mesh = t.Triangulate(vertices, new Configuration());
+
+ Assert.AreEqual(6, vertices.Count);
+ Assert.AreEqual(6, mesh.Vertices.Count);
+ Assert.AreEqual(1, mesh.Vertices
+ .Where(v => v.Type == VertexType.UndeadVertex)
+ .Count());
+ }
+
+ private List GetVertices()
+ {
+ return new List()
+ {
+ new Vertex(0.0, 0.0),
+ new Vertex(1.0, 0.0),
+ new Vertex(1.0, 1.0),
+ new Vertex(1.0, 1.0), // duplicate
+ new Vertex(0.0, 1.0),
+ new Vertex(0.5, 0.5)
+ };
+ }
+ }
+}
diff --git a/src/Triangle.Tests/Meshing/Iterators/RegionIteratorTest.cs b/src/Triangle.Tests/Meshing/Iterators/RegionIteratorTest.cs
new file mode 100644
index 0000000..1d799e8
--- /dev/null
+++ b/src/Triangle.Tests/Meshing/Iterators/RegionIteratorTest.cs
@@ -0,0 +1,35 @@
+using NUnit.Framework;
+using TriangleNet.Geometry;
+using TriangleNet.Meshing.Iterators;
+using TriangleNet.Tools;
+using TriangleNet.Topology;
+
+namespace TriangleNet.Tests.Meshing.Iterators
+{
+ public class RegionIteratorTest
+ {
+ public void TestProcessRegionProtected()
+ {
+ var poly = new Polygon();
+
+ // Outer region.
+ poly.Add(Helper.Rectangle(-2d, 2d, 2d, -2d, 2));
+
+ // Inner region.
+ poly.Add(Helper.Rectangle(-1d, 1d, 1d, -1d, 1));
+
+ poly.Regions.Add(new RegionPointer(0d, 0d, 1));
+
+ var mesh = (Mesh)poly.Triangulate();
+
+ var iterator = new RegionIterator(mesh);
+
+ var qtree = new TriangleQuadTree(mesh);
+
+ // Find a seeding triangle in region 1.
+ var seed = (Triangle)qtree.Query(0.0, 0.0);
+
+ iterator.Process(seed, t => Assert.AreEqual(1, t.Label));
+ }
+ }
+}
diff --git a/src/Triangle.Tests/RobustPredicatesTest.cs b/src/Triangle.Tests/RobustPredicatesTest.cs
new file mode 100644
index 0000000..8f0b0c4
--- /dev/null
+++ b/src/Triangle.Tests/RobustPredicatesTest.cs
@@ -0,0 +1,55 @@
+using NUnit.Framework;
+using TriangleNet.Geometry;
+
+namespace TriangleNet.Tests
+{
+ public class RobustPredicatesTest
+ {
+ [Test]
+ public void TestCounterClockwise()
+ {
+ var robust = RobustPredicates.Default;
+
+ var a = new Point(-1d, 0d);
+ var b = new Point( 0d, 1d);
+
+ Assert.IsTrue(robust.CounterClockwise(a, b, new Point(1d, 0d)) < 0d);
+ Assert.IsTrue(robust.CounterClockwise(a, b, new Point(0d, 2d)) > 0d);
+ Assert.IsTrue(robust.CounterClockwise(a, b, new Point(1d, 2d)) == 0d);
+ }
+
+ [Test]
+ public void TestInCircle()
+ {
+ var robust = RobustPredicates.Default;
+
+ var a = new Point(-1d, 0d);
+ var b = new Point(0d, 1d);
+ var c = new Point(1d, 0d);
+
+ Assert.IsTrue(robust.InCircle(a, b, c, new Point(0d, 0.5)) < 0d);
+ Assert.IsTrue(robust.InCircle(a, b, c, new Point(0d, 1.5)) > 0d);
+ Assert.IsTrue(robust.InCircle(a, b, c, new Point(0d, 1d)) == 0d);
+ }
+
+ [Test]
+ public void TestFindCircumcenter()
+ {
+ var robust = RobustPredicates.Default;
+
+ var a = new Point(-1d, 0d);
+ var b = new Point(0d, 1d);
+ var c = new Point(1d, 0d);
+
+ double xi = 0d, eta = 0d;
+
+ var actual = robust.FindCircumcenter(a, b, c, ref xi, ref eta);
+ var expected = new Point(0d, 0d);
+
+ Assert.AreEqual(expected.X, actual.X);
+ Assert.AreEqual(expected.Y, actual.Y);
+ Assert.AreEqual(0.0, xi);
+ Assert.AreEqual(0.5, eta);
+ }
+ }
+}
diff --git a/src/Triangle.Tests/Smoothing/SimpleSmootherTest.cs b/src/Triangle.Tests/Smoothing/SimpleSmootherTest.cs
new file mode 100644
index 0000000..318cb87
--- /dev/null
+++ b/src/Triangle.Tests/Smoothing/SimpleSmootherTest.cs
@@ -0,0 +1,71 @@
+using NUnit.Framework;
+using System.Collections.Generic;
+using System.Linq;
+using TriangleNet.Geometry;
+using TriangleNet.Meshing;
+using TriangleNet.Smoothing;
+
+namespace TriangleNet.Tests.Smoothing
+{
+ public class SimpleSmootherTest
+ {
+ [Test]
+ public void TestSmoothWithDuplicate()
+ {
+ var poly = GetPolygon();
+
+ var options = new ConstraintOptions() { ConformingDelaunay = true };
+
+ var quality = new QualityOptions()
+ {
+ MinimumAngle = 30.0
+ };
+
+ var mesh = poly.Triangulate(options, quality);
+
+ Assert.AreEqual(1, mesh.Vertices
+ .Where(v => v.Type == VertexType.UndeadVertex)
+ .Count());
+
+ quality.MaximumArea = 0.2;
+
+ mesh.Refine(quality, true);
+
+ Assert.AreEqual(1, mesh.Vertices
+ .Where(v => v.Type == VertexType.UndeadVertex)
+ .Count());
+
+ var smoother = new SimpleSmoother();
+
+ // Smooth mesh.
+ smoother.Smooth(mesh, 25);
+ }
+
+ private Polygon GetPolygon()
+ {
+ var poly = new Polygon(7);
+
+ var p = new List()
+ {
+ new Vertex(0.0, 0.0, 1),
+ new Vertex(2.0, 0.0, 1),
+ new Vertex(2.0, 1.0, 1),
+ new Vertex(2.0, 2.0, 1),
+ new Vertex(0.0, 2.0, 1),
+ new Vertex(1.5, 1.6, 1),
+ new Vertex(2.0, 0.0, 1) // duplicate
+ };
+
+ poly.Points.AddRange(p);
+
+ poly.Add(new Segment(p[0], p[1], 1));
+ poly.Add(new Segment(p[1], p[2], 1));
+ poly.Add(new Segment(p[2], p[3], 1));
+ poly.Add(new Segment(p[3], p[4], 1));
+ poly.Add(new Segment(p[4], p[0], 1));
+ poly.Add(new Segment(p[2], p[5], 2));
+
+ return poly;
+ }
+ }
+}
diff --git a/src/Triangle.Tests/Tools/IntersectionHelperTest.cs b/src/Triangle.Tests/Tools/IntersectionHelperTest.cs
new file mode 100644
index 0000000..d8f2c69
--- /dev/null
+++ b/src/Triangle.Tests/Tools/IntersectionHelperTest.cs
@@ -0,0 +1,41 @@
+using NUnit.Framework;
+using TriangleNet.Geometry;
+using TriangleNet.Tools;
+
+namespace TriangleNet.Tests.Tools
+{
+ public class IntersectionHelperTest
+ {
+ [Test]
+ public void TestIsPointOnSegment()
+ {
+ var a = new Vertex(1.0, 1.0);
+ var b = new Vertex(2.0, 2.0);
+
+ // Test point = segment start point.
+ Assert.IsTrue(IntersectionHelper.IsPointOnSegment(a, b, new Vertex(1.0, 1.0)));
+
+ // Test point = segment end point.
+ Assert.IsTrue(IntersectionHelper.IsPointOnSegment(a, b, new Vertex(2.0, 2.0)));
+
+ // Test point on segment.
+ Assert.IsTrue(IntersectionHelper.IsPointOnSegment(a, b, new Vertex(1.5, 1.5)));
+
+ // Test point collinear, but not on segment.
+ Assert.IsFalse(IntersectionHelper.IsPointOnSegment(a, b, new Vertex(0.0, 0.0)));
+ Assert.IsFalse(IntersectionHelper.IsPointOnSegment(a, b, new Vertex(3.0, 3.0)));
+
+ // Test point not on segment.
+ Assert.IsFalse(IntersectionHelper.IsPointOnSegment(a, b, new Vertex(1.5, 0.5)));
+
+ double eps = 1e-12;
+
+ // Test point collinear near endpoint, but not on segment.
+ Assert.IsFalse(IntersectionHelper.IsPointOnSegment(a, b, new Vertex(2.0 + eps, 2.0 + eps)));
+ Assert.IsFalse(IntersectionHelper.IsPointOnSegment(a, b, new Vertex(2.0 - eps, 2.0 + eps)));
+
+ // Test point collinear near endpoint on segment.
+ Assert.IsTrue(IntersectionHelper.IsPointOnSegment(a, b, new Vertex(2.0 - eps, 2.0 - eps)));
+ }
+ }
+}
diff --git a/src/Triangle.Tests/Topology/OtriTest.cs b/src/Triangle.Tests/Topology/OtriTest.cs
new file mode 100644
index 0000000..6719bfa
--- /dev/null
+++ b/src/Triangle.Tests/Topology/OtriTest.cs
@@ -0,0 +1,496 @@
+
+namespace TriangleNet.Tests
+{
+ using NUnit.Framework;
+ using TriangleNet.Geometry;
+ using TriangleNet.Topology;
+
+ // The Otri (orientent triangle) struct is the heart of Triangle's mesh
+ // datastructure. It basically represents one of the three edges of the
+ // triangle by associating an orientation to the triangle object.
+ //
+ // For testing, a minimal example mesh is considered. It consists of
+ // 6 vertices and 4 triangles.
+ //
+ // Vertices:
+ // X [-2] [0] [2] [-1] [1] [0]
+ // Y [ 0] [0] [0] [ 1] [1] [2]
+ //
+ // Triangles and neighbors and neighbor orientations:
+ // [3 0 1] [-1 1 -1] [- 2 -]
+ // [3 1 4] [ 2 3 0] [2 0 1]
+ // [4 1 2] [-1 -1 1] [- - 0]
+ // [5 3 4] [ 1 -1 -1] [1 - -]
+ //
+ // The shape is one large triangle, split into four smaller ones.
+
+ public class OtriTest
+ {
+ // The vertices of the mesh.
+ Vertex[] vertices;
+
+ private Triangle[] CreateExampleMesh()
+ {
+ var triangles = new Triangle[4];
+
+ // Outer space triangle.
+ var dummy = new Triangle() { id = -1 };
+
+ // Setup triangles. Keep in mind the ordering:
+ //
+ // The CreateTriangle method takes vertex arguments in range org-dest-apex,
+ // but internally the vertices get stored in an array with ordering
+ //
+ // [0] = apex
+ // [1] = org
+ // [2] = dest
+ //
+ // This is because, for example, and oriented triange will return as its
+ // origin (Org() method) the element at index [(orientation + 1) % 3].
+ var t0 = triangles[0] = Helper.CreateTriangle(0, vertices[0], vertices[1], vertices[3]);
+ var t1 = triangles[1] = Helper.CreateTriangle(1, vertices[1], vertices[4], vertices[3]);
+ var t2 = triangles[2] = Helper.CreateTriangle(2, vertices[1], vertices[2], vertices[4]);
+ var t3 = triangles[3] = Helper.CreateTriangle(3, vertices[3], vertices[4], vertices[5]);
+
+ // Setup connectivity of triangle 0.
+ t0.neighbors[0].tri = dummy;
+ t0.neighbors[1].tri = t1;
+ t0.neighbors[1].orient = 2;
+ t0.neighbors[2].tri = dummy;
+
+ // Setup connectivity of triangle 1.
+ t1.neighbors[0].tri = t2;
+ t1.neighbors[0].orient = 2;
+ t1.neighbors[1].tri = t3;
+ t1.neighbors[1].orient = 0;
+ t1.neighbors[2].tri = t0;
+ t1.neighbors[2].orient = 1;
+
+ // Setup connectivity of triangle 2.
+ t2.neighbors[0].tri = dummy;
+ t2.neighbors[1].tri = dummy;
+ t2.neighbors[2].tri = t1;
+ t2.neighbors[2].orient = 0;
+
+ // Setup connectivity of triangle 3.
+ t3.neighbors[0].tri = t1;
+ t3.neighbors[0].orient = 1;
+ t3.neighbors[1].tri = dummy;
+ t3.neighbors[2].tri = dummy;
+
+ return triangles;
+ }
+
+ [SetUp]
+ public void Initialize()
+ {
+ vertices = new Vertex[6];
+
+ vertices[0] = new Vertex(-2.0, 0.0) { id = 0 };
+ vertices[1] = new Vertex( 0.0, 0.0) { id = 1 };
+ vertices[2] = new Vertex( 2.0, 0.0) { id = 2 };
+ vertices[3] = new Vertex(-1.0, 1.0) { id = 3 };
+ vertices[4] = new Vertex( 1.0, 1.0) { id = 4 };
+ vertices[5] = new Vertex( 0.0, 2.0) { id = 5 };
+ }
+
+ [Test]
+ public void TestOrg()
+ {
+ Otri t = default;
+
+ t.tri = Helper.CreateTriangle(0, vertices[1], vertices[4], vertices[3]);
+
+ t.orient = 0;
+ Assert.AreEqual(1, t.Org().ID);
+
+ t.orient = 1;
+ Assert.AreEqual(4, t.Org().ID);
+
+ t.orient = 2;
+ Assert.AreEqual(3, t.Org().ID);
+ }
+
+ [Test]
+ public void TestDest()
+ {
+ Otri t = default;
+
+ t.tri = Helper.CreateTriangle(0, vertices[1], vertices[4], vertices[3]);
+
+ t.orient = 0;
+ Assert.AreEqual(4, t.Dest().ID);
+
+ t.orient = 1;
+ Assert.AreEqual(3, t.Dest().ID);
+
+ t.orient = 2;
+ Assert.AreEqual(1, t.Dest().ID);
+ }
+
+ [Test]
+ public void TestApex()
+ {
+ Otri t = default;
+
+ t.tri = Helper.CreateTriangle(0, vertices[1], vertices[4], vertices[3]);
+
+ t.orient = 0;
+ Assert.AreEqual(3, t.Apex().ID);
+
+ t.orient = 1;
+ Assert.AreEqual(1, t.Apex().ID);
+
+ t.orient = 2;
+ Assert.AreEqual(4, t.Apex().ID);
+ }
+
+ [Test]
+ public void TestSym()
+ {
+ var triangles = CreateExampleMesh();
+
+ Otri t = default;
+ Otri s = default;
+
+ // The center triangle.
+ t.tri = triangles[1];
+
+ t.orient = 0;
+ t.Sym(ref s);
+ Assert.AreEqual(2, s.tri.ID);
+
+ t.orient = 1;
+ t.Sym(ref s);
+ Assert.AreEqual(3, s.tri.ID);
+
+ t.orient = 2;
+ t.Sym(ref s);
+ Assert.AreEqual(0, s.tri.ID);
+ }
+
+ [Test]
+ public void TestLnext()
+ {
+ var triangles = CreateExampleMesh();
+
+ Otri t = default;
+
+ // The center triangle.
+ t.tri = triangles[1];
+ t.orient = 0;
+
+ t.Lnext();
+ Assert.AreEqual(4, t.Org().ID);
+
+ t.Lnext();
+ Assert.AreEqual(3, t.Org().ID);
+
+ t.Lnext();
+ Assert.AreEqual(1, t.Org().ID);
+ }
+
+ [Test]
+ public void TestLprev()
+ {
+ var triangles = CreateExampleMesh();
+
+ Otri t = default;
+
+ // The center triangle.
+ t.tri = triangles[1];
+ t.orient = 0;
+
+ t.Lprev();
+ Assert.AreEqual(3, t.Org().ID);
+
+ t.Lprev();
+ Assert.AreEqual(4, t.Org().ID);
+
+ t.Lprev();
+ Assert.AreEqual(1, t.Org().ID);
+ }
+
+ [Test]
+ public void TestOnext()
+ {
+ var triangles = CreateExampleMesh();
+
+ Otri t = default;
+
+ // Start with the bottom right triangle.
+ t.tri = triangles[2];
+
+ // Start with edge 1 -> 2.
+ t.orient = 0;
+
+ // Make sure we're on the correct edge.
+ Assert.AreEqual(1, t.Org().ID);
+ Assert.AreEqual(2, t.Dest().ID);
+
+ t.Onext();
+ Assert.AreEqual(1, t.Org().ID);
+ Assert.AreEqual(4, t.Dest().ID);
+ Assert.AreEqual(1, t.tri.ID);
+
+ t.Onext();
+ Assert.AreEqual(1, t.Org().ID);
+ Assert.AreEqual(3, t.Dest().ID);
+ Assert.AreEqual(0, t.tri.ID);
+
+ // Out of mesh.
+ t.Onext();
+ Assert.AreEqual(-1, t.tri.ID);
+ }
+
+ [Test]
+ public void TestOprev()
+ {
+ var triangles = CreateExampleMesh();
+
+ Otri t = default;
+
+ // Start with the bottom left triangle.
+ t.tri = triangles[0];
+
+ // Start with edge 1 -> 3.
+ t.orient = 1;
+
+ // Make sure we're on the correct edge.
+ Assert.AreEqual(1, t.Org().ID);
+ Assert.AreEqual(3, t.Dest().ID);
+
+ t.Oprev();
+ Assert.AreEqual(1, t.Org().ID);
+ Assert.AreEqual(4, t.Dest().ID);
+ Assert.AreEqual(1, t.tri.ID);
+
+ t.Oprev();
+ Assert.AreEqual(1, t.Org().ID);
+ Assert.AreEqual(2, t.Dest().ID);
+ Assert.AreEqual(2, t.tri.ID);
+
+ // Out of mesh.
+ t.Oprev();
+ Assert.AreEqual(-1, t.tri.ID);
+ }
+
+ [Test]
+ public void TestDnext()
+ {
+ var triangles = CreateExampleMesh();
+
+ Otri t = default;
+
+ // Start with the bottom left triangle.
+ t.tri = triangles[0];
+
+ // Start with edge 1 -> 3.
+ t.orient = 1;
+
+ // Make sure we're on the correct edge.
+ Assert.AreEqual(1, t.Org().ID);
+ Assert.AreEqual(3, t.Dest().ID);
+
+ t.Dnext();
+ Assert.AreEqual(4, t.Org().ID);
+ Assert.AreEqual(3, t.Dest().ID);
+ Assert.AreEqual(1, t.tri.ID);
+
+ t.Dnext();
+ Assert.AreEqual(5, t.Org().ID);
+ Assert.AreEqual(3, t.Dest().ID);
+ Assert.AreEqual(3, t.tri.ID);
+
+ // Out of mesh.
+ t.Dnext();
+ Assert.AreEqual(-1, t.tri.ID);
+ }
+
+ [Test]
+ public void TestDprev()
+ {
+ var triangles = CreateExampleMesh();
+
+ Otri t = default;
+
+ // Start with the top triangle.
+ t.tri = triangles[3];
+
+ // Start with edge 5 -> 3.
+ t.orient = 2;
+
+ // Make sure we're on the correct edge.
+ Assert.AreEqual(5, t.Org().ID);
+ Assert.AreEqual(3, t.Dest().ID);
+
+ t.Dprev();
+ Assert.AreEqual(4, t.Org().ID);
+ Assert.AreEqual(3, t.Dest().ID);
+ Assert.AreEqual(1, t.tri.ID);
+
+ t.Dprev();
+ Assert.AreEqual(1, t.Org().ID);
+ Assert.AreEqual(3, t.Dest().ID);
+ Assert.AreEqual(0, t.tri.ID);
+
+ // Out of mesh.
+ t.Dprev();
+ Assert.AreEqual(-1, t.tri.ID);
+ }
+
+ [Test]
+ public void TestRnext()
+ {
+ var triangles = CreateExampleMesh();
+
+ Otri t = default;
+
+ // Start with the bottom left triangle.
+ t.tri = triangles[0];
+
+ // Start with edge 1 -> 3.
+ t.orient = 1;
+
+ // Make sure we're on the correct edge.
+ Assert.AreEqual(1, t.Org().ID);
+ Assert.AreEqual(3, t.Dest().ID);
+
+ t.Rnext();
+ Assert.AreEqual(4, t.Org().ID);
+ Assert.AreEqual(1, t.Dest().ID);
+ Assert.AreEqual(2, t.tri.ID);
+
+ t.Rnext();
+ Assert.AreEqual(3, t.Org().ID);
+ Assert.AreEqual(4, t.Dest().ID);
+ Assert.AreEqual(3, t.tri.ID);
+
+ // Back where we started.
+ t.Rnext();
+ Assert.AreEqual(0, t.tri.ID);
+ }
+
+ [Test]
+ public void TestRprev()
+ {
+ var triangles = CreateExampleMesh();
+
+ Otri t = default;
+
+ // Start with the top triangle.
+ t.tri = triangles[3];
+
+ // Start with edge 3 -> 4.
+ t.orient = 0;
+
+ // Make sure we're on the correct edge.
+ Assert.AreEqual(3, t.Org().ID);
+ Assert.AreEqual(4, t.Dest().ID);
+
+ t.Rprev();
+ Assert.AreEqual(4, t.Org().ID);
+ Assert.AreEqual(1, t.Dest().ID);
+ Assert.AreEqual(2, t.tri.ID);
+
+ t.Rprev();
+ Assert.AreEqual(1, t.Org().ID);
+ Assert.AreEqual(3, t.Dest().ID);
+ Assert.AreEqual(0, t.tri.ID);
+
+ // Back where we started.
+ t.Rprev();
+ Assert.AreEqual(3, t.tri.ID);
+ }
+
+ [Test]
+ public void TestBond()
+ {
+ Otri s = default;
+ Otri t = default;
+
+ Otri tmp = default;
+
+ s.tri = Helper.CreateTriangle(0, vertices[0], vertices[1], vertices[3]);
+ t.tri = Helper.CreateTriangle(1, vertices[1], vertices[4], vertices[3]);
+
+ s.orient = 1; // Edge 1 -> 3.
+ t.orient = 2; // Edge 3 -> 1.
+
+ // Make sure we're on the correct edges.
+ Assert.AreEqual(1, s.Org().ID);
+ Assert.AreEqual(3, s.Dest().ID);
+ Assert.AreEqual(3, t.Org().ID);
+ Assert.AreEqual(1, t.Dest().ID);
+
+ // Check that the triangles don't have neighbors.
+ s.Sym(ref tmp);
+ //Assert.AreEqual(-1, tmp.tri.ID);
+ Assert.IsNull(tmp.tri);
+ t.Sym(ref tmp);
+ //Assert.AreEqual(-1, tmp.tri.ID);
+ Assert.IsNull(tmp.tri);
+
+ // Bond the two triangles.
+ s.Bond(ref t);
+
+ // Check that neighbors are properly set.
+ s.Sym(ref tmp);
+ Assert.AreEqual(1, tmp.tri.ID);
+ t.Sym(ref tmp);
+ Assert.AreEqual(0, tmp.tri.ID);
+ }
+
+ [Test]
+ public void TestDissolve()
+ {
+ // Outer space triangle.
+ var dummy = new Triangle() { id = -1 };
+
+ var triangles = CreateExampleMesh();
+
+ Otri s = default;
+ Otri t = default;
+
+ Otri tmp = default;
+
+ // The bottom left triangle with edge 1 -> 3.
+ s.tri = triangles[0];
+ s.orient = 1;
+
+ // The center triangle with edge 3 -> 1.
+ t.tri = triangles[1];
+ t.orient = 2;
+
+ // Make sure we're on the correct edges.
+ Assert.AreEqual(1, s.Org().ID);
+ Assert.AreEqual(3, s.Dest().ID);
+ Assert.AreEqual(3, t.Org().ID);
+ Assert.AreEqual(1, t.Dest().ID);
+
+ // Check that neighbors are properly set.
+ s.Sym(ref tmp);
+ Assert.AreEqual(1, tmp.tri.ID);
+ t.Sym(ref tmp);
+ Assert.AreEqual(0, tmp.tri.ID);
+
+ // Now dissolve the bond from one side.
+ s.Dissolve(dummy);
+
+ // Check neighbors.
+ s.Sym(ref tmp);
+ Assert.AreEqual(-1, tmp.tri.ID);
+ t.Sym(ref tmp);
+ Assert.AreEqual(0, tmp.tri.ID);
+
+ // And dissolve the bond from the other side.
+ t.Dissolve(dummy);
+
+ // Check neighbors.
+ s.Sym(ref tmp);
+ Assert.AreEqual(-1, tmp.tri.ID);
+ t.Sym(ref tmp);
+ Assert.AreEqual(-1, tmp.tri.ID);
+ }
+ }
+}
diff --git a/src/Triangle.Tests/Triangle.Tests.csproj b/src/Triangle.Tests/Triangle.Tests.csproj
new file mode 100644
index 0000000..47b78b0
--- /dev/null
+++ b/src/Triangle.Tests/Triangle.Tests.csproj
@@ -0,0 +1,21 @@
+
+
+
+ net6.0
+ TriangleNet.Tests
+ Triangle.Tests
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Triangle.Viewer.sln b/src/Triangle.Viewer.sln
new file mode 100644
index 0000000..23fae3d
--- /dev/null
+++ b/src/Triangle.Viewer.sln
@@ -0,0 +1,51 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.32126.317
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Triangle.Viewer", "Triangle.Viewer\Triangle.Viewer.csproj", "{336AAF8A-5316-4303-9E73-5E38BD0B28AF}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Triangle.Rendering", "Triangle.Rendering\Triangle.Rendering.csproj", "{41022E0E-BD0F-439E-BC3A-AABB1B43471B}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Triangle.Rendering.GDI", "Triangle.Rendering.GDI\Triangle.Rendering.GDI.csproj", "{D535E102-92B4-4F92-B284-A7170AE00CD6}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Debug|x64.ActiveCfg = Debug|x64
+ {336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Debug|x64.Build.0 = Debug|x64
+ {336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Release|x64.ActiveCfg = Release|x64
+ {336AAF8A-5316-4303-9E73-5E38BD0B28AF}.Release|x64.Build.0 = Release|x64
+ {41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Debug|x64.ActiveCfg = Debug|x64
+ {41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Debug|x64.Build.0 = Debug|x64
+ {41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Release|x64.ActiveCfg = Release|x64
+ {41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Release|x64.Build.0 = Release|x64
+ {D535E102-92B4-4F92-B284-A7170AE00CD6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D535E102-92B4-4F92-B284-A7170AE00CD6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D535E102-92B4-4F92-B284-A7170AE00CD6}.Debug|x64.ActiveCfg = Debug|x64
+ {D535E102-92B4-4F92-B284-A7170AE00CD6}.Debug|x64.Build.0 = Debug|x64
+ {D535E102-92B4-4F92-B284-A7170AE00CD6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D535E102-92B4-4F92-B284-A7170AE00CD6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D535E102-92B4-4F92-B284-A7170AE00CD6}.Release|x64.ActiveCfg = Release|x64
+ {D535E102-92B4-4F92-B284-A7170AE00CD6}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {90F4F9E9-43D6-4A3D-91D5-B2DF113E13AE}
+ EndGlobalSection
+EndGlobal
diff --git a/Triangle.NET/TestApp/Controls/AngleHistogram.cs b/src/Triangle.Viewer/Controls/AngleHistogram.cs
similarity index 68%
rename from Triangle.NET/TestApp/Controls/AngleHistogram.cs
rename to src/Triangle.Viewer/Controls/AngleHistogram.cs
index 3837e40..d6a6fc4 100644
--- a/Triangle.NET/TestApp/Controls/AngleHistogram.cs
+++ b/src/Triangle.Viewer/Controls/AngleHistogram.cs
@@ -1,207 +1,207 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace MeshExplorer.Controls
-{
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Windows.Forms;
- using System.Drawing.Text;
-
- ///
- /// Displays an angle histogram.
- ///
- ///
- /// The angle histogram is divided into two parts: the minimum angles
- /// on the left side (0 to 60 degrees) and the maximum angles on the
- /// right (60 to 180 degrees).
- ///
- public class AngleHistogram : Control
- {
- #region Designer
-
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Component Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- components = new System.ComponentModel.Container();
- }
-
- #endregion
-
- #endregion
-
- int[] maxAngles;
- int[] minAngles;
-
- Brush fillBlue1 = new SolidBrush(Color.FromArgb(60, 100, 140));
- Brush fillBlue2 = new SolidBrush(Color.FromArgb(110, 150, 200));
-
- Brush textBack = new SolidBrush(Color.FromArgb(72, 0, 0, 0));
-
- // The maximum number of angles
- int maxAngleCount = 0;
-
- ///
- /// Initializes a new instance of the control.
- ///
- public AngleHistogram()
- {
- this.BackColor = ColorScheme.ColorGray78;
- InitializeComponent();
- }
-
- ///
- /// Updates the histogram data and invalidates the control.
- ///
- public void SetData(int[] dataMin, int[] dataMax)
- {
- maxAngleCount = 0;
-
- this.minAngles = dataMin;
- this.maxAngles = dataMax;
-
- ParseData(dataMin);
- ParseData(dataMax);
-
- if (maxAngleCount == 0)
- {
- this.maxAngles = null;
- return;
- }
-
- this.Invalidate();
- }
-
- private void ParseData(int[] data)
- {
- if (data != null)
- {
- for (int i = 0; i < data.Length; i++)
- {
- if (data[i] > maxAngleCount)
- {
- maxAngleCount = data[i];
- }
- }
- }
- }
-
- int padding = 1;
- int paddingBottom = 0;
- int paddingTop = 15;
-
- private void DrawHistogram(Graphics g, int offset, int left, int size, int[] data, Brush brush, Brush brushTop)
- {
- int count = maxAngleCount;
- int totalHeight = this.Height - paddingBottom - paddingTop;
-
- int n = offset == 0 ? data.Length / 3 : data.Length;
- float value = 0;
-
- for (int i = offset; i < n; i++)
- {
- if (data[i] > 0)
- {
- // Scale to control height
- value = totalHeight * data[i] / count;
-
- // Fill bar
- g.FillRectangle(brush,
- left + i * size, this.Height - paddingBottom - value,
- size - 1, value);
-
- // Draw top of bar (just a little effect ...)
- if (value > 2)
- {
- g.FillRectangle(brushTop,
- left + i * size, this.Height - paddingBottom - value,
- size - 1, 2);
- }
- }
- }
- }
-
- ///
- /// Draws the labels on the bottom.
- ///
- private void DrawStrings(Graphics g, SizeF fSize, int size, int middle)
- {
- int fHeight = (int)(fSize.Height + 2);
- g.FillRectangle(textBack, 0, this.Height - fHeight, this.Width, fHeight);
-
- g.DrawString("0", this.Font, Brushes.White, padding, this.Height - fSize.Height - 1);
- g.DrawString("60", this.Font, Brushes.White,
- this.minAngles.Length * size / 3.0f - 2 * fSize.Width,
- this.Height - fSize.Height - 1);
-
- g.DrawString("60", this.Font, Brushes.White, middle, this.Height - fSize.Height - 1);
- g.DrawString("180", this.Font, Brushes.White,
- this.Width - 3 * fSize.Width,
- this.Height - fSize.Height - 1);
- }
-
- protected override void OnPaint(PaintEventArgs e)
- {
- Graphics g = e.Graphics;
-
- g.FillRectangle(new SolidBrush(this.BackColor), this.ClientRectangle);
-
- if (this.minAngles == null || this.maxAngles == null)
- {
- return;
- }
-
- SizeF fSize = g.MeasureString("0", this.Font, this.Width);
-
- int n = this.minAngles.Length;
-
- // Hack --- TODO: Change stats class
- if (n != this.maxAngles.Length)
- {
- n = this.minAngles.Length + this.maxAngles.Length;
- }
-
- // Each bar takes up this space
- int size = (this.Width - 2 * padding) / (n + 1);
-
- // Make pixel align
- int middle = this.Width - padding - n * size;
-
- DrawHistogram(g, 0, padding, size, this.minAngles, Brushes.DarkGreen, Brushes.Green);
- DrawHistogram(g, n / 3, middle, size, this.maxAngles, fillBlue1, fillBlue2);
-
- g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
-
- DrawStrings(g, fSize, size, middle + n / 3 * size);
- }
- }
-}
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+//
+// -----------------------------------------------------------------------
+
+namespace MeshExplorer.Controls
+{
+ using System.Drawing;
+ using System.Drawing.Text;
+ using System.Windows.Forms;
+
+ ///
+ /// Displays an angle histogram.
+ ///
+ ///
+ /// The angle histogram is divided into two parts: the minimum angles
+ /// on the left side (0 to 60 degrees) and the maximum angles on the
+ /// right (60 to 180 degrees).
+ ///
+ public class AngleHistogram : Control
+ {
+ #region Designer
+
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ components = new System.ComponentModel.Container();
+ }
+
+ #endregion
+
+ #endregion
+
+ int[] maxAngles;
+ int[] minAngles;
+
+ Brush fillBlue1 = new SolidBrush(Color.FromArgb(60, 100, 140));
+ Brush fillBlue2 = new SolidBrush(Color.FromArgb(110, 150, 200));
+
+ Brush textBack = new SolidBrush(Color.FromArgb(72, 0, 0, 0));
+
+ // The maximum number of angles
+ int maxAngleCount = 0;
+
+ ///
+ /// Initializes a new instance of the control.
+ ///
+ public AngleHistogram()
+ {
+ BackColor = ColorScheme.ColorGray78;
+ InitializeComponent();
+ }
+
+ ///
+ /// Updates the histogram data and invalidates the control.
+ ///
+ public void SetData(int[] dataMin, int[] dataMax)
+ {
+ maxAngleCount = 0;
+
+ minAngles = dataMin;
+ maxAngles = dataMax;
+
+ ParseData(dataMin);
+ ParseData(dataMax);
+
+ if (maxAngleCount == 0)
+ {
+ maxAngles = null;
+ return;
+ }
+
+ Invalidate();
+ }
+
+ private void ParseData(int[] data)
+ {
+ if (data != null)
+ {
+ for (int i = 0; i < data.Length; i++)
+ {
+ if (data[i] > maxAngleCount)
+ {
+ maxAngleCount = data[i];
+ }
+ }
+ }
+ }
+
+ int padding = 1;
+ int paddingBottom = 0;
+ int paddingTop = 15;
+
+ private void DrawHistogram(Graphics g, int offset, int left, int size, int[] data, Brush brush, Brush brushTop)
+ {
+ int count = maxAngleCount;
+ int totalHeight = Height - paddingBottom - paddingTop;
+
+ int n = offset == 0 ? data.Length / 3 : data.Length;
+
+ for (int i = offset; i < n; i++)
+ {
+ if (data[i] > 0)
+ {
+ // Scale to control height
+ float value = totalHeight * data[i] / count;
+
+ // Fill bar
+ g.FillRectangle(brush,
+ left + i * size, Height - paddingBottom - value,
+ size - 1, value);
+
+ // Draw top of bar (just a little effect ...)
+ if (value > 2)
+ {
+ g.FillRectangle(brushTop,
+ left + i * size, Height - paddingBottom - value,
+ size - 1, 2);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Draws the labels on the bottom.
+ ///
+ private void DrawStrings(Graphics g, SizeF fSize, int size, int middle)
+ {
+ int fHeight = (int)(fSize.Height + 2);
+
+ g.FillRectangle(textBack, 0, Height - fHeight, Width, fHeight);
+
+ var p = new Point(0, Height - (int)fSize.Height - 1);
+
+ p.X = padding;
+ TextRenderer.DrawText(g, "0", Font, p, Color.White);
+
+ p.X = (int)(minAngles.Length * size / 3.0f - 2 * fSize.Width);
+ TextRenderer.DrawText(g, "60", Font, p, Color.White);
+
+ p.X = middle;
+ TextRenderer.DrawText(g, "60", Font, p, Color.White);
+
+ p.X = (int)(Width - 3 * fSize.Width);
+ TextRenderer.DrawText(g, "180", Font, p, Color.White);
+ }
+
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ Graphics g = e.Graphics;
+
+ g.FillRectangle(new SolidBrush(BackColor), ClientRectangle);
+
+ if (minAngles == null || maxAngles == null)
+ {
+ return;
+ }
+
+ int n = minAngles.Length;
+
+ // Hack --- TODO: Change stats class
+ if (n != maxAngles.Length)
+ {
+ n = minAngles.Length + maxAngles.Length;
+ }
+
+ // Each bar takes up this space
+ int size = (Width - 2 * padding) / (n + 1);
+
+ // Make pixel align
+ int middle = Width - padding - n * size;
+
+ DrawHistogram(g, 0, padding, size, minAngles, Brushes.DarkGreen, Brushes.Green);
+ DrawHistogram(g, n / 3, middle, size, maxAngles, fillBlue1, fillBlue2);
+
+ g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
+
+ SizeF fSize = g.MeasureString("0", Font, Width);
+
+ DrawStrings(g, fSize, size, middle + n / 3 * size);
+ }
+ }
+}
diff --git a/Triangle.NET/TestApp/Controls/ColorScheme.cs b/src/Triangle.Viewer/Controls/ColorScheme.cs
similarity index 91%
rename from Triangle.NET/TestApp/Controls/ColorScheme.cs
rename to src/Triangle.Viewer/Controls/ColorScheme.cs
index 3486b90..80dd676 100644
--- a/Triangle.NET/TestApp/Controls/ColorScheme.cs
+++ b/src/Triangle.Viewer/Controls/ColorScheme.cs
@@ -1,38 +1,34 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace MeshExplorer.Controls
-{
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Drawing;
-
- ///
- /// Dark user interface color scheme.
- ///
- public static class ColorScheme
- {
- public static Color ColorGray13 = Color.FromArgb(13, 13, 13);
- public static Color ColorGray46 = Color.FromArgb(46, 46, 46);
- public static Color ColorGray64 = Color.FromArgb(64, 64, 64);
- public static Color ColorGray68 = Color.FromArgb(68, 68, 68);
- public static Color ColorGray78 = Color.FromArgb(78, 78, 78);
- public static Color ColorGray89 = Color.FromArgb(89, 89, 89);
- public static Color ColorGray98 = Color.FromArgb(98, 98, 98);
- public static Color ColorGray107 = Color.FromArgb(107, 107, 107);
- public static Color ColorGray110 = Color.FromArgb(110, 110, 110);
- public static Color ColorGray122 = Color.FromArgb(122, 122, 122);
-
- public static Brush BrushGray68 = new SolidBrush(ColorGray68);
- public static Brush BrushGray78 = new SolidBrush(ColorGray78);
-
- // Linear gradient horizontal
- public static Brush SliderBorderBrush = new SolidBrush(ColorGray46);
- public static Brush SliderFillBrush = new SolidBrush(ColorGray89);
- }
-}
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+//
+// -----------------------------------------------------------------------
+
+namespace MeshExplorer.Controls
+{
+ using System.Drawing;
+
+ ///
+ /// Dark user interface color scheme.
+ ///
+ public static class ColorScheme
+ {
+ public static Color ColorGray13 = Color.FromArgb(13, 13, 13);
+ public static Color ColorGray46 = Color.FromArgb(46, 46, 46);
+ public static Color ColorGray64 = Color.FromArgb(64, 64, 64);
+ public static Color ColorGray68 = Color.FromArgb(68, 68, 68);
+ public static Color ColorGray78 = Color.FromArgb(78, 78, 78);
+ public static Color ColorGray89 = Color.FromArgb(89, 89, 89);
+ public static Color ColorGray98 = Color.FromArgb(98, 98, 98);
+ public static Color ColorGray107 = Color.FromArgb(107, 107, 107);
+ public static Color ColorGray110 = Color.FromArgb(110, 110, 110);
+ public static Color ColorGray122 = Color.FromArgb(122, 122, 122);
+
+ public static Brush BrushGray68 = new SolidBrush(ColorGray68);
+ public static Brush BrushGray78 = new SolidBrush(ColorGray78);
+
+ // Linear gradient horizontal
+ public static Brush SliderBorderBrush = new SolidBrush(ColorGray46);
+ public static Brush SliderFillBrush = new SolidBrush(ColorGray89);
+ }
+}
diff --git a/Triangle.NET/TestApp/Controls/DarkButton.cs b/src/Triangle.Viewer/Controls/DarkButton.cs
similarity index 95%
rename from Triangle.NET/TestApp/Controls/DarkButton.cs
rename to src/Triangle.Viewer/Controls/DarkButton.cs
index 69d4f07..1c2dd91 100644
--- a/Triangle.NET/TestApp/Controls/DarkButton.cs
+++ b/src/Triangle.Viewer/Controls/DarkButton.cs
@@ -1,190 +1,186 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace MeshExplorer.Controls
-{
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Text;
- using System.Windows.Forms;
-
- public class DarkButton : Button
- {
- #region Designer
-
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Component Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- components = new System.ComponentModel.Container();
- }
-
- #endregion
-
- #endregion
-
- enum eButtonState { Normal, MouseOver, Down }
- eButtonState m_State = eButtonState.Normal;
-
- // Make sure the control is invalidated when the text is changed.
- public override string Text
- {
- get { return base.Text; }
- set { base.Text = value; this.Invalidate(); }
- }
-
- ///
- /// Initializes a new instance of the control.
- ///
- public DarkButton()
- {
- InitializeComponent();
- }
-
- #region Control overrides
-
- protected override void OnPaint(PaintEventArgs e)
- {
- e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
- e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
-
- float down = 0.0f;
-
- // Colors and brushes
- Pen brushBorder = null;
- LinearGradientMode mode = LinearGradientMode.Vertical;
- LinearGradientBrush brushOuter = null;
- LinearGradientBrush brushInner = null;
-
- Rectangle newRect = new Rectangle(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width - 1, ClientRectangle.Height - 1);
- Color text_color = Color.White;
-
- if (Enabled)
- {
- if (base.Focused)
- brushBorder = new Pen(Color.FromArgb(24, 24, 24), 1f);
- else
- brushBorder = new Pen(Color.FromArgb(56, 56, 56), 1f);
-
- switch (m_State)
- {
- case eButtonState.Normal:
- brushOuter = new LinearGradientBrush(newRect, Color.FromArgb(123, 123, 123), Color.FromArgb(77, 77, 77), mode);
- brushInner = new LinearGradientBrush(newRect, Color.FromArgb(104, 104, 104), Color.FromArgb(71, 71, 71), mode);
- e.Graphics.FillRectangle(brushOuter, newRect);
- newRect.Inflate(-1, -1);
- e.Graphics.FillRectangle(brushInner, newRect);
- newRect.Inflate(1, 1);
- break;
-
- case eButtonState.MouseOver:
- brushOuter = new LinearGradientBrush(newRect, Color.FromArgb(140, 140, 140), Color.FromArgb(87, 87, 87), mode);
- brushInner = new LinearGradientBrush(newRect, Color.FromArgb(118, 118, 118), Color.FromArgb(81, 81, 81), mode);
- e.Graphics.FillRectangle(brushOuter, newRect);
- newRect.Inflate(-1, -1);
- e.Graphics.FillRectangle(brushInner, newRect);
- newRect.Inflate(1, 1);
- break;
-
- case eButtonState.Down:
- down = 1.0f;
- brushOuter = new LinearGradientBrush(newRect, Color.FromArgb(108, 108, 108), Color.FromArgb(68, 68, 68), mode);
- brushInner = new LinearGradientBrush(newRect, Color.FromArgb(92, 92, 92), Color.FromArgb(62, 62, 62), mode);
- e.Graphics.FillRectangle(brushOuter, newRect);
- newRect.Inflate(-1, -1);
- e.Graphics.FillRectangle(brushInner, newRect);
- newRect.Inflate(1, 1);
- break;
- }
-
- e.Graphics.DrawRectangle(brushBorder, newRect);
- }
- else
- {
- text_color = Color.FromArgb(110, 110, 110);
- brushBorder = new Pen(Color.FromArgb(48, 48, 48), 1f);
- brushOuter = new LinearGradientBrush(newRect, Color.FromArgb(82, 82, 82), Color.FromArgb(67, 67, 67), mode);
- brushInner = new LinearGradientBrush(newRect, Color.FromArgb(76, 76, 76), Color.FromArgb(65, 65, 65), mode);
- e.Graphics.FillRectangle(brushOuter, newRect);
- newRect.Inflate(-1, -1);
- e.Graphics.FillRectangle(brushInner, newRect);
- newRect.Inflate(1, 1);
- e.Graphics.DrawRectangle(brushBorder, newRect);
- }
-
-
- string largetext = this.Text;
-
- SizeF szL = e.Graphics.MeasureString(this.Text, base.Font, this.Width);
- if (Enabled)
- {
- e.Graphics.DrawString(largetext, base.Font, Brushes.Black,
- new RectangleF(new PointF((this.Width - szL.Width) / 2, (this.Height - szL.Height) / 2 + 1 + down), szL));
- }
- e.Graphics.DrawString(largetext, base.Font, new SolidBrush(text_color),
- new RectangleF(new PointF((this.Width - szL.Width) / 2, (this.Height - szL.Height) / 2 + down), szL));
-
- brushOuter.Dispose();
- brushInner.Dispose();
- brushBorder.Dispose();
- }
-
- protected override void OnMouseLeave(System.EventArgs e)
- {
- m_State = eButtonState.Normal;
- this.Invalidate();
- base.OnMouseLeave(e);
- }
-
- protected override void OnMouseEnter(System.EventArgs e)
- {
- m_State = eButtonState.MouseOver;
- this.Invalidate();
- base.OnMouseEnter(e);
- }
-
- protected override void OnMouseUp(System.Windows.Forms.MouseEventArgs e)
- {
- m_State = eButtonState.MouseOver;
- this.Invalidate();
- base.OnMouseUp(e);
- }
-
- protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
- {
- m_State = eButtonState.Down;
- this.Invalidate();
- base.OnMouseDown(e);
- }
-
- #endregion
- }
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+//
+// -----------------------------------------------------------------------
+
+namespace MeshExplorer.Controls
+{
+ using System.Drawing;
+ using System.Drawing.Drawing2D;
+ using System.Windows.Forms;
+
+ public class DarkButton : Button
+ {
+ #region Designer
+
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ components = new System.ComponentModel.Container();
+ }
+
+ #endregion
+
+ #endregion
+
+ enum eButtonState { Normal, MouseOver, Down }
+ eButtonState m_State = eButtonState.Normal;
+
+ // Make sure the control is invalidated when the text is changed.
+ public override string Text
+ {
+ get { return base.Text; }
+ set { base.Text = value; this.Invalidate(); }
+ }
+
+ ///
+ /// Initializes a new instance of the control.
+ ///
+ public DarkButton()
+ {
+ InitializeComponent();
+ }
+
+ #region Control overrides
+
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
+ e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
+
+ float down = 0.0f;
+
+ // Colors and brushes
+ Pen brushBorder = null;
+ LinearGradientMode mode = LinearGradientMode.Vertical;
+ LinearGradientBrush brushOuter = null;
+ LinearGradientBrush brushInner = null;
+
+ Rectangle newRect = new Rectangle(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width - 1, ClientRectangle.Height - 1);
+ Color text_color = Color.White;
+
+ if (Enabled)
+ {
+ if (base.Focused)
+ brushBorder = new Pen(Color.FromArgb(24, 24, 24), 1f);
+ else
+ brushBorder = new Pen(Color.FromArgb(56, 56, 56), 1f);
+
+ switch (m_State)
+ {
+ case eButtonState.Normal:
+ brushOuter = new LinearGradientBrush(newRect, Color.FromArgb(123, 123, 123), Color.FromArgb(77, 77, 77), mode);
+ brushInner = new LinearGradientBrush(newRect, Color.FromArgb(104, 104, 104), Color.FromArgb(71, 71, 71), mode);
+ e.Graphics.FillRectangle(brushOuter, newRect);
+ newRect.Inflate(-1, -1);
+ e.Graphics.FillRectangle(brushInner, newRect);
+ newRect.Inflate(1, 1);
+ break;
+
+ case eButtonState.MouseOver:
+ brushOuter = new LinearGradientBrush(newRect, Color.FromArgb(140, 140, 140), Color.FromArgb(87, 87, 87), mode);
+ brushInner = new LinearGradientBrush(newRect, Color.FromArgb(118, 118, 118), Color.FromArgb(81, 81, 81), mode);
+ e.Graphics.FillRectangle(brushOuter, newRect);
+ newRect.Inflate(-1, -1);
+ e.Graphics.FillRectangle(brushInner, newRect);
+ newRect.Inflate(1, 1);
+ break;
+
+ case eButtonState.Down:
+ down = 1.0f;
+ brushOuter = new LinearGradientBrush(newRect, Color.FromArgb(108, 108, 108), Color.FromArgb(68, 68, 68), mode);
+ brushInner = new LinearGradientBrush(newRect, Color.FromArgb(92, 92, 92), Color.FromArgb(62, 62, 62), mode);
+ e.Graphics.FillRectangle(brushOuter, newRect);
+ newRect.Inflate(-1, -1);
+ e.Graphics.FillRectangle(brushInner, newRect);
+ newRect.Inflate(1, 1);
+ break;
+ }
+
+ e.Graphics.DrawRectangle(brushBorder, newRect);
+ }
+ else
+ {
+ text_color = Color.FromArgb(110, 110, 110);
+ brushBorder = new Pen(Color.FromArgb(48, 48, 48), 1f);
+ brushOuter = new LinearGradientBrush(newRect, Color.FromArgb(82, 82, 82), Color.FromArgb(67, 67, 67), mode);
+ brushInner = new LinearGradientBrush(newRect, Color.FromArgb(76, 76, 76), Color.FromArgb(65, 65, 65), mode);
+ e.Graphics.FillRectangle(brushOuter, newRect);
+ newRect.Inflate(-1, -1);
+ e.Graphics.FillRectangle(brushInner, newRect);
+ newRect.Inflate(1, 1);
+ e.Graphics.DrawRectangle(brushBorder, newRect);
+ }
+
+
+ string largetext = this.Text;
+
+ SizeF szL = e.Graphics.MeasureString(this.Text, base.Font, this.Width);
+ if (Enabled)
+ {
+ e.Graphics.DrawString(largetext, base.Font, Brushes.Black,
+ new RectangleF(new PointF((this.Width - szL.Width) / 2, (this.Height - szL.Height) / 2 + 1 + down), szL));
+ }
+ e.Graphics.DrawString(largetext, base.Font, new SolidBrush(text_color),
+ new RectangleF(new PointF((this.Width - szL.Width) / 2, (this.Height - szL.Height) / 2 + down), szL));
+
+ brushOuter.Dispose();
+ brushInner.Dispose();
+ brushBorder.Dispose();
+ }
+
+ protected override void OnMouseLeave(System.EventArgs e)
+ {
+ m_State = eButtonState.Normal;
+ this.Invalidate();
+ base.OnMouseLeave(e);
+ }
+
+ protected override void OnMouseEnter(System.EventArgs e)
+ {
+ m_State = eButtonState.MouseOver;
+ this.Invalidate();
+ base.OnMouseEnter(e);
+ }
+
+ protected override void OnMouseUp(System.Windows.Forms.MouseEventArgs e)
+ {
+ m_State = eButtonState.MouseOver;
+ this.Invalidate();
+ base.OnMouseUp(e);
+ }
+
+ protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
+ {
+ m_State = eButtonState.Down;
+ this.Invalidate();
+ base.OnMouseDown(e);
+ }
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/Triangle.NET/TestApp/Controls/DarkCheckBox.cs b/src/Triangle.Viewer/Controls/DarkCheckBox.cs
similarity index 96%
rename from Triangle.NET/TestApp/Controls/DarkCheckBox.cs
rename to src/Triangle.Viewer/Controls/DarkCheckBox.cs
index 726d43d..71793af 100644
--- a/Triangle.NET/TestApp/Controls/DarkCheckBox.cs
+++ b/src/Triangle.Viewer/Controls/DarkCheckBox.cs
@@ -1,239 +1,237 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace MeshExplorer.Controls
-{
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Windows.Forms;
- using System.Drawing.Text;
-
- ///
- /// Dark checkbox control.
- ///
- public class DarkCheckBox : ButtonBase
- {
- #region Designer
-
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Component Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- components = new System.ComponentModel.Container();
- }
-
- #endregion
-
- #endregion
-
- enum eButtonState { Normal, MouseOver, Down }
- eButtonState m_State = eButtonState.Normal;
-
- // Make sure the control is invalidated when the text is changed.
- public override string Text
- {
- get { return base.Text; }
- set { base.Text = value; this.Invalidate(); }
- }
-
- int boxSize = 13;
-
- bool isChecked = false;
- public bool Checked
- {
- get { return isChecked; }
- set { isChecked = value; this.Invalidate(); }
- }
-
- ///
- /// Initializes a new instance of the control.
- ///
- public DarkCheckBox()
- {
- this.BackColor = Color.FromArgb(76, 76, 76);
- InitializeComponent();
- }
-
- private void DrawText(Graphics g, Color forecolor, Point location)
- {
- if (this.UseCompatibleTextRendering)
- {
- //using (StringFormat stringFormat = this.CreateStringFormat())
- {
- if (this.Enabled)
- {
- g.DrawString(this.Text, base.Font, new SolidBrush(forecolor), location.X, location.Y);
- }
- else
- {
- g.DrawString(this.Text, base.Font, new SolidBrush(forecolor), location.X, location.Y);
- }
- }
- }
- else
- {
- //TextFormatFlags textFormatFlags = this.CreateTextFormatFlags();
- if (this.Enabled)
- {
- TextRenderer.DrawText((IDeviceContext)g, this.Text, this.Font, location, forecolor);
- }
- else
- {
- //forecolor = TextRenderer.DisabledTextColor(this.BackColor);
- TextRenderer.DrawText((IDeviceContext)g, this.Text, this.Font, location, forecolor);
- }
- }
- }
-
- #region Control overrides
-
- protected override void OnPaint(PaintEventArgs e)
- {
- //base.OnPaint(e);
- e.Graphics.FillRectangle(new SolidBrush(this.BackColor), this.ClientRectangle);
-
- Pen checkMark = new Pen(Color.White, 1.8f);
- checkMark.StartCap = LineCap.Round;
- checkMark.EndCap = LineCap.Round;
-
- // Colors and brushes
- Pen brushBorder = null;
- LinearGradientMode mode = LinearGradientMode.Vertical;
- LinearGradientBrush brushOuter = null;
- LinearGradientBrush brushInner = null;
-
- int y = (this.Height - boxSize) / 2;
-
- Rectangle newRect = new Rectangle(1, y, boxSize, boxSize);
- Color text_color = Color.White;
-
- brushOuter = new LinearGradientBrush(newRect, ColorScheme.ColorGray107, ColorScheme.ColorGray110, mode);
- e.Graphics.FillRectangle(brushOuter, newRect);
-
- newRect = new Rectangle(2, y + 1, boxSize - 3, boxSize - 3);
-
- if (Enabled)
- {
- if (base.Focused)
- brushBorder = new Pen(Color.FromArgb(60, 60, 60), 1f);
- else
- brushBorder = new Pen(Color.FromArgb(38, 38, 38), 1f);
-
- switch (m_State)
- {
- case eButtonState.Normal:
- brushInner = new LinearGradientBrush(newRect, Color.FromArgb(111, 111, 111), Color.FromArgb(80, 80, 80), mode);
- e.Graphics.FillRectangle(brushInner, newRect);
- break;
-
- case eButtonState.MouseOver:
- brushInner = new LinearGradientBrush(newRect, Color.FromArgb(118, 118, 118), Color.FromArgb(81, 81, 81), mode);
- e.Graphics.FillRectangle(brushInner, newRect);
- break;
-
- case eButtonState.Down:
- brushInner = new LinearGradientBrush(newRect, Color.FromArgb(92, 92, 92), Color.FromArgb(62, 62, 62), mode);
- e.Graphics.FillRectangle(brushInner, newRect);
- break;
- }
-
- e.Graphics.DrawRectangle(brushBorder, newRect);
-
- }
- else
- {
- brushInner = new LinearGradientBrush(newRect, Color.FromArgb(76, 76, 76), Color.FromArgb(65, 65, 65), mode);
- e.Graphics.FillRectangle(brushInner, newRect);
-
- brushBorder = new Pen(Color.FromArgb(48, 48, 48), 1f);
- e.Graphics.DrawRectangle(brushBorder, newRect);
-
- text_color = Color.FromArgb(160, 160, 160);
- checkMark.Color = Color.FromArgb(180, 180, 180);
- }
-
- e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
-
- SizeF szL = e.Graphics.MeasureString(this.Text, base.Font, this.Width);
- DrawText(e.Graphics, text_color, new Point(boxSize + 4, (int)((this.Height - szL.Height) / 2) + 1));
-
- if (this.isChecked)
- {
- e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
-
- e.Graphics.DrawLine(checkMark, 4, newRect.Bottom - boxSize / 2, newRect.Left + boxSize / 2.5f, newRect.Bottom - 2);
- e.Graphics.DrawLine(checkMark, newRect.Left + boxSize / 2.6f, newRect.Bottom - 2, newRect.Right, newRect.Top);
- }
-
- if (brushOuter != null) brushOuter.Dispose();
- if (brushInner != null) brushInner.Dispose();
- if (brushBorder != null) brushBorder.Dispose();
- if (checkMark != null) checkMark.Dispose();
- }
-
- protected override void OnMouseLeave(System.EventArgs e)
- {
- m_State = eButtonState.Normal;
- this.Invalidate();
- base.OnMouseLeave(e);
- }
-
- protected override void OnMouseEnter(System.EventArgs e)
- {
- m_State = eButtonState.MouseOver;
- this.Invalidate();
- base.OnMouseEnter(e);
- }
-
- protected override void OnMouseUp(System.Windows.Forms.MouseEventArgs e)
- {
- m_State = eButtonState.MouseOver;
- this.Invalidate();
- base.OnMouseUp(e);
- }
-
- protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
- {
- m_State = eButtonState.Down;
- this.Invalidate();
- base.OnMouseDown(e);
- }
-
- protected override void OnClick(EventArgs e)
- {
- this.isChecked = !this.isChecked;
- this.Invalidate();
- base.OnClick(e);
- }
-
- #endregion
- }
-}
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+//
+// -----------------------------------------------------------------------
+
+namespace MeshExplorer.Controls
+{
+ using System;
+ using System.Drawing;
+ using System.Drawing.Drawing2D;
+ using System.Drawing.Text;
+ using System.Windows.Forms;
+
+ ///
+ /// Dark checkbox control.
+ ///
+ public class DarkCheckBox : ButtonBase
+ {
+ #region Designer
+
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ components = new System.ComponentModel.Container();
+ }
+
+ #endregion
+
+ #endregion
+
+ enum eButtonState { Normal, MouseOver, Down }
+ eButtonState m_State = eButtonState.Normal;
+
+ // Make sure the control is invalidated when the text is changed.
+ public override string Text
+ {
+ get { return base.Text; }
+ set { base.Text = value; this.Invalidate(); }
+ }
+
+ int boxSize = 13;
+
+ bool isChecked = false;
+ public bool Checked
+ {
+ get { return isChecked; }
+ set { isChecked = value; this.Invalidate(); }
+ }
+
+ ///
+ /// Initializes a new instance of the control.
+ ///
+ public DarkCheckBox()
+ {
+ this.BackColor = Color.FromArgb(76, 76, 76);
+ InitializeComponent();
+ }
+
+ private void DrawText(Graphics g, Color forecolor, Point location)
+ {
+ if (this.UseCompatibleTextRendering)
+ {
+ //using (StringFormat stringFormat = this.CreateStringFormat())
+ {
+ if (this.Enabled)
+ {
+ g.DrawString(this.Text, base.Font, new SolidBrush(forecolor), location.X, location.Y);
+ }
+ else
+ {
+ g.DrawString(this.Text, base.Font, new SolidBrush(forecolor), location.X, location.Y);
+ }
+ }
+ }
+ else
+ {
+ //TextFormatFlags textFormatFlags = this.CreateTextFormatFlags();
+ if (this.Enabled)
+ {
+ TextRenderer.DrawText((IDeviceContext)g, this.Text, this.Font, location, forecolor);
+ }
+ else
+ {
+ //forecolor = TextRenderer.DisabledTextColor(this.BackColor);
+ TextRenderer.DrawText((IDeviceContext)g, this.Text, this.Font, location, forecolor);
+ }
+ }
+ }
+
+ #region Control overrides
+
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ //base.OnPaint(e);
+ e.Graphics.FillRectangle(new SolidBrush(this.BackColor), this.ClientRectangle);
+
+ Pen checkMark = new Pen(Color.White, 1.8f);
+ checkMark.StartCap = LineCap.Round;
+ checkMark.EndCap = LineCap.Round;
+
+ // Colors and brushes
+ Pen brushBorder = null;
+ LinearGradientMode mode = LinearGradientMode.Vertical;
+ LinearGradientBrush brushOuter = null;
+ LinearGradientBrush brushInner = null;
+
+ int y = (this.Height - boxSize) / 2;
+
+ Rectangle newRect = new Rectangle(1, y, boxSize, boxSize);
+ Color text_color = Color.White;
+
+ brushOuter = new LinearGradientBrush(newRect, ColorScheme.ColorGray107, ColorScheme.ColorGray110, mode);
+ e.Graphics.FillRectangle(brushOuter, newRect);
+
+ newRect = new Rectangle(2, y + 1, boxSize - 3, boxSize - 3);
+
+ if (Enabled)
+ {
+ if (base.Focused)
+ brushBorder = new Pen(Color.FromArgb(60, 60, 60), 1f);
+ else
+ brushBorder = new Pen(Color.FromArgb(38, 38, 38), 1f);
+
+ switch (m_State)
+ {
+ case eButtonState.Normal:
+ brushInner = new LinearGradientBrush(newRect, Color.FromArgb(111, 111, 111), Color.FromArgb(80, 80, 80), mode);
+ e.Graphics.FillRectangle(brushInner, newRect);
+ break;
+
+ case eButtonState.MouseOver:
+ brushInner = new LinearGradientBrush(newRect, Color.FromArgb(118, 118, 118), Color.FromArgb(81, 81, 81), mode);
+ e.Graphics.FillRectangle(brushInner, newRect);
+ break;
+
+ case eButtonState.Down:
+ brushInner = new LinearGradientBrush(newRect, Color.FromArgb(92, 92, 92), Color.FromArgb(62, 62, 62), mode);
+ e.Graphics.FillRectangle(brushInner, newRect);
+ break;
+ }
+
+ e.Graphics.DrawRectangle(brushBorder, newRect);
+
+ }
+ else
+ {
+ brushInner = new LinearGradientBrush(newRect, Color.FromArgb(76, 76, 76), Color.FromArgb(65, 65, 65), mode);
+ e.Graphics.FillRectangle(brushInner, newRect);
+
+ brushBorder = new Pen(Color.FromArgb(48, 48, 48), 1f);
+ e.Graphics.DrawRectangle(brushBorder, newRect);
+
+ text_color = Color.FromArgb(160, 160, 160);
+ checkMark.Color = Color.FromArgb(180, 180, 180);
+ }
+
+ e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
+
+ SizeF szL = e.Graphics.MeasureString(this.Text, base.Font, this.Width);
+ DrawText(e.Graphics, text_color, new Point(boxSize + 4, (int)((this.Height - szL.Height) / 2) + 1));
+
+ if (this.isChecked)
+ {
+ e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
+
+ e.Graphics.DrawLine(checkMark, 4, newRect.Bottom - boxSize / 2, newRect.Left + boxSize / 2.5f, newRect.Bottom - 2);
+ e.Graphics.DrawLine(checkMark, newRect.Left + boxSize / 2.6f, newRect.Bottom - 2, newRect.Right, newRect.Top);
+ }
+
+ if (brushOuter != null) brushOuter.Dispose();
+ if (brushInner != null) brushInner.Dispose();
+ if (brushBorder != null) brushBorder.Dispose();
+ if (checkMark != null) checkMark.Dispose();
+ }
+
+ protected override void OnMouseLeave(System.EventArgs e)
+ {
+ m_State = eButtonState.Normal;
+ this.Invalidate();
+ base.OnMouseLeave(e);
+ }
+
+ protected override void OnMouseEnter(System.EventArgs e)
+ {
+ m_State = eButtonState.MouseOver;
+ this.Invalidate();
+ base.OnMouseEnter(e);
+ }
+
+ protected override void OnMouseUp(System.Windows.Forms.MouseEventArgs e)
+ {
+ m_State = eButtonState.MouseOver;
+ this.Invalidate();
+ base.OnMouseUp(e);
+ }
+
+ protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
+ {
+ m_State = eButtonState.Down;
+ this.Invalidate();
+ base.OnMouseDown(e);
+ }
+
+ protected override void OnClick(EventArgs e)
+ {
+ this.isChecked = !this.isChecked;
+ this.Invalidate();
+ base.OnClick(e);
+ }
+
+ #endregion
+ }
+}
diff --git a/Triangle.NET/TestApp/Controls/DarkListBox.cs b/src/Triangle.Viewer/Controls/DarkListBox.cs
similarity index 85%
rename from Triangle.NET/TestApp/Controls/DarkListBox.cs
rename to src/Triangle.Viewer/Controls/DarkListBox.cs
index a927deb..c5a8555 100644
--- a/Triangle.NET/TestApp/Controls/DarkListBox.cs
+++ b/src/Triangle.Viewer/Controls/DarkListBox.cs
@@ -1,82 +1,76 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace MeshExplorer.Controls
-{
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Windows.Forms;
- using System.Drawing;
-
- ///
- /// Dark listbox control.
- ///
- public class DarkListBox : ListBox
- {
- Font _boldFont;
-
- ///
- /// Initializes a new instance of the control.
- ///
- public DarkListBox()
- {
- _boldFont = new Font(base.Font.FontFamily, base.Font.Size, FontStyle.Bold);
-
- this.DrawMode = DrawMode.OwnerDrawVariable;
- this.ItemHeight = 22;
- this.FontChanged += new EventHandler(ListBoxFontChanged);
- this.BackColor = Color.FromArgb(96, 96, 96);
- }
-
- void ListBoxFontChanged(object sender, EventArgs e)
- {
- _boldFont = new Font(base.Font.FontFamily, base.Font.Size, FontStyle.Bold);
- }
-
- protected override void OnMeasureItem(MeasureItemEventArgs e)
- {
- e.ItemHeight = 22;
- }
-
- protected override void OnDrawItem(DrawItemEventArgs e)
- {
- if (this.Items.Count == 0)
- {
- return;
- }
-
- e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
-
- int index = e.Index;
-
- string content = "[Error]";
-
- if (index < this.Items.Count && index >= 0)
- {
- content = this.Items[index].ToString();
- }
-
- Color color = (e.Index % 2) == 0 ? Color.FromArgb(85, 85, 85) : Color.FromArgb(90, 90, 90);
-
- if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
- {
- color = Color.FromArgb(100, 105, 110);
- }
-
- using (SolidBrush background = new SolidBrush(color))
- {
- e.Graphics.FillRectangle(background, e.Bounds);
- }
-
- using (SolidBrush pen = new SolidBrush(Color.White))
- {
- e.Graphics.DrawString(content, this.Font, pen,
- new PointF(10, e.Bounds.Y + 3), StringFormat.GenericDefault);
- }
- }
- }
-}
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+//
+// -----------------------------------------------------------------------
+
+namespace MeshExplorer.Controls
+{
+ using System;
+ using System.Drawing;
+ using System.Windows.Forms;
+
+ ///
+ /// Dark listbox control.
+ ///
+ public class DarkListBox : ListBox
+ {
+ Font _boldFont;
+
+ ///
+ /// Initializes a new instance of the control.
+ ///
+ public DarkListBox()
+ {
+ _boldFont = new Font(base.Font.FontFamily, base.Font.Size, FontStyle.Bold);
+
+ this.DrawMode = DrawMode.OwnerDrawVariable;
+ this.ItemHeight = 22;
+ this.FontChanged += new EventHandler(ListBoxFontChanged);
+ this.BackColor = Color.FromArgb(96, 96, 96);
+ }
+
+ void ListBoxFontChanged(object sender, EventArgs e)
+ {
+ _boldFont = new Font(base.Font.FontFamily, base.Font.Size, FontStyle.Bold);
+ }
+
+ protected override void OnMeasureItem(MeasureItemEventArgs e)
+ {
+ e.ItemHeight = 22;
+ }
+
+ protected override void OnDrawItem(DrawItemEventArgs e)
+ {
+ if (this.Items.Count == 0)
+ {
+ return;
+ }
+
+ e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
+
+ int index = e.Index;
+
+ string content = "[Error]";
+
+ if (index < this.Items.Count && index >= 0)
+ {
+ content = this.Items[index].ToString();
+ }
+
+ Color color = (e.Index % 2) == 0 ? Color.FromArgb(85, 85, 85) : Color.FromArgb(90, 90, 90);
+
+ if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
+ {
+ color = Color.FromArgb(100, 105, 110);
+ }
+
+ using (SolidBrush background = new SolidBrush(color))
+ {
+ e.Graphics.FillRectangle(background, e.Bounds);
+ }
+
+ TextRenderer.DrawText(e.Graphics, content, Font, new Point(10, e.Bounds.Y + 3), Color.White, TextFormatFlags.EndEllipsis);
+ }
+ }
+}
diff --git a/Triangle.NET/TestApp/Controls/DarkSlider.cs b/src/Triangle.Viewer/Controls/DarkSlider.cs
similarity index 96%
rename from Triangle.NET/TestApp/Controls/DarkSlider.cs
rename to src/Triangle.Viewer/Controls/DarkSlider.cs
index d2f67ac..6f6f83a 100644
--- a/Triangle.NET/TestApp/Controls/DarkSlider.cs
+++ b/src/Triangle.Viewer/Controls/DarkSlider.cs
@@ -1,453 +1,450 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-// Original code on CodeProject: Owner-drawn trackbar (slider), Michal Brylka
-//
-// -----------------------------------------------------------------------
-
-namespace MeshExplorer.Controls
-{
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Windows.Forms;
- using System.Drawing;
- using System.Drawing.Drawing2D;
-
- ///
- /// Encapsulates control that visualy displays certain integer value and allows user to change
- /// it within desired range. It imitates as far as
- /// mouse usage is concerned.
- ///
- public class DarkSlider : Control
- {
- #region Designer
-
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Component Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- components = new System.ComponentModel.Container();
- }
-
- #endregion
-
- #endregion
-
- #region Events
-
- ///
- /// Fires when Slider position has changed
- ///
- public event EventHandler ValueChanging;
-
- private void OnValueChanging()
- {
- var evt = ValueChanging;
-
- if (evt != null)
- {
- evt(this, EventArgs.Empty);
- }
- }
-
- ///
- /// Fires when Slider position has changed
- ///
- public event EventHandler ValueChanged;
-
- private void OnValueChanged()
- {
- var evt = ValueChanged;
-
- if (evt != null)
- {
- evt(this, EventArgs.Empty);
- }
- }
-
- #endregion
-
- #region Properties
-
- int thumbSize = 7;
- private Rectangle thumbRect; //bounding rectangle of thumb area
- private Rectangle barRect; //bounding rectangle of bar area
- private bool mouseInThumbRegion = false;
-
- private int trackerValue = 50;
- ///
- /// Gets or sets the value of Slider.
- ///
- /// The value.
- public int Value
- {
- get { return trackerValue; }
- set
- {
- if (value >= barMinimum & value <= barMaximum)
- {
- trackerValue = value;
- if (ValueChanged != null) ValueChanged(this, new EventArgs());
- Invalidate();
- }
- // ArgumentOutOfRangeException("Value is outside appropriate range (min, max)");
- }
- }
-
-
- private int barMinimum = 0;
- ///
- /// Gets or sets the minimum value.
- ///
- /// The minimum value.
- public int Minimum
- {
- get { return barMinimum; }
- set
- {
- if (value < barMaximum)
- {
- barMinimum = value;
- if (trackerValue < barMinimum)
- {
- trackerValue = barMinimum;
- if (ValueChanged != null) ValueChanged(this, new EventArgs());
- }
- Invalidate();
- }
- // ArgumentOutOfRangeException("Minimal value is greather than maximal one");
- }
- }
-
-
- private int barMaximum = 100;
- ///
- /// Gets or sets the maximum value.
- ///
- /// The maximum value.
- public int Maximum
- {
- get { return barMaximum; }
- set
- {
- if (value > barMinimum)
- {
- barMaximum = value;
- if (trackerValue > barMaximum)
- {
- trackerValue = barMaximum;
- if (ValueChanged != null) ValueChanged(this, new EventArgs());
- }
- Invalidate();
- }
- // ArgumentOutOfRangeException("Maximal value is lower than minimal one");
- }
- }
-
- private uint criticalPercent = 0;
- ///
- /// Gets or sets trackbar's small change. It affects how to behave when directional keys are pressed
- ///
- /// The small change value.
- public uint CriticalPercent
- {
- get { return criticalPercent; }
- set { criticalPercent = value; }
- }
-
- private Color thumbOuterColor = Color.White;
- private Color thumbInnerColor = Color.Gainsboro;
- private Color thumbPenColor = Color.Silver;
- private Color barOuterColor = Color.SkyBlue;
- private Color barInnerColor = Color.DarkSlateBlue;
- private Color barPenColor = Color.Gainsboro;
- private Color elapsedOuterColor = Color.DarkGreen;
- private Color elapsedInnerColor = Color.Chartreuse;
-
- #endregion
-
- #region Constructors
-
- ///
- /// Initializes a new instance of the control.
- ///
- public DarkSlider()
- {
- InitializeComponent();
- SetStyle(ControlStyles.AllPaintingInWmPaint
- | ControlStyles.OptimizedDoubleBuffer
- | ControlStyles.ResizeRedraw
- | ControlStyles.Selectable
- | ControlStyles.SupportsTransparentBackColor
- | ControlStyles.UserMouse
- | ControlStyles.UserPaint, true);
-
- BackColor = Color.Transparent;
-
- Minimum = 0;
- Maximum = 100;
- Value = 50;
- }
-
- #endregion
-
- #region Paint
-
- ///
- /// Raises the event.
- ///
- /// A that contains the event data.
- protected override void OnPaint(PaintEventArgs e)
- {
- if (!Enabled)
- {
- DrawDisabledSlider(e.Graphics);
- }
- else
- {
- //if (mouseEffects && mouseInRegion)
- //{
- // Color[] lightenedColors = LightenColors(thumbOuterColor, thumbInnerColor, thumbPenColor,
- // barOuterColor, barInnerColor, barPenColor,
- // elapsedOuterColor, elapsedInnerColor);
- // DrawColorSlider(e, lightenedColors[0], lightenedColors[1], lightenedColors[2], lightenedColors[3],
- // lightenedColors[4], lightenedColors[5], lightenedColors[6], lightenedColors[7]);
- //}
- //else
- {
- DrawColorSlider(e.Graphics);
- }
- }
- }
-
- private void DrawDisabledSlider(Graphics g)
- {
- try
- {
- //adjust drawing rects
- barRect = new Rectangle(1, this.Height / 2, this.Width - 2, 5);
-
- Brush sliderLGBrushH = new LinearGradientBrush(barRect, ColorScheme.ColorGray122,
- ColorScheme.ColorGray107, LinearGradientMode.Horizontal);
-
- //draw bar
- {
- // Background gradient
- g.FillRectangle(sliderLGBrushH, barRect);
- // Background fill
- g.FillRectangle(ColorScheme.SliderBorderBrush,
- barRect.Left + 1, barRect.Top, barRect.Width - 2, barRect.Height - 1);
- // Bar fill
- g.FillRectangle(ColorScheme.SliderFillBrush,
- barRect.Left + 2, barRect.Top + 1, barRect.Width - 4, barRect.Height - 3);
- }
-
- sliderLGBrushH.Dispose();
- }
- catch (Exception)
- { }
- finally
- { }
- }
-
- ///
- /// Draws the colorslider control using passed colors.
- ///
- private void DrawColorSlider(Graphics g)
- {
- try
- {
- //set up thumbRect aproprietly
- int track = (((trackerValue - barMinimum) * (ClientRectangle.Width - thumbSize)) / (barMaximum - barMinimum));
- thumbRect = new Rectangle(track, this.Height / 2 - 3, thumbSize - 1, 10);
-
- //adjust drawing rects
- barRect = new Rectangle(1, this.Height / 2, this.Width - 2, 5);
-
- //get thumb shape path
- GraphicsPath thumbPath = new GraphicsPath();
- thumbPath.AddPolygon(new Point[] {
- new Point(thumbRect.Left, thumbRect.Top),
- new Point(thumbRect.Right, thumbRect.Top),
- new Point(thumbRect.Right, thumbRect.Bottom - 4),
- new Point(thumbRect.Left + thumbRect.Width / 2, thumbRect.Bottom),
- new Point(thumbRect.Left, thumbRect.Bottom - 4)
- });
-
- Brush sliderLGBrushH = new LinearGradientBrush(barRect, ColorScheme.ColorGray122,
- ColorScheme.ColorGray107, LinearGradientMode.Horizontal);
-
- Brush barFill = (criticalPercent > 0 && trackerValue > criticalPercent) ? Brushes.Peru : Brushes.Green;
-
- //draw bar
- {
- // Background gradient
- g.FillRectangle(sliderLGBrushH, barRect);
- // Background fill
- g.FillRectangle(ColorScheme.SliderBorderBrush,
- barRect.Left + 1, barRect.Top, barRect.Width - 2, barRect.Height - 1);
- // Bar fill
- g.FillRectangle(ColorScheme.SliderFillBrush,
- barRect.Left + 2, barRect.Top + 1, barRect.Width - 4, barRect.Height - 3);
- // Elapsed bar fill
-
- g.FillRectangle(barFill,
- barRect.Left + 2, barRect.Top + 1, thumbRect.Left + thumbSize / 2 - 2, barRect.Height - 3);
-
- //draw bar band
- //g.DrawRectangle(barPen, barRect);
- }
-
- sliderLGBrushH.Dispose();
-
- //draw thumb
- Brush brushInner = new LinearGradientBrush(thumbRect,
- Color.FromArgb(111, 111, 111), Color.FromArgb(80, 80, 80),
- LinearGradientMode.Vertical);
-
- g.SmoothingMode = SmoothingMode.AntiAlias;
- g.FillPath(brushInner, thumbPath);
- g.DrawPath(Pens.Black, thumbPath);
-
- brushInner.Dispose();
- //draw thumb band
- //Color newThumbPenColor = thumbPenColorPaint;
- //if (mouseEffects && (Capture || mouseInThumbRegion))
- // newThumbPenColor = ControlPaint.Dark(newThumbPenColor);
- //g.DrawPath(thumbPen, thumbPath);
- }
- catch (Exception)
- { }
- finally
- { }
- }
-
- #endregion
-
- #region Overided events
-
- ///
- /// Raises the event.
- ///
- /// An that contains the event data.
- protected override void OnEnabledChanged(EventArgs e)
- {
- base.OnEnabledChanged(e);
- Invalidate();
- }
-
- ///
- /// Raises the event.
- ///
- /// An that contains the event data.
- protected override void OnMouseLeave(EventArgs e)
- {
- base.OnMouseLeave(e);
- mouseInThumbRegion = false;
- }
-
- ///
- /// Raises the event.
- ///
- /// A that contains the event data.
- protected override void OnMouseDown(MouseEventArgs e)
- {
- base.OnMouseDown(e);
- if (e.Button == MouseButtons.Left && this.Enabled)
- {
- this.Capture = true;
- OnValueChanging();
- OnMouseMove(e);
- }
- }
-
- ///
- /// Raises the event.
- ///
- /// A that contains the event data.
- protected override void OnMouseMove(MouseEventArgs e)
- {
- base.OnMouseMove(e);
- mouseInThumbRegion = thumbRect.Contains(e.Location);
- if (Capture & e.Button == MouseButtons.Left)
- {
- Point pt = e.Location;
- int p = pt.X;
- int margin = thumbSize >> 1;
- p -= margin;
- float coef = (float)(barMaximum - barMinimum) /
- (float)(ClientSize.Width - 2 * margin);
- trackerValue = (int)(p * coef + barMinimum);
-
- if (trackerValue <= barMinimum)
- {
- trackerValue = barMinimum;
- }
- else if (trackerValue >= barMaximum)
- {
- trackerValue = barMaximum;
- }
-
- OnValueChanging();
- }
- Invalidate();
- }
-
- ///
- /// Raises the event.
- ///
- /// A that contains the event data.
- protected override void OnMouseUp(MouseEventArgs e)
- {
- if (this.Enabled)
- {
- base.OnMouseUp(e);
- this.Capture = false;
- mouseInThumbRegion = thumbRect.Contains(e.Location);
- OnValueChanged();
- Invalidate();
- }
- }
-
- #endregion
-
- #region Help routines
-
- ///
- /// Sets the trackbar value so that it wont exceed allowed range.
- ///
- /// The value.
- private void SetProperValue(int val)
- {
- if (val < barMinimum) Value = barMinimum;
- else if (val > barMaximum) Value = barMaximum;
- else Value = val;
- }
-
- #endregion
- }
-}
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+// Original code on CodeProject: Owner-drawn trackbar (slider), Michal Brylka
+//
+// -----------------------------------------------------------------------
+
+namespace MeshExplorer.Controls
+{
+ using System;
+ using System.Drawing;
+ using System.Drawing.Drawing2D;
+ using System.Windows.Forms;
+
+ ///
+ /// Encapsulates control that visualy displays certain integer value and allows user to change
+ /// it within desired range. It imitates as far as
+ /// mouse usage is concerned.
+ ///
+ public class DarkSlider : Control
+ {
+ #region Designer
+
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ components = new System.ComponentModel.Container();
+ }
+
+ #endregion
+
+ #endregion
+
+ #region Events
+
+ ///
+ /// Fires when Slider position has changed
+ ///
+ public event EventHandler ValueChanging;
+
+ private void OnValueChanging()
+ {
+ var evt = ValueChanging;
+
+ if (evt != null)
+ {
+ evt(this, EventArgs.Empty);
+ }
+ }
+
+ ///
+ /// Fires when Slider position has changed
+ ///
+ public event EventHandler ValueChanged;
+
+ private void OnValueChanged()
+ {
+ var evt = ValueChanged;
+
+ if (evt != null)
+ {
+ evt(this, EventArgs.Empty);
+ }
+ }
+
+ #endregion
+
+ #region Properties
+
+ int thumbSize = 7;
+ private Rectangle thumbRect; //bounding rectangle of thumb area
+ private Rectangle barRect; //bounding rectangle of bar area
+ private bool mouseInThumbRegion = false;
+
+ private int trackerValue = 50;
+ ///
+ /// Gets or sets the value of Slider.
+ ///
+ /// The value.
+ public int Value
+ {
+ get { return trackerValue; }
+ set
+ {
+ if (value >= barMinimum & value <= barMaximum)
+ {
+ trackerValue = value;
+ if (ValueChanged != null) ValueChanged(this, new EventArgs());
+ Invalidate();
+ }
+ // ArgumentOutOfRangeException("Value is outside appropriate range (min, max)");
+ }
+ }
+
+
+ private int barMinimum = 0;
+ ///
+ /// Gets or sets the minimum value.
+ ///
+ /// The minimum value.
+ public int Minimum
+ {
+ get { return barMinimum; }
+ set
+ {
+ if (value < barMaximum)
+ {
+ barMinimum = value;
+ if (trackerValue < barMinimum)
+ {
+ trackerValue = barMinimum;
+ if (ValueChanged != null) ValueChanged(this, new EventArgs());
+ }
+ Invalidate();
+ }
+ // ArgumentOutOfRangeException("Minimal value is greather than maximal one");
+ }
+ }
+
+
+ private int barMaximum = 100;
+ ///
+ /// Gets or sets the maximum value.
+ ///
+ /// The maximum value.
+ public int Maximum
+ {
+ get { return barMaximum; }
+ set
+ {
+ if (value > barMinimum)
+ {
+ barMaximum = value;
+ if (trackerValue > barMaximum)
+ {
+ trackerValue = barMaximum;
+ if (ValueChanged != null) ValueChanged(this, new EventArgs());
+ }
+ Invalidate();
+ }
+ // ArgumentOutOfRangeException("Maximal value is lower than minimal one");
+ }
+ }
+
+ private uint criticalPercent = 0;
+ ///
+ /// Gets or sets trackbar's small change. It affects how to behave when directional keys are pressed
+ ///
+ /// The small change value.
+ public uint CriticalPercent
+ {
+ get { return criticalPercent; }
+ set { criticalPercent = value; }
+ }
+
+ private Color thumbOuterColor = Color.White;
+ private Color thumbInnerColor = Color.Gainsboro;
+ private Color thumbPenColor = Color.Silver;
+ private Color barOuterColor = Color.SkyBlue;
+ private Color barInnerColor = Color.DarkSlateBlue;
+ private Color barPenColor = Color.Gainsboro;
+ private Color elapsedOuterColor = Color.DarkGreen;
+ private Color elapsedInnerColor = Color.Chartreuse;
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Initializes a new instance of the control.
+ ///
+ public DarkSlider()
+ {
+ InitializeComponent();
+ SetStyle(ControlStyles.AllPaintingInWmPaint
+ | ControlStyles.OptimizedDoubleBuffer
+ | ControlStyles.ResizeRedraw
+ | ControlStyles.Selectable
+ | ControlStyles.SupportsTransparentBackColor
+ | ControlStyles.UserMouse
+ | ControlStyles.UserPaint, true);
+
+ BackColor = Color.Transparent;
+
+ Minimum = 0;
+ Maximum = 100;
+ Value = 50;
+ }
+
+ #endregion
+
+ #region Paint
+
+ ///
+ /// Raises the event.
+ ///
+ /// A that contains the event data.
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ if (!Enabled)
+ {
+ DrawDisabledSlider(e.Graphics);
+ }
+ else
+ {
+ //if (mouseEffects && mouseInRegion)
+ //{
+ // Color[] lightenedColors = LightenColors(thumbOuterColor, thumbInnerColor, thumbPenColor,
+ // barOuterColor, barInnerColor, barPenColor,
+ // elapsedOuterColor, elapsedInnerColor);
+ // DrawColorSlider(e, lightenedColors[0], lightenedColors[1], lightenedColors[2], lightenedColors[3],
+ // lightenedColors[4], lightenedColors[5], lightenedColors[6], lightenedColors[7]);
+ //}
+ //else
+ {
+ DrawColorSlider(e.Graphics);
+ }
+ }
+ }
+
+ private void DrawDisabledSlider(Graphics g)
+ {
+ try
+ {
+ //adjust drawing rects
+ barRect = new Rectangle(1, this.Height / 2, this.Width - 2, 5);
+
+ Brush sliderLGBrushH = new LinearGradientBrush(barRect, ColorScheme.ColorGray122,
+ ColorScheme.ColorGray107, LinearGradientMode.Horizontal);
+
+ //draw bar
+ {
+ // Background gradient
+ g.FillRectangle(sliderLGBrushH, barRect);
+ // Background fill
+ g.FillRectangle(ColorScheme.SliderBorderBrush,
+ barRect.Left + 1, barRect.Top, barRect.Width - 2, barRect.Height - 1);
+ // Bar fill
+ g.FillRectangle(ColorScheme.SliderFillBrush,
+ barRect.Left + 2, barRect.Top + 1, barRect.Width - 4, barRect.Height - 3);
+ }
+
+ sliderLGBrushH.Dispose();
+ }
+ catch (Exception)
+ { }
+ finally
+ { }
+ }
+
+ ///
+ /// Draws the colorslider control using passed colors.
+ ///
+ private void DrawColorSlider(Graphics g)
+ {
+ try
+ {
+ //set up thumbRect aproprietly
+ int track = (((trackerValue - barMinimum) * (ClientRectangle.Width - thumbSize)) / (barMaximum - barMinimum));
+ thumbRect = new Rectangle(track, this.Height / 2 - 3, thumbSize - 1, 10);
+
+ //adjust drawing rects
+ barRect = new Rectangle(1, this.Height / 2, this.Width - 2, 5);
+
+ //get thumb shape path
+ GraphicsPath thumbPath = new GraphicsPath();
+ thumbPath.AddPolygon(new Point[] {
+ new Point(thumbRect.Left, thumbRect.Top),
+ new Point(thumbRect.Right, thumbRect.Top),
+ new Point(thumbRect.Right, thumbRect.Bottom - 4),
+ new Point(thumbRect.Left + thumbRect.Width / 2, thumbRect.Bottom),
+ new Point(thumbRect.Left, thumbRect.Bottom - 4)
+ });
+
+ Brush sliderLGBrushH = new LinearGradientBrush(barRect, ColorScheme.ColorGray122,
+ ColorScheme.ColorGray107, LinearGradientMode.Horizontal);
+
+ Brush barFill = (criticalPercent > 0 && trackerValue > criticalPercent) ? Brushes.Peru : Brushes.Green;
+
+ //draw bar
+ {
+ // Background gradient
+ g.FillRectangle(sliderLGBrushH, barRect);
+ // Background fill
+ g.FillRectangle(ColorScheme.SliderBorderBrush,
+ barRect.Left + 1, barRect.Top, barRect.Width - 2, barRect.Height - 1);
+ // Bar fill
+ g.FillRectangle(ColorScheme.SliderFillBrush,
+ barRect.Left + 2, barRect.Top + 1, barRect.Width - 4, barRect.Height - 3);
+ // Elapsed bar fill
+
+ g.FillRectangle(barFill,
+ barRect.Left + 2, barRect.Top + 1, thumbRect.Left + thumbSize / 2 - 2, barRect.Height - 3);
+
+ //draw bar band
+ //g.DrawRectangle(barPen, barRect);
+ }
+
+ sliderLGBrushH.Dispose();
+
+ //draw thumb
+ Brush brushInner = new LinearGradientBrush(thumbRect,
+ Color.FromArgb(111, 111, 111), Color.FromArgb(80, 80, 80),
+ LinearGradientMode.Vertical);
+
+ g.SmoothingMode = SmoothingMode.AntiAlias;
+ g.FillPath(brushInner, thumbPath);
+ g.DrawPath(Pens.Black, thumbPath);
+
+ brushInner.Dispose();
+ //draw thumb band
+ //Color newThumbPenColor = thumbPenColorPaint;
+ //if (mouseEffects && (Capture || mouseInThumbRegion))
+ // newThumbPenColor = ControlPaint.Dark(newThumbPenColor);
+ //g.DrawPath(thumbPen, thumbPath);
+ }
+ catch (Exception)
+ { }
+ finally
+ { }
+ }
+
+ #endregion
+
+ #region Overided events
+
+ ///
+ /// Raises the event.
+ ///
+ /// An that contains the event data.
+ protected override void OnEnabledChanged(EventArgs e)
+ {
+ base.OnEnabledChanged(e);
+ Invalidate();
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ /// An that contains the event data.
+ protected override void OnMouseLeave(EventArgs e)
+ {
+ base.OnMouseLeave(e);
+ mouseInThumbRegion = false;
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ /// A that contains the event data.
+ protected override void OnMouseDown(MouseEventArgs e)
+ {
+ base.OnMouseDown(e);
+ if (e.Button == MouseButtons.Left && this.Enabled)
+ {
+ this.Capture = true;
+ OnValueChanging();
+ OnMouseMove(e);
+ }
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ /// A that contains the event data.
+ protected override void OnMouseMove(MouseEventArgs e)
+ {
+ base.OnMouseMove(e);
+ mouseInThumbRegion = thumbRect.Contains(e.Location);
+ if (Capture & e.Button == MouseButtons.Left)
+ {
+ Point pt = e.Location;
+ int p = pt.X;
+ int margin = thumbSize >> 1;
+ p -= margin;
+ float coef = (float)(barMaximum - barMinimum) /
+ (float)(ClientSize.Width - 2 * margin);
+ trackerValue = (int)(p * coef + barMinimum);
+
+ if (trackerValue <= barMinimum)
+ {
+ trackerValue = barMinimum;
+ }
+ else if (trackerValue >= barMaximum)
+ {
+ trackerValue = barMaximum;
+ }
+
+ OnValueChanging();
+ }
+ Invalidate();
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ /// A that contains the event data.
+ protected override void OnMouseUp(MouseEventArgs e)
+ {
+ if (this.Enabled)
+ {
+ base.OnMouseUp(e);
+ this.Capture = false;
+ mouseInThumbRegion = thumbRect.Contains(e.Location);
+ OnValueChanged();
+ Invalidate();
+ }
+ }
+
+ #endregion
+
+ #region Help routines
+
+ ///
+ /// Sets the trackbar value so that it wont exceed allowed range.
+ ///
+ /// The value.
+ private void SetProperValue(int val)
+ {
+ if (val < barMinimum) Value = barMinimum;
+ else if (val > barMaximum) Value = barMaximum;
+ else Value = val;
+ }
+
+ #endregion
+ }
+}
diff --git a/Triangle.NET/TestApp/Controls/DarkTabControl.cs b/src/Triangle.Viewer/Controls/DarkTabControl.cs
similarity index 95%
rename from Triangle.NET/TestApp/Controls/DarkTabControl.cs
rename to src/Triangle.Viewer/Controls/DarkTabControl.cs
index 831ee07..50b58f5 100644
--- a/Triangle.NET/TestApp/Controls/DarkTabControl.cs
+++ b/src/Triangle.Viewer/Controls/DarkTabControl.cs
@@ -1,190 +1,188 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-// Original code on CodeProject: A .NET Flat TabControl (CustomDraw), Oscar Londono
-//
-// -----------------------------------------------------------------------
-
-namespace MeshExplorer.Controls
-{
- using System;
- using System.ComponentModel;
- using System.Drawing;
- using System.Windows.Forms;
- using System.Drawing.Text;
-
- ///
- /// Summary description for FlatTabControl.
- ///
- public class DarkTabControl : System.Windows.Forms.TabControl
- {
- #region Designer
-
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Component Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- components = new System.ComponentModel.Container();
- }
-
- #endregion
-
- #endregion
-
- private const int margin = 5;
- private Color backColor = ColorScheme.ColorGray68;
-
- ///
- /// Initializes a new instance of the control.
- ///
- public DarkTabControl()
- {
- // This call is required by the Windows.Forms Form Designer.
- InitializeComponent();
-
- base.Multiline = false;
-
- // double buffering
- this.SetStyle(ControlStyles.UserPaint, true);
- this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
- this.SetStyle(ControlStyles.DoubleBuffer, true);
- this.SetStyle(ControlStyles.ResizeRedraw, true);
- this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
-
- this.SelectedIndexChanged += (obj, evt) => { Invalidate(); };
- }
-
- #region Properties
-
- new public TabAlignment Alignment
- {
- get { return base.Alignment; }
- set
- {
- TabAlignment ta = value;
- if ((ta != TabAlignment.Top) && (ta != TabAlignment.Bottom))
- {
- ta = TabAlignment.Top;
- }
-
- base.Alignment = ta;
- }
- }
-
- public override Color BackColor
- {
- get
- {
- return backColor;
- }
- set
- {
- base.BackColor = backColor;
- }
- }
-
- #endregion
-
- protected override void OnPaint(PaintEventArgs e)
- {
- base.OnPaint(e);
-
- DrawControl(e.Graphics);
- }
-
- private void DrawControl(Graphics g)
- {
- if (!Visible)
- {
- return;
- }
-
- Rectangle controlBounds = this.ClientRectangle;
- Rectangle tabBounds = this.DisplayRectangle;
-
- // Fill client area
- Brush br = new SolidBrush(this.BackColor);
- g.FillRectangle(br, controlBounds);
- br.Dispose();
-
- int width = tabBounds.Width + margin;
-
- // Clip region for drawing tabs
- Region clip = g.Clip;
- Rectangle region = new Rectangle(tabBounds.Left, controlBounds.Top, width - margin, controlBounds.Height);
-
- g.SetClip(region);
-
- // Draw tabs
- for (int i = 0; i < this.TabCount; i++)
- {
- DrawTab(g, this.TabPages[i], i);
- }
-
- g.Clip = clip;
- }
-
- private void DrawTab(Graphics g, TabPage tabPage, int index)
- {
- Rectangle tabBounds = this.GetTabRect(index);
-
- bool selected = (this.SelectedIndex == index);
-
- // Fill this tab with background color
- g.FillRectangle(selected ? Brushes.DimGray : ColorScheme.BrushGray68, tabBounds);
-
- if (selected)
- {
- // Clear bottom lines
- Pen pen = new Pen(tabPage.BackColor);
-
- switch (this.Alignment)
- {
- case TabAlignment.Top:
- g.DrawLine(pen, tabBounds.Left, tabBounds.Bottom, tabBounds.Right - 1, tabBounds.Bottom);
- g.DrawLine(pen, tabBounds.Left, tabBounds.Bottom + 1, tabBounds.Right - 1, tabBounds.Bottom + 1);
- break;
-
- case TabAlignment.Bottom:
- g.DrawLine(pen, tabBounds.Left, tabBounds.Top, tabBounds.Right - 1, tabBounds.Top);
- g.DrawLine(pen, tabBounds.Left, tabBounds.Top - 1, tabBounds.Right - 1, tabBounds.Top - 1);
- g.DrawLine(pen, tabBounds.Left, tabBounds.Top - 2, tabBounds.Right - 1, tabBounds.Top - 2);
- break;
- }
-
- pen.Dispose();
- }
-
- // Draw string
- StringFormat stringFormat = new StringFormat();
- stringFormat.Alignment = StringAlignment.Center;
- stringFormat.LineAlignment = StringAlignment.Center;
-
- g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
-
- g.DrawString(tabPage.Text, Font, Brushes.White, tabBounds, stringFormat);
- }
- }
-}
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+// Original code on CodeProject: A .NET Flat TabControl (CustomDraw), Oscar Londono
+//
+// -----------------------------------------------------------------------
+
+namespace MeshExplorer.Controls
+{
+ using System.Drawing;
+ using System.Drawing.Text;
+ using System.Windows.Forms;
+
+ ///
+ /// Summary description for FlatTabControl.
+ ///
+ public class DarkTabControl : System.Windows.Forms.TabControl
+ {
+ #region Designer
+
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ components = new System.ComponentModel.Container();
+ }
+
+ #endregion
+
+ #endregion
+
+ private const int margin = 5;
+ private Color backColor = ColorScheme.ColorGray68;
+
+ ///
+ /// Initializes a new instance of the control.
+ ///
+ public DarkTabControl()
+ {
+ // This call is required by the Windows.Forms Form Designer.
+ InitializeComponent();
+
+ base.Multiline = false;
+
+ // double buffering
+ this.SetStyle(ControlStyles.UserPaint, true);
+ this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
+ this.SetStyle(ControlStyles.DoubleBuffer, true);
+ this.SetStyle(ControlStyles.ResizeRedraw, true);
+ this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
+
+ this.SelectedIndexChanged += (obj, evt) => { Invalidate(); };
+ }
+
+ #region Properties
+
+ new public TabAlignment Alignment
+ {
+ get { return base.Alignment; }
+ set
+ {
+ TabAlignment ta = value;
+ if ((ta != TabAlignment.Top) && (ta != TabAlignment.Bottom))
+ {
+ ta = TabAlignment.Top;
+ }
+
+ base.Alignment = ta;
+ }
+ }
+
+ public override Color BackColor
+ {
+ get
+ {
+ return backColor;
+ }
+ set
+ {
+ base.BackColor = backColor;
+ }
+ }
+
+ #endregion
+
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ base.OnPaint(e);
+
+ DrawControl(e.Graphics);
+ }
+
+ private void DrawControl(Graphics g)
+ {
+ if (!Visible)
+ {
+ return;
+ }
+
+ Rectangle controlBounds = this.ClientRectangle;
+ Rectangle tabBounds = this.DisplayRectangle;
+
+ // Fill client area
+ Brush br = new SolidBrush(this.BackColor);
+ g.FillRectangle(br, controlBounds);
+ br.Dispose();
+
+ int width = tabBounds.Width + margin;
+
+ // Clip region for drawing tabs
+ Region clip = g.Clip;
+ Rectangle region = new Rectangle(tabBounds.Left, controlBounds.Top, width - margin, controlBounds.Height);
+
+ g.SetClip(region);
+
+ // Draw tabs
+ for (int i = 0; i < this.TabCount; i++)
+ {
+ DrawTab(g, this.TabPages[i], i);
+ }
+
+ g.Clip = clip;
+ }
+
+ private void DrawTab(Graphics g, TabPage tabPage, int index)
+ {
+ Rectangle tabBounds = this.GetTabRect(index);
+
+ bool selected = (this.SelectedIndex == index);
+
+ // Fill this tab with background color
+ g.FillRectangle(selected ? Brushes.DimGray : ColorScheme.BrushGray68, tabBounds);
+
+ if (selected)
+ {
+ // Clear bottom lines
+ Pen pen = new Pen(tabPage.BackColor);
+
+ switch (this.Alignment)
+ {
+ case TabAlignment.Top:
+ g.DrawLine(pen, tabBounds.Left, tabBounds.Bottom, tabBounds.Right - 1, tabBounds.Bottom);
+ g.DrawLine(pen, tabBounds.Left, tabBounds.Bottom + 1, tabBounds.Right - 1, tabBounds.Bottom + 1);
+ break;
+
+ case TabAlignment.Bottom:
+ g.DrawLine(pen, tabBounds.Left, tabBounds.Top, tabBounds.Right - 1, tabBounds.Top);
+ g.DrawLine(pen, tabBounds.Left, tabBounds.Top - 1, tabBounds.Right - 1, tabBounds.Top - 1);
+ g.DrawLine(pen, tabBounds.Left, tabBounds.Top - 2, tabBounds.Right - 1, tabBounds.Top - 2);
+ break;
+ }
+
+ pen.Dispose();
+ }
+
+ // Draw string
+ StringFormat stringFormat = new StringFormat();
+ stringFormat.Alignment = StringAlignment.Center;
+ stringFormat.LineAlignment = StringAlignment.Center;
+
+ g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
+
+ g.DrawString(tabPage.Text, Font, Brushes.White, tabBounds, stringFormat);
+ }
+ }
+}
diff --git a/Triangle.NET/TestApp/Controls/DarkTextBox.cs b/src/Triangle.Viewer/Controls/DarkTextBox.cs
similarity index 94%
rename from Triangle.NET/TestApp/Controls/DarkTextBox.cs
rename to src/Triangle.Viewer/Controls/DarkTextBox.cs
index bfd759b..8e72def 100644
--- a/Triangle.NET/TestApp/Controls/DarkTextBox.cs
+++ b/src/Triangle.Viewer/Controls/DarkTextBox.cs
@@ -1,209 +1,220 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace MeshExplorer.Controls
-{
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Windows.Forms;
-
- ///
- /// Dark textbox control.
- ///
- public class DarkTextBox : Control
- {
- #region Designer
-
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Component Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- components = new System.ComponentModel.Container();
-
- this.textBox = new System.Windows.Forms.TextBox();
- this.SuspendLayout();
- //
- // textBox
- //
- this.textBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
- this.textBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
- this.textBox.Location = new System.Drawing.Point(4, 2);
- this.textBox.Name = "textBox";
- this.textBox.TabIndex = 0;
- //
- // DarkTextBox
- //
- this.BackColor = System.Drawing.Color.White;
- this.Controls.Add(this.textBox);
- this.Cursor = Cursors.IBeam;
- this.Size = new System.Drawing.Size(150, 22);
- this.ResumeLayout(false);
- this.PerformLayout();
- }
-
- #endregion
-
- #endregion
-
- TextBox textBox;
-
- ///
- /// Initializes a new instance of the control.
- ///
- public DarkTextBox()
- {
- InitializeComponent();
-
- this.MouseClick += delegate(object sender, MouseEventArgs e)
- {
- if (e.Button == MouseButtons.Left) textBox.Focus();
- };
-
- textBox.Font = this.Font;
- textBox.Location = new Point(4, (this.Height - textBox.Height) / 2);
- textBox.Width = this.Width - 8;
- textBox.TextAlign = HorizontalAlignment.Left;
- textBox.ForeColor = this.ForeColor;
- //textBox.MaxLength = 6;
-
- textBox.GotFocus += delegate(object sender, EventArgs e)
- {
- textBox.ForeColor = this.ForeColor;
- };
-
- textBox.LostFocus += delegate(object sender, EventArgs e)
- {
- textBox.ForeColor = ColorScheme.ColorGray68;
- };
- }
-
- protected override void OnPaint(PaintEventArgs e)
- {
- Graphics g = e.Graphics;
-
- Rectangle rect = this.ClientRectangle;
-
- //Brush brushOuter = new LinearGradientBrush(rect, Color.FromArgb(82, 82, 82),
- // Color.FromArgb(96, 96, 96), LinearGradientMode.Vertical);
-
- Pen borderTop = new Pen(Color.FromArgb(76, 76, 76), 1f);
- Pen borderBottom = new Pen(Color.FromArgb(128, 128, 128), 1f);
-
- //e.Graphics.FillRectangle(brushOuter, rect);
-
- rect = new Rectangle(1, 1, this.Width - 3, this.Height - 3);
- g.FillRectangle(new SolidBrush(this.BackColor), rect);
-
- g.DrawLine(borderTop, 0, 0, this.Width - 1, 0);
- g.DrawLine(borderTop, 0, 0, 0, this.Height - 1);
- g.DrawLine(borderBottom, 1, this.Height - 1, this.Width - 1, this.Height - 1);
- g.DrawLine(borderBottom, this.Width - 1, this.Height - 1, this.Width - 1, this.Height - 1);
-
-
- //brushOuter.Dispose();
- borderTop.Dispose();
- borderBottom.Dispose();
-
- base.OnPaint(e);
- }
-
- #region Property overrides
-
- public override Font Font
- {
- get
- {
- return base.Font;
- }
- set
- {
- textBox.Font = value;
- base.Font = value;
- }
- }
-
- public override String Text
- {
- get
- {
- return textBox.Text;
- }
- set
- {
- textBox.Text = value;
- }
- }
-
- public override Color ForeColor
- {
- get
- {
- return base.ForeColor;
- }
- set
- {
- textBox.ForeColor = value;
- base.ForeColor = value;
- }
- }
-
- public override Color BackColor
- {
- get
- {
- return base.BackColor;
- }
- set
- {
- textBox.BackColor = value;
- base.BackColor = value;
- }
- }
-
- #endregion
-
- #region Textbox properties
-
- public HorizontalAlignment TextAlign
- {
- get
- {
- return textBox.TextAlign;
- }
- set
- {
- textBox.TextAlign = value;
- }
- }
-
- #endregion
- }
-}
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+//
+// -----------------------------------------------------------------------
+
+namespace MeshExplorer.Controls
+{
+ using System;
+ using System.Drawing;
+ using System.Windows.Forms;
+
+ ///
+ /// Dark textbox control.
+ ///
+ public class DarkTextBox : Control
+ {
+ #region Designer
+
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ components = new System.ComponentModel.Container();
+
+ this.textBox = new System.Windows.Forms.TextBox();
+ this.SuspendLayout();
+ //
+ // textBox
+ //
+ this.textBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
+ this.textBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
+ this.textBox.Location = new System.Drawing.Point(4, 2);
+ this.textBox.Name = "textBox";
+ this.textBox.TabIndex = 0;
+ //
+ // DarkTextBox
+ //
+ this.BackColor = System.Drawing.Color.White;
+ this.Controls.Add(this.textBox);
+ this.Cursor = Cursors.IBeam;
+ this.Size = new System.Drawing.Size(150, 22);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+ }
+
+ #endregion
+
+ #endregion
+
+ TextBox textBox;
+
+ ///
+ /// Initializes a new instance of the control.
+ ///
+ public DarkTextBox()
+ {
+ InitializeComponent();
+
+ this.MouseClick += delegate(object sender, MouseEventArgs e)
+ {
+ if (e.Button == MouseButtons.Left) textBox.Focus();
+ };
+
+ textBox.Font = this.Font;
+ textBox.Location = new Point(4, (this.Height - textBox.Height) / 2);
+ textBox.Width = this.Width - 8;
+ textBox.TextAlign = HorizontalAlignment.Left;
+ textBox.ForeColor = this.ForeColor;
+ //textBox.MaxLength = 6;
+
+ textBox.GotFocus += delegate(object sender, EventArgs e)
+ {
+ textBox.ForeColor = this.ForeColor;
+ };
+
+ textBox.LostFocus += delegate(object sender, EventArgs e)
+ {
+ textBox.ForeColor = ColorScheme.ColorGray68;
+ };
+
+ textBox.KeyDown += delegate(object sender, KeyEventArgs e)
+ {
+ if (e.KeyCode == Keys.Enter)
+ {
+ e.SuppressKeyPress = true;
+ OnKeyDown(e);
+ }
+ };
+ }
+
+ protected override void OnKeyDown(KeyEventArgs e)
+ {
+ base.OnKeyDown(e);
+ }
+
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ Graphics g = e.Graphics;
+
+ Rectangle rect = this.ClientRectangle;
+
+ //Brush brushOuter = new LinearGradientBrush(rect, Color.FromArgb(82, 82, 82),
+ // Color.FromArgb(96, 96, 96), LinearGradientMode.Vertical);
+
+ Pen borderTop = new Pen(Color.FromArgb(76, 76, 76), 1f);
+ Pen borderBottom = new Pen(Color.FromArgb(128, 128, 128), 1f);
+
+ //e.Graphics.FillRectangle(brushOuter, rect);
+
+ rect = new Rectangle(1, 1, this.Width - 3, this.Height - 3);
+ g.FillRectangle(new SolidBrush(this.BackColor), rect);
+
+ g.DrawLine(borderTop, 0, 0, this.Width - 1, 0);
+ g.DrawLine(borderTop, 0, 0, 0, this.Height - 1);
+ g.DrawLine(borderBottom, 1, this.Height - 1, this.Width - 1, this.Height - 1);
+ g.DrawLine(borderBottom, this.Width - 1, this.Height - 1, this.Width - 1, this.Height - 1);
+
+
+ //brushOuter.Dispose();
+ borderTop.Dispose();
+ borderBottom.Dispose();
+
+ base.OnPaint(e);
+ }
+
+ #region Property overrides
+
+ public override Font Font
+ {
+ get
+ {
+ return base.Font;
+ }
+ set
+ {
+ textBox.Font = value;
+ base.Font = value;
+ }
+ }
+
+ public override String Text
+ {
+ get
+ {
+ return textBox.Text;
+ }
+ set
+ {
+ textBox.Text = value;
+ }
+ }
+
+ public override Color ForeColor
+ {
+ get
+ {
+ return base.ForeColor;
+ }
+ set
+ {
+ textBox.ForeColor = value;
+ base.ForeColor = value;
+ }
+ }
+
+ public override Color BackColor
+ {
+ get
+ {
+ return base.BackColor;
+ }
+ set
+ {
+ textBox.BackColor = value;
+ base.BackColor = value;
+ }
+ }
+
+ #endregion
+
+ #region Textbox properties
+
+ public HorizontalAlignment TextAlign
+ {
+ get
+ {
+ return textBox.TextAlign;
+ }
+ set
+ {
+ textBox.TextAlign = value;
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/Triangle.NET/TestApp/Controls/DarkToolStripRenderer.cs b/src/Triangle.Viewer/Controls/DarkToolStripRenderer.cs
similarity index 93%
rename from Triangle.NET/TestApp/Controls/DarkToolStripRenderer.cs
rename to src/Triangle.Viewer/Controls/DarkToolStripRenderer.cs
index c0ce39e..331ed22 100644
--- a/Triangle.NET/TestApp/Controls/DarkToolStripRenderer.cs
+++ b/src/Triangle.Viewer/Controls/DarkToolStripRenderer.cs
@@ -1,85 +1,81 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace MeshExplorer.Controls
-{
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Windows.Forms;
- using System.Drawing;
- using System.Drawing.Drawing2D;
-
- ///
- /// Toolstrip render for dark menu.
- ///
- public class DarkToolStripRenderer : ToolStripRenderer
- {
- protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
- {
- e.TextColor = e.Item.Enabled ? Color.White : Color.Gray;
-
- base.OnRenderItemText(e);
- }
-
- protected override void OnRenderItemCheck(ToolStripItemImageRenderEventArgs e)
- {
- int h = e.Item.Height;
- int size = h / 2 - 2; // Box size
- Rectangle rect = new Rectangle(10, (h - size) / 2, size - 2, size);
-
- var mode = e.Graphics.SmoothingMode;
-
- using (Pen pen = new Pen(Color.White, 1.6f))
- {
- e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
- e.Graphics.DrawLine(pen, rect.Left, rect.Bottom - size / 2, rect.Left + size / 2.5f, rect.Bottom - 2);
- e.Graphics.DrawLine(pen, rect.Left + size / 2.6f, rect.Bottom - 2, rect.Right, rect.Top);
- }
-
- e.Graphics.SmoothingMode = mode;
- }
-
- protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e)
- {
- if (!e.Item.Selected && !e.Item.Pressed)
- {
- e.ArrowColor = ColorScheme.ColorGray89;
- }
-
- base.OnRenderArrow(e);
- }
-
- protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e)
- {
- e.Graphics.FillRectangle(ColorScheme.BrushGray78, 0, 2, e.Item.Width, 1);
- }
-
- protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
- {
- if (e.Item.Enabled)
- {
- if (e.Item.Selected || e.Item.Pressed)
- {
- e.Graphics.FillRectangle(Brushes.DimGray, 0, 0, e.Item.Width, e.Item.Height);
- }
- else
- {
- e.Graphics.FillRectangle(ColorScheme.BrushGray68, 0, 0, e.Item.Width, e.Item.Height);
- }
- }
-
- //base.OnRenderMenuItemBackground(e);
- }
-
- protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e)
- {
- e.Graphics.FillRectangle(ColorScheme.BrushGray68, e.AffectedBounds);
- //base.OnRenderToolStripBackground(e);
- }
- }
-}
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+//
+// -----------------------------------------------------------------------
+
+namespace MeshExplorer.Controls
+{
+ using System.Drawing;
+ using System.Drawing.Drawing2D;
+ using System.Windows.Forms;
+
+ ///
+ /// Toolstrip render for dark menu.
+ ///
+ public class DarkToolStripRenderer : ToolStripRenderer
+ {
+ protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
+ {
+ e.TextColor = e.Item.Enabled ? Color.White : Color.Gray;
+
+ base.OnRenderItemText(e);
+ }
+
+ protected override void OnRenderItemCheck(ToolStripItemImageRenderEventArgs e)
+ {
+ int h = e.Item.Height;
+ int size = h / 2 - 2; // Box size
+ Rectangle rect = new Rectangle(10, (h - size) / 2, size - 2, size);
+
+ var mode = e.Graphics.SmoothingMode;
+
+ using (Pen pen = new Pen(Color.White, 1.6f))
+ {
+ e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
+ e.Graphics.DrawLine(pen, rect.Left, rect.Bottom - size / 2, rect.Left + size / 2.5f, rect.Bottom - 2);
+ e.Graphics.DrawLine(pen, rect.Left + size / 2.6f, rect.Bottom - 2, rect.Right, rect.Top);
+ }
+
+ e.Graphics.SmoothingMode = mode;
+ }
+
+ protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e)
+ {
+ if (!e.Item.Selected && !e.Item.Pressed)
+ {
+ e.ArrowColor = ColorScheme.ColorGray89;
+ }
+
+ base.OnRenderArrow(e);
+ }
+
+ protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e)
+ {
+ e.Graphics.FillRectangle(ColorScheme.BrushGray78, 0, 2, e.Item.Width, 1);
+ }
+
+ protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
+ {
+ if (e.Item.Enabled)
+ {
+ if (e.Item.Selected || e.Item.Pressed)
+ {
+ e.Graphics.FillRectangle(Brushes.DimGray, 0, 0, e.Item.Width, e.Item.Height);
+ }
+ else
+ {
+ e.Graphics.FillRectangle(ColorScheme.BrushGray68, 0, 0, e.Item.Width, e.Item.Height);
+ }
+ }
+
+ //base.OnRenderMenuItemBackground(e);
+ }
+
+ protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e)
+ {
+ e.Graphics.FillRectangle(ColorScheme.BrushGray68, e.AffectedBounds);
+ //base.OnRenderToolStripBackground(e);
+ }
+ }
+}
diff --git a/Triangle.NET/TestApp/DarkMessageBox.cs b/src/Triangle.Viewer/DarkMessageBox.cs
similarity index 97%
rename from Triangle.NET/TestApp/DarkMessageBox.cs
rename to src/Triangle.Viewer/DarkMessageBox.cs
index b1ad107..2c65c20 100644
--- a/Triangle.NET/TestApp/DarkMessageBox.cs
+++ b/src/Triangle.Viewer/DarkMessageBox.cs
@@ -1,179 +1,179 @@
-using System.Drawing;
-using System.Windows.Forms;
-
-namespace MeshExplorer
-{
- class DarkMessageBox : Form
- {
- #region Designer
-
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- this.btnCancel = new MeshExplorer.Controls.DarkButton();
- this.btnOk = new MeshExplorer.Controls.DarkButton();
- this.lbMessage = new System.Windows.Forms.Label();
- this.lbInfo = new System.Windows.Forms.Label();
- this.SuspendLayout();
- //
- // btnCancel
- //
- this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
- this.btnCancel.Location = new System.Drawing.Point(336, 87);
- this.btnCancel.Name = "btnCancel";
- this.btnCancel.Size = new System.Drawing.Size(92, 23);
- this.btnCancel.TabIndex = 0;
- this.btnCancel.Text = "Cancel";
- this.btnCancel.UseVisualStyleBackColor = true;
- //
- // btnOk
- //
- this.btnOk.DialogResult = System.Windows.Forms.DialogResult.OK;
- this.btnOk.Location = new System.Drawing.Point(234, 87);
- this.btnOk.Name = "btnOk";
- this.btnOk.Size = new System.Drawing.Size(92, 23);
- this.btnOk.TabIndex = 1;
- this.btnOk.Text = "Ok";
- this.btnOk.UseVisualStyleBackColor = true;
- //
- // lbMessage
- //
- this.lbMessage.BackColor = System.Drawing.Color.Transparent;
- this.lbMessage.ForeColor = System.Drawing.Color.White;
- this.lbMessage.Location = new System.Drawing.Point(12, 9);
- this.lbMessage.Name = "lbMessage";
- this.lbMessage.Size = new System.Drawing.Size(412, 30);
- this.lbMessage.TabIndex = 2;
- this.lbMessage.Text = "Message";
- //
- // lbInfo
- //
- this.lbInfo.AutoSize = true;
- this.lbInfo.BackColor = System.Drawing.Color.Transparent;
- this.lbInfo.ForeColor = System.Drawing.Color.White;
- this.lbInfo.Location = new System.Drawing.Point(12, 47);
- this.lbInfo.Name = "lbInfo";
- this.lbInfo.Size = new System.Drawing.Size(28, 13);
- this.lbInfo.TabIndex = 3;
- this.lbInfo.Text = "Info";
- //
- // DarkMessageBox
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(76)))), ((int)(((byte)(76)))), ((int)(((byte)(76)))));
- this.ClientSize = new System.Drawing.Size(436, 118);
- this.Controls.Add(this.lbInfo);
- this.Controls.Add(this.lbMessage);
- this.Controls.Add(this.btnOk);
- this.Controls.Add(this.btnCancel);
- this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
- this.MaximizeBox = false;
- this.MinimizeBox = false;
- this.Name = "DarkMessageBox";
- this.ShowInTaskbar = false;
- this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
- this.Text = "Message Box";
- this.ResumeLayout(false);
- this.PerformLayout();
-
- }
-
- #endregion
-
- private Controls.DarkButton btnCancel;
- private Label lbMessage;
- private Label lbInfo;
- private Controls.DarkButton btnOk;
-
- #endregion
-
- public DarkMessageBox()
- {
- InitializeComponent();
- }
-
- protected override void OnPaint(PaintEventArgs e)
- {
- base.OnPaint(e);
-
- var rect = this.ClientRectangle;
- rect.Height -= 40;
-
- e.Graphics.FillRectangle(Brushes.DimGray, rect);
- }
-
- public static DialogResult Show(string title, string message, string info, MessageBoxButtons buttons)
- {
- DarkMessageBox dialog = new DarkMessageBox();
-
- SetButtonsText(dialog, buttons);
-
- dialog.Text = title;
-
- dialog.lbInfo.Text = info;
- dialog.lbMessage.Text = message;
-
- return dialog.ShowDialog();
- }
-
- public static DialogResult Show(string title, string message, string info)
- {
- return Show(title, message, info, MessageBoxButtons.OKCancel);
- }
-
- public static DialogResult Show(string title, string message, MessageBoxButtons buttons)
- {
- return Show(title, message, "", buttons);
- }
-
- public static DialogResult Show(string title, string message)
- {
- return Show(title, message, "", MessageBoxButtons.OKCancel);
- }
-
- private static void SetButtonsText(DarkMessageBox dialog, MessageBoxButtons buttons)
- {
- if (buttons == MessageBoxButtons.OKCancel)
- {
- dialog.btnOk.Text = "OK";
- dialog.btnCancel.Text = "Cancel";
- }
- else if (buttons == MessageBoxButtons.YesNo)
- {
- dialog.btnOk.Text = "Yes";
- dialog.btnCancel.Text = "No";
- }
- else
- {
- dialog.btnCancel.Text = "Close";
- dialog.btnOk.Visible = false;
- dialog.btnOk.Enabled = false;
- }
- }
- }
-}
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace MeshExplorer
+{
+ class DarkMessageBox : Form
+ {
+ #region Designer
+
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.btnCancel = new MeshExplorer.Controls.DarkButton();
+ this.btnOk = new MeshExplorer.Controls.DarkButton();
+ this.lbMessage = new System.Windows.Forms.Label();
+ this.lbInfo = new System.Windows.Forms.Label();
+ this.SuspendLayout();
+ //
+ // btnCancel
+ //
+ this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this.btnCancel.Location = new System.Drawing.Point(336, 87);
+ this.btnCancel.Name = "btnCancel";
+ this.btnCancel.Size = new System.Drawing.Size(92, 23);
+ this.btnCancel.TabIndex = 0;
+ this.btnCancel.Text = "Cancel";
+ this.btnCancel.UseVisualStyleBackColor = true;
+ //
+ // btnOk
+ //
+ this.btnOk.DialogResult = System.Windows.Forms.DialogResult.OK;
+ this.btnOk.Location = new System.Drawing.Point(234, 87);
+ this.btnOk.Name = "btnOk";
+ this.btnOk.Size = new System.Drawing.Size(92, 23);
+ this.btnOk.TabIndex = 1;
+ this.btnOk.Text = "Ok";
+ this.btnOk.UseVisualStyleBackColor = true;
+ //
+ // lbMessage
+ //
+ this.lbMessage.BackColor = System.Drawing.Color.Transparent;
+ this.lbMessage.ForeColor = System.Drawing.Color.White;
+ this.lbMessage.Location = new System.Drawing.Point(12, 9);
+ this.lbMessage.Name = "lbMessage";
+ this.lbMessage.Size = new System.Drawing.Size(412, 30);
+ this.lbMessage.TabIndex = 2;
+ this.lbMessage.Text = "Message";
+ //
+ // lbInfo
+ //
+ this.lbInfo.AutoSize = true;
+ this.lbInfo.BackColor = System.Drawing.Color.Transparent;
+ this.lbInfo.ForeColor = System.Drawing.Color.White;
+ this.lbInfo.Location = new System.Drawing.Point(12, 47);
+ this.lbInfo.Name = "lbInfo";
+ this.lbInfo.Size = new System.Drawing.Size(28, 13);
+ this.lbInfo.TabIndex = 3;
+ this.lbInfo.Text = "Info";
+ //
+ // DarkMessageBox
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(76)))), ((int)(((byte)(76)))), ((int)(((byte)(76)))));
+ this.ClientSize = new System.Drawing.Size(436, 118);
+ this.Controls.Add(this.lbInfo);
+ this.Controls.Add(this.lbMessage);
+ this.Controls.Add(this.btnOk);
+ this.Controls.Add(this.btnCancel);
+ this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "DarkMessageBox";
+ this.ShowInTaskbar = false;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "Message Box";
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private Controls.DarkButton btnCancel;
+ private Label lbMessage;
+ private Label lbInfo;
+ private Controls.DarkButton btnOk;
+
+ #endregion
+
+ public DarkMessageBox()
+ {
+ InitializeComponent();
+ }
+
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ base.OnPaint(e);
+
+ var rect = this.ClientRectangle;
+ rect.Height -= 40;
+
+ e.Graphics.FillRectangle(Brushes.DimGray, rect);
+ }
+
+ public static DialogResult Show(string title, string message, string info, MessageBoxButtons buttons)
+ {
+ DarkMessageBox dialog = new DarkMessageBox();
+
+ SetButtonsText(dialog, buttons);
+
+ dialog.Text = title;
+
+ dialog.lbInfo.Text = info;
+ dialog.lbMessage.Text = message;
+
+ return dialog.ShowDialog();
+ }
+
+ public static DialogResult Show(string title, string message, string info)
+ {
+ return Show(title, message, info, MessageBoxButtons.OKCancel);
+ }
+
+ public static DialogResult Show(string title, string message, MessageBoxButtons buttons)
+ {
+ return Show(title, message, "", buttons);
+ }
+
+ public static DialogResult Show(string title, string message)
+ {
+ return Show(title, message, "", MessageBoxButtons.OKCancel);
+ }
+
+ private static void SetButtonsText(DarkMessageBox dialog, MessageBoxButtons buttons)
+ {
+ if (buttons == MessageBoxButtons.OKCancel)
+ {
+ dialog.btnOk.Text = "OK";
+ dialog.btnCancel.Text = "Cancel";
+ }
+ else if (buttons == MessageBoxButtons.YesNo)
+ {
+ dialog.btnOk.Text = "Yes";
+ dialog.btnCancel.Text = "No";
+ }
+ else
+ {
+ dialog.btnCancel.Text = "Close";
+ dialog.btnOk.Visible = false;
+ dialog.btnOk.Enabled = false;
+ }
+ }
+ }
+}
diff --git a/Triangle.NET/TestApp/FormExport.Designer.cs b/src/Triangle.Viewer/FormExport.Designer.cs
similarity index 97%
rename from Triangle.NET/TestApp/FormExport.Designer.cs
rename to src/Triangle.Viewer/FormExport.Designer.cs
index eba850d..0a12657 100644
--- a/Triangle.NET/TestApp/FormExport.Designer.cs
+++ b/src/Triangle.Viewer/FormExport.Designer.cs
@@ -1,202 +1,202 @@
-namespace MeshExplorer
-{
- partial class FormExport
- {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- this.label2 = new System.Windows.Forms.Label();
- this.label3 = new System.Windows.Forms.Label();
- this.label1 = new System.Windows.Forms.Label();
- this.lbSize = new System.Windows.Forms.Label();
- this.cbUseCompression = new MeshExplorer.Controls.DarkCheckBox();
- this.darkSlider1 = new MeshExplorer.Controls.DarkSlider();
- this.darkTextBox1 = new MeshExplorer.Controls.DarkTextBox();
- this.darkListBox1 = new MeshExplorer.Controls.DarkListBox();
- this.darkButton1 = new MeshExplorer.Controls.DarkButton();
- this.btnExport = new MeshExplorer.Controls.DarkButton();
- this.SuspendLayout();
- //
- // label2
- //
- this.label2.AutoSize = true;
- this.label2.BackColor = System.Drawing.Color.Transparent;
- this.label2.Location = new System.Drawing.Point(12, 9);
- this.label2.Name = "label2";
- this.label2.Size = new System.Drawing.Size(65, 13);
- this.label2.TabIndex = 2;
- this.label2.Text = "File fromat:\r\n";
- //
- // label3
- //
- this.label3.AutoSize = true;
- this.label3.BackColor = System.Drawing.Color.Transparent;
- this.label3.Location = new System.Drawing.Point(12, 190);
- this.label3.Name = "label3";
- this.label3.Size = new System.Drawing.Size(59, 13);
- this.label3.TabIndex = 2;
- this.label3.Text = "File name:";
- //
- // label1
- //
- this.label1.AutoSize = true;
- this.label1.BackColor = System.Drawing.Color.Transparent;
- this.label1.Location = new System.Drawing.Point(12, 148);
- this.label1.Name = "label1";
- this.label1.Size = new System.Drawing.Size(74, 13);
- this.label1.TabIndex = 2;
- this.label1.Text = "Image width:";
- //
- // lbSize
- //
- this.lbSize.AutoSize = true;
- this.lbSize.BackColor = System.Drawing.Color.Transparent;
- this.lbSize.ForeColor = System.Drawing.Color.Gray;
- this.lbSize.Location = new System.Drawing.Point(272, 148);
- this.lbSize.Name = "lbSize";
- this.lbSize.Size = new System.Drawing.Size(40, 13);
- this.lbSize.TabIndex = 2;
- this.lbSize.Text = "800 px";
- //
- // cbUseCompression
- //
- this.cbUseCompression.BackColor = System.Drawing.Color.DimGray;
- this.cbUseCompression.Checked = false;
- this.cbUseCompression.Enabled = false;
- this.cbUseCompression.Location = new System.Drawing.Point(15, 231);
- this.cbUseCompression.Name = "cbUseCompression";
- this.cbUseCompression.Size = new System.Drawing.Size(297, 23);
- this.cbUseCompression.TabIndex = 6;
- this.cbUseCompression.Text = "Use GZip compression";
- this.cbUseCompression.UseVisualStyleBackColor = false;
- //
- // darkSlider1
- //
- this.darkSlider1.BackColor = System.Drawing.Color.Transparent;
- this.darkSlider1.CriticalPercent = ((uint)(0u));
- this.darkSlider1.Location = new System.Drawing.Point(15, 161);
- this.darkSlider1.Maximum = 100;
- this.darkSlider1.Minimum = 0;
- this.darkSlider1.Name = "darkSlider1";
- this.darkSlider1.Size = new System.Drawing.Size(297, 17);
- this.darkSlider1.TabIndex = 5;
- this.darkSlider1.Text = "darkSlider1";
- this.darkSlider1.Value = 35;
- this.darkSlider1.ValueChanging += new System.EventHandler(this.darkSlider1_ValueChanging);
- //
- // darkTextBox1
- //
- this.darkTextBox1.BackColor = System.Drawing.Color.White;
- this.darkTextBox1.Cursor = System.Windows.Forms.Cursors.IBeam;
- this.darkTextBox1.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.darkTextBox1.ForeColor = System.Drawing.Color.Black;
- this.darkTextBox1.Location = new System.Drawing.Point(12, 206);
- this.darkTextBox1.Name = "darkTextBox1";
- this.darkTextBox1.Size = new System.Drawing.Size(300, 21);
- this.darkTextBox1.TabIndex = 4;
- this.darkTextBox1.TextAlign = System.Windows.Forms.HorizontalAlignment.Left;
- //
- // darkListBox1
- //
- this.darkListBox1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(96)))), ((int)(((byte)(96)))), ((int)(((byte)(96)))));
- this.darkListBox1.BorderStyle = System.Windows.Forms.BorderStyle.None;
- this.darkListBox1.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable;
- this.darkListBox1.FormattingEnabled = true;
- this.darkListBox1.ItemHeight = 22;
- this.darkListBox1.Items.AddRange(new object[] {
- "Portable Network Graphics (*.png)",
- "Encapsulated PostScript (*.eps)",
- "Scalable Vector Graphics (*.svg)"});
- this.darkListBox1.Location = new System.Drawing.Point(12, 25);
- this.darkListBox1.Name = "darkListBox1";
- this.darkListBox1.Size = new System.Drawing.Size(302, 110);
- this.darkListBox1.TabIndex = 3;
- this.darkListBox1.SelectedIndexChanged += new System.EventHandler(this.darkListBox1_SelectedIndexChanged);
- //
- // darkButton1
- //
- this.darkButton1.DialogResult = System.Windows.Forms.DialogResult.Cancel;
- this.darkButton1.Location = new System.Drawing.Point(144, 270);
- this.darkButton1.Name = "darkButton1";
- this.darkButton1.Size = new System.Drawing.Size(82, 23);
- this.darkButton1.TabIndex = 1;
- this.darkButton1.Text = "Cancel";
- this.darkButton1.UseVisualStyleBackColor = true;
- //
- // btnExport
- //
- this.btnExport.DialogResult = System.Windows.Forms.DialogResult.OK;
- this.btnExport.Location = new System.Drawing.Point(232, 270);
- this.btnExport.Name = "btnExport";
- this.btnExport.Size = new System.Drawing.Size(82, 23);
- this.btnExport.TabIndex = 0;
- this.btnExport.Text = "Save";
- this.btnExport.UseVisualStyleBackColor = true;
- //
- // FormExport
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(76)))), ((int)(((byte)(76)))), ((int)(((byte)(76)))));
- this.ClientSize = new System.Drawing.Size(324, 299);
- this.Controls.Add(this.cbUseCompression);
- this.Controls.Add(this.darkSlider1);
- this.Controls.Add(this.darkTextBox1);
- this.Controls.Add(this.darkListBox1);
- this.Controls.Add(this.label2);
- this.Controls.Add(this.lbSize);
- this.Controls.Add(this.label1);
- this.Controls.Add(this.label3);
- this.Controls.Add(this.darkButton1);
- this.Controls.Add(this.btnExport);
- this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.ForeColor = System.Drawing.Color.White;
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
- this.MaximizeBox = false;
- this.MinimizeBox = false;
- this.Name = "FormExport";
- this.ShowInTaskbar = false;
- this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
- this.Text = "Export Image";
- this.ResumeLayout(false);
- this.PerformLayout();
-
- }
-
- #endregion
-
- private Controls.DarkButton btnExport;
- private Controls.DarkButton darkButton1;
- private Controls.DarkListBox darkListBox1;
- private System.Windows.Forms.Label label2;
- private Controls.DarkTextBox darkTextBox1;
- private System.Windows.Forms.Label label3;
- private System.Windows.Forms.Label label1;
- private Controls.DarkSlider darkSlider1;
- private System.Windows.Forms.Label lbSize;
- private Controls.DarkCheckBox cbUseCompression;
- }
+namespace MeshExplorer
+{
+ partial class FormExport
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.label2 = new System.Windows.Forms.Label();
+ this.label3 = new System.Windows.Forms.Label();
+ this.label1 = new System.Windows.Forms.Label();
+ this.lbSize = new System.Windows.Forms.Label();
+ this.cbUseCompression = new MeshExplorer.Controls.DarkCheckBox();
+ this.darkSlider1 = new MeshExplorer.Controls.DarkSlider();
+ this.darkTextBox1 = new MeshExplorer.Controls.DarkTextBox();
+ this.darkListBox1 = new MeshExplorer.Controls.DarkListBox();
+ this.darkButton1 = new MeshExplorer.Controls.DarkButton();
+ this.btnExport = new MeshExplorer.Controls.DarkButton();
+ this.SuspendLayout();
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.BackColor = System.Drawing.Color.Transparent;
+ this.label2.Location = new System.Drawing.Point(12, 9);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(65, 13);
+ this.label2.TabIndex = 2;
+ this.label2.Text = "File fromat:\r\n";
+ //
+ // label3
+ //
+ this.label3.AutoSize = true;
+ this.label3.BackColor = System.Drawing.Color.Transparent;
+ this.label3.Location = new System.Drawing.Point(12, 190);
+ this.label3.Name = "label3";
+ this.label3.Size = new System.Drawing.Size(59, 13);
+ this.label3.TabIndex = 2;
+ this.label3.Text = "File name:";
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.BackColor = System.Drawing.Color.Transparent;
+ this.label1.Location = new System.Drawing.Point(12, 148);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(74, 13);
+ this.label1.TabIndex = 2;
+ this.label1.Text = "Image width:";
+ //
+ // lbSize
+ //
+ this.lbSize.AutoSize = true;
+ this.lbSize.BackColor = System.Drawing.Color.Transparent;
+ this.lbSize.ForeColor = System.Drawing.Color.Gray;
+ this.lbSize.Location = new System.Drawing.Point(272, 148);
+ this.lbSize.Name = "lbSize";
+ this.lbSize.Size = new System.Drawing.Size(40, 13);
+ this.lbSize.TabIndex = 2;
+ this.lbSize.Text = "800 px";
+ //
+ // cbUseCompression
+ //
+ this.cbUseCompression.BackColor = System.Drawing.Color.DimGray;
+ this.cbUseCompression.Checked = false;
+ this.cbUseCompression.Enabled = false;
+ this.cbUseCompression.Location = new System.Drawing.Point(15, 231);
+ this.cbUseCompression.Name = "cbUseCompression";
+ this.cbUseCompression.Size = new System.Drawing.Size(297, 23);
+ this.cbUseCompression.TabIndex = 6;
+ this.cbUseCompression.Text = "Use GZip compression";
+ this.cbUseCompression.UseVisualStyleBackColor = false;
+ //
+ // darkSlider1
+ //
+ this.darkSlider1.BackColor = System.Drawing.Color.Transparent;
+ this.darkSlider1.CriticalPercent = ((uint)(0u));
+ this.darkSlider1.Location = new System.Drawing.Point(15, 161);
+ this.darkSlider1.Maximum = 100;
+ this.darkSlider1.Minimum = 0;
+ this.darkSlider1.Name = "darkSlider1";
+ this.darkSlider1.Size = new System.Drawing.Size(297, 17);
+ this.darkSlider1.TabIndex = 5;
+ this.darkSlider1.Text = "darkSlider1";
+ this.darkSlider1.Value = 35;
+ this.darkSlider1.ValueChanging += new System.EventHandler(this.darkSlider1_ValueChanging);
+ //
+ // darkTextBox1
+ //
+ this.darkTextBox1.BackColor = System.Drawing.Color.White;
+ this.darkTextBox1.Cursor = System.Windows.Forms.Cursors.IBeam;
+ this.darkTextBox1.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.darkTextBox1.ForeColor = System.Drawing.Color.Black;
+ this.darkTextBox1.Location = new System.Drawing.Point(12, 206);
+ this.darkTextBox1.Name = "darkTextBox1";
+ this.darkTextBox1.Size = new System.Drawing.Size(300, 21);
+ this.darkTextBox1.TabIndex = 4;
+ this.darkTextBox1.TextAlign = System.Windows.Forms.HorizontalAlignment.Left;
+ //
+ // darkListBox1
+ //
+ this.darkListBox1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(96)))), ((int)(((byte)(96)))), ((int)(((byte)(96)))));
+ this.darkListBox1.BorderStyle = System.Windows.Forms.BorderStyle.None;
+ this.darkListBox1.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable;
+ this.darkListBox1.FormattingEnabled = true;
+ this.darkListBox1.ItemHeight = 22;
+ this.darkListBox1.Items.AddRange(new object[] {
+ "Portable Network Graphics (*.png)",
+ "Encapsulated PostScript (*.eps)",
+ "Scalable Vector Graphics (*.svg)"});
+ this.darkListBox1.Location = new System.Drawing.Point(12, 25);
+ this.darkListBox1.Name = "darkListBox1";
+ this.darkListBox1.Size = new System.Drawing.Size(302, 110);
+ this.darkListBox1.TabIndex = 3;
+ this.darkListBox1.SelectedIndexChanged += new System.EventHandler(this.darkListBox1_SelectedIndexChanged);
+ //
+ // darkButton1
+ //
+ this.darkButton1.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this.darkButton1.Location = new System.Drawing.Point(144, 270);
+ this.darkButton1.Name = "darkButton1";
+ this.darkButton1.Size = new System.Drawing.Size(82, 23);
+ this.darkButton1.TabIndex = 1;
+ this.darkButton1.Text = "Cancel";
+ this.darkButton1.UseVisualStyleBackColor = true;
+ //
+ // btnExport
+ //
+ this.btnExport.DialogResult = System.Windows.Forms.DialogResult.OK;
+ this.btnExport.Location = new System.Drawing.Point(232, 270);
+ this.btnExport.Name = "btnExport";
+ this.btnExport.Size = new System.Drawing.Size(82, 23);
+ this.btnExport.TabIndex = 0;
+ this.btnExport.Text = "Save";
+ this.btnExport.UseVisualStyleBackColor = true;
+ //
+ // FormExport
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(76)))), ((int)(((byte)(76)))), ((int)(((byte)(76)))));
+ this.ClientSize = new System.Drawing.Size(324, 299);
+ this.Controls.Add(this.cbUseCompression);
+ this.Controls.Add(this.darkSlider1);
+ this.Controls.Add(this.darkTextBox1);
+ this.Controls.Add(this.darkListBox1);
+ this.Controls.Add(this.label2);
+ this.Controls.Add(this.lbSize);
+ this.Controls.Add(this.label1);
+ this.Controls.Add(this.label3);
+ this.Controls.Add(this.darkButton1);
+ this.Controls.Add(this.btnExport);
+ this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.ForeColor = System.Drawing.Color.White;
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "FormExport";
+ this.ShowInTaskbar = false;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "Export Image";
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private Controls.DarkButton btnExport;
+ private Controls.DarkButton darkButton1;
+ private Controls.DarkListBox darkListBox1;
+ private System.Windows.Forms.Label label2;
+ private Controls.DarkTextBox darkTextBox1;
+ private System.Windows.Forms.Label label3;
+ private System.Windows.Forms.Label label1;
+ private Controls.DarkSlider darkSlider1;
+ private System.Windows.Forms.Label lbSize;
+ private Controls.DarkCheckBox cbUseCompression;
+ }
}
\ No newline at end of file
diff --git a/Triangle.NET/TestApp/FormExport.cs b/src/Triangle.Viewer/FormExport.cs
similarity index 96%
rename from Triangle.NET/TestApp/FormExport.cs
rename to src/Triangle.Viewer/FormExport.cs
index 58ad249..8d8fad1 100644
--- a/Triangle.NET/TestApp/FormExport.cs
+++ b/src/Triangle.Viewer/FormExport.cs
@@ -1,82 +1,82 @@
-using System;
-using System.Drawing;
-using System.IO;
-using System.Windows.Forms;
-
-namespace MeshExplorer
-{
- public partial class FormExport : Form
- {
- public FormExport()
- {
- InitializeComponent();
- }
-
- public int ImageFormat
- {
- get { return darkListBox1.SelectedIndex; }
- }
-
- public int ImageSize
- {
- get
- {
- int size = (int)((2000.0 - 200.0) / 100.0 * darkSlider1.Value + 200.0);
- return size - (size % 50);
- }
- }
-
- public string ImageName
- {
- get { return darkTextBox1.Text; }
- set { darkTextBox1.Text = value; }
- }
-
- public bool UseCompression
- {
- get { return cbUseCompression.Enabled && cbUseCompression.Checked; }
- }
-
- protected override void OnPaint(PaintEventArgs e)
- {
- base.OnPaint(e);
-
- var rect = this.ClientRectangle;
- rect.Height -= 40;
-
- e.Graphics.FillRectangle(Brushes.DimGray, rect);
- }
-
- private void darkListBox1_SelectedIndexChanged(object sender, EventArgs e)
- {
- string filename = darkTextBox1.Text;
-
- if (!String.IsNullOrWhiteSpace(filename))
- {
- string ext = ".png";
-
- cbUseCompression.Enabled = darkListBox1.SelectedIndex > 0;
-
- if (darkListBox1.SelectedIndex == 1)
- {
- ext = ".eps";
- }
- else if (darkListBox1.SelectedIndex == 2)
- {
- ext = ".svg";
- }
-
- darkTextBox1.Text = Path.ChangeExtension(filename, ext);
- }
- }
-
- private void darkSlider1_ValueChanging(object sender, EventArgs e)
- {
- int size = (int)((2000.0 - 200.0) / 100.0 * darkSlider1.Value + 200.0);
-
- size = size - (size % 50);
-
- lbSize.Text = size + " px";
- }
- }
-}
+using System;
+using System.Drawing;
+using System.IO;
+using System.Windows.Forms;
+
+namespace MeshExplorer
+{
+ public partial class FormExport : Form
+ {
+ public FormExport()
+ {
+ InitializeComponent();
+ }
+
+ public int ImageFormat
+ {
+ get { return darkListBox1.SelectedIndex; }
+ }
+
+ public int ImageSize
+ {
+ get
+ {
+ int size = (int)((2000.0 - 200.0) / 100.0 * darkSlider1.Value + 200.0);
+ return size - (size % 50);
+ }
+ }
+
+ public string ImageName
+ {
+ get { return darkTextBox1.Text; }
+ set { darkTextBox1.Text = value; }
+ }
+
+ public bool UseCompression
+ {
+ get { return cbUseCompression.Enabled && cbUseCompression.Checked; }
+ }
+
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ base.OnPaint(e);
+
+ var rect = this.ClientRectangle;
+ rect.Height -= 40;
+
+ e.Graphics.FillRectangle(Brushes.DimGray, rect);
+ }
+
+ private void darkListBox1_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ string filename = darkTextBox1.Text;
+
+ if (!String.IsNullOrWhiteSpace(filename))
+ {
+ string ext = ".png";
+
+ cbUseCompression.Enabled = darkListBox1.SelectedIndex > 0;
+
+ if (darkListBox1.SelectedIndex == 1)
+ {
+ ext = ".eps";
+ }
+ else if (darkListBox1.SelectedIndex == 2)
+ {
+ ext = ".svg";
+ }
+
+ darkTextBox1.Text = Path.ChangeExtension(filename, ext);
+ }
+ }
+
+ private void darkSlider1_ValueChanging(object sender, EventArgs e)
+ {
+ int size = (int)((2000.0 - 200.0) / 100.0 * darkSlider1.Value + 200.0);
+
+ size = size - (size % 50);
+
+ lbSize.Text = size + " px";
+ }
+ }
+}
diff --git a/Triangle.NET/TestApp/FormExport.resx b/src/Triangle.Viewer/FormExport.resx
similarity index 97%
rename from Triangle.NET/TestApp/FormExport.resx
rename to src/Triangle.Viewer/FormExport.resx
index 29dcb1b..1af7de1 100644
--- a/Triangle.NET/TestApp/FormExport.resx
+++ b/src/Triangle.Viewer/FormExport.resx
@@ -1,120 +1,120 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
\ No newline at end of file
diff --git a/Triangle.NET/TestApp/FormGenerator.Designer.cs b/src/Triangle.Viewer/FormGenerator.Designer.cs
similarity index 97%
rename from Triangle.NET/TestApp/FormGenerator.Designer.cs
rename to src/Triangle.Viewer/FormGenerator.Designer.cs
index efc2b44..ae1855c 100644
--- a/Triangle.NET/TestApp/FormGenerator.Designer.cs
+++ b/src/Triangle.Viewer/FormGenerator.Designer.cs
@@ -1,242 +1,242 @@
-namespace MeshExplorer
-{
- partial class FormGenerator
- {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- this.lbParam1 = new System.Windows.Forms.Label();
- this.lbParam2 = new System.Windows.Forms.Label();
- this.lbParam3 = new System.Windows.Forms.Label();
- this.lbParam1Val = new System.Windows.Forms.Label();
- this.lbParam2Val = new System.Windows.Forms.Label();
- this.lbParam3Val = new System.Windows.Forms.Label();
- this.lbDescription = new System.Windows.Forms.Label();
- this.sliderParam3 = new MeshExplorer.Controls.DarkSlider();
- this.sliderParam2 = new MeshExplorer.Controls.DarkSlider();
- this.sliderParam1 = new MeshExplorer.Controls.DarkSlider();
- this.darkListBox1 = new MeshExplorer.Controls.DarkListBox();
- this.btnClose = new MeshExplorer.Controls.DarkButton();
- this.btnGenerate = new MeshExplorer.Controls.DarkButton();
- this.SuspendLayout();
- //
- // lbParam1
- //
- this.lbParam1.BackColor = System.Drawing.Color.DimGray;
- this.lbParam1.ForeColor = System.Drawing.Color.White;
- this.lbParam1.Location = new System.Drawing.Point(171, 24);
- this.lbParam1.Name = "lbParam1";
- this.lbParam1.Size = new System.Drawing.Size(114, 13);
- this.lbParam1.TabIndex = 4;
- this.lbParam1.Text = "Param 1:";
- //
- // lbParam2
- //
- this.lbParam2.BackColor = System.Drawing.Color.DimGray;
- this.lbParam2.ForeColor = System.Drawing.Color.White;
- this.lbParam2.Location = new System.Drawing.Point(171, 47);
- this.lbParam2.Name = "lbParam2";
- this.lbParam2.Size = new System.Drawing.Size(114, 13);
- this.lbParam2.TabIndex = 4;
- this.lbParam2.Text = "Param 2:";
- //
- // lbParam3
- //
- this.lbParam3.BackColor = System.Drawing.Color.DimGray;
- this.lbParam3.ForeColor = System.Drawing.Color.White;
- this.lbParam3.Location = new System.Drawing.Point(171, 70);
- this.lbParam3.Name = "lbParam3";
- this.lbParam3.Size = new System.Drawing.Size(114, 13);
- this.lbParam3.TabIndex = 4;
- this.lbParam3.Text = "Param 3:";
- //
- // lbParam1Val
- //
- this.lbParam1Val.BackColor = System.Drawing.Color.DimGray;
- this.lbParam1Val.ForeColor = System.Drawing.Color.White;
- this.lbParam1Val.Location = new System.Drawing.Point(436, 24);
- this.lbParam1Val.Name = "lbParam1Val";
- this.lbParam1Val.Size = new System.Drawing.Size(40, 13);
- this.lbParam1Val.TabIndex = 4;
- this.lbParam1Val.Text = "-";
- //
- // lbParam2Val
- //
- this.lbParam2Val.BackColor = System.Drawing.Color.DimGray;
- this.lbParam2Val.ForeColor = System.Drawing.Color.White;
- this.lbParam2Val.Location = new System.Drawing.Point(436, 47);
- this.lbParam2Val.Name = "lbParam2Val";
- this.lbParam2Val.Size = new System.Drawing.Size(40, 13);
- this.lbParam2Val.TabIndex = 4;
- this.lbParam2Val.Text = "-";
- //
- // lbParam3Val
- //
- this.lbParam3Val.BackColor = System.Drawing.Color.DimGray;
- this.lbParam3Val.ForeColor = System.Drawing.Color.White;
- this.lbParam3Val.Location = new System.Drawing.Point(436, 70);
- this.lbParam3Val.Name = "lbParam3Val";
- this.lbParam3Val.Size = new System.Drawing.Size(40, 13);
- this.lbParam3Val.TabIndex = 4;
- this.lbParam3Val.Text = "-";
- //
- // lbDescription
- //
- this.lbDescription.BackColor = System.Drawing.Color.DimGray;
- this.lbDescription.ForeColor = System.Drawing.Color.White;
- this.lbDescription.Location = new System.Drawing.Point(171, 104);
- this.lbDescription.Name = "lbDescription";
- this.lbDescription.Size = new System.Drawing.Size(94, 13);
- this.lbDescription.TabIndex = 4;
- this.lbDescription.Text = "Description";
- //
- // sliderParam3
- //
- this.sliderParam3.BackColor = System.Drawing.Color.Transparent;
- this.sliderParam3.CriticalPercent = ((uint)(0u));
- this.sliderParam3.Enabled = false;
- this.sliderParam3.Location = new System.Drawing.Point(291, 64);
- this.sliderParam3.Maximum = 100;
- this.sliderParam3.Minimum = 0;
- this.sliderParam3.Name = "sliderParam3";
- this.sliderParam3.Size = new System.Drawing.Size(138, 23);
- this.sliderParam3.TabIndex = 3;
- this.sliderParam3.Text = "sliderParam3";
- this.sliderParam3.Value = 50;
- this.sliderParam3.ValueChanging += new System.EventHandler(this.sliderParam3_ValueChanging);
- //
- // sliderParam2
- //
- this.sliderParam2.BackColor = System.Drawing.Color.Transparent;
- this.sliderParam2.CriticalPercent = ((uint)(0u));
- this.sliderParam2.Enabled = false;
- this.sliderParam2.Location = new System.Drawing.Point(291, 41);
- this.sliderParam2.Maximum = 100;
- this.sliderParam2.Minimum = 0;
- this.sliderParam2.Name = "sliderParam2";
- this.sliderParam2.Size = new System.Drawing.Size(138, 23);
- this.sliderParam2.TabIndex = 3;
- this.sliderParam2.Text = "sliderParam2";
- this.sliderParam2.Value = 50;
- this.sliderParam2.ValueChanging += new System.EventHandler(this.sliderParam2_ValueChanging);
- //
- // sliderParam1
- //
- this.sliderParam1.BackColor = System.Drawing.Color.Transparent;
- this.sliderParam1.CriticalPercent = ((uint)(0u));
- this.sliderParam1.Enabled = false;
- this.sliderParam1.Location = new System.Drawing.Point(291, 18);
- this.sliderParam1.Maximum = 100;
- this.sliderParam1.Minimum = 0;
- this.sliderParam1.Name = "sliderParam1";
- this.sliderParam1.Size = new System.Drawing.Size(138, 23);
- this.sliderParam1.TabIndex = 3;
- this.sliderParam1.Text = "sliderParam1";
- this.sliderParam1.Value = 50;
- this.sliderParam1.ValueChanging += new System.EventHandler(this.sliderParam1_ValueChanging);
- //
- // darkListBox1
- //
- this.darkListBox1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(96)))), ((int)(((byte)(96)))), ((int)(((byte)(96)))));
- this.darkListBox1.BorderStyle = System.Windows.Forms.BorderStyle.None;
- this.darkListBox1.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable;
- this.darkListBox1.FormattingEnabled = true;
- this.darkListBox1.ItemHeight = 22;
- this.darkListBox1.Location = new System.Drawing.Point(5, 5);
- this.darkListBox1.Name = "darkListBox1";
- this.darkListBox1.Size = new System.Drawing.Size(160, 228);
- this.darkListBox1.TabIndex = 2;
- this.darkListBox1.SelectedIndexChanged += new System.EventHandler(this.darkListBox1_SelectedIndexChanged);
- //
- // btnClose
- //
- this.btnClose.Location = new System.Drawing.Point(291, 247);
- this.btnClose.Name = "btnClose";
- this.btnClose.Size = new System.Drawing.Size(94, 23);
- this.btnClose.TabIndex = 1;
- this.btnClose.Text = "Close";
- this.btnClose.UseVisualStyleBackColor = true;
- this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
- //
- // btnGenerate
- //
- this.btnGenerate.Location = new System.Drawing.Point(391, 247);
- this.btnGenerate.Name = "btnGenerate";
- this.btnGenerate.Size = new System.Drawing.Size(94, 23);
- this.btnGenerate.TabIndex = 0;
- this.btnGenerate.Text = "Generate";
- this.btnGenerate.UseVisualStyleBackColor = true;
- this.btnGenerate.Click += new System.EventHandler(this.btnGenerate_Click);
- //
- // FormGenerator
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(76)))), ((int)(((byte)(76)))), ((int)(((byte)(76)))));
- this.ClientSize = new System.Drawing.Size(495, 278);
- this.Controls.Add(this.lbParam3Val);
- this.Controls.Add(this.lbDescription);
- this.Controls.Add(this.lbParam3);
- this.Controls.Add(this.lbParam2Val);
- this.Controls.Add(this.lbParam2);
- this.Controls.Add(this.lbParam1Val);
- this.Controls.Add(this.lbParam1);
- this.Controls.Add(this.sliderParam3);
- this.Controls.Add(this.sliderParam2);
- this.Controls.Add(this.sliderParam1);
- this.Controls.Add(this.darkListBox1);
- this.Controls.Add(this.btnClose);
- this.Controls.Add(this.btnGenerate);
- this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
- this.MaximizeBox = false;
- this.MinimizeBox = false;
- this.Name = "FormGenerator";
- this.ShowInTaskbar = false;
- this.Text = "Input Generator";
- this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormGenerator_FormClosing);
- this.Load += new System.EventHandler(this.FormGenerator_Load);
- this.ResumeLayout(false);
-
- }
-
- #endregion
-
- private Controls.DarkButton btnGenerate;
- private Controls.DarkButton btnClose;
- private Controls.DarkListBox darkListBox1;
- private Controls.DarkSlider sliderParam1;
- private Controls.DarkSlider sliderParam2;
- private Controls.DarkSlider sliderParam3;
- private System.Windows.Forms.Label lbParam1;
- private System.Windows.Forms.Label lbParam2;
- private System.Windows.Forms.Label lbParam3;
- private System.Windows.Forms.Label lbParam1Val;
- private System.Windows.Forms.Label lbParam2Val;
- private System.Windows.Forms.Label lbParam3Val;
- private System.Windows.Forms.Label lbDescription;
- }
+namespace MeshExplorer
+{
+ partial class FormGenerator
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.lbParam1 = new System.Windows.Forms.Label();
+ this.lbParam2 = new System.Windows.Forms.Label();
+ this.lbParam3 = new System.Windows.Forms.Label();
+ this.lbParam1Val = new System.Windows.Forms.Label();
+ this.lbParam2Val = new System.Windows.Forms.Label();
+ this.lbParam3Val = new System.Windows.Forms.Label();
+ this.lbDescription = new System.Windows.Forms.Label();
+ this.sliderParam3 = new MeshExplorer.Controls.DarkSlider();
+ this.sliderParam2 = new MeshExplorer.Controls.DarkSlider();
+ this.sliderParam1 = new MeshExplorer.Controls.DarkSlider();
+ this.darkListBox1 = new MeshExplorer.Controls.DarkListBox();
+ this.btnClose = new MeshExplorer.Controls.DarkButton();
+ this.btnGenerate = new MeshExplorer.Controls.DarkButton();
+ this.SuspendLayout();
+ //
+ // lbParam1
+ //
+ this.lbParam1.BackColor = System.Drawing.Color.DimGray;
+ this.lbParam1.ForeColor = System.Drawing.Color.White;
+ this.lbParam1.Location = new System.Drawing.Point(171, 24);
+ this.lbParam1.Name = "lbParam1";
+ this.lbParam1.Size = new System.Drawing.Size(114, 13);
+ this.lbParam1.TabIndex = 4;
+ this.lbParam1.Text = "Param 1:";
+ //
+ // lbParam2
+ //
+ this.lbParam2.BackColor = System.Drawing.Color.DimGray;
+ this.lbParam2.ForeColor = System.Drawing.Color.White;
+ this.lbParam2.Location = new System.Drawing.Point(171, 47);
+ this.lbParam2.Name = "lbParam2";
+ this.lbParam2.Size = new System.Drawing.Size(114, 13);
+ this.lbParam2.TabIndex = 4;
+ this.lbParam2.Text = "Param 2:";
+ //
+ // lbParam3
+ //
+ this.lbParam3.BackColor = System.Drawing.Color.DimGray;
+ this.lbParam3.ForeColor = System.Drawing.Color.White;
+ this.lbParam3.Location = new System.Drawing.Point(171, 70);
+ this.lbParam3.Name = "lbParam3";
+ this.lbParam3.Size = new System.Drawing.Size(114, 13);
+ this.lbParam3.TabIndex = 4;
+ this.lbParam3.Text = "Param 3:";
+ //
+ // lbParam1Val
+ //
+ this.lbParam1Val.BackColor = System.Drawing.Color.DimGray;
+ this.lbParam1Val.ForeColor = System.Drawing.Color.White;
+ this.lbParam1Val.Location = new System.Drawing.Point(436, 24);
+ this.lbParam1Val.Name = "lbParam1Val";
+ this.lbParam1Val.Size = new System.Drawing.Size(40, 13);
+ this.lbParam1Val.TabIndex = 4;
+ this.lbParam1Val.Text = "-";
+ //
+ // lbParam2Val
+ //
+ this.lbParam2Val.BackColor = System.Drawing.Color.DimGray;
+ this.lbParam2Val.ForeColor = System.Drawing.Color.White;
+ this.lbParam2Val.Location = new System.Drawing.Point(436, 47);
+ this.lbParam2Val.Name = "lbParam2Val";
+ this.lbParam2Val.Size = new System.Drawing.Size(40, 13);
+ this.lbParam2Val.TabIndex = 4;
+ this.lbParam2Val.Text = "-";
+ //
+ // lbParam3Val
+ //
+ this.lbParam3Val.BackColor = System.Drawing.Color.DimGray;
+ this.lbParam3Val.ForeColor = System.Drawing.Color.White;
+ this.lbParam3Val.Location = new System.Drawing.Point(436, 70);
+ this.lbParam3Val.Name = "lbParam3Val";
+ this.lbParam3Val.Size = new System.Drawing.Size(40, 13);
+ this.lbParam3Val.TabIndex = 4;
+ this.lbParam3Val.Text = "-";
+ //
+ // lbDescription
+ //
+ this.lbDescription.BackColor = System.Drawing.Color.DimGray;
+ this.lbDescription.ForeColor = System.Drawing.Color.White;
+ this.lbDescription.Location = new System.Drawing.Point(171, 104);
+ this.lbDescription.Name = "lbDescription";
+ this.lbDescription.Size = new System.Drawing.Size(94, 13);
+ this.lbDescription.TabIndex = 4;
+ this.lbDescription.Text = "Description";
+ //
+ // sliderParam3
+ //
+ this.sliderParam3.BackColor = System.Drawing.Color.Transparent;
+ this.sliderParam3.CriticalPercent = ((uint)(0u));
+ this.sliderParam3.Enabled = false;
+ this.sliderParam3.Location = new System.Drawing.Point(291, 64);
+ this.sliderParam3.Maximum = 100;
+ this.sliderParam3.Minimum = 0;
+ this.sliderParam3.Name = "sliderParam3";
+ this.sliderParam3.Size = new System.Drawing.Size(138, 23);
+ this.sliderParam3.TabIndex = 3;
+ this.sliderParam3.Text = "sliderParam3";
+ this.sliderParam3.Value = 50;
+ this.sliderParam3.ValueChanging += new System.EventHandler(this.sliderParam3_ValueChanging);
+ //
+ // sliderParam2
+ //
+ this.sliderParam2.BackColor = System.Drawing.Color.Transparent;
+ this.sliderParam2.CriticalPercent = ((uint)(0u));
+ this.sliderParam2.Enabled = false;
+ this.sliderParam2.Location = new System.Drawing.Point(291, 41);
+ this.sliderParam2.Maximum = 100;
+ this.sliderParam2.Minimum = 0;
+ this.sliderParam2.Name = "sliderParam2";
+ this.sliderParam2.Size = new System.Drawing.Size(138, 23);
+ this.sliderParam2.TabIndex = 3;
+ this.sliderParam2.Text = "sliderParam2";
+ this.sliderParam2.Value = 50;
+ this.sliderParam2.ValueChanging += new System.EventHandler(this.sliderParam2_ValueChanging);
+ //
+ // sliderParam1
+ //
+ this.sliderParam1.BackColor = System.Drawing.Color.Transparent;
+ this.sliderParam1.CriticalPercent = ((uint)(0u));
+ this.sliderParam1.Enabled = false;
+ this.sliderParam1.Location = new System.Drawing.Point(291, 18);
+ this.sliderParam1.Maximum = 100;
+ this.sliderParam1.Minimum = 0;
+ this.sliderParam1.Name = "sliderParam1";
+ this.sliderParam1.Size = new System.Drawing.Size(138, 23);
+ this.sliderParam1.TabIndex = 3;
+ this.sliderParam1.Text = "sliderParam1";
+ this.sliderParam1.Value = 50;
+ this.sliderParam1.ValueChanging += new System.EventHandler(this.sliderParam1_ValueChanging);
+ //
+ // darkListBox1
+ //
+ this.darkListBox1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(96)))), ((int)(((byte)(96)))), ((int)(((byte)(96)))));
+ this.darkListBox1.BorderStyle = System.Windows.Forms.BorderStyle.None;
+ this.darkListBox1.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable;
+ this.darkListBox1.FormattingEnabled = true;
+ this.darkListBox1.ItemHeight = 22;
+ this.darkListBox1.Location = new System.Drawing.Point(5, 5);
+ this.darkListBox1.Name = "darkListBox1";
+ this.darkListBox1.Size = new System.Drawing.Size(160, 228);
+ this.darkListBox1.TabIndex = 2;
+ this.darkListBox1.SelectedIndexChanged += new System.EventHandler(this.darkListBox1_SelectedIndexChanged);
+ //
+ // btnClose
+ //
+ this.btnClose.Location = new System.Drawing.Point(291, 247);
+ this.btnClose.Name = "btnClose";
+ this.btnClose.Size = new System.Drawing.Size(94, 23);
+ this.btnClose.TabIndex = 1;
+ this.btnClose.Text = "Close";
+ this.btnClose.UseVisualStyleBackColor = true;
+ this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
+ //
+ // btnGenerate
+ //
+ this.btnGenerate.Location = new System.Drawing.Point(391, 247);
+ this.btnGenerate.Name = "btnGenerate";
+ this.btnGenerate.Size = new System.Drawing.Size(94, 23);
+ this.btnGenerate.TabIndex = 0;
+ this.btnGenerate.Text = "Generate";
+ this.btnGenerate.UseVisualStyleBackColor = true;
+ this.btnGenerate.Click += new System.EventHandler(this.btnGenerate_Click);
+ //
+ // FormGenerator
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(76)))), ((int)(((byte)(76)))), ((int)(((byte)(76)))));
+ this.ClientSize = new System.Drawing.Size(495, 278);
+ this.Controls.Add(this.lbParam3Val);
+ this.Controls.Add(this.lbDescription);
+ this.Controls.Add(this.lbParam3);
+ this.Controls.Add(this.lbParam2Val);
+ this.Controls.Add(this.lbParam2);
+ this.Controls.Add(this.lbParam1Val);
+ this.Controls.Add(this.lbParam1);
+ this.Controls.Add(this.sliderParam3);
+ this.Controls.Add(this.sliderParam2);
+ this.Controls.Add(this.sliderParam1);
+ this.Controls.Add(this.darkListBox1);
+ this.Controls.Add(this.btnClose);
+ this.Controls.Add(this.btnGenerate);
+ this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "FormGenerator";
+ this.ShowInTaskbar = false;
+ this.Text = "Input Generator";
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormGenerator_FormClosing);
+ this.Load += new System.EventHandler(this.FormGenerator_Load);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private Controls.DarkButton btnGenerate;
+ private Controls.DarkButton btnClose;
+ private Controls.DarkListBox darkListBox1;
+ private Controls.DarkSlider sliderParam1;
+ private Controls.DarkSlider sliderParam2;
+ private Controls.DarkSlider sliderParam3;
+ private System.Windows.Forms.Label lbParam1;
+ private System.Windows.Forms.Label lbParam2;
+ private System.Windows.Forms.Label lbParam3;
+ private System.Windows.Forms.Label lbParam1Val;
+ private System.Windows.Forms.Label lbParam2Val;
+ private System.Windows.Forms.Label lbParam3Val;
+ private System.Windows.Forms.Label lbDescription;
+ }
}
\ No newline at end of file
diff --git a/Triangle.NET/TestApp/FormGenerator.cs b/src/Triangle.Viewer/FormGenerator.cs
similarity index 96%
rename from Triangle.NET/TestApp/FormGenerator.cs
rename to src/Triangle.Viewer/FormGenerator.cs
index e88145e..61776f3 100644
--- a/Triangle.NET/TestApp/FormGenerator.cs
+++ b/src/Triangle.Viewer/FormGenerator.cs
@@ -1,150 +1,150 @@
-using System;
-using System.Drawing;
-using System.Windows.Forms;
-using MeshExplorer.Generators;
-using TriangleNet.Geometry;
-
-namespace MeshExplorer
-{
- public partial class FormGenerator : Form
- {
- public event EventHandler InputGenerated;
-
- IGenerator currentGenerator;
-
- public FormGenerator()
- {
- InitializeComponent();
- }
-
- private void UpdateControls()
- {
- if (currentGenerator.ParameterCount > 0)
- {
- sliderParam1.Enabled = true;
- lbParam1.Text = currentGenerator.ParameterDescription(0);
- lbParam1Val.Text = currentGenerator.ParameterDescription(0, sliderParam1.Value);
- }
- else
- {
- sliderParam1.Enabled = false;
- lbParam1.Text = "";
- lbParam1Val.Text = "";
- }
-
- if (currentGenerator.ParameterCount > 1)
- {
- sliderParam2.Enabled = true;
- lbParam2.Text = currentGenerator.ParameterDescription(1);
- lbParam2Val.Text = currentGenerator.ParameterDescription(1, sliderParam2.Value);
- }
- else
- {
- sliderParam2.Enabled = false;
- lbParam2.Text = "";
- lbParam2Val.Text = "";
- }
-
- if (currentGenerator.ParameterCount > 2)
- {
- sliderParam3.Enabled = true;
- lbParam3.Text = currentGenerator.ParameterDescription(2);
- lbParam3Val.Text = currentGenerator.ParameterDescription(2, sliderParam3.Value);
- }
- else
- {
- sliderParam3.Enabled = false;
- lbParam3.Text = "";
- lbParam3Val.Text = "";
- }
- }
-
- private void btnGenerate_Click(object sender, EventArgs e)
- {
- if (currentGenerator != null && InputGenerated != null)
- {
- try
- {
- var input = currentGenerator.Generate(sliderParam1.Value,
- sliderParam2.Value, sliderParam3.Value);
-
- InputGenerated(input, EventArgs.Empty);
- }
- catch (Exception ex)
- {
- DarkMessageBox.Show("Exception", ex.Message);
- }
- }
- }
-
- private void btnClose_Click(object sender, EventArgs e)
- {
- this.Hide();
- }
-
- private void FormGenerator_FormClosing(object sender, FormClosingEventArgs e)
- {
- if (e.CloseReason == CloseReason.UserClosing)
- {
- e.Cancel = true;
- this.Hide();
- }
- }
-
- protected override void OnPaint(PaintEventArgs e)
- {
- base.OnPaint(e);
-
- var rect = this.ClientRectangle;
- rect.Height -= 40;
-
- e.Graphics.FillRectangle(Brushes.DimGray, rect);
- }
-
- private void darkListBox1_SelectedIndexChanged(object sender, EventArgs e)
- {
- currentGenerator = darkListBox1.SelectedItem as IGenerator;
-
- if (currentGenerator != null)
- {
- UpdateControls();
- }
- }
-
- private void sliderParam1_ValueChanging(object sender, EventArgs e)
- {
- if (currentGenerator != null)
- {
- lbParam1Val.Text = currentGenerator.ParameterDescription(0, sliderParam1.Value);
- }
- }
-
- private void sliderParam2_ValueChanging(object sender, EventArgs e)
- {
- if (currentGenerator != null)
- {
- lbParam2Val.Text = currentGenerator.ParameterDescription(1, sliderParam2.Value);
- }
- }
-
- private void sliderParam3_ValueChanging(object sender, EventArgs e)
- {
- if (currentGenerator != null)
- {
- lbParam3Val.Text = currentGenerator.ParameterDescription(2, sliderParam3.Value);
- }
- }
-
- private void FormGenerator_Load(object sender, EventArgs e)
- {
- darkListBox1.Items.Add(new RandomPoints());
- darkListBox1.Items.Add(new RandomPointsCircle());
- darkListBox1.Items.Add(new StarInBox());
- darkListBox1.Items.Add(new RingPolygon());
- darkListBox1.Items.Add(new BoxWithHole());
- darkListBox1.Items.Add(new CircleWithHole());
-
- darkListBox1.SelectedIndex = 0;
- }
- }
-}
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+using MeshExplorer.Generators;
+using TriangleNet.Geometry;
+
+namespace MeshExplorer
+{
+ public partial class FormGenerator : Form
+ {
+ public event EventHandler InputGenerated;
+
+ IGenerator currentGenerator;
+
+ public FormGenerator()
+ {
+ InitializeComponent();
+ }
+
+ private void UpdateControls()
+ {
+ if (currentGenerator.ParameterCount > 0)
+ {
+ sliderParam1.Enabled = true;
+ lbParam1.Text = currentGenerator.ParameterDescription(0);
+ lbParam1Val.Text = currentGenerator.ParameterDescription(0, sliderParam1.Value);
+ }
+ else
+ {
+ sliderParam1.Enabled = false;
+ lbParam1.Text = "";
+ lbParam1Val.Text = "";
+ }
+
+ if (currentGenerator.ParameterCount > 1)
+ {
+ sliderParam2.Enabled = true;
+ lbParam2.Text = currentGenerator.ParameterDescription(1);
+ lbParam2Val.Text = currentGenerator.ParameterDescription(1, sliderParam2.Value);
+ }
+ else
+ {
+ sliderParam2.Enabled = false;
+ lbParam2.Text = "";
+ lbParam2Val.Text = "";
+ }
+
+ if (currentGenerator.ParameterCount > 2)
+ {
+ sliderParam3.Enabled = true;
+ lbParam3.Text = currentGenerator.ParameterDescription(2);
+ lbParam3Val.Text = currentGenerator.ParameterDescription(2, sliderParam3.Value);
+ }
+ else
+ {
+ sliderParam3.Enabled = false;
+ lbParam3.Text = "";
+ lbParam3Val.Text = "";
+ }
+ }
+
+ private void btnGenerate_Click(object sender, EventArgs e)
+ {
+ if (currentGenerator != null && InputGenerated != null)
+ {
+ try
+ {
+ var input = currentGenerator.Generate(sliderParam1.Value,
+ sliderParam2.Value, sliderParam3.Value);
+
+ InputGenerated(input, EventArgs.Empty);
+ }
+ catch (Exception ex)
+ {
+ DarkMessageBox.Show("Exception", ex.Message);
+ }
+ }
+ }
+
+ private void btnClose_Click(object sender, EventArgs e)
+ {
+ this.Hide();
+ }
+
+ private void FormGenerator_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ if (e.CloseReason == CloseReason.UserClosing)
+ {
+ e.Cancel = true;
+ this.Hide();
+ }
+ }
+
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ base.OnPaint(e);
+
+ var rect = this.ClientRectangle;
+ rect.Height -= 40;
+
+ e.Graphics.FillRectangle(Brushes.DimGray, rect);
+ }
+
+ private void darkListBox1_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ currentGenerator = darkListBox1.SelectedItem as IGenerator;
+
+ if (currentGenerator != null)
+ {
+ UpdateControls();
+ }
+ }
+
+ private void sliderParam1_ValueChanging(object sender, EventArgs e)
+ {
+ if (currentGenerator != null)
+ {
+ lbParam1Val.Text = currentGenerator.ParameterDescription(0, sliderParam1.Value);
+ }
+ }
+
+ private void sliderParam2_ValueChanging(object sender, EventArgs e)
+ {
+ if (currentGenerator != null)
+ {
+ lbParam2Val.Text = currentGenerator.ParameterDescription(1, sliderParam2.Value);
+ }
+ }
+
+ private void sliderParam3_ValueChanging(object sender, EventArgs e)
+ {
+ if (currentGenerator != null)
+ {
+ lbParam3Val.Text = currentGenerator.ParameterDescription(2, sliderParam3.Value);
+ }
+ }
+
+ private void FormGenerator_Load(object sender, EventArgs e)
+ {
+ darkListBox1.Items.Add(new RandomPoints());
+ darkListBox1.Items.Add(new RandomPointsCircle());
+ darkListBox1.Items.Add(new StarInBox());
+ darkListBox1.Items.Add(new RingPolygon());
+ darkListBox1.Items.Add(new BoxWithHole());
+ darkListBox1.Items.Add(new CircleWithHole());
+
+ darkListBox1.SelectedIndex = 0;
+ }
+ }
+}
diff --git a/Triangle.NET/TestApp/FormGenerator.resx b/src/Triangle.Viewer/FormGenerator.resx
similarity index 97%
rename from Triangle.NET/TestApp/FormGenerator.resx
rename to src/Triangle.Viewer/FormGenerator.resx
index 29dcb1b..1af7de1 100644
--- a/Triangle.NET/TestApp/FormGenerator.resx
+++ b/src/Triangle.Viewer/FormGenerator.resx
@@ -1,120 +1,120 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
\ No newline at end of file
diff --git a/Triangle.NET/TestApp/FormLog.Designer.cs b/src/Triangle.Viewer/FormLog.Designer.cs
similarity index 97%
rename from Triangle.NET/TestApp/FormLog.Designer.cs
rename to src/Triangle.Viewer/FormLog.Designer.cs
index f680174..bf0cf74 100644
--- a/Triangle.NET/TestApp/FormLog.Designer.cs
+++ b/src/Triangle.Viewer/FormLog.Designer.cs
@@ -1,90 +1,90 @@
-namespace MeshExplorer
-{
- partial class FormLog
- {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- this.listLog = new System.Windows.Forms.ListView();
- this.colMessage = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
- this.colInfo = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
- this.SuspendLayout();
- //
- // listLog
- //
- this.listLog.BackColor = System.Drawing.Color.White;
- this.listLog.BorderStyle = System.Windows.Forms.BorderStyle.None;
- this.listLog.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
- this.colMessage,
- this.colInfo});
- this.listLog.Dock = System.Windows.Forms.DockStyle.Fill;
- this.listLog.ForeColor = System.Drawing.Color.White;
- this.listLog.FullRowSelect = true;
- this.listLog.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
- this.listLog.Location = new System.Drawing.Point(0, 0);
- this.listLog.Name = "listLog";
- this.listLog.Size = new System.Drawing.Size(584, 262);
- this.listLog.TabIndex = 2;
- this.listLog.UseCompatibleStateImageBehavior = false;
- this.listLog.View = System.Windows.Forms.View.Details;
- this.listLog.DoubleClick += new System.EventHandler(this.listLog_DoubleClick);
- this.listLog.KeyDown += new System.Windows.Forms.KeyEventHandler(this.listLog_KeyDown);
- //
- // colMessage
- //
- this.colMessage.Text = "Message";
- this.colMessage.Width = 350;
- //
- // colInfo
- //
- this.colInfo.Text = "Info";
- this.colInfo.Width = 200;
- //
- // FormLog
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(584, 262);
- this.Controls.Add(this.listLog);
- this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.MaximizeBox = false;
- this.MinimizeBox = false;
- this.Name = "FormLog";
- this.ShowIcon = false;
- this.ShowInTaskbar = false;
- this.Text = "Log";
- this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormLog_FormClosing);
- this.ResumeLayout(false);
-
- }
-
- #endregion
-
- private System.Windows.Forms.ListView listLog;
- private System.Windows.Forms.ColumnHeader colMessage;
- private System.Windows.Forms.ColumnHeader colInfo;
- }
+namespace MeshExplorer
+{
+ partial class FormLog
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.listLog = new System.Windows.Forms.ListView();
+ this.colMessage = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.colInfo = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.SuspendLayout();
+ //
+ // listLog
+ //
+ this.listLog.BackColor = System.Drawing.Color.White;
+ this.listLog.BorderStyle = System.Windows.Forms.BorderStyle.None;
+ this.listLog.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this.colMessage,
+ this.colInfo});
+ this.listLog.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.listLog.ForeColor = System.Drawing.Color.White;
+ this.listLog.FullRowSelect = true;
+ this.listLog.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
+ this.listLog.Location = new System.Drawing.Point(0, 0);
+ this.listLog.Name = "listLog";
+ this.listLog.Size = new System.Drawing.Size(584, 262);
+ this.listLog.TabIndex = 2;
+ this.listLog.UseCompatibleStateImageBehavior = false;
+ this.listLog.View = System.Windows.Forms.View.Details;
+ this.listLog.DoubleClick += new System.EventHandler(this.listLog_DoubleClick);
+ this.listLog.KeyDown += new System.Windows.Forms.KeyEventHandler(this.listLog_KeyDown);
+ //
+ // colMessage
+ //
+ this.colMessage.Text = "Message";
+ this.colMessage.Width = 350;
+ //
+ // colInfo
+ //
+ this.colInfo.Text = "Info";
+ this.colInfo.Width = 200;
+ //
+ // FormLog
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(584, 262);
+ this.Controls.Add(this.listLog);
+ this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "FormLog";
+ this.ShowIcon = false;
+ this.ShowInTaskbar = false;
+ this.Text = "Log";
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormLog_FormClosing);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.ListView listLog;
+ private System.Windows.Forms.ColumnHeader colMessage;
+ private System.Windows.Forms.ColumnHeader colInfo;
+ }
}
\ No newline at end of file
diff --git a/Triangle.NET/TestApp/FormLog.cs b/src/Triangle.Viewer/FormLog.cs
similarity index 94%
rename from Triangle.NET/TestApp/FormLog.cs
rename to src/Triangle.Viewer/FormLog.cs
index 1d2677b..ca38d8d 100644
--- a/Triangle.NET/TestApp/FormLog.cs
+++ b/src/Triangle.Viewer/FormLog.cs
@@ -1,139 +1,138 @@
-using System;
-using System.Drawing;
-using System.Text;
-using System.Windows.Forms;
-using TriangleNet;
-using TriangleNet.Logging;
-
-namespace MeshExplorer
-{
- public partial class FormLog : Form
- {
- public FormLog()
- {
- InitializeComponent();
- }
-
- public void AddItem(string message, bool warning)
- {
- var log = Log.Instance;
-
- if (warning)
- {
- log.Warning(message, "Mesh Explorer");
- }
- else
- {
- log.Info(message);
- }
- }
-
- public void UpdateItems()
- {
- listLog.Items.Clear();
-
- var log = Log.Instance;
-
- foreach (var item in log.Data)
- {
- listLog.Items.Add(CreateListViewItem(item));
- }
- }
-
- private ListViewItem CreateListViewItem(LogItem item)
- {
- ListViewItem lvi = new ListViewItem(new string[] { item.Message, item.Info });
-
- if (item.Level == LogLevel.Error)
- {
- lvi.ForeColor = Color.DarkRed;
- }
- else if (item.Level == LogLevel.Warning)
- {
- lvi.ForeColor = Color.Peru;
- }
- else
- {
- lvi.ForeColor = Color.Black;
- }
-
- lvi.UseItemStyleForSubItems = true;
-
- return lvi;
- }
-
- private void FormLog_FormClosing(object sender, FormClosingEventArgs e)
- {
- if (e.CloseReason == CloseReason.UserClosing)
- {
- e.Cancel = true;
- this.Hide();
- }
- }
-
- private void listLog_KeyDown(object sender, KeyEventArgs e)
- {
- if (e.KeyCode == Keys.C)
- {
- if (ModifierKeys == Keys.Control)
- {
- var selection = listLog.SelectedItems;
-
- if (selection != null && selection.Count > 0)
- {
- StringBuilder sb = new StringBuilder();
-
- foreach (var item in selection)
- {
- GetRowText(sb, item);
- }
-
- Clipboard.SetText(sb.ToString());
- }
- }
- }
- else if (e.KeyCode == Keys.Delete)
- {
- if (ModifierKeys == Keys.Control)
- {
- listLog.Items.Clear();
- Log.Instance.Clear();
- }
- }
- }
-
- private void listLog_DoubleClick(object sender, EventArgs e)
- {
- StringBuilder sb = new StringBuilder();
-
- foreach (var item in listLog.SelectedItems)
- {
- GetRowText(sb, item);
- }
-
- if (sb.Length > 0)
- {
- Clipboard.SetText(sb.ToString());
- }
- }
-
- private void GetRowText(StringBuilder sb, object item)
- {
- var row = item as ListViewItem;
-
- if (row != null)
- {
- foreach (var col in row.SubItems)
- {
- var lvi = col as ListViewItem.ListViewSubItem;
-
- if (lvi != null)
- {
- sb.Append(lvi.Text);
- sb.Append("; ");
- }
- }
- }
- }
- }
-}
+using System;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+using TriangleNet;
+
+namespace MeshExplorer
+{
+ public partial class FormLog : Form
+ {
+ public FormLog()
+ {
+ InitializeComponent();
+ }
+
+ public void AddItem(string message, bool warning)
+ {
+ var log = Log.Instance;
+
+ if (warning)
+ {
+ log.Warning(message, "Mesh Explorer");
+ }
+ else
+ {
+ log.Info(message);
+ }
+ }
+
+ public void UpdateItems()
+ {
+ listLog.Items.Clear();
+
+ var log = Log.Instance;
+
+ foreach (var item in log.Data)
+ {
+ listLog.Items.Add(CreateListViewItem(item));
+ }
+ }
+
+ private ListViewItem CreateListViewItem(LogItem item)
+ {
+ ListViewItem lvi = new ListViewItem(new string[] { item.Message, item.Details });
+
+ if (item.Level == LogLevel.Error)
+ {
+ lvi.ForeColor = Color.DarkRed;
+ }
+ else if (item.Level == LogLevel.Warning)
+ {
+ lvi.ForeColor = Color.Peru;
+ }
+ else
+ {
+ lvi.ForeColor = Color.Black;
+ }
+
+ lvi.UseItemStyleForSubItems = true;
+
+ return lvi;
+ }
+
+ private void FormLog_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ if (e.CloseReason == CloseReason.UserClosing)
+ {
+ e.Cancel = true;
+ this.Hide();
+ }
+ }
+
+ private void listLog_KeyDown(object sender, KeyEventArgs e)
+ {
+ if (e.KeyCode == Keys.C)
+ {
+ if (ModifierKeys == Keys.Control)
+ {
+ var selection = listLog.SelectedItems;
+
+ if (selection != null && selection.Count > 0)
+ {
+ StringBuilder sb = new StringBuilder();
+
+ foreach (var item in selection)
+ {
+ GetRowText(sb, item);
+ }
+
+ Clipboard.SetText(sb.ToString());
+ }
+ }
+ }
+ else if (e.KeyCode == Keys.Delete)
+ {
+ if (ModifierKeys == Keys.Control)
+ {
+ listLog.Items.Clear();
+ Log.Instance.Clear();
+ }
+ }
+ }
+
+ private void listLog_DoubleClick(object sender, EventArgs e)
+ {
+ StringBuilder sb = new StringBuilder();
+
+ foreach (var item in listLog.SelectedItems)
+ {
+ GetRowText(sb, item);
+ }
+
+ if (sb.Length > 0)
+ {
+ Clipboard.SetText(sb.ToString());
+ }
+ }
+
+ private void GetRowText(StringBuilder sb, object item)
+ {
+ var row = item as ListViewItem;
+
+ if (row != null)
+ {
+ foreach (var col in row.SubItems)
+ {
+ var lvi = col as ListViewItem.ListViewSubItem;
+
+ if (lvi != null)
+ {
+ sb.Append(lvi.Text);
+ sb.Append("; ");
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Triangle.NET/TestApp/FormLog.resx b/src/Triangle.Viewer/FormLog.resx
similarity index 97%
rename from Triangle.NET/TestApp/FormLog.resx
rename to src/Triangle.Viewer/FormLog.resx
index 29dcb1b..1af7de1 100644
--- a/Triangle.NET/TestApp/FormLog.resx
+++ b/src/Triangle.Viewer/FormLog.resx
@@ -1,120 +1,120 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
\ No newline at end of file
diff --git a/Triangle.NET/TestApp/FormMain.Designer.cs b/src/Triangle.Viewer/FormMain.Designer.cs
similarity index 98%
rename from Triangle.NET/TestApp/FormMain.Designer.cs
rename to src/Triangle.Viewer/FormMain.Designer.cs
index ac0e044..f76312c 100644
--- a/Triangle.NET/TestApp/FormMain.Designer.cs
+++ b/src/Triangle.Viewer/FormMain.Designer.cs
@@ -1,418 +1,418 @@
-namespace MeshExplorer
-{
- partial class FormMain
- {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- this.splitContainer = new System.Windows.Forms.SplitContainer();
- this.btnSmooth = new MeshExplorer.Controls.DarkButton();
- this.flatTabControl1 = new MeshExplorer.Controls.DarkTabControl();
- this.tabPage1 = new System.Windows.Forms.TabPage();
- this.meshControlView = new MeshExplorer.Views.MeshControlView();
- this.tabPage2 = new System.Windows.Forms.TabPage();
- this.statisticView = new MeshExplorer.Views.StatisticView();
- this.tabPage3 = new System.Windows.Forms.TabPage();
- this.aboutView = new MeshExplorer.Views.AboutView();
- this.menuStrip1 = new System.Windows.Forms.MenuStrip();
- this.menuFile = new System.Windows.Forms.ToolStripMenuItem();
- this.menuFileOpen = new System.Windows.Forms.ToolStripMenuItem();
- this.menuFileSave = new System.Windows.Forms.ToolStripMenuItem();
- this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator();
- this.menuFileExport = new System.Windows.Forms.ToolStripMenuItem();
- this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
- this.menuFileQuit = new System.Windows.Forms.ToolStripMenuItem();
- this.menuView = new System.Windows.Forms.ToolStripMenuItem();
- this.menuViewVoronoi = new System.Windows.Forms.ToolStripMenuItem();
- this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
- this.menuViewLog = new System.Windows.Forms.ToolStripMenuItem();
- this.menuTools = new System.Windows.Forms.ToolStripMenuItem();
- this.menuToolsGen = new System.Windows.Forms.ToolStripMenuItem();
- this.menuToolsCheck = new System.Windows.Forms.ToolStripMenuItem();
- this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator();
- this.menuToolsTopology = new System.Windows.Forms.ToolStripMenuItem();
- this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();
- this.menuToolsRcm = new System.Windows.Forms.ToolStripMenuItem();
- this.btnMesh = new MeshExplorer.Controls.DarkButton();
- ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
- this.splitContainer.Panel1.SuspendLayout();
- this.splitContainer.SuspendLayout();
- this.flatTabControl1.SuspendLayout();
- this.tabPage1.SuspendLayout();
- this.tabPage2.SuspendLayout();
- this.tabPage3.SuspendLayout();
- this.menuStrip1.SuspendLayout();
- this.SuspendLayout();
- //
- // splitContainer
- //
- this.splitContainer.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(68)))), ((int)(((byte)(68)))), ((int)(((byte)(68)))));
- this.splitContainer.Dock = System.Windows.Forms.DockStyle.Fill;
- this.splitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
- this.splitContainer.IsSplitterFixed = true;
- this.splitContainer.Location = new System.Drawing.Point(0, 0);
- this.splitContainer.Name = "splitContainer";
- //
- // splitContainer.Panel1
- //
- this.splitContainer.Panel1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(76)))), ((int)(((byte)(76)))), ((int)(((byte)(76)))));
- this.splitContainer.Panel1.Controls.Add(this.btnSmooth);
- this.splitContainer.Panel1.Controls.Add(this.flatTabControl1);
- this.splitContainer.Panel1.Controls.Add(this.menuStrip1);
- this.splitContainer.Panel1.Controls.Add(this.btnMesh);
- //
- // splitContainer.Panel2
- //
- this.splitContainer.Panel2.BackColor = System.Drawing.Color.Black;
- this.splitContainer.Size = new System.Drawing.Size(992, 623);
- this.splitContainer.SplitterDistance = 280;
- this.splitContainer.SplitterWidth = 1;
- this.splitContainer.TabIndex = 0;
- //
- // btnSmooth
- //
- this.btnSmooth.Enabled = false;
- this.btnSmooth.Location = new System.Drawing.Point(146, 44);
- this.btnSmooth.Name = "btnSmooth";
- this.btnSmooth.Size = new System.Drawing.Size(130, 23);
- this.btnSmooth.TabIndex = 12;
- this.btnSmooth.Text = "Smooth";
- this.btnSmooth.UseVisualStyleBackColor = true;
- this.btnSmooth.Click += new System.EventHandler(this.btnSmooth_Click);
- //
- // flatTabControl1
- //
- this.flatTabControl1.Alignment = System.Windows.Forms.TabAlignment.Bottom;
- this.flatTabControl1.Controls.Add(this.tabPage1);
- this.flatTabControl1.Controls.Add(this.tabPage2);
- this.flatTabControl1.Controls.Add(this.tabPage3);
- this.flatTabControl1.Location = new System.Drawing.Point(0, 73);
- this.flatTabControl1.Name = "flatTabControl1";
- this.flatTabControl1.SelectedIndex = 0;
- this.flatTabControl1.Size = new System.Drawing.Size(280, 538);
- this.flatTabControl1.TabIndex = 1;
- //
- // tabPage1
- //
- this.tabPage1.BackColor = System.Drawing.Color.DimGray;
- this.tabPage1.Controls.Add(this.meshControlView);
- this.tabPage1.ForeColor = System.Drawing.Color.DarkGray;
- this.tabPage1.Location = new System.Drawing.Point(4, 4);
- this.tabPage1.Name = "tabPage1";
- this.tabPage1.Size = new System.Drawing.Size(272, 509);
- this.tabPage1.TabIndex = 0;
- this.tabPage1.Text = "Mesh Control";
- //
- // meshControlView
- //
- this.meshControlView.BackColor = System.Drawing.Color.DimGray;
- this.meshControlView.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.meshControlView.ForeColor = System.Drawing.Color.DarkGray;
- this.meshControlView.Location = new System.Drawing.Point(0, 0);
- this.meshControlView.Name = "meshControlView";
- this.meshControlView.Size = new System.Drawing.Size(272, 509);
- this.meshControlView.TabIndex = 0;
- //
- // tabPage2
- //
- this.tabPage2.BackColor = System.Drawing.Color.DimGray;
- this.tabPage2.Controls.Add(this.statisticView);
- this.tabPage2.ForeColor = System.Drawing.Color.White;
- this.tabPage2.Location = new System.Drawing.Point(4, 4);
- this.tabPage2.Name = "tabPage2";
- this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
- this.tabPage2.Size = new System.Drawing.Size(272, 509);
- this.tabPage2.TabIndex = 1;
- this.tabPage2.Text = "Statistic";
- //
- // statisticView
- //
- this.statisticView.BackColor = System.Drawing.Color.DimGray;
- this.statisticView.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.statisticView.ForeColor = System.Drawing.Color.DarkGray;
- this.statisticView.Location = new System.Drawing.Point(0, 0);
- this.statisticView.Name = "statisticView";
- this.statisticView.Size = new System.Drawing.Size(272, 509);
- this.statisticView.TabIndex = 0;
- //
- // tabPage3
- //
- this.tabPage3.BackColor = System.Drawing.Color.DimGray;
- this.tabPage3.Controls.Add(this.aboutView);
- this.tabPage3.Location = new System.Drawing.Point(4, 4);
- this.tabPage3.Name = "tabPage3";
- this.tabPage3.Padding = new System.Windows.Forms.Padding(3);
- this.tabPage3.Size = new System.Drawing.Size(272, 509);
- this.tabPage3.TabIndex = 2;
- this.tabPage3.Text = "About";
- //
- // aboutView
- //
- this.aboutView.BackColor = System.Drawing.Color.DimGray;
- this.aboutView.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.aboutView.ForeColor = System.Drawing.Color.DarkGray;
- this.aboutView.Location = new System.Drawing.Point(0, 0);
- this.aboutView.Name = "aboutView";
- this.aboutView.Size = new System.Drawing.Size(272, 509);
- this.aboutView.TabIndex = 0;
- //
- // menuStrip1
- //
- this.menuStrip1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
- this.menuStrip1.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.menuStrip1.GripMargin = new System.Windows.Forms.Padding(0);
- this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.menuFile,
- this.menuView,
- this.menuTools});
- this.menuStrip1.Location = new System.Drawing.Point(0, 0);
- this.menuStrip1.Name = "menuStrip1";
- this.menuStrip1.Padding = new System.Windows.Forms.Padding(0);
- this.menuStrip1.Size = new System.Drawing.Size(280, 24);
- this.menuStrip1.TabIndex = 0;
- this.menuStrip1.Text = "menuStrip1";
- //
- // menuFile
- //
- this.menuFile.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
- this.menuFile.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
- this.menuFile.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.menuFileOpen,
- this.menuFileSave,
- this.toolStripSeparator3,
- this.menuFileExport,
- this.toolStripSeparator2,
- this.menuFileQuit});
- this.menuFile.Name = "menuFile";
- this.menuFile.Size = new System.Drawing.Size(37, 24);
- this.menuFile.Text = "File";
- //
- // menuFileOpen
- //
- this.menuFileOpen.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
- this.menuFileOpen.Name = "menuFileOpen";
- this.menuFileOpen.Size = new System.Drawing.Size(141, 22);
- this.menuFileOpen.Text = "Open";
- this.menuFileOpen.Click += new System.EventHandler(this.menuFileOpen_Click);
- //
- // menuFileSave
- //
- this.menuFileSave.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
- this.menuFileSave.Enabled = false;
- this.menuFileSave.Name = "menuFileSave";
- this.menuFileSave.Size = new System.Drawing.Size(141, 22);
- this.menuFileSave.Text = "Save";
- this.menuFileSave.Click += new System.EventHandler(this.menuFileSave_Click);
- //
- // toolStripSeparator3
- //
- this.toolStripSeparator3.Name = "toolStripSeparator3";
- this.toolStripSeparator3.Size = new System.Drawing.Size(138, 6);
- //
- // menuFileExport
- //
- this.menuFileExport.Enabled = false;
- this.menuFileExport.Name = "menuFileExport";
- this.menuFileExport.Size = new System.Drawing.Size(141, 22);
- this.menuFileExport.Text = "Export Image";
- this.menuFileExport.Click += new System.EventHandler(this.menuFileExport_Click);
- //
- // toolStripSeparator2
- //
- this.toolStripSeparator2.Name = "toolStripSeparator2";
- this.toolStripSeparator2.Size = new System.Drawing.Size(138, 6);
- //
- // menuFileQuit
- //
- this.menuFileQuit.Name = "menuFileQuit";
- this.menuFileQuit.Size = new System.Drawing.Size(141, 22);
- this.menuFileQuit.Text = "Quit";
- this.menuFileQuit.Click += new System.EventHandler(this.menuFileQuit_Click);
- //
- // menuView
- //
- this.menuView.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.menuViewVoronoi,
- this.toolStripSeparator1,
- this.menuViewLog});
- this.menuView.Name = "menuView";
- this.menuView.Size = new System.Drawing.Size(44, 24);
- this.menuView.Text = "View";
- //
- // menuViewVoronoi
- //
- this.menuViewVoronoi.Enabled = false;
- this.menuViewVoronoi.Name = "menuViewVoronoi";
- this.menuViewVoronoi.Size = new System.Drawing.Size(162, 22);
- this.menuViewVoronoi.Text = "Voronoi Diagram";
- this.menuViewVoronoi.Click += new System.EventHandler(this.menuViewVoronoi_Click);
- //
- // toolStripSeparator1
- //
- this.toolStripSeparator1.Name = "toolStripSeparator1";
- this.toolStripSeparator1.Size = new System.Drawing.Size(159, 6);
- //
- // menuViewLog
- //
- this.menuViewLog.Name = "menuViewLog";
- this.menuViewLog.Size = new System.Drawing.Size(162, 22);
- this.menuViewLog.Text = "Show Log";
- this.menuViewLog.Click += new System.EventHandler(this.menuViewLog_Click);
- //
- // menuTools
- //
- this.menuTools.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.menuToolsGen,
- this.menuToolsCheck,
- this.toolStripSeparator5,
- this.menuToolsTopology,
- this.toolStripSeparator4,
- this.menuToolsRcm});
- this.menuTools.Name = "menuTools";
- this.menuTools.Size = new System.Drawing.Size(46, 24);
- this.menuTools.Text = "Tools";
- //
- // menuToolsGen
- //
- this.menuToolsGen.Name = "menuToolsGen";
- this.menuToolsGen.Size = new System.Drawing.Size(195, 22);
- this.menuToolsGen.Text = "Input Generator";
- this.menuToolsGen.Click += new System.EventHandler(this.menuToolsGenerator_Click);
- //
- // menuToolsCheck
- //
- this.menuToolsCheck.Enabled = false;
- this.menuToolsCheck.Name = "menuToolsCheck";
- this.menuToolsCheck.Size = new System.Drawing.Size(195, 22);
- this.menuToolsCheck.Text = "Check Mesh";
- this.menuToolsCheck.Click += new System.EventHandler(this.menuToolsCheck_Click);
- //
- // toolStripSeparator5
- //
- this.toolStripSeparator5.Name = "toolStripSeparator5";
- this.toolStripSeparator5.Size = new System.Drawing.Size(192, 6);
- //
- // menuToolsTopology
- //
- this.menuToolsTopology.Name = "menuToolsTopology";
- this.menuToolsTopology.Size = new System.Drawing.Size(195, 22);
- this.menuToolsTopology.Text = "Topology Explorer";
- this.menuToolsTopology.Click += new System.EventHandler(this.menuToolsTopology_Click);
- //
- // toolStripSeparator4
- //
- this.toolStripSeparator4.Name = "toolStripSeparator4";
- this.toolStripSeparator4.Size = new System.Drawing.Size(192, 6);
- //
- // menuToolsRcm
- //
- this.menuToolsRcm.Enabled = false;
- this.menuToolsRcm.Name = "menuToolsRcm";
- this.menuToolsRcm.Size = new System.Drawing.Size(195, 22);
- this.menuToolsRcm.Text = "Renumber nodes (RCM)";
- this.menuToolsRcm.Click += new System.EventHandler(this.menuToolsRcm_Click);
- //
- // btnMesh
- //
- this.btnMesh.Enabled = false;
- this.btnMesh.Location = new System.Drawing.Point(4, 44);
- this.btnMesh.Name = "btnMesh";
- this.btnMesh.Size = new System.Drawing.Size(130, 23);
- this.btnMesh.TabIndex = 12;
- this.btnMesh.Text = "Triangulate";
- this.btnMesh.UseVisualStyleBackColor = true;
- this.btnMesh.Click += new System.EventHandler(this.btnMesh_Click);
- //
- // FormMain
- //
- this.AllowDrop = true;
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(76)))), ((int)(((byte)(76)))), ((int)(((byte)(76)))));
- this.ClientSize = new System.Drawing.Size(992, 623);
- this.Controls.Add(this.splitContainer);
- this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.KeyPreview = true;
- this.MainMenuStrip = this.menuStrip1;
- this.MinimumSize = new System.Drawing.Size(1000, 650);
- this.Name = "FormMain";
- this.Text = "Triangle.NET - Mesh Explorer";
- this.Load += new System.EventHandler(this.Form1_Load);
- this.ResizeBegin += new System.EventHandler(this.ResizeBeginHandler);
- this.ResizeEnd += new System.EventHandler(this.ResizeEndHandler);
- this.DragDrop += new System.Windows.Forms.DragEventHandler(this.frmDragDrop);
- this.DragOver += new System.Windows.Forms.DragEventHandler(this.frmDragOver);
- this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyUp);
- this.Resize += new System.EventHandler(this.ResizeHandler);
- this.splitContainer.Panel1.ResumeLayout(false);
- this.splitContainer.Panel1.PerformLayout();
- ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit();
- this.splitContainer.ResumeLayout(false);
- this.flatTabControl1.ResumeLayout(false);
- this.tabPage1.ResumeLayout(false);
- this.tabPage2.ResumeLayout(false);
- this.tabPage3.ResumeLayout(false);
- this.menuStrip1.ResumeLayout(false);
- this.menuStrip1.PerformLayout();
- this.ResumeLayout(false);
-
- }
-
- #endregion
-
- private System.Windows.Forms.SplitContainer splitContainer;
- private System.Windows.Forms.MenuStrip menuStrip1;
- private System.Windows.Forms.ToolStripMenuItem menuFile;
- private System.Windows.Forms.ToolStripMenuItem menuFileOpen;
- private System.Windows.Forms.ToolStripMenuItem menuFileSave;
- private Controls.DarkTabControl flatTabControl1;
- private System.Windows.Forms.TabPage tabPage1;
- private System.Windows.Forms.TabPage tabPage2;
- private Controls.DarkButton btnSmooth;
- private Controls.DarkButton btnMesh;
- private System.Windows.Forms.TabPage tabPage3;
- private System.Windows.Forms.ToolStripMenuItem menuView;
- private System.Windows.Forms.ToolStripMenuItem menuViewVoronoi;
- private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
- private System.Windows.Forms.ToolStripMenuItem menuViewLog;
- private System.Windows.Forms.ToolStripMenuItem menuTools;
- private System.Windows.Forms.ToolStripMenuItem menuToolsGen;
- private System.Windows.Forms.ToolStripMenuItem menuToolsCheck;
- private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
- private System.Windows.Forms.ToolStripMenuItem menuFileQuit;
- private System.Windows.Forms.ToolStripSeparator toolStripSeparator3;
- private System.Windows.Forms.ToolStripMenuItem menuFileExport;
- private System.Windows.Forms.ToolStripSeparator toolStripSeparator4;
- private System.Windows.Forms.ToolStripMenuItem menuToolsRcm;
- private Views.MeshControlView meshControlView;
- private Views.StatisticView statisticView;
- private Views.AboutView aboutView;
- private System.Windows.Forms.ToolStripSeparator toolStripSeparator5;
- private System.Windows.Forms.ToolStripMenuItem menuToolsTopology;
-
- }
-}
-
+namespace MeshExplorer
+{
+ partial class FormMain
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.splitContainer = new System.Windows.Forms.SplitContainer();
+ this.btnSmooth = new MeshExplorer.Controls.DarkButton();
+ this.flatTabControl1 = new MeshExplorer.Controls.DarkTabControl();
+ this.tabPage1 = new System.Windows.Forms.TabPage();
+ this.meshControlView = new MeshExplorer.Views.MeshControlView();
+ this.tabPage2 = new System.Windows.Forms.TabPage();
+ this.statisticView = new MeshExplorer.Views.StatisticView();
+ this.tabPage3 = new System.Windows.Forms.TabPage();
+ this.aboutView = new MeshExplorer.Views.AboutView();
+ this.menuStrip1 = new System.Windows.Forms.MenuStrip();
+ this.menuFile = new System.Windows.Forms.ToolStripMenuItem();
+ this.menuFileOpen = new System.Windows.Forms.ToolStripMenuItem();
+ this.menuFileSave = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator();
+ this.menuFileExport = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
+ this.menuFileQuit = new System.Windows.Forms.ToolStripMenuItem();
+ this.menuView = new System.Windows.Forms.ToolStripMenuItem();
+ this.menuViewVoronoi = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
+ this.menuViewLog = new System.Windows.Forms.ToolStripMenuItem();
+ this.menuTools = new System.Windows.Forms.ToolStripMenuItem();
+ this.menuToolsGen = new System.Windows.Forms.ToolStripMenuItem();
+ this.menuToolsCheck = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator();
+ this.menuToolsTopology = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();
+ this.menuToolsRcm = new System.Windows.Forms.ToolStripMenuItem();
+ this.btnMesh = new MeshExplorer.Controls.DarkButton();
+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
+ this.splitContainer.Panel1.SuspendLayout();
+ this.splitContainer.SuspendLayout();
+ this.flatTabControl1.SuspendLayout();
+ this.tabPage1.SuspendLayout();
+ this.tabPage2.SuspendLayout();
+ this.tabPage3.SuspendLayout();
+ this.menuStrip1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // splitContainer
+ //
+ this.splitContainer.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(68)))), ((int)(((byte)(68)))), ((int)(((byte)(68)))));
+ this.splitContainer.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.splitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
+ this.splitContainer.IsSplitterFixed = true;
+ this.splitContainer.Location = new System.Drawing.Point(0, 0);
+ this.splitContainer.Name = "splitContainer";
+ //
+ // splitContainer.Panel1
+ //
+ this.splitContainer.Panel1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(76)))), ((int)(((byte)(76)))), ((int)(((byte)(76)))));
+ this.splitContainer.Panel1.Controls.Add(this.btnSmooth);
+ this.splitContainer.Panel1.Controls.Add(this.flatTabControl1);
+ this.splitContainer.Panel1.Controls.Add(this.menuStrip1);
+ this.splitContainer.Panel1.Controls.Add(this.btnMesh);
+ //
+ // splitContainer.Panel2
+ //
+ this.splitContainer.Panel2.BackColor = System.Drawing.Color.Black;
+ this.splitContainer.Size = new System.Drawing.Size(992, 623);
+ this.splitContainer.SplitterDistance = 280;
+ this.splitContainer.SplitterWidth = 1;
+ this.splitContainer.TabIndex = 0;
+ //
+ // btnSmooth
+ //
+ this.btnSmooth.Enabled = false;
+ this.btnSmooth.Location = new System.Drawing.Point(146, 44);
+ this.btnSmooth.Name = "btnSmooth";
+ this.btnSmooth.Size = new System.Drawing.Size(130, 23);
+ this.btnSmooth.TabIndex = 12;
+ this.btnSmooth.Text = "Smooth";
+ this.btnSmooth.UseVisualStyleBackColor = true;
+ this.btnSmooth.Click += new System.EventHandler(this.btnSmooth_Click);
+ //
+ // flatTabControl1
+ //
+ this.flatTabControl1.Alignment = System.Windows.Forms.TabAlignment.Bottom;
+ this.flatTabControl1.Controls.Add(this.tabPage1);
+ this.flatTabControl1.Controls.Add(this.tabPage2);
+ this.flatTabControl1.Controls.Add(this.tabPage3);
+ this.flatTabControl1.Location = new System.Drawing.Point(0, 73);
+ this.flatTabControl1.Name = "flatTabControl1";
+ this.flatTabControl1.SelectedIndex = 0;
+ this.flatTabControl1.Size = new System.Drawing.Size(280, 538);
+ this.flatTabControl1.TabIndex = 1;
+ //
+ // tabPage1
+ //
+ this.tabPage1.BackColor = System.Drawing.Color.DimGray;
+ this.tabPage1.Controls.Add(this.meshControlView);
+ this.tabPage1.ForeColor = System.Drawing.Color.DarkGray;
+ this.tabPage1.Location = new System.Drawing.Point(4, 4);
+ this.tabPage1.Name = "tabPage1";
+ this.tabPage1.Size = new System.Drawing.Size(272, 509);
+ this.tabPage1.TabIndex = 0;
+ this.tabPage1.Text = "Mesh Control";
+ //
+ // meshControlView
+ //
+ this.meshControlView.BackColor = System.Drawing.Color.DimGray;
+ this.meshControlView.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.meshControlView.ForeColor = System.Drawing.Color.DarkGray;
+ this.meshControlView.Location = new System.Drawing.Point(0, 0);
+ this.meshControlView.Name = "meshControlView";
+ this.meshControlView.Size = new System.Drawing.Size(272, 509);
+ this.meshControlView.TabIndex = 0;
+ //
+ // tabPage2
+ //
+ this.tabPage2.BackColor = System.Drawing.Color.DimGray;
+ this.tabPage2.Controls.Add(this.statisticView);
+ this.tabPage2.ForeColor = System.Drawing.Color.White;
+ this.tabPage2.Location = new System.Drawing.Point(4, 4);
+ this.tabPage2.Name = "tabPage2";
+ this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
+ this.tabPage2.Size = new System.Drawing.Size(272, 509);
+ this.tabPage2.TabIndex = 1;
+ this.tabPage2.Text = "Statistic";
+ //
+ // statisticView
+ //
+ this.statisticView.BackColor = System.Drawing.Color.DimGray;
+ this.statisticView.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.statisticView.ForeColor = System.Drawing.Color.DarkGray;
+ this.statisticView.Location = new System.Drawing.Point(0, 0);
+ this.statisticView.Name = "statisticView";
+ this.statisticView.Size = new System.Drawing.Size(272, 509);
+ this.statisticView.TabIndex = 0;
+ //
+ // tabPage3
+ //
+ this.tabPage3.BackColor = System.Drawing.Color.DimGray;
+ this.tabPage3.Controls.Add(this.aboutView);
+ this.tabPage3.Location = new System.Drawing.Point(4, 4);
+ this.tabPage3.Name = "tabPage3";
+ this.tabPage3.Padding = new System.Windows.Forms.Padding(3);
+ this.tabPage3.Size = new System.Drawing.Size(272, 509);
+ this.tabPage3.TabIndex = 2;
+ this.tabPage3.Text = "About";
+ //
+ // aboutView
+ //
+ this.aboutView.BackColor = System.Drawing.Color.DimGray;
+ this.aboutView.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.aboutView.ForeColor = System.Drawing.Color.DarkGray;
+ this.aboutView.Location = new System.Drawing.Point(0, 0);
+ this.aboutView.Name = "aboutView";
+ this.aboutView.Size = new System.Drawing.Size(272, 509);
+ this.aboutView.TabIndex = 0;
+ //
+ // menuStrip1
+ //
+ this.menuStrip1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
+ this.menuStrip1.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.menuStrip1.GripMargin = new System.Windows.Forms.Padding(0);
+ this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.menuFile,
+ this.menuView,
+ this.menuTools});
+ this.menuStrip1.Location = new System.Drawing.Point(0, 0);
+ this.menuStrip1.Name = "menuStrip1";
+ this.menuStrip1.Padding = new System.Windows.Forms.Padding(0);
+ this.menuStrip1.Size = new System.Drawing.Size(280, 24);
+ this.menuStrip1.TabIndex = 0;
+ this.menuStrip1.Text = "menuStrip1";
+ //
+ // menuFile
+ //
+ this.menuFile.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
+ this.menuFile.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
+ this.menuFile.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.menuFileOpen,
+ this.menuFileSave,
+ this.toolStripSeparator3,
+ this.menuFileExport,
+ this.toolStripSeparator2,
+ this.menuFileQuit});
+ this.menuFile.Name = "menuFile";
+ this.menuFile.Size = new System.Drawing.Size(37, 24);
+ this.menuFile.Text = "File";
+ //
+ // menuFileOpen
+ //
+ this.menuFileOpen.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
+ this.menuFileOpen.Name = "menuFileOpen";
+ this.menuFileOpen.Size = new System.Drawing.Size(141, 22);
+ this.menuFileOpen.Text = "Open";
+ this.menuFileOpen.Click += new System.EventHandler(this.menuFileOpen_Click);
+ //
+ // menuFileSave
+ //
+ this.menuFileSave.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
+ this.menuFileSave.Enabled = false;
+ this.menuFileSave.Name = "menuFileSave";
+ this.menuFileSave.Size = new System.Drawing.Size(141, 22);
+ this.menuFileSave.Text = "Save";
+ this.menuFileSave.Click += new System.EventHandler(this.menuFileSave_Click);
+ //
+ // toolStripSeparator3
+ //
+ this.toolStripSeparator3.Name = "toolStripSeparator3";
+ this.toolStripSeparator3.Size = new System.Drawing.Size(138, 6);
+ //
+ // menuFileExport
+ //
+ this.menuFileExport.Enabled = false;
+ this.menuFileExport.Name = "menuFileExport";
+ this.menuFileExport.Size = new System.Drawing.Size(141, 22);
+ this.menuFileExport.Text = "Export Image";
+ this.menuFileExport.Click += new System.EventHandler(this.menuFileExport_Click);
+ //
+ // toolStripSeparator2
+ //
+ this.toolStripSeparator2.Name = "toolStripSeparator2";
+ this.toolStripSeparator2.Size = new System.Drawing.Size(138, 6);
+ //
+ // menuFileQuit
+ //
+ this.menuFileQuit.Name = "menuFileQuit";
+ this.menuFileQuit.Size = new System.Drawing.Size(141, 22);
+ this.menuFileQuit.Text = "Quit";
+ this.menuFileQuit.Click += new System.EventHandler(this.menuFileQuit_Click);
+ //
+ // menuView
+ //
+ this.menuView.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.menuViewVoronoi,
+ this.toolStripSeparator1,
+ this.menuViewLog});
+ this.menuView.Name = "menuView";
+ this.menuView.Size = new System.Drawing.Size(44, 24);
+ this.menuView.Text = "View";
+ //
+ // menuViewVoronoi
+ //
+ this.menuViewVoronoi.Enabled = false;
+ this.menuViewVoronoi.Name = "menuViewVoronoi";
+ this.menuViewVoronoi.Size = new System.Drawing.Size(162, 22);
+ this.menuViewVoronoi.Text = "Voronoi Diagram";
+ this.menuViewVoronoi.Click += new System.EventHandler(this.menuViewVoronoi_Click);
+ //
+ // toolStripSeparator1
+ //
+ this.toolStripSeparator1.Name = "toolStripSeparator1";
+ this.toolStripSeparator1.Size = new System.Drawing.Size(159, 6);
+ //
+ // menuViewLog
+ //
+ this.menuViewLog.Name = "menuViewLog";
+ this.menuViewLog.Size = new System.Drawing.Size(162, 22);
+ this.menuViewLog.Text = "Show Log";
+ this.menuViewLog.Click += new System.EventHandler(this.menuViewLog_Click);
+ //
+ // menuTools
+ //
+ this.menuTools.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.menuToolsGen,
+ this.menuToolsCheck,
+ this.toolStripSeparator5,
+ this.menuToolsTopology,
+ this.toolStripSeparator4,
+ this.menuToolsRcm});
+ this.menuTools.Name = "menuTools";
+ this.menuTools.Size = new System.Drawing.Size(46, 24);
+ this.menuTools.Text = "Tools";
+ //
+ // menuToolsGen
+ //
+ this.menuToolsGen.Name = "menuToolsGen";
+ this.menuToolsGen.Size = new System.Drawing.Size(195, 22);
+ this.menuToolsGen.Text = "Input Generator";
+ this.menuToolsGen.Click += new System.EventHandler(this.menuToolsGenerator_Click);
+ //
+ // menuToolsCheck
+ //
+ this.menuToolsCheck.Enabled = false;
+ this.menuToolsCheck.Name = "menuToolsCheck";
+ this.menuToolsCheck.Size = new System.Drawing.Size(195, 22);
+ this.menuToolsCheck.Text = "Check Mesh";
+ this.menuToolsCheck.Click += new System.EventHandler(this.menuToolsCheck_Click);
+ //
+ // toolStripSeparator5
+ //
+ this.toolStripSeparator5.Name = "toolStripSeparator5";
+ this.toolStripSeparator5.Size = new System.Drawing.Size(192, 6);
+ //
+ // menuToolsTopology
+ //
+ this.menuToolsTopology.Name = "menuToolsTopology";
+ this.menuToolsTopology.Size = new System.Drawing.Size(195, 22);
+ this.menuToolsTopology.Text = "Topology Explorer";
+ this.menuToolsTopology.Click += new System.EventHandler(this.menuToolsTopology_Click);
+ //
+ // toolStripSeparator4
+ //
+ this.toolStripSeparator4.Name = "toolStripSeparator4";
+ this.toolStripSeparator4.Size = new System.Drawing.Size(192, 6);
+ //
+ // menuToolsRcm
+ //
+ this.menuToolsRcm.Enabled = false;
+ this.menuToolsRcm.Name = "menuToolsRcm";
+ this.menuToolsRcm.Size = new System.Drawing.Size(195, 22);
+ this.menuToolsRcm.Text = "Renumber nodes (RCM)";
+ this.menuToolsRcm.Click += new System.EventHandler(this.menuToolsRcm_Click);
+ //
+ // btnMesh
+ //
+ this.btnMesh.Enabled = false;
+ this.btnMesh.Location = new System.Drawing.Point(4, 44);
+ this.btnMesh.Name = "btnMesh";
+ this.btnMesh.Size = new System.Drawing.Size(130, 23);
+ this.btnMesh.TabIndex = 12;
+ this.btnMesh.Text = "Triangulate";
+ this.btnMesh.UseVisualStyleBackColor = true;
+ this.btnMesh.Click += new System.EventHandler(this.btnMesh_Click);
+ //
+ // FormMain
+ //
+ this.AllowDrop = true;
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(76)))), ((int)(((byte)(76)))), ((int)(((byte)(76)))));
+ this.ClientSize = new System.Drawing.Size(992, 623);
+ this.Controls.Add(this.splitContainer);
+ this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.KeyPreview = true;
+ this.MainMenuStrip = this.menuStrip1;
+ this.MinimumSize = new System.Drawing.Size(1000, 650);
+ this.Name = "FormMain";
+ this.Text = "Triangle.NET - Mesh Explorer";
+ this.Load += new System.EventHandler(this.Form1_Load);
+ this.ResizeBegin += new System.EventHandler(this.ResizeBeginHandler);
+ this.ResizeEnd += new System.EventHandler(this.ResizeEndHandler);
+ this.DragDrop += new System.Windows.Forms.DragEventHandler(this.frmDragDrop);
+ this.DragOver += new System.Windows.Forms.DragEventHandler(this.frmDragOver);
+ this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyUp);
+ this.Resize += new System.EventHandler(this.ResizeHandler);
+ this.splitContainer.Panel1.ResumeLayout(false);
+ this.splitContainer.Panel1.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit();
+ this.splitContainer.ResumeLayout(false);
+ this.flatTabControl1.ResumeLayout(false);
+ this.tabPage1.ResumeLayout(false);
+ this.tabPage2.ResumeLayout(false);
+ this.tabPage3.ResumeLayout(false);
+ this.menuStrip1.ResumeLayout(false);
+ this.menuStrip1.PerformLayout();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.SplitContainer splitContainer;
+ private System.Windows.Forms.MenuStrip menuStrip1;
+ private System.Windows.Forms.ToolStripMenuItem menuFile;
+ private System.Windows.Forms.ToolStripMenuItem menuFileOpen;
+ private System.Windows.Forms.ToolStripMenuItem menuFileSave;
+ private Controls.DarkTabControl flatTabControl1;
+ private System.Windows.Forms.TabPage tabPage1;
+ private System.Windows.Forms.TabPage tabPage2;
+ private Controls.DarkButton btnSmooth;
+ private Controls.DarkButton btnMesh;
+ private System.Windows.Forms.TabPage tabPage3;
+ private System.Windows.Forms.ToolStripMenuItem menuView;
+ private System.Windows.Forms.ToolStripMenuItem menuViewVoronoi;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
+ private System.Windows.Forms.ToolStripMenuItem menuViewLog;
+ private System.Windows.Forms.ToolStripMenuItem menuTools;
+ private System.Windows.Forms.ToolStripMenuItem menuToolsGen;
+ private System.Windows.Forms.ToolStripMenuItem menuToolsCheck;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
+ private System.Windows.Forms.ToolStripMenuItem menuFileQuit;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator3;
+ private System.Windows.Forms.ToolStripMenuItem menuFileExport;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator4;
+ private System.Windows.Forms.ToolStripMenuItem menuToolsRcm;
+ private Views.MeshControlView meshControlView;
+ private Views.StatisticView statisticView;
+ private Views.AboutView aboutView;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator5;
+ private System.Windows.Forms.ToolStripMenuItem menuToolsTopology;
+
+ }
+}
+
diff --git a/Triangle.NET/TestApp/FormMain.cs b/src/Triangle.Viewer/FormMain.cs
similarity index 96%
rename from Triangle.NET/TestApp/FormMain.cs
rename to src/Triangle.Viewer/FormMain.cs
index 93d652d..96191b4 100644
--- a/Triangle.NET/TestApp/FormMain.cs
+++ b/src/Triangle.Viewer/FormMain.cs
@@ -1,795 +1,795 @@
-using System;
-using System.Drawing;
-using System.IO;
-using System.Windows.Forms;
-using MeshExplorer.Controls;
-using MeshExplorer.IO;
-using TriangleNet;
-using TriangleNet.Geometry;
-using TriangleNet.Meshing;
-using TriangleNet.Meshing.Algorithm;
-using TriangleNet.Rendering;
-using TriangleNet.Smoothing;
-using TriangleNet.Voronoi;
-
-namespace MeshExplorer
-{
- public partial class FormMain : Form
- {
- Settings settings;
-
- Mesh mesh;
- IPolygon input;
- VoronoiBase voronoi;
-
- FormLog frmLog;
- FormGenerator frmGenerator;
-
- RenderManager renderManager;
-
- public FormMain()
- {
- InitializeComponent();
-
- ToolStripManager.Renderer = new DarkToolStripRenderer();
- }
-
- private void Form1_Load(object sender, EventArgs e)
- {
- oldClientSize = this.ClientSize;
-
- settings = new Settings();
-
- renderManager = new RenderManager();
-
- IRenderControl control = new TriangleNet.Rendering.GDI.RenderControl();
-
- /*
- if (!renderManager.TryCreateControl("Triangle.Rendering.SharpGL.dll",
- new string[] { "SharpGL.dll" }, out control))
- {
- control = new TriangleNet.Rendering.GDI.RenderControl();
-
- if (frmLog == null)
- {
- frmLog = new FormLog();
- }
-
- frmLog.AddItem("Failed to initialize OpenGL.", true);
- }
- //*/
-
- if (control != null)
- {
- InitializeRenderControl((Control)control);
- renderManager.Initialize(control);
- }
- else
- {
- DarkMessageBox.Show("Ooops ...", "Failed to initialize renderer.");
- }
- }
-
- private void InitializeRenderControl(Control control)
- {
- this.splitContainer.SuspendLayout();
- this.splitContainer.Panel2.Controls.Add(control);
-
- var size = this.splitContainer.Panel2.ClientRectangle;
-
- // Initialize control
- control.BackColor = Color.Black;
- control.Dock = DockStyle.Fill;
- control.Font = new Font("Consolas", 8.25F, FontStyle.Regular, GraphicsUnit.Point, ((byte)(0)));
- control.Location = new System.Drawing.Point(0, 0);
- control.Name = "renderControl1";
- control.Size = new Size(size.Width, size.Height);
- control.TabIndex = 0;
- control.Text = "renderControl1";
-
- this.splitContainer.ResumeLayout();
- }
-
- protected override void OnMouseWheel(MouseEventArgs e)
- {
- if (splitContainer.Panel2.Bounds.Contains(e.Location))
- {
- var control = renderManager.Control as Control;
-
- // Set focus on the render control.
- if (control != null && !control.Focused)
- {
- control.Focus();
- }
- }
- }
-
- private void Form1_KeyUp(object sender, KeyEventArgs e)
- {
- switch (e.KeyCode)
- {
- case Keys.F3:
- OpenWithDialog();
- break;
- case Keys.F4:
- Save();
- break;
- case Keys.F5:
- Reload();
- break;
- case Keys.F8:
- TriangulateOrRefine();
- break;
- case Keys.F9:
- Smooth();
- break;
- case Keys.F12:
- ShowLog();
- break;
- }
- }
-
- void frmGenerator_InputGenerated(object sender, EventArgs e)
- {
- this.input = sender as IPolygon;
-
- if (input != null)
- {
- settings.CurrentFile = "tmp-" + DateTime.Now.ToString("HH-mm-ss");
- HandleNewInput();
- }
- }
-
- private void btnMesh_Click(object sender, EventArgs e)
- {
- TriangulateOrRefine();
- }
-
- private void btnSmooth_Click(object sender, EventArgs e)
- {
- Smooth();
- }
-
- #region Drag and drop
-
- private void frmDragDrop(object sender, DragEventArgs e)
- {
- if (e.Data.GetDataPresent(DataFormats.FileDrop))
- {
- string[] args = (string[])e.Data.GetData(DataFormats.FileDrop);
-
- Open(args[0]);
- }
- }
-
- private void frmDragOver(object sender, DragEventArgs e)
- {
- if (e.Data.GetDataPresent(DataFormats.FileDrop))
- {
- string[] args = (string[])e.Data.GetData(DataFormats.FileDrop);
-
- if (args.Length > 1)
- {
- e.Effect = DragDropEffects.None;
- return;
- }
-
- string file = args[0].ToLower();
-
- // Check if file extension is known
- if (FileProcessor.CanHandleFile(file))
- {
- e.Effect = DragDropEffects.Copy;
- }
- }
- else
- {
- e.Effect = DragDropEffects.None;
- }
- }
-
- #endregion
-
- #region Resize event handler
-
- bool isResizing = false;
- Size oldClientSize;
-
- private void ResizeHandler(object sender, EventArgs e)
- {
- // Handle window minimize and maximize
- if (!isResizing)
- {
- renderManager.Resize();
- }
- }
-
- private void ResizeEndHandler(object sender, EventArgs e)
- {
- isResizing = false;
-
- if (this.ClientSize != this.oldClientSize)
- {
- this.oldClientSize = this.ClientSize;
- renderManager.Resize();
- }
- }
-
- private void ResizeBeginHandler(object sender, EventArgs e)
- {
- isResizing = true;
- }
-
- #endregion
-
- #region State changes
-
- private void LockOnException()
- {
- btnMesh.Enabled = false;
- btnSmooth.Enabled = false;
-
- //menuFileSave.Enabled = false;
- //menuFileExport.Enabled = false;
- menuViewVoronoi.Enabled = false;
- menuToolsCheck.Enabled = false;
- menuToolsRcm.Enabled = false;
-
- settings.ExceptionThrown = true;
- }
-
- private void HandleNewInput()
- {
- // Reset mesh
- mesh = null;
- voronoi = null;
-
- // Reset state
- settings.RefineMode = false;
- settings.ExceptionThrown = false;
-
- // Reset buttons
- btnMesh.Enabled = true;
- btnMesh.Text = "Triangulate";
- btnSmooth.Enabled = false;
-
- // Update Statistic view
- statisticView.HandleNewInput(input);
-
- // Clear voronoi
- menuViewVoronoi.Checked = false;
-
- // Disable menu items
- menuFileSave.Enabled = false;
- menuFileExport.Enabled = false;
- menuViewVoronoi.Enabled = false;
- menuToolsCheck.Enabled = false;
- menuToolsRcm.Enabled = false;
-
- // Render input
- renderManager.Set(input);
-
- // Update window caption
- this.Text = "Triangle.NET - Mesh Explorer - " + settings.CurrentFile;
- }
-
- private void HandleMeshImport()
- {
- voronoi = null;
-
- // Render mesh
- renderManager.Set(mesh, true);
-
- // Update window caption
- this.Text = "Triangle.NET - Mesh Explorer - " + settings.CurrentFile;
-
- // Update Statistic view
- statisticView.HandleMeshImport(input, mesh);
-
- // Set refine mode
- btnMesh.Enabled = true;
- btnMesh.Text = "Refine";
-
- settings.RefineMode = true;
-
- HandleMeshChange();
- }
-
- private void HandleMeshUpdate()
- {
- // Render mesh
- renderManager.Set(mesh, false);
-
- // Update Statistic view
- statisticView.HandleMeshUpdate(mesh);
-
- HandleMeshChange();
- }
-
- private void HandleMeshChange()
- {
- // Update Statistic view
- statisticView.HandleMeshChange(mesh);
-
- // TODO: Should the Voronoi diagram automatically update?
- voronoi = null;
- menuViewVoronoi.Checked = false;
-
- // Enable menu items
- menuFileSave.Enabled = true;
- menuFileExport.Enabled = true;
- menuViewVoronoi.Enabled = true;
- menuToolsCheck.Enabled = true;
- menuToolsRcm.Enabled = true;
- }
-
- #endregion
-
- #region Commands
-
- private void OpenWithDialog()
- {
- OpenFileDialog ofd = new OpenFileDialog();
-
- ofd.Filter = settings.OfdFilter;
- ofd.FilterIndex = settings.OfdFilterIndex;
- ofd.InitialDirectory = settings.OfdDirectory;
- ofd.FileName = "";
-
- if (ofd.ShowDialog() == DialogResult.OK)
- {
- if (Open(ofd.FileName))
- {
- // Update folder settings
- settings.OfdFilterIndex = ofd.FilterIndex;
- settings.OfdDirectory = Path.GetDirectoryName(ofd.FileName);
- }
- }
- }
-
- private bool Open(string filename)
- {
- if (!FileProcessor.CanHandleFile(filename))
- {
- // TODO: show message.
- }
- else
- {
- if (FileProcessor.ContainsMeshData(filename))
- {
- if (filename.EndsWith(".ele") || DarkMessageBox.Show("Import mesh", Settings.ImportString,
- "Do you want to import the mesh?", MessageBoxButtons.YesNo) == DialogResult.OK)
- {
- input = null;
-
- try
- {
- mesh = FileProcessor.Import(filename);
- }
- catch (Exception e)
- {
- DarkMessageBox.Show("Import mesh error", e.Message, MessageBoxButtons.OK);
- return false;
- }
-
- if (mesh != null)
- {
- statisticView.UpdateStatistic(mesh);
-
- // Update settings
- settings.CurrentFile = Path.GetFileName(filename);
-
- HandleMeshImport();
- btnSmooth.Enabled = true; // TODO: Remove
- }
- // else Message
-
- return true;
- }
- }
-
- input = FileProcessor.Read(filename);
- }
-
- if (input != null)
- {
- // Update settings
- settings.CurrentFile = Path.GetFileName(filename);
-
- HandleNewInput();
- }
- // else Message
-
- return true;
- }
-
- private void Save()
- {
- SaveFileDialog sfd = new SaveFileDialog();
-
- sfd.Filter = settings.SfdFilter;
- sfd.FilterIndex = settings.SfdFilterIndex;
- sfd.InitialDirectory = settings.SfdDirectory;
- sfd.FileName = "";
-
- if (sfd.ShowDialog() == DialogResult.OK)
- {
- FileProcessor.Save(sfd.FileName, mesh);
- }
- }
-
- private void Reload()
- {
- if (input != null)
- {
- mesh = null;
- settings.RefineMode = false;
- settings.ExceptionThrown = false;
-
- HandleNewInput();
- }
- }
-
- private void TriangulateOrRefine()
- {
- if ((input == null && !settings.RefineMode) || settings.ExceptionThrown)
- {
- return;
- }
-
- if (settings.RefineMode == false)
- {
- Triangulate();
-
- if (meshControlView.ParamQualityChecked)
- {
- btnMesh.Text = "Refine";
- btnSmooth.Enabled = mesh.IsPolygon;
- }
- }
- else if (meshControlView.ParamQualityChecked)
- {
- Refine();
- }
- }
-
- private void Triangulate()
- {
- if (input == null) return;
-
- var options = new ConstraintOptions();
- var quality = new QualityOptions();
-
- if (meshControlView.ParamConformDelChecked)
- {
- options.ConformingDelaunay = true;
- }
-
- if (meshControlView.ParamQualityChecked)
- {
- quality.MinimumAngle = meshControlView.ParamMinAngleValue;
-
- double maxAngle = meshControlView.ParamMaxAngleValue;
-
- if (maxAngle < 180)
- {
- quality.MaximumAngle = maxAngle;
- }
-
- // Ignore area constraints on initial triangulation.
-
- //double area = slMaxArea.Value * 0.01;
- //if (area > 0 && area < 1)
- //{
- // var size = input.Bounds;
- // double min = Math.Min(size.Width, size.Height);
- // mesh.SetOption(Options.MaxArea, area * min);
- //}
- }
-
- if (meshControlView.ParamConvexChecked)
- {
- options.Convex = true;
- }
-
- try
- {
- if (meshControlView.ParamSweeplineChecked)
- {
- mesh = (Mesh)input.Triangulate(options, quality, new SweepLine());
- }
- else
- {
- mesh = (Mesh)input.Triangulate(options, quality);
- }
-
- statisticView.UpdateStatistic(mesh);
-
- HandleMeshUpdate();
-
- if (meshControlView.ParamQualityChecked)
- {
- settings.RefineMode = true;
- }
- }
- catch (Exception ex)
- {
- LockOnException();
- DarkMessageBox.Show("Exception - Triangulate", ex.Message, MessageBoxButtons.OK);
- }
-
- UpdateLog();
- }
-
- private void Refine()
- {
- if (mesh == null) return;
-
- double area = meshControlView.ParamMaxAreaValue;
-
- var quality = new QualityOptions();
-
- if (area > 0 && area < 1)
- {
- quality.MaximumArea = area * statisticView.Statistic.LargestArea;
- }
-
- quality.MinimumAngle = meshControlView.ParamMinAngleValue;
-
- double maxAngle = meshControlView.ParamMaxAngleValue;
-
- if (maxAngle < 180)
- {
- quality.MaximumAngle = maxAngle;
- }
-
- try
- {
- mesh.Refine(quality, meshControlView.ParamConformDelChecked);
-
- statisticView.UpdateStatistic(mesh);
-
- HandleMeshUpdate();
- }
- catch (Exception ex)
- {
- LockOnException();
- DarkMessageBox.Show("Exception - Refine", ex.Message, MessageBoxButtons.OK);
- }
-
- UpdateLog();
- }
-
- private void Renumber()
- {
- if (mesh == null || settings.ExceptionThrown) return;
-
- bool tmp = Log.Verbose;
- Log.Verbose = true;
-
- mesh.Renumber(NodeNumbering.CuthillMcKee);
- ShowLog();
-
- Log.Verbose = tmp;
- }
-
- private void Smooth()
- {
- if (mesh == null || settings.ExceptionThrown) return;
-
- if (!mesh.IsPolygon)
- {
- return;
- }
-
- var smoother = new SimpleSmoother();
-
- try
- {
- smoother.Smooth(this.mesh);
-
- statisticView.UpdateStatistic(mesh);
-
- HandleMeshUpdate();
- }
- catch (Exception ex)
- {
- LockOnException();
- DarkMessageBox.Show("Exception - Smooth", ex.Message, MessageBoxButtons.OK);
- }
-
- UpdateLog();
- }
-
- private bool CreateVoronoi()
- {
- if (mesh == null)
- {
- return false;
- }
-
- if (mesh.IsPolygon)
- {
- try
- {
- this.voronoi = new BoundedVoronoi(mesh);
- }
- catch (Exception ex)
- {
- if (!meshControlView.ParamConformDelChecked)
- {
- DarkMessageBox.Show("Exception - Bounded Voronoi", Settings.VoronoiString, MessageBoxButtons.OK);
- }
- else
- {
- DarkMessageBox.Show("Exception - Bounded Voronoi", ex.Message, MessageBoxButtons.OK);
- }
-
- return false;
- }
- }
- else
- {
- this.voronoi = new StandardVoronoi(mesh);
- }
-
- // HACK: List -> ICollection ? Nope, no way.
- // Vertex[] -> ICollection ? Well, ok.
- renderManager.Set(voronoi.Vertices.ToArray(), voronoi.Edges, false);
-
- return true;
- }
-
- private void ShowLog()
- {
- if (frmLog == null)
- {
- frmLog = new FormLog();
- }
-
- UpdateLog();
-
- if (!frmLog.Visible)
- {
- frmLog.Show(this);
- }
- }
-
- private void UpdateLog()
- {
- if (frmLog != null)
- {
- frmLog.UpdateItems();
- }
- }
-
- #endregion
-
- #region Menu Handler
-
- private void menuFileOpen_Click(object sender, EventArgs e)
- {
- OpenWithDialog();
- }
-
- private void menuFileSave_Click(object sender, EventArgs ev)
- {
- if (mesh != null)
- {
- Save();
- }
- }
-
- private void menuFileExport_Click(object sender, EventArgs e)
- {
- if (mesh != null)
- {
- FormExport export = new FormExport();
-
- string file = settings.OfdDirectory;
-
- if (!file.EndsWith("\\"))
- {
- file += "\\";
- }
-
- file += settings.CurrentFile;
-
- export.ImageName = Path.ChangeExtension(file, ".png");
-
- if (export.ShowDialog() == DialogResult.OK)
- {
- int format = export.ImageFormat;
- int size = export.ImageSize;
- bool compress = export.UseCompression;
-
- var writer = new ImageWriter();
-
- writer.Export(this.mesh, export.ImageName, format, size, compress);
- }
- }
- }
-
- private void menuFileQuit_Click(object sender, EventArgs e)
- {
- this.Close();
- }
-
- private void menuViewVoronoi_Click(object sender, EventArgs e)
- {
- if (this.voronoi == null)
- {
- menuViewVoronoi.Checked = CreateVoronoi();
- }
- else
- {
- bool visible = menuViewVoronoi.Checked;
-
- renderManager.Enable(4, !visible);
- menuViewVoronoi.Checked = !visible;
- }
- }
-
- private void menuViewLog_Click(object sender, EventArgs e)
- {
- ShowLog();
- }
-
- private void menuToolsGenerator_Click(object sender, EventArgs e)
- {
- if (frmGenerator == null || frmGenerator.IsDisposed)
- {
- frmGenerator = new FormGenerator();
- frmGenerator.InputGenerated += new EventHandler(frmGenerator_InputGenerated);
- }
-
- if (!frmGenerator.Visible)
- {
- frmGenerator.Show();
- }
- else
- {
- frmGenerator.Activate();
- }
- }
-
- private void menuToolsCheck_Click(object sender, EventArgs e)
- {
- if (mesh != null)
- {
- bool save = Log.Verbose;
-
- Log.Verbose = true;
-
- bool isConsistent = MeshValidator.IsConsistent(mesh);
- bool isDelaunay = MeshValidator.IsDelaunay(mesh);
-
- Log.Verbose = save;
-
- if (isConsistent)
- {
- Log.Instance.Info("Mesh topology appears to be consistent.");
- }
-
- if (isDelaunay)
- {
- Log.Instance.Info("Mesh is (conforming) Delaunay.");
- }
-
- ShowLog();
- }
- }
-
- private void menuToolsTopology_Click(object sender, EventArgs e)
- {
- (new FormTopology()).ShowDialog(this);
- }
-
- private void menuToolsRcm_Click(object sender, EventArgs e)
- {
- Renumber();
- }
-
- #endregion
- }
-}
+using System;
+using System.Drawing;
+using System.IO;
+using System.Windows.Forms;
+using MeshExplorer.Controls;
+using MeshExplorer.IO;
+using TriangleNet;
+using TriangleNet.Geometry;
+using TriangleNet.Meshing;
+using TriangleNet.Meshing.Algorithm;
+using TriangleNet.Rendering;
+using TriangleNet.Smoothing;
+using TriangleNet.Voronoi;
+
+namespace MeshExplorer
+{
+ public partial class FormMain : Form
+ {
+ Settings settings;
+
+ Mesh mesh;
+ IPolygon input;
+ VoronoiBase voronoi;
+
+ FormLog frmLog;
+ FormGenerator frmGenerator;
+
+ RenderManager renderManager;
+
+ public FormMain()
+ {
+ InitializeComponent();
+
+ ToolStripManager.Renderer = new DarkToolStripRenderer();
+ }
+
+ private void Form1_Load(object sender, EventArgs e)
+ {
+ oldClientSize = this.ClientSize;
+
+ settings = new Settings();
+
+ renderManager = new RenderManager();
+
+ IRenderControl control = new TriangleNet.Rendering.GDI.RenderControl();
+
+ /*
+ if (!renderManager.TryCreateControl("Triangle.Rendering.SharpGL.dll",
+ new string[] { "SharpGL.dll" }, out control))
+ {
+ control = new TriangleNet.Rendering.GDI.RenderControl();
+
+ if (frmLog == null)
+ {
+ frmLog = new FormLog();
+ }
+
+ frmLog.AddItem("Failed to initialize OpenGL.", true);
+ }
+ //*/
+
+ if (control != null)
+ {
+ InitializeRenderControl((Control)control);
+ renderManager.Initialize(control, new TriangleNet.Rendering.GDI.LayerRenderer());
+ }
+ else
+ {
+ DarkMessageBox.Show("Ooops ...", "Failed to initialize renderer.");
+ }
+ }
+
+ private void InitializeRenderControl(Control control)
+ {
+ this.splitContainer.SuspendLayout();
+ this.splitContainer.Panel2.Controls.Add(control);
+
+ var size = this.splitContainer.Panel2.ClientRectangle;
+
+ // Initialize control
+ control.BackColor = Color.Black;
+ control.Dock = DockStyle.Fill;
+ control.Font = new Font("Consolas", 8.25F, FontStyle.Regular, GraphicsUnit.Point, ((byte)(0)));
+ control.Location = new System.Drawing.Point(0, 0);
+ control.Name = "renderControl1";
+ control.Size = new Size(size.Width, size.Height);
+ control.TabIndex = 0;
+ control.Text = "renderControl1";
+
+ this.splitContainer.ResumeLayout();
+ }
+
+ protected override void OnMouseWheel(MouseEventArgs e)
+ {
+ if (splitContainer.Panel2.Bounds.Contains(e.Location))
+ {
+ var control = renderManager.Control as Control;
+
+ // Set focus on the render control.
+ if (control != null && !control.Focused)
+ {
+ control.Focus();
+ }
+ }
+ }
+
+ private void Form1_KeyUp(object sender, KeyEventArgs e)
+ {
+ switch (e.KeyCode)
+ {
+ case Keys.F3:
+ OpenWithDialog();
+ break;
+ case Keys.F4:
+ Save();
+ break;
+ case Keys.F5:
+ Reload();
+ break;
+ case Keys.F8:
+ TriangulateOrRefine();
+ break;
+ case Keys.F9:
+ Smooth();
+ break;
+ case Keys.F12:
+ ShowLog();
+ break;
+ }
+ }
+
+ void frmGenerator_InputGenerated(object sender, EventArgs e)
+ {
+ this.input = sender as IPolygon;
+
+ if (input != null)
+ {
+ settings.CurrentFile = "tmp-" + DateTime.Now.ToString("HH-mm-ss");
+ HandleNewInput();
+ }
+ }
+
+ private void btnMesh_Click(object sender, EventArgs e)
+ {
+ TriangulateOrRefine();
+ }
+
+ private void btnSmooth_Click(object sender, EventArgs e)
+ {
+ Smooth();
+ }
+
+ #region Drag and drop
+
+ private void frmDragDrop(object sender, DragEventArgs e)
+ {
+ if (e.Data.GetDataPresent(DataFormats.FileDrop))
+ {
+ string[] args = (string[])e.Data.GetData(DataFormats.FileDrop);
+
+ Open(args[0]);
+ }
+ }
+
+ private void frmDragOver(object sender, DragEventArgs e)
+ {
+ if (e.Data.GetDataPresent(DataFormats.FileDrop))
+ {
+ string[] args = (string[])e.Data.GetData(DataFormats.FileDrop);
+
+ if (args.Length > 1)
+ {
+ e.Effect = DragDropEffects.None;
+ return;
+ }
+
+ string file = args[0].ToLower();
+
+ // Check if file extension is known
+ if (FileProcessor.CanHandleFile(file))
+ {
+ e.Effect = DragDropEffects.Copy;
+ }
+ }
+ else
+ {
+ e.Effect = DragDropEffects.None;
+ }
+ }
+
+ #endregion
+
+ #region Resize event handler
+
+ bool isResizing = false;
+ Size oldClientSize;
+
+ private void ResizeHandler(object sender, EventArgs e)
+ {
+ // Handle window minimize and maximize
+ if (!isResizing)
+ {
+ renderManager.Resize();
+ }
+ }
+
+ private void ResizeEndHandler(object sender, EventArgs e)
+ {
+ isResizing = false;
+
+ if (this.ClientSize != this.oldClientSize)
+ {
+ this.oldClientSize = this.ClientSize;
+ renderManager.Resize();
+ }
+ }
+
+ private void ResizeBeginHandler(object sender, EventArgs e)
+ {
+ isResizing = true;
+ }
+
+ #endregion
+
+ #region State changes
+
+ private void LockOnException()
+ {
+ btnMesh.Enabled = false;
+ btnSmooth.Enabled = false;
+
+ //menuFileSave.Enabled = false;
+ //menuFileExport.Enabled = false;
+ menuViewVoronoi.Enabled = false;
+ menuToolsCheck.Enabled = false;
+ menuToolsRcm.Enabled = false;
+
+ settings.ExceptionThrown = true;
+ }
+
+ private void HandleNewInput()
+ {
+ // Reset mesh
+ mesh = null;
+ voronoi = null;
+
+ // Reset state
+ settings.RefineMode = false;
+ settings.ExceptionThrown = false;
+
+ // Reset buttons
+ btnMesh.Enabled = true;
+ btnMesh.Text = "Triangulate";
+ btnSmooth.Enabled = false;
+
+ // Update Statistic view
+ statisticView.HandleNewInput(input);
+
+ // Clear voronoi
+ menuViewVoronoi.Checked = false;
+
+ // Disable menu items
+ menuFileSave.Enabled = false;
+ menuFileExport.Enabled = false;
+ menuViewVoronoi.Enabled = false;
+ menuToolsCheck.Enabled = false;
+ menuToolsRcm.Enabled = false;
+
+ // Render input
+ renderManager.Set(input);
+
+ // Update window caption
+ this.Text = "Triangle.NET - Mesh Explorer - " + settings.CurrentFile;
+ }
+
+ private void HandleMeshImport()
+ {
+ voronoi = null;
+
+ // Render mesh
+ renderManager.Set(mesh, true);
+
+ // Update window caption
+ this.Text = "Triangle.NET - Mesh Explorer - " + settings.CurrentFile;
+
+ // Update Statistic view
+ statisticView.HandleMeshImport(input, mesh);
+
+ // Set refine mode
+ btnMesh.Enabled = true;
+ btnMesh.Text = "Refine";
+
+ settings.RefineMode = true;
+
+ HandleMeshChange();
+ }
+
+ private void HandleMeshUpdate()
+ {
+ // Render mesh
+ renderManager.Set(mesh, false);
+
+ // Update Statistic view
+ statisticView.HandleMeshUpdate(mesh);
+
+ HandleMeshChange();
+ }
+
+ private void HandleMeshChange()
+ {
+ // Update Statistic view
+ statisticView.HandleMeshChange(mesh);
+
+ // TODO: Should the Voronoi diagram automatically update?
+ voronoi = null;
+ menuViewVoronoi.Checked = false;
+
+ // Enable menu items
+ menuFileSave.Enabled = true;
+ menuFileExport.Enabled = true;
+ menuViewVoronoi.Enabled = true;
+ menuToolsCheck.Enabled = true;
+ menuToolsRcm.Enabled = true;
+ }
+
+ #endregion
+
+ #region Commands
+
+ private void OpenWithDialog()
+ {
+ OpenFileDialog ofd = new OpenFileDialog();
+
+ ofd.Filter = settings.OfdFilter;
+ ofd.FilterIndex = settings.OfdFilterIndex;
+ ofd.InitialDirectory = settings.OfdDirectory;
+ ofd.FileName = "";
+
+ if (ofd.ShowDialog() == DialogResult.OK)
+ {
+ if (Open(ofd.FileName))
+ {
+ // Update folder settings
+ settings.OfdFilterIndex = ofd.FilterIndex;
+ settings.OfdDirectory = Path.GetDirectoryName(ofd.FileName);
+ }
+ }
+ }
+
+ private bool Open(string filename)
+ {
+ if (!FileProcessor.CanHandleFile(filename))
+ {
+ // TODO: show message.
+ }
+ else
+ {
+ if (FileProcessor.ContainsMeshData(filename))
+ {
+ if (filename.EndsWith(".ele") || DarkMessageBox.Show("Import mesh", Settings.ImportString,
+ "Do you want to import the mesh?", MessageBoxButtons.YesNo) == DialogResult.OK)
+ {
+ input = null;
+
+ try
+ {
+ mesh = FileProcessor.Import(filename);
+ }
+ catch (Exception e)
+ {
+ DarkMessageBox.Show("Import mesh error", e.Message, MessageBoxButtons.OK);
+ return false;
+ }
+
+ if (mesh != null)
+ {
+ statisticView.UpdateStatistic(mesh);
+
+ // Update settings
+ settings.CurrentFile = Path.GetFileName(filename);
+
+ HandleMeshImport();
+ btnSmooth.Enabled = true; // TODO: Remove
+ }
+ // else Message
+
+ return true;
+ }
+ }
+
+ input = FileProcessor.Read(filename);
+ }
+
+ if (input != null)
+ {
+ // Update settings
+ settings.CurrentFile = Path.GetFileName(filename);
+
+ HandleNewInput();
+ }
+ // else Message
+
+ return true;
+ }
+
+ private void Save()
+ {
+ SaveFileDialog sfd = new SaveFileDialog();
+
+ sfd.Filter = settings.SfdFilter;
+ sfd.FilterIndex = settings.SfdFilterIndex;
+ sfd.InitialDirectory = settings.SfdDirectory;
+ sfd.FileName = "";
+
+ if (sfd.ShowDialog() == DialogResult.OK)
+ {
+ FileProcessor.Save(sfd.FileName, mesh);
+ }
+ }
+
+ private void Reload()
+ {
+ if (input != null)
+ {
+ mesh = null;
+ settings.RefineMode = false;
+ settings.ExceptionThrown = false;
+
+ HandleNewInput();
+ }
+ }
+
+ private void TriangulateOrRefine()
+ {
+ if ((input == null && !settings.RefineMode) || settings.ExceptionThrown)
+ {
+ return;
+ }
+
+ if (settings.RefineMode == false)
+ {
+ Triangulate();
+
+ if (meshControlView.ParamQualityChecked)
+ {
+ btnMesh.Text = "Refine";
+ btnSmooth.Enabled = mesh.IsPolygon;
+ }
+ }
+ else if (meshControlView.ParamQualityChecked)
+ {
+ Refine();
+ }
+ }
+
+ private void Triangulate()
+ {
+ if (input == null) return;
+
+ var options = new ConstraintOptions();
+ var quality = new QualityOptions();
+
+ if (meshControlView.ParamConformDelChecked)
+ {
+ options.ConformingDelaunay = true;
+ }
+
+ if (meshControlView.ParamQualityChecked)
+ {
+ quality.MinimumAngle = meshControlView.ParamMinAngleValue;
+
+ double maxAngle = meshControlView.ParamMaxAngleValue;
+
+ if (maxAngle < 180)
+ {
+ quality.MaximumAngle = maxAngle;
+ }
+
+ // Ignore area constraints on initial triangulation.
+
+ //double area = slMaxArea.Value * 0.01;
+ //if (area > 0 && area < 1)
+ //{
+ // var size = input.Bounds;
+ // double min = Math.Min(size.Width, size.Height);
+ // mesh.SetOption(Options.MaxArea, area * min);
+ //}
+ }
+
+ if (meshControlView.ParamConvexChecked)
+ {
+ options.Convex = true;
+ }
+
+ try
+ {
+ if (meshControlView.ParamSweeplineChecked)
+ {
+ mesh = (Mesh)input.Triangulate(options, quality, new SweepLine());
+ }
+ else
+ {
+ mesh = (Mesh)input.Triangulate(options, quality);
+ }
+
+ statisticView.UpdateStatistic(mesh);
+
+ HandleMeshUpdate();
+
+ if (meshControlView.ParamQualityChecked)
+ {
+ settings.RefineMode = true;
+ }
+ }
+ catch (Exception ex)
+ {
+ LockOnException();
+ DarkMessageBox.Show("Exception - Triangulate", ex.Message, MessageBoxButtons.OK);
+ }
+
+ UpdateLog();
+ }
+
+ private void Refine()
+ {
+ if (mesh == null) return;
+
+ double area = meshControlView.ParamMaxAreaValue;
+
+ var quality = new QualityOptions();
+
+ if (area > 0 && area < 1)
+ {
+ quality.MaximumArea = area * statisticView.Statistic.LargestArea;
+ }
+
+ quality.MinimumAngle = meshControlView.ParamMinAngleValue;
+
+ double maxAngle = meshControlView.ParamMaxAngleValue;
+
+ if (maxAngle < 180)
+ {
+ quality.MaximumAngle = maxAngle;
+ }
+
+ try
+ {
+ mesh.Refine(quality, meshControlView.ParamConformDelChecked);
+
+ statisticView.UpdateStatistic(mesh);
+
+ HandleMeshUpdate();
+ }
+ catch (Exception ex)
+ {
+ LockOnException();
+ DarkMessageBox.Show("Exception - Refine", ex.Message, MessageBoxButtons.OK);
+ }
+
+ UpdateLog();
+ }
+
+ private void Renumber()
+ {
+ if (mesh == null || settings.ExceptionThrown) return;
+
+ bool tmp = Log.Verbose;
+ Log.Verbose = true;
+
+ mesh.Renumber(NodeNumbering.CuthillMcKee);
+ ShowLog();
+
+ Log.Verbose = tmp;
+ }
+
+ private void Smooth()
+ {
+ if (mesh == null || settings.ExceptionThrown) return;
+
+ if (!mesh.IsPolygon)
+ {
+ return;
+ }
+
+ var smoother = new SimpleSmoother();
+
+ try
+ {
+ smoother.Smooth(this.mesh);
+
+ statisticView.UpdateStatistic(mesh);
+
+ HandleMeshUpdate();
+ }
+ catch (Exception ex)
+ {
+ LockOnException();
+ DarkMessageBox.Show("Exception - Smooth", ex.Message, MessageBoxButtons.OK);
+ }
+
+ UpdateLog();
+ }
+
+ private bool CreateVoronoi()
+ {
+ if (mesh == null)
+ {
+ return false;
+ }
+
+ if (mesh.IsPolygon)
+ {
+ try
+ {
+ this.voronoi = new BoundedVoronoi(mesh);
+ }
+ catch (Exception ex)
+ {
+ if (!meshControlView.ParamConformDelChecked)
+ {
+ DarkMessageBox.Show("Exception - Bounded Voronoi", Settings.VoronoiString, MessageBoxButtons.OK);
+ }
+ else
+ {
+ DarkMessageBox.Show("Exception - Bounded Voronoi", ex.Message, MessageBoxButtons.OK);
+ }
+
+ return false;
+ }
+ }
+ else
+ {
+ this.voronoi = new StandardVoronoi(mesh);
+ }
+
+ // HACK: List -> ICollection ? Nope, no way.
+ // Vertex[] -> ICollection ? Well, ok.
+ renderManager.Set(voronoi.Vertices.ToArray(), voronoi.Edges, false);
+
+ return true;
+ }
+
+ private void ShowLog()
+ {
+ if (frmLog == null)
+ {
+ frmLog = new FormLog();
+ }
+
+ UpdateLog();
+
+ if (!frmLog.Visible)
+ {
+ frmLog.Show(this);
+ }
+ }
+
+ private void UpdateLog()
+ {
+ if (frmLog != null)
+ {
+ frmLog.UpdateItems();
+ }
+ }
+
+ #endregion
+
+ #region Menu Handler
+
+ private void menuFileOpen_Click(object sender, EventArgs e)
+ {
+ OpenWithDialog();
+ }
+
+ private void menuFileSave_Click(object sender, EventArgs ev)
+ {
+ if (mesh != null)
+ {
+ Save();
+ }
+ }
+
+ private void menuFileExport_Click(object sender, EventArgs e)
+ {
+ if (mesh != null)
+ {
+ FormExport export = new FormExport();
+
+ string file = settings.OfdDirectory;
+
+ if (!file.EndsWith("\\"))
+ {
+ file += "\\";
+ }
+
+ file += settings.CurrentFile;
+
+ export.ImageName = Path.ChangeExtension(file, ".png");
+
+ if (export.ShowDialog() == DialogResult.OK)
+ {
+ int format = export.ImageFormat;
+ int size = export.ImageSize;
+ bool compress = export.UseCompression;
+
+ var writer = new ImageWriter();
+
+ writer.Export(this.mesh, export.ImageName, format, size, compress);
+ }
+ }
+ }
+
+ private void menuFileQuit_Click(object sender, EventArgs e)
+ {
+ this.Close();
+ }
+
+ private void menuViewVoronoi_Click(object sender, EventArgs e)
+ {
+ if (this.voronoi == null)
+ {
+ menuViewVoronoi.Checked = CreateVoronoi();
+ }
+ else
+ {
+ bool visible = menuViewVoronoi.Checked;
+
+ renderManager.Enable(4, !visible);
+ menuViewVoronoi.Checked = !visible;
+ }
+ }
+
+ private void menuViewLog_Click(object sender, EventArgs e)
+ {
+ ShowLog();
+ }
+
+ private void menuToolsGenerator_Click(object sender, EventArgs e)
+ {
+ if (frmGenerator == null || frmGenerator.IsDisposed)
+ {
+ frmGenerator = new FormGenerator();
+ frmGenerator.InputGenerated += new EventHandler(frmGenerator_InputGenerated);
+ }
+
+ if (!frmGenerator.Visible)
+ {
+ frmGenerator.Show();
+ }
+ else
+ {
+ frmGenerator.Activate();
+ }
+ }
+
+ private void menuToolsCheck_Click(object sender, EventArgs e)
+ {
+ if (mesh != null)
+ {
+ bool save = Log.Verbose;
+
+ Log.Verbose = true;
+
+ bool isConsistent = MeshValidator.IsConsistent(mesh);
+ bool isDelaunay = MeshValidator.IsDelaunay(mesh);
+
+ Log.Verbose = save;
+
+ if (isConsistent)
+ {
+ Log.Instance.Info("Mesh topology appears to be consistent.");
+ }
+
+ if (isDelaunay)
+ {
+ Log.Instance.Info("Mesh is (conforming) Delaunay.");
+ }
+
+ ShowLog();
+ }
+ }
+
+ private void menuToolsTopology_Click(object sender, EventArgs e)
+ {
+ (new FormTopology()).ShowDialog(this);
+ }
+
+ private void menuToolsRcm_Click(object sender, EventArgs e)
+ {
+ Renumber();
+ }
+
+ #endregion
+ }
+}
diff --git a/Triangle.NET/TestApp/FormMain.resx b/src/Triangle.Viewer/FormMain.resx
similarity index 97%
rename from Triangle.NET/TestApp/FormMain.resx
rename to src/Triangle.Viewer/FormMain.resx
index 0f6d8eb..d5494e3 100644
--- a/Triangle.NET/TestApp/FormMain.resx
+++ b/src/Triangle.Viewer/FormMain.resx
@@ -1,123 +1,123 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- 17, 17
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
\ No newline at end of file
diff --git a/Triangle.NET/TestApp/FormTopology.Designer.cs b/src/Triangle.Viewer/FormTopology.Designer.cs
similarity index 97%
rename from Triangle.NET/TestApp/FormTopology.Designer.cs
rename to src/Triangle.Viewer/FormTopology.Designer.cs
index 5d95f85..0d2c35d 100644
--- a/Triangle.NET/TestApp/FormTopology.Designer.cs
+++ b/src/Triangle.Viewer/FormTopology.Designer.cs
@@ -1,112 +1,112 @@
-namespace MeshExplorer
-{
- partial class FormTopology
- {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- this.splitContainer1 = new System.Windows.Forms.SplitContainer();
- this.renderControl = new MeshExplorer.Topology.TopologyRenderControl();
- this.topoControlView = new MeshExplorer.Topology.TopologyControlView();
- ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
- this.splitContainer1.Panel1.SuspendLayout();
- this.splitContainer1.Panel2.SuspendLayout();
- this.splitContainer1.SuspendLayout();
- this.SuspendLayout();
- //
- // splitContainer1
- //
- this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
- this.splitContainer1.IsSplitterFixed = true;
- this.splitContainer1.Location = new System.Drawing.Point(0, 0);
- this.splitContainer1.Name = "splitContainer1";
- //
- // splitContainer1.Panel1
- //
- this.splitContainer1.Panel1.Controls.Add(this.renderControl);
- //
- // splitContainer1.Panel2
- //
- this.splitContainer1.Panel2.Controls.Add(this.topoControlView);
- this.splitContainer1.Size = new System.Drawing.Size(674, 455);
- this.splitContainer1.SplitterDistance = 475;
- this.splitContainer1.SplitterWidth = 1;
- this.splitContainer1.TabIndex = 0;
- //
- // renderControl
- //
- this.renderControl.BackColor = System.Drawing.Color.Black;
- this.renderControl.Dock = System.Windows.Forms.DockStyle.Fill;
- this.renderControl.Location = new System.Drawing.Point(0, 0);
- this.renderControl.Name = "renderControl";
- this.renderControl.Size = new System.Drawing.Size(475, 455);
- this.renderControl.TabIndex = 0;
- this.renderControl.Text = "topologyRenderControl";
- this.renderControl.MouseClick += new System.Windows.Forms.MouseEventHandler(this.renderControl_MouseClick);
- //
- // topoControlView
- //
- this.topoControlView.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(76)))), ((int)(((byte)(76)))), ((int)(((byte)(76)))));
- this.topoControlView.Dock = System.Windows.Forms.DockStyle.Fill;
- this.topoControlView.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.topoControlView.ForeColor = System.Drawing.Color.White;
- this.topoControlView.Location = new System.Drawing.Point(0, 0);
- this.topoControlView.Name = "topoControlView";
- this.topoControlView.Size = new System.Drawing.Size(198, 455);
- this.topoControlView.TabIndex = 2;
- //
- // FormTopology
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(76)))), ((int)(((byte)(76)))), ((int)(((byte)(76)))));
- this.ClientSize = new System.Drawing.Size(674, 455);
- this.Controls.Add(this.splitContainer1);
- this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.ForeColor = System.Drawing.Color.White;
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
- this.MaximizeBox = false;
- this.MinimizeBox = false;
- this.Name = "FormTopology";
- this.ShowIcon = false;
- this.ShowInTaskbar = false;
- this.Text = "Triangle.NET - Topology Explorer";
- this.Load += new System.EventHandler(this.FormTopology_Load);
- this.splitContainer1.Panel1.ResumeLayout(false);
- this.splitContainer1.Panel2.ResumeLayout(false);
- ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
- this.splitContainer1.ResumeLayout(false);
- this.ResumeLayout(false);
-
- }
-
- #endregion
-
- private System.Windows.Forms.SplitContainer splitContainer1;
- private Topology.TopologyRenderControl renderControl;
- private Topology.TopologyControlView topoControlView;
- }
+namespace MeshExplorer
+{
+ partial class FormTopology
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.splitContainer1 = new System.Windows.Forms.SplitContainer();
+ this.renderControl = new MeshExplorer.Topology.TopologyRenderControl();
+ this.topoControlView = new MeshExplorer.Topology.TopologyControlView();
+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
+ this.splitContainer1.Panel1.SuspendLayout();
+ this.splitContainer1.Panel2.SuspendLayout();
+ this.splitContainer1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // splitContainer1
+ //
+ this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.splitContainer1.IsSplitterFixed = true;
+ this.splitContainer1.Location = new System.Drawing.Point(0, 0);
+ this.splitContainer1.Name = "splitContainer1";
+ //
+ // splitContainer1.Panel1
+ //
+ this.splitContainer1.Panel1.Controls.Add(this.renderControl);
+ //
+ // splitContainer1.Panel2
+ //
+ this.splitContainer1.Panel2.Controls.Add(this.topoControlView);
+ this.splitContainer1.Size = new System.Drawing.Size(674, 455);
+ this.splitContainer1.SplitterDistance = 475;
+ this.splitContainer1.SplitterWidth = 1;
+ this.splitContainer1.TabIndex = 0;
+ //
+ // renderControl
+ //
+ this.renderControl.BackColor = System.Drawing.Color.Black;
+ this.renderControl.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.renderControl.Location = new System.Drawing.Point(0, 0);
+ this.renderControl.Name = "renderControl";
+ this.renderControl.Size = new System.Drawing.Size(475, 455);
+ this.renderControl.TabIndex = 0;
+ this.renderControl.Text = "topologyRenderControl";
+ this.renderControl.MouseClick += new System.Windows.Forms.MouseEventHandler(this.renderControl_MouseClick);
+ //
+ // topoControlView
+ //
+ this.topoControlView.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(76)))), ((int)(((byte)(76)))), ((int)(((byte)(76)))));
+ this.topoControlView.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.topoControlView.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.topoControlView.ForeColor = System.Drawing.Color.White;
+ this.topoControlView.Location = new System.Drawing.Point(0, 0);
+ this.topoControlView.Name = "topoControlView";
+ this.topoControlView.Size = new System.Drawing.Size(198, 455);
+ this.topoControlView.TabIndex = 2;
+ //
+ // FormTopology
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(76)))), ((int)(((byte)(76)))), ((int)(((byte)(76)))));
+ this.ClientSize = new System.Drawing.Size(674, 455);
+ this.Controls.Add(this.splitContainer1);
+ this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.ForeColor = System.Drawing.Color.White;
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "FormTopology";
+ this.ShowIcon = false;
+ this.ShowInTaskbar = false;
+ this.Text = "Triangle.NET - Topology Explorer";
+ this.Load += new System.EventHandler(this.FormTopology_Load);
+ this.splitContainer1.Panel1.ResumeLayout(false);
+ this.splitContainer1.Panel2.ResumeLayout(false);
+ ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
+ this.splitContainer1.ResumeLayout(false);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.SplitContainer splitContainer1;
+ private Topology.TopologyRenderControl renderControl;
+ private Topology.TopologyControlView topoControlView;
+ }
}
\ No newline at end of file
diff --git a/Triangle.NET/TestApp/FormTopology.cs b/src/Triangle.Viewer/FormTopology.cs
similarity index 86%
rename from Triangle.NET/TestApp/FormTopology.cs
rename to src/Triangle.Viewer/FormTopology.cs
index 3600993..bc09e0d 100644
--- a/Triangle.NET/TestApp/FormTopology.cs
+++ b/src/Triangle.Viewer/FormTopology.cs
@@ -1,114 +1,113 @@
-using System;
-using System.Windows.Forms;
-using MeshExplorer.Topology;
-using TriangleNet;
-using TriangleNet.Geometry;
-using TriangleNet.Meshing;
-using TriangleNet.Tools;
-using TriangleNet.Topology;
-
-namespace MeshExplorer
-{
- public partial class FormTopology : Form
- {
- Mesh mesh;
- TriangleQuadTree tree;
- Otri current;
-
- public FormTopology()
- {
- InitializeComponent();
- }
-
- private void FormTopology_Load(object sender, EventArgs e)
- {
- mesh = (Mesh)GenericMesher.StructuredMesh(new Rectangle(0.0, 0.0, 4.0, 4.0), 4, 4);
-
- renderControl.Initialize(mesh);
-
- topoControlView.PrimitiveCommandInvoked += PrimitiveCommandHandler;
-
- current = default(Otri);
- }
-
- void PrimitiveCommandHandler(object sender, GenericEventArgs e)
- {
- if (current.Triangle != null)
- {
- InvokePrimitive(e.Argument);
- }
- }
-
- private void renderControl_MouseClick(object sender, MouseEventArgs e)
- {
- var p = e.Location;
- var size = renderControl.Size;
-
- var tri = FindTriangleAt(((float)p.X) / size.Width, ((float)p.Y) / size.Height);
-
- current.Triangle = (Triangle)tri;
-
- renderControl.Update(current);
- topoControlView.SetTriangle(current.Triangle);
- }
-
- private ITriangle FindTriangleAt(float x, float y)
- {
- // Get mesh coordinates
- var p = new System.Drawing.PointF(x, y);
- renderControl.Zoom.ScreenToWorld(ref p);
-
- topoControlView.SetPosition(p);
-
- if (tree == null)
- {
- tree = new TriangleQuadTree(mesh, 5, 2);
- }
-
- return tree.Query(p.X, p.Y);
- }
-
- private void InvokePrimitive(string name)
- {
- if (name == "sym")
- {
- current.Sym();
- }
- else if (name == "lnext")
- {
- current.Lnext();
- }
- else if (name == "lprev")
- {
- current.Lprev();
- }
- else if (name == "onext")
- {
- current.Onext();
- }
- else if (name == "oprev")
- {
- current.Oprev();
- }
- else if (name == "dnext")
- {
- current.Dnext();
- }
- else if (name == "dprev")
- {
- current.Dprev();
- }
- else if (name == "rnext")
- {
- current.Rnext();
- }
- else if (name == "rprev")
- {
- current.Rprev();
- }
-
- renderControl.Update(current);
- topoControlView.SetTriangle(current.Triangle);
- }
- }
-}
+using System;
+using System.Windows.Forms;
+using TriangleNet;
+using TriangleNet.Geometry;
+using TriangleNet.Meshing;
+using TriangleNet.Tools;
+using TriangleNet.Topology;
+
+namespace MeshExplorer
+{
+ public partial class FormTopology : Form
+ {
+ Mesh mesh;
+ TriangleQuadTree tree;
+ Otri current;
+
+ public FormTopology()
+ {
+ InitializeComponent();
+ }
+
+ private void FormTopology_Load(object sender, EventArgs e)
+ {
+ mesh = (Mesh)GenericMesher.StructuredMesh(new Rectangle(0.0, 0.0, 4.0, 4.0), 4, 4);
+
+ renderControl.Initialize(mesh);
+
+ topoControlView.PrimitiveCommandInvoked += PrimitiveCommandHandler;
+
+ current = default(Otri);
+ }
+
+ void PrimitiveCommandHandler(object sender, GenericEventArgs e)
+ {
+ if (current.Triangle != null)
+ {
+ InvokePrimitive(e.Argument);
+ }
+ }
+
+ private void renderControl_MouseClick(object sender, MouseEventArgs e)
+ {
+ var p = e.Location;
+ var size = renderControl.Size;
+
+ var tri = FindTriangleAt(((float)p.X) / size.Width, ((float)p.Y) / size.Height);
+
+ current.Triangle = (Triangle)tri;
+
+ renderControl.Update(current);
+ topoControlView.SetTriangle(current.Triangle);
+ }
+
+ private ITriangle FindTriangleAt(float xr, float yr)
+ {
+ // Get mesh coordinates
+ var p = new System.Drawing.PointF(xr, yr);
+ renderControl.Zoom.ScreenToWorld(p, out double x, out double y);
+
+ topoControlView.SetPosition(x, y);
+
+ if (tree == null)
+ {
+ tree = new TriangleQuadTree(mesh, 5, 2);
+ }
+
+ return tree.Query(x, y);
+ }
+
+ private void InvokePrimitive(string name)
+ {
+ if (name == "sym")
+ {
+ current.Sym();
+ }
+ else if (name == "lnext")
+ {
+ current.Lnext();
+ }
+ else if (name == "lprev")
+ {
+ current.Lprev();
+ }
+ else if (name == "onext")
+ {
+ current.Onext();
+ }
+ else if (name == "oprev")
+ {
+ current.Oprev();
+ }
+ else if (name == "dnext")
+ {
+ current.Dnext();
+ }
+ else if (name == "dprev")
+ {
+ current.Dprev();
+ }
+ else if (name == "rnext")
+ {
+ current.Rnext();
+ }
+ else if (name == "rprev")
+ {
+ current.Rprev();
+ }
+
+ renderControl.Update(current);
+ topoControlView.SetTriangle(current.Triangle);
+ }
+ }
+}
diff --git a/Triangle.NET/TestApp/FormTopology.resx b/src/Triangle.Viewer/FormTopology.resx
similarity index 97%
rename from Triangle.NET/TestApp/FormTopology.resx
rename to src/Triangle.Viewer/FormTopology.resx
index 29dcb1b..1af7de1 100644
--- a/Triangle.NET/TestApp/FormTopology.resx
+++ b/src/Triangle.Viewer/FormTopology.resx
@@ -1,120 +1,120 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
\ No newline at end of file
diff --git a/Triangle.NET/TestApp/Generators/BaseGenerator.cs b/src/Triangle.Viewer/Generators/BaseGenerator.cs
similarity index 96%
rename from Triangle.NET/TestApp/Generators/BaseGenerator.cs
rename to src/Triangle.Viewer/Generators/BaseGenerator.cs
index 48d231d..6ded8ab 100644
--- a/Triangle.NET/TestApp/Generators/BaseGenerator.cs
+++ b/src/Triangle.Viewer/Generators/BaseGenerator.cs
@@ -1,158 +1,158 @@
-// -----------------------------------------------------------------------
-//
-// TODO: Update copyright text.
-//
-// -----------------------------------------------------------------------
-
-namespace MeshExplorer.Generators
-{
- using System;
- using System.Collections.Generic;
- using TriangleNet.Geometry;
-
- ///
- /// TODO: Update summary.
- ///
- public abstract class BaseGenerator : IGenerator
- {
- private static int MAX_PARAMS = 3;
-
- protected string name = "Name";
- protected string description = "Description";
- protected int parameter = 0;
-
- protected string[] descriptions = new string[MAX_PARAMS];
- protected int[][] ranges = new int[MAX_PARAMS][];
-
- public virtual string Name { get { return name; } }
- public virtual string Description { get { return description; } }
- public virtual int ParameterCount { get { return parameter; } }
-
- public virtual string ParameterDescription(int paramIndex)
- {
- if (descriptions[paramIndex] == null)
- {
- return String.Empty;
- }
-
- return descriptions[paramIndex];
- }
-
- public virtual string ParameterDescription(int paramIndex, double paramValue)
- {
- int[] range = ranges[paramIndex];
-
- if (range == null)
- {
- return String.Empty;
- }
-
- int num = GetParamValueInt(paramIndex, paramValue);
- return num.ToString();
- }
-
- public abstract IPolygon Generate(double param0, double param1, double param2);
-
- #region Contour helpers
-
- protected List CreateCircle(double r, int n, int boundary = 0)
- {
- return CreateCircle(0.0, 0.0, r, n, boundary);
- }
-
- protected List CreateCircle(double x, double y, double r, int n, int boundary = 0)
- {
- return CreateEllipse(0.0, 0.0, r, 1.0, 1.0, n, boundary);
- }
-
- protected List CreateEllipse(double r, double a, double b, int n, int boundary = 0)
- {
- return CreateEllipse(0.0, 0.0, r, a, b, n, boundary);
- }
-
- protected List CreateEllipse(double x, double y, double r, double a, double b, int n, int boundary = 0)
- {
- var contour = new List(n);
-
- double dphi = 2 * Math.PI / n;
-
- for (int i = 0; i < n; i++)
- {
- contour.Add(new Vertex(x + a * r * Math.Cos(i * dphi), y + b * r * Math.Sin(i * dphi), boundary));
- }
-
- return contour;
- }
-
- protected List CreateRectangle(Rectangle rect, int n, int boundary = 0)
- {
- return CreateRectangle(rect, n, n, boundary);
- }
-
- protected List CreateRectangle(Rectangle rect, int nH, int nV, int boundary = 0)
- {
- var contour = new List(2 * nH + 2 * nV);
-
- // Horizontal and vertical step sizes.
- double stepH = rect.Width / nH;
- double stepV = rect.Height / nV;
-
- // Left box boundary points
- for (int i = 0; i < nV; i++)
- {
- contour.Add(new Vertex(rect.Left, rect.Bottom + i * stepV, 1));
- }
-
- // Top box boundary points
- for (int i = 0; i < nH; i++)
- {
- contour.Add(new Vertex(rect.Left + i * stepH, rect.Top, 1));
- }
-
- // Right box boundary points
- for (int i = 0; i < nV; i++)
- {
- contour.Add(new Vertex(rect.Right, rect.Top - i * stepV, 1));
- }
-
- // Bottom box boundary points
- for (int i = 0; i < nH; i++)
- {
- contour.Add(new Vertex(rect.Right - i * stepH, rect.Bottom, 1));
- }
-
- return contour;
- }
-
- #endregion
-
- protected int GetParamValueInt(int paramIndex, double paramOffset)
- {
- int[] range = ranges[paramIndex];
-
- if (range == null)
- {
- return 0;
- }
-
- return (int)((range[1] - range[0]) / 100.0 * paramOffset + range[0]);
- }
-
- protected double GetParamValueDouble(int paramIndex, double paramOffset)
- {
- int[] range = ranges[paramIndex];
-
- if (range == null)
- {
- return 0;
- }
-
- return ((range[1] - range[0]) / 100.0 * paramOffset + range[0]);
- }
-
- public override string ToString()
- {
- return this.Name;
- }
- }
-}
+// -----------------------------------------------------------------------
+//
+// TODO: Update copyright text.
+//
+// -----------------------------------------------------------------------
+
+namespace MeshExplorer.Generators
+{
+ using System;
+ using System.Collections.Generic;
+ using TriangleNet.Geometry;
+
+ ///
+ /// TODO: Update summary.
+ ///
+ public abstract class BaseGenerator : IGenerator
+ {
+ private static int MAX_PARAMS = 3;
+
+ protected string name = "Name";
+ protected string description = "Description";
+ protected int parameter = 0;
+
+ protected string[] descriptions = new string[MAX_PARAMS];
+ protected int[][] ranges = new int[MAX_PARAMS][];
+
+ public virtual string Name { get { return name; } }
+ public virtual string Description { get { return description; } }
+ public virtual int ParameterCount { get { return parameter; } }
+
+ public virtual string ParameterDescription(int paramIndex)
+ {
+ if (descriptions[paramIndex] == null)
+ {
+ return String.Empty;
+ }
+
+ return descriptions[paramIndex];
+ }
+
+ public virtual string ParameterDescription(int paramIndex, double paramValue)
+ {
+ int[] range = ranges[paramIndex];
+
+ if (range == null)
+ {
+ return String.Empty;
+ }
+
+ int num = GetParamValueInt(paramIndex, paramValue);
+ return num.ToString();
+ }
+
+ public abstract IPolygon Generate(double param0, double param1, double param2);
+
+ #region Contour helpers
+
+ protected List CreateCircle(double r, int n, int boundary = 0)
+ {
+ return CreateCircle(0.0, 0.0, r, n, boundary);
+ }
+
+ protected List CreateCircle(double x, double y, double r, int n, int boundary = 0)
+ {
+ return CreateEllipse(0.0, 0.0, r, 1.0, 1.0, n, boundary);
+ }
+
+ protected List CreateEllipse(double r, double a, double b, int n, int boundary = 0)
+ {
+ return CreateEllipse(0.0, 0.0, r, a, b, n, boundary);
+ }
+
+ protected List CreateEllipse(double x, double y, double r, double a, double b, int n, int boundary = 0)
+ {
+ var contour = new List(n);
+
+ double dphi = 2 * Math.PI / n;
+
+ for (int i = 0; i < n; i++)
+ {
+ contour.Add(new Vertex(x + a * r * Math.Cos(i * dphi), y + b * r * Math.Sin(i * dphi), boundary));
+ }
+
+ return contour;
+ }
+
+ protected List CreateRectangle(Rectangle rect, int n, int boundary = 0)
+ {
+ return CreateRectangle(rect, n, n, boundary);
+ }
+
+ protected List CreateRectangle(Rectangle rect, int nH, int nV, int boundary = 0)
+ {
+ var contour = new List(2 * nH + 2 * nV);
+
+ // Horizontal and vertical step sizes.
+ double stepH = rect.Width / nH;
+ double stepV = rect.Height / nV;
+
+ // Left box boundary points
+ for (int i = 0; i < nV; i++)
+ {
+ contour.Add(new Vertex(rect.Left, rect.Bottom + i * stepV, 1));
+ }
+
+ // Top box boundary points
+ for (int i = 0; i < nH; i++)
+ {
+ contour.Add(new Vertex(rect.Left + i * stepH, rect.Top, 1));
+ }
+
+ // Right box boundary points
+ for (int i = 0; i < nV; i++)
+ {
+ contour.Add(new Vertex(rect.Right, rect.Top - i * stepV, 1));
+ }
+
+ // Bottom box boundary points
+ for (int i = 0; i < nH; i++)
+ {
+ contour.Add(new Vertex(rect.Right - i * stepH, rect.Bottom, 1));
+ }
+
+ return contour;
+ }
+
+ #endregion
+
+ protected int GetParamValueInt(int paramIndex, double paramOffset)
+ {
+ int[] range = ranges[paramIndex];
+
+ if (range == null)
+ {
+ return 0;
+ }
+
+ return (int)((range[1] - range[0]) / 100.0 * paramOffset + range[0]);
+ }
+
+ protected double GetParamValueDouble(int paramIndex, double paramOffset)
+ {
+ int[] range = ranges[paramIndex];
+
+ if (range == null)
+ {
+ return 0;
+ }
+
+ return ((range[1] - range[0]) / 100.0 * paramOffset + range[0]);
+ }
+
+ public override string ToString()
+ {
+ return this.Name;
+ }
+ }
+}
diff --git a/Triangle.NET/TestApp/Generators/BoxWithHole.cs b/src/Triangle.Viewer/Generators/BoxWithHole.cs
similarity index 86%
rename from Triangle.NET/TestApp/Generators/BoxWithHole.cs
rename to src/Triangle.Viewer/Generators/BoxWithHole.cs
index 2a08cd7..dedc425 100644
--- a/Triangle.NET/TestApp/Generators/BoxWithHole.cs
+++ b/src/Triangle.Viewer/Generators/BoxWithHole.cs
@@ -1,51 +1,51 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace MeshExplorer.Generators
-{
- using System;
- using TriangleNet.Geometry;
-
- ///
- /// Generates a star contained in a box.
- ///
- public class BoxWithHole : BaseGenerator
- {
- public BoxWithHole()
- {
- name = "Box with Hole";
- description = "";
- parameter = 3;
-
- descriptions[0] = "Points on box sides:";
- descriptions[1] = "Points on hole:";
- descriptions[2] = "Radius:";
-
- ranges[0] = new int[] { 5, 50 };
- ranges[1] = new int[] { 10, 200 };
- ranges[2] = new int[] { 5, 20 };
- }
-
- public override IPolygon Generate(double param0, double param1, double param2)
- {
- int n = GetParamValueInt(1, param1);
-
- var input = new Polygon(n + 4);
-
- double r = GetParamValueInt(2, param2);
-
- // Generate circle (hole)
- input.AddContour(CreateCircle(r, n, 1), 1, new Point(0, 0));
-
- n = GetParamValueInt(0, param0);
-
- // Generate box
- input.AddContour(CreateRectangle(new Rectangle(-50, -50, 100, 100), n, 2), 2);
-
- return input;
- }
- }
-}
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+//
+// -----------------------------------------------------------------------
+
+namespace MeshExplorer.Generators
+{
+ using System;
+ using TriangleNet.Geometry;
+
+ ///
+ /// Generates a star contained in a box.
+ ///
+ public class BoxWithHole : BaseGenerator
+ {
+ public BoxWithHole()
+ {
+ name = "Box with Hole";
+ description = "";
+ parameter = 3;
+
+ descriptions[0] = "Points on box sides:";
+ descriptions[1] = "Points on hole:";
+ descriptions[2] = "Radius:";
+
+ ranges[0] = new int[] { 5, 50 };
+ ranges[1] = new int[] { 10, 200 };
+ ranges[2] = new int[] { 5, 20 };
+ }
+
+ public override IPolygon Generate(double param0, double param1, double param2)
+ {
+ int n = GetParamValueInt(1, param1);
+
+ var input = new Polygon(n + 4);
+
+ double r = GetParamValueInt(2, param2);
+
+ // Generate circle (hole)
+ input.Add(new Contour(CreateCircle(r, n, 1), 1), new Point(0, 0));
+
+ n = GetParamValueInt(0, param0);
+
+ // Generate box
+ input.Add(new Contour(CreateRectangle(new Rectangle(-50, -50, 100, 100), n, 2), 2));
+
+ return input;
+ }
+ }
+}
diff --git a/Triangle.NET/TestApp/Generators/CircleWithHole.cs b/src/Triangle.Viewer/Generators/CircleWithHole.cs
similarity index 85%
rename from Triangle.NET/TestApp/Generators/CircleWithHole.cs
rename to src/Triangle.Viewer/Generators/CircleWithHole.cs
index d0e5325..22dad3d 100644
--- a/Triangle.NET/TestApp/Generators/CircleWithHole.cs
+++ b/src/Triangle.Viewer/Generators/CircleWithHole.cs
@@ -1,64 +1,64 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace MeshExplorer.Generators
-{
- using TriangleNet.Geometry;
-
- ///
- /// Generates a ring polygon.
- ///
- public class CircleWithHole : BaseGenerator
- {
- public CircleWithHole()
- {
- name = "Circle with Hole";
- description = "";
- parameter = 2;
-
- descriptions[0] = "Number of points:";
- descriptions[1] = "Outer radius:";
-
- ranges[0] = new int[] { 100, 250 };
- ranges[1] = new int[] { 2, 15 };
- }
-
- public override IPolygon Generate(double param0, double param1, double param2)
- {
- // Number of points on the outer circle
- int n = GetParamValueInt(0, param0);
-
- double radius = GetParamValueInt(1, param1);
-
- // Current radius and step size
- double r, h = radius / n;
-
- var input = new Polygon(n + 1);
-
- // Inner cirlce (radius = 1) (hole)
- r = 1;
- input.AddContour(CreateCircle(r, (int)(r / h), 1), 1, new Point(0, 0));
-
- // Center cirlce
- r = (radius + 1.0) / 2.0;
- input.AddContour(CreateCircle(r, (int)(r / h), 2), 2);
-
- //count = input.Count;
-
- // Outer cirlce
- r = radius;
- input.AddContour(CreateCircle(r, (int)(r / h), 3), 3);
-
- // Regions: |++++++|++++++|---|
- // r 1 0
-
- input.Regions.Add(new RegionPointer((r + 3.0) / 4.0, 0, 1));
- input.Regions.Add(new RegionPointer((3 * r + 1.0) / 4.0, 0, 2));
-
- return input;
- }
- }
-}
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+//
+// -----------------------------------------------------------------------
+
+namespace MeshExplorer.Generators
+{
+ using TriangleNet.Geometry;
+
+ ///
+ /// Generates a ring polygon.
+ ///
+ public class CircleWithHole : BaseGenerator
+ {
+ public CircleWithHole()
+ {
+ name = "Circle with Hole";
+ description = "";
+ parameter = 2;
+
+ descriptions[0] = "Number of points:";
+ descriptions[1] = "Outer radius:";
+
+ ranges[0] = new int[] { 100, 250 };
+ ranges[1] = new int[] { 2, 15 };
+ }
+
+ public override IPolygon Generate(double param0, double param1, double param2)
+ {
+ // Number of points on the outer circle
+ int n = GetParamValueInt(0, param0);
+
+ double radius = GetParamValueInt(1, param1);
+
+ // Current radius and step size
+ double r, h = radius / n;
+
+ var input = new Polygon(n + 1);
+
+ // Inner cirlce (radius = 1) (hole)
+ r = 1;
+ input.Add(new Contour(CreateCircle(r, (int)(r / h), 1), 1), new Point(0, 0));
+
+ // Center cirlce
+ r = (radius + 1.0) / 2.0;
+ input.Add(new Contour(CreateCircle(r, (int)(r / h), 2), 2));
+
+ //count = input.Count;
+
+ // Outer cirlce
+ r = radius;
+ input.Add(new Contour(CreateCircle(r, (int)(r / h), 3), 3));
+
+ // Regions: |++++++|++++++|---|
+ // r 1 0
+
+ input.Regions.Add(new RegionPointer((r + 3.0) / 4.0, 0, 1));
+ input.Regions.Add(new RegionPointer((3 * r + 1.0) / 4.0, 0, 2));
+
+ return input;
+ }
+ }
+}
diff --git a/Triangle.NET/TestApp/Generators/IGenerator.cs b/src/Triangle.Viewer/Generators/IGenerator.cs
similarity index 97%
rename from Triangle.NET/TestApp/Generators/IGenerator.cs
rename to src/Triangle.Viewer/Generators/IGenerator.cs
index 116ae45..1f7498f 100644
--- a/Triangle.NET/TestApp/Generators/IGenerator.cs
+++ b/src/Triangle.Viewer/Generators/IGenerator.cs
@@ -1,23 +1,23 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace MeshExplorer.Generators
-{
- using TriangleNet.Geometry;
-
- ///
- /// Interface for generating input geometries.
- ///
- public interface IGenerator
- {
- string Name { get; }
- string Description { get; }
- int ParameterCount { get; }
- string ParameterDescription(int paramIndex);
- string ParameterDescription(int paramIndex, double paramValue);
- IPolygon Generate(double param1, double param2, double param3);
- }
-}
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+//
+// -----------------------------------------------------------------------
+
+namespace MeshExplorer.Generators
+{
+ using TriangleNet.Geometry;
+
+ ///
+ /// Interface for generating input geometries.
+ ///
+ public interface IGenerator
+ {
+ string Name { get; }
+ string Description { get; }
+ int ParameterCount { get; }
+ string ParameterDescription(int paramIndex);
+ string ParameterDescription(int paramIndex, double paramValue);
+ IPolygon Generate(double param1, double param2, double param3);
+ }
+}
diff --git a/Triangle.NET/TestApp/Generators/RandomPoints.cs b/src/Triangle.Viewer/Generators/RandomPoints.cs
similarity index 96%
rename from Triangle.NET/TestApp/Generators/RandomPoints.cs
rename to src/Triangle.Viewer/Generators/RandomPoints.cs
index f0441f5..3dcb82c 100644
--- a/Triangle.NET/TestApp/Generators/RandomPoints.cs
+++ b/src/Triangle.Viewer/Generators/RandomPoints.cs
@@ -1,55 +1,55 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace MeshExplorer.Generators
-{
- using TriangleNet.Geometry;
-
- ///
- /// Simple random points generator.
- ///
- public class RandomPoints : BaseGenerator
- {
- public RandomPoints()
- {
- name = "Random Points";
- description = "";
- parameter = 3;
-
- descriptions[0] = "Number of points:";
- descriptions[1] = "Width:";
- descriptions[2] = "Height:";
-
- ranges[0] = new int[] { 10, 5000 };
- ranges[1] = new int[] { 10, 200 };
- ranges[2] = new int[] { 10, 200 };
- }
-
- public override IPolygon Generate(double param0, double param1, double param2)
- {
- int numPoints = GetParamValueInt(0, param0);
- numPoints = (numPoints / 10) * 10;
-
- if (numPoints < ranges[0][0])
- {
- numPoints = ranges[0][0];
- }
-
- var input = new Polygon(numPoints);
-
- int width = GetParamValueInt(1, param1);
- int height = GetParamValueInt(2, param2);
-
- for (int i = 0; i < numPoints; i++)
- {
- input.Add(new Vertex(Util.Random.NextDouble() * width,
- Util.Random.NextDouble() * height));
- }
-
- return input;
- }
- }
-}
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+//
+// -----------------------------------------------------------------------
+
+namespace MeshExplorer.Generators
+{
+ using TriangleNet.Geometry;
+
+ ///
+ /// Simple random points generator.
+ ///
+ public class RandomPoints : BaseGenerator
+ {
+ public RandomPoints()
+ {
+ name = "Random Points";
+ description = "";
+ parameter = 3;
+
+ descriptions[0] = "Number of points:";
+ descriptions[1] = "Width:";
+ descriptions[2] = "Height:";
+
+ ranges[0] = new int[] { 10, 5000 };
+ ranges[1] = new int[] { 10, 200 };
+ ranges[2] = new int[] { 10, 200 };
+ }
+
+ public override IPolygon Generate(double param0, double param1, double param2)
+ {
+ int numPoints = GetParamValueInt(0, param0);
+ numPoints = (numPoints / 10) * 10;
+
+ if (numPoints < ranges[0][0])
+ {
+ numPoints = ranges[0][0];
+ }
+
+ var input = new Polygon(numPoints);
+
+ int width = GetParamValueInt(1, param1);
+ int height = GetParamValueInt(2, param2);
+
+ for (int i = 0; i < numPoints; i++)
+ {
+ input.Add(new Vertex(Util.Random.NextDouble() * width,
+ Util.Random.NextDouble() * height));
+ }
+
+ return input;
+ }
+ }
+}
diff --git a/Triangle.NET/TestApp/Generators/RandomPointsCircle.cs b/src/Triangle.Viewer/Generators/RandomPointsCircle.cs
similarity index 96%
rename from Triangle.NET/TestApp/Generators/RandomPointsCircle.cs
rename to src/Triangle.Viewer/Generators/RandomPointsCircle.cs
index 7dd3ef7..d988f9e 100644
--- a/Triangle.NET/TestApp/Generators/RandomPointsCircle.cs
+++ b/src/Triangle.Viewer/Generators/RandomPointsCircle.cs
@@ -1,100 +1,100 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace MeshExplorer.Generators
-{
- using System;
- using TriangleNet.Geometry;
-
- ///
- /// Simple random points generator (points distributed in a circle).
- ///
- public class RandomPointsCircle : BaseGenerator
- {
- public RandomPointsCircle()
- {
- name = "Random Points (Circle)";
- description = "";
- parameter = 2;
-
- descriptions[0] = "Number of points:";
- descriptions[1] = "Distribution:";
-
- ranges[0] = new int[] { 5, 5000 };
- ranges[1] = new int[] { 0, 1 };
- }
-
- public override string ParameterDescription(int paramIndex, double paramValue)
- {
- if (paramIndex == 0)
- {
- int numPoints = GetParamValueInt(paramIndex, paramValue);
- numPoints = (numPoints / 10) * 10;
-
- if (numPoints < 5)
- {
- numPoints = 5;
- }
-
- return numPoints.ToString();
- }
-
- if (paramIndex == 1)
- {
- double exp = (paramValue + 10) / 100;
-
- if (exp > 1.092)
- {
- exp = 1.1;
- }
-
- return exp.ToString("0.00", Util.Nfi);
- }
-
- return "";
- }
-
- public override IPolygon Generate(double param0, double param1, double param2)
- {
- int numPoints = GetParamValueInt(0, param0);
- numPoints = (numPoints / 10) * 10;
-
- if (numPoints < 5)
- {
- numPoints = 5;
- }
-
- double exp = (param1 + 10) / 100;
-
- var input = new Polygon(numPoints);
-
- int i = 0, cNum = 2 * (int)Math.Floor(Math.Sqrt(numPoints));
-
- double r, phi, radius = 100, step = 2 * Math.PI / cNum;
-
- // Distrubute points equally on circle border
- for (; i < cNum; i++)
- {
- // Add a little error
- r = Util.Random.NextDouble();
-
- input.Add(new Vertex((radius + r) * Math.Cos(i * step),
- (radius + r) * Math.Sin(i * step)));
- }
-
- for (; i < numPoints; i++)
- {
- // Use sqrt(rand) to get normal distribution right.
- r = Math.Pow(Util.Random.NextDouble(), exp) * radius;
- phi = Util.Random.NextDouble() * Math.PI * 2;
-
- input.Add(new Vertex(r * Math.Cos(phi), r * Math.Sin(phi)));
- }
-
- return input;
- }
- }
-}
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+//
+// -----------------------------------------------------------------------
+
+namespace MeshExplorer.Generators
+{
+ using System;
+ using TriangleNet.Geometry;
+
+ ///
+ /// Simple random points generator (points distributed in a circle).
+ ///
+ public class RandomPointsCircle : BaseGenerator
+ {
+ public RandomPointsCircle()
+ {
+ name = "Random Points (Circle)";
+ description = "";
+ parameter = 2;
+
+ descriptions[0] = "Number of points:";
+ descriptions[1] = "Distribution:";
+
+ ranges[0] = new int[] { 5, 5000 };
+ ranges[1] = new int[] { 0, 1 };
+ }
+
+ public override string ParameterDescription(int paramIndex, double paramValue)
+ {
+ if (paramIndex == 0)
+ {
+ int numPoints = GetParamValueInt(paramIndex, paramValue);
+ numPoints = (numPoints / 10) * 10;
+
+ if (numPoints < 5)
+ {
+ numPoints = 5;
+ }
+
+ return numPoints.ToString();
+ }
+
+ if (paramIndex == 1)
+ {
+ double exp = (paramValue + 10) / 100;
+
+ if (exp > 1.092)
+ {
+ exp = 1.1;
+ }
+
+ return exp.ToString("0.00", Util.Nfi);
+ }
+
+ return "";
+ }
+
+ public override IPolygon Generate(double param0, double param1, double param2)
+ {
+ int numPoints = GetParamValueInt(0, param0);
+ numPoints = (numPoints / 10) * 10;
+
+ if (numPoints < 5)
+ {
+ numPoints = 5;
+ }
+
+ double exp = (param1 + 10) / 100;
+
+ var input = new Polygon(numPoints);
+
+ int i = 0, cNum = 2 * (int)Math.Floor(Math.Sqrt(numPoints));
+
+ double r, phi, radius = 100, step = 2 * Math.PI / cNum;
+
+ // Distrubute points equally on circle border
+ for (; i < cNum; i++)
+ {
+ // Add a little error
+ r = Util.Random.NextDouble();
+
+ input.Add(new Vertex((radius + r) * Math.Cos(i * step),
+ (radius + r) * Math.Sin(i * step)));
+ }
+
+ for (; i < numPoints; i++)
+ {
+ // Use sqrt(rand) to get normal distribution right.
+ r = Math.Pow(Util.Random.NextDouble(), exp) * radius;
+ phi = Util.Random.NextDouble() * Math.PI * 2;
+
+ input.Add(new Vertex(r * Math.Cos(phi), r * Math.Sin(phi)));
+ }
+
+ return input;
+ }
+ }
+}
diff --git a/Triangle.NET/TestApp/Generators/RingPolygon.cs b/src/Triangle.Viewer/Generators/RingPolygon.cs
similarity index 93%
rename from Triangle.NET/TestApp/Generators/RingPolygon.cs
rename to src/Triangle.Viewer/Generators/RingPolygon.cs
index 08ded0a..658f89a 100644
--- a/Triangle.NET/TestApp/Generators/RingPolygon.cs
+++ b/src/Triangle.Viewer/Generators/RingPolygon.cs
@@ -1,100 +1,100 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace MeshExplorer.Generators
-{
- using System;
- using System.Collections.Generic;
- using TriangleNet.Geometry;
-
- ///
- /// Generates a ring polygon.
- ///
- public class RingPolygon : BaseGenerator
- {
- public RingPolygon()
- {
- name = "Ring";
- description = "";
- parameter = 2;
-
- descriptions[0] = "Number of points:";
- descriptions[1] = "Variation:";
-
- ranges[0] = new int[] { 50, 250 };
- ranges[1] = new int[] { 0, 1 };
- }
-
- public override string ParameterDescription(int paramIndex, double paramValue)
- {
- if (paramIndex == 0)
- {
- int numRays = GetParamValueInt(paramIndex, paramValue);
- return numRays.ToString();
- }
-
- if (paramIndex == 1)
- {
- double variation = GetParamValueDouble(paramIndex, paramValue);
- return variation.ToString("0.0", Util.Nfi);
- }
-
- return "";
- }
-
- public override IPolygon Generate(double param0, double param1, double param2)
- {
- int n = GetParamValueInt(0, param0);
- int m = n / 2;
-
- var input = new Polygon(n + 1);
-
- double ro, r = 10;
- double step = 2 * Math.PI / m;
-
- var inner = new List(m);
-
- // Inner ring
- for (int i = 0; i < m; i++)
- {
- inner.Add(new Vertex(r * Math.Cos(i * step), r * Math.Sin(i * step)));
- }
-
- input.AddContour(inner, 1);
-
- r = 1.5 * r;
-
- var outer = new List(n);
-
- step = 2 * Math.PI / n;
- double offset = step / 2;
-
- // Outer ring
- for (int i = 0; i < n; i++)
- {
- ro = r;
-
- if (i % 2 == 0)
- {
- ro = r + r * Util.Random.NextDouble() * (param1 / 100);
- }
-
- outer.Add(new Vertex(ro * Math.Cos(i * step + offset), ro * Math.Sin(i * step + offset)));
- }
-
- input.AddContour(outer, 2);
-
- input.Holes.Add(new Point(0, 0));
-
- return input;
- }
-
- public override string ToString()
- {
- return this.Name;
- }
- }
-}
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+//
+// -----------------------------------------------------------------------
+
+namespace MeshExplorer.Generators
+{
+ using System;
+ using System.Collections.Generic;
+ using TriangleNet.Geometry;
+
+ ///
+ /// Generates a ring polygon.
+ ///
+ public class RingPolygon : BaseGenerator
+ {
+ public RingPolygon()
+ {
+ name = "Ring";
+ description = "";
+ parameter = 2;
+
+ descriptions[0] = "Number of points:";
+ descriptions[1] = "Variation:";
+
+ ranges[0] = new int[] { 50, 250 };
+ ranges[1] = new int[] { 0, 1 };
+ }
+
+ public override string ParameterDescription(int paramIndex, double paramValue)
+ {
+ if (paramIndex == 0)
+ {
+ int numRays = GetParamValueInt(paramIndex, paramValue);
+ return numRays.ToString();
+ }
+
+ if (paramIndex == 1)
+ {
+ double variation = GetParamValueDouble(paramIndex, paramValue);
+ return variation.ToString("0.0", Util.Nfi);
+ }
+
+ return "";
+ }
+
+ public override IPolygon Generate(double param0, double param1, double param2)
+ {
+ int n = GetParamValueInt(0, param0);
+ int m = n / 2;
+
+ var input = new Polygon(n + 1);
+
+ double ro, r = 10;
+ double step = 2 * Math.PI / m;
+
+ var inner = new List(m);
+
+ // Inner ring
+ for (int i = 0; i < m; i++)
+ {
+ inner.Add(new Vertex(r * Math.Cos(i * step), r * Math.Sin(i * step)));
+ }
+
+ input.Add(new Contour(inner, 1));
+
+ r = 1.5 * r;
+
+ var outer = new List(n);
+
+ step = 2 * Math.PI / n;
+ double offset = step / 2;
+
+ // Outer ring
+ for (int i = 0; i < n; i++)
+ {
+ ro = r;
+
+ if (i % 2 == 0)
+ {
+ ro = r + r * Util.Random.NextDouble() * (param1 / 100);
+ }
+
+ outer.Add(new Vertex(ro * Math.Cos(i * step + offset), ro * Math.Sin(i * step + offset)));
+ }
+
+ input.Add(new Contour(outer, 2));
+
+ input.Holes.Add(new Point(0, 0));
+
+ return input;
+ }
+
+ public override string ToString()
+ {
+ return this.Name;
+ }
+ }
+}
diff --git a/Triangle.NET/TestApp/Generators/StarInBox.cs b/src/Triangle.Viewer/Generators/StarInBox.cs
similarity index 96%
rename from Triangle.NET/TestApp/Generators/StarInBox.cs
rename to src/Triangle.Viewer/Generators/StarInBox.cs
index b35c68b..c95c833 100644
--- a/Triangle.NET/TestApp/Generators/StarInBox.cs
+++ b/src/Triangle.Viewer/Generators/StarInBox.cs
@@ -1,63 +1,63 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace MeshExplorer.Generators
-{
- using System;
- using TriangleNet.Geometry;
-
- ///
- /// Generates a star contained in a box.
- ///
- public class StarInBox : BaseGenerator
- {
- public StarInBox()
- {
- name = "Star in Box";
- description = "";
- parameter = 1;
-
- descriptions[0] = "Number of rays:";
-
- ranges[0] = new int[] { 3, 61 };
- }
-
- public override IPolygon Generate(double param0, double param1, double param2)
- {
- int numRays = GetParamValueInt(0, param0);
-
- var g = new Polygon(numRays + 4);
-
- g.Add(new Vertex(0, 0)); // Center
-
- double x, y, r, e, step = 2 * Math.PI / numRays;
-
- for (int i = 0; i < numRays; i++)
- {
- e = Util.Random.NextDouble() * step * 0.7;
- r = (Util.Random.NextDouble() + 0.7) * 0.5;
- x = r * Math.Cos(i * step + e);
- y = r * Math.Sin(i * step + e);
-
- g.Add(new Vertex(x, y, 2));
- g.Add(new Segment(g.Points[0], g.Points[i + 1], 2));
- }
-
- g.Add(new Vertex(-1, -1, 1)); // Box
- g.Add(new Vertex(1, -1, 1));
- g.Add(new Vertex(1, 1, 1));
- g.Add(new Vertex(-1, 1, 1));
-
- numRays = g.Count;
- g.Add(new Segment(g.Points[numRays - 1], g.Points[numRays - 2], 1));
- g.Add(new Segment(g.Points[numRays - 2], g.Points[numRays - 3], 1));
- g.Add(new Segment(g.Points[numRays - 3], g.Points[numRays - 4], 1));
- g.Add(new Segment(g.Points[numRays - 4], g.Points[numRays - 1], 1));
-
- return g;
- }
- }
-}
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+//
+// -----------------------------------------------------------------------
+
+namespace MeshExplorer.Generators
+{
+ using System;
+ using TriangleNet.Geometry;
+
+ ///
+ /// Generates a star contained in a box.
+ ///
+ public class StarInBox : BaseGenerator
+ {
+ public StarInBox()
+ {
+ name = "Star in Box";
+ description = "";
+ parameter = 1;
+
+ descriptions[0] = "Number of rays:";
+
+ ranges[0] = new int[] { 3, 61 };
+ }
+
+ public override IPolygon Generate(double param0, double param1, double param2)
+ {
+ int numRays = GetParamValueInt(0, param0);
+
+ var g = new Polygon(numRays + 4);
+
+ g.Add(new Vertex(0, 0)); // Center
+
+ double x, y, r, e, step = 2 * Math.PI / numRays;
+
+ for (int i = 0; i < numRays; i++)
+ {
+ e = Util.Random.NextDouble() * step * 0.7;
+ r = (Util.Random.NextDouble() + 0.7) * 0.5;
+ x = r * Math.Cos(i * step + e);
+ y = r * Math.Sin(i * step + e);
+
+ g.Add(new Vertex(x, y, 2));
+ g.Add(new Segment(g.Points[0], g.Points[i + 1], 2));
+ }
+
+ g.Add(new Vertex(-1, -1, 1)); // Box
+ g.Add(new Vertex(1, -1, 1));
+ g.Add(new Vertex(1, 1, 1));
+ g.Add(new Vertex(-1, 1, 1));
+
+ numRays = g.Count;
+ g.Add(new Segment(g.Points[numRays - 1], g.Points[numRays - 2], 1));
+ g.Add(new Segment(g.Points[numRays - 2], g.Points[numRays - 3], 1));
+ g.Add(new Segment(g.Points[numRays - 3], g.Points[numRays - 4], 1));
+ g.Add(new Segment(g.Points[numRays - 4], g.Points[numRays - 1], 1));
+
+ return g;
+ }
+ }
+}
diff --git a/Triangle.NET/TestApp/GenericEventArgs.cs b/src/Triangle.Viewer/GenericEventArgs.cs
similarity index 94%
rename from Triangle.NET/TestApp/GenericEventArgs.cs
rename to src/Triangle.Viewer/GenericEventArgs.cs
index 9a68171..ea43c90 100644
--- a/Triangle.NET/TestApp/GenericEventArgs.cs
+++ b/src/Triangle.Viewer/GenericEventArgs.cs
@@ -1,19 +1,19 @@
-using System;
-
-namespace MeshExplorer
-{
- public class GenericEventArgs : EventArgs
- {
- T argument;
-
- public T Argument
- {
- get { return argument; }
- }
-
- public GenericEventArgs(T arg)
- {
- argument = arg;
- }
- }
-}
+using System;
+
+namespace MeshExplorer
+{
+ public class GenericEventArgs : EventArgs
+ {
+ T argument;
+
+ public T Argument
+ {
+ get { return argument; }
+ }
+
+ public GenericEventArgs(T arg)
+ {
+ argument = arg;
+ }
+ }
+}
diff --git a/Triangle.NET/TestApp/IO/FileProcessor.cs b/src/Triangle.Viewer/IO/FileProcessor.cs
similarity index 95%
rename from Triangle.NET/TestApp/IO/FileProcessor.cs
rename to src/Triangle.Viewer/IO/FileProcessor.cs
index 353a8f4..d676664 100644
--- a/Triangle.NET/TestApp/IO/FileProcessor.cs
+++ b/src/Triangle.Viewer/IO/FileProcessor.cs
@@ -1,126 +1,125 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace MeshExplorer.IO
-{
- using System;
- using System.Collections.Generic;
- using System.IO;
- using MeshExplorer.IO.Formats;
- using TriangleNet.IO;
- using TriangleNet.Geometry;
- using TriangleNet;
-
- ///
- /// Provides static methods to read and write mesh files.
- ///
- public static class FileProcessor
- {
- static Dictionary container = new Dictionary();
-
- public static bool CanHandleFile(string path)
- {
- if (File.Exists(path))
- {
- var provider = GetProviderInstance(path);
-
- if (provider != null)
- {
- return true;
- }
- }
-
- return false;
- }
-
- ///
- /// Returns true, if the given file contains mesh information.
- ///
- ///
- ///
- public static bool ContainsMeshData(string path)
- {
- IMeshFile provider = GetProviderInstance(path);
-
- return provider.ContainsMeshData(path);
- }
-
- ///
- /// Read an input geometry from given file.
- ///
- public static IPolygon Read(string path)
- {
- var provider = GetProviderInstance(path);
-
- return provider.Read(path);
- }
-
- ///
- /// Read a mesh from given file.
- ///
- ///
- ///
- public static Mesh Import(string path)
- {
- var provider = GetProviderInstance(path);
-
- return (Mesh)provider.Import(path);
- }
-
- ///
- /// Save the current mesh to given file.
- ///
- public static void Save(string path, Mesh mesh)
- {
- IMeshFile provider = GetProviderInstance(path);
-
- provider.Write(mesh, path);
- }
-
- private static IMeshFile GetProviderInstance(string path)
- {
- string ext = Path.GetExtension(path);
-
- IMeshFile provider = null;
-
- if (container.ContainsKey(ext))
- {
- provider = container[ext];
- }
- else
- {
- provider = CreateProviderInstance(ext);
- }
-
- return provider;
- }
-
- private static IMeshFile CreateProviderInstance(string ext)
- {
- // TODO: automate by using IMeshFormat's Extensions property.
-
- IMeshFile provider = null;
-
- if (ext == ".node" || ext == ".poly" || ext == ".ele")
- {
- provider = new TriangleFile();
- }
- else if (ext == ".json")
- {
- provider = new JsonFile();
- }
-
- if (provider == null)
- {
- throw new NotImplementedException("File format not implemented.");
- }
-
- container.Add(ext, provider);
-
- return provider;
- }
- }
-}
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+//
+// -----------------------------------------------------------------------
+
+namespace MeshExplorer.IO
+{
+ using MeshExplorer.IO.Formats;
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+ using TriangleNet;
+ using TriangleNet.Geometry;
+
+ ///
+ /// Provides static methods to read and write mesh files.
+ ///
+ public static class FileProcessor
+ {
+ static Dictionary container = new Dictionary();
+
+ public static bool CanHandleFile(string path)
+ {
+ if (File.Exists(path))
+ {
+ var provider = GetProviderInstance(path);
+
+ if (provider != null)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ ///
+ /// Returns true, if the given file contains mesh information.
+ ///
+ ///
+ ///
+ public static bool ContainsMeshData(string path)
+ {
+ IMeshFile provider = GetProviderInstance(path);
+
+ return provider.ContainsMeshData(path);
+ }
+
+ ///
+ /// Read an input geometry from given file.
+ ///
+ public static IPolygon Read(string path)
+ {
+ var provider = GetProviderInstance(path);
+
+ return provider.Read(path);
+ }
+
+ ///
+ /// Read a mesh from given file.
+ ///
+ ///
+ ///
+ public static Mesh Import(string path)
+ {
+ var provider = GetProviderInstance(path);
+
+ return (Mesh)provider.Import(path);
+ }
+
+ ///
+ /// Save the current mesh to given file.
+ ///
+ public static void Save(string path, Mesh mesh)
+ {
+ IMeshFile provider = GetProviderInstance(path);
+
+ provider.Write(mesh, path);
+ }
+
+ private static IMeshFile GetProviderInstance(string path)
+ {
+ string ext = Path.GetExtension(path);
+
+ IMeshFile provider = null;
+
+ if (container.ContainsKey(ext))
+ {
+ provider = container[ext];
+ }
+ else
+ {
+ provider = CreateProviderInstance(ext);
+ }
+
+ return provider;
+ }
+
+ private static IMeshFile CreateProviderInstance(string ext)
+ {
+ // TODO: automate by using IMeshFormat's Extensions property.
+
+ IMeshFile provider = null;
+
+ if (ext == ".node" || ext == ".poly" || ext == ".ele")
+ {
+ provider = new TriangleFile();
+ }
+ else if (ext == ".json")
+ {
+ provider = new JsonFile();
+ }
+
+ if (provider == null)
+ {
+ throw new NotImplementedException("File format not implemented.");
+ }
+
+ container.Add(ext, provider);
+
+ return provider;
+ }
+ }
+}
diff --git a/Triangle.NET/TestApp/IO/Formats/JsonFile.cs b/src/Triangle.Viewer/IO/Formats/JsonFile.cs
similarity index 96%
rename from Triangle.NET/TestApp/IO/Formats/JsonFile.cs
rename to src/Triangle.Viewer/IO/Formats/JsonFile.cs
index dc37bdd..4dacc1c 100644
--- a/Triangle.NET/TestApp/IO/Formats/JsonFile.cs
+++ b/src/Triangle.Viewer/IO/Formats/JsonFile.cs
@@ -1,574 +1,574 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace MeshExplorer.IO.Formats
-{
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.IO;
- using System.Text;
- using TriangleNet;
- using TriangleNet.Topology;
- using TriangleNet.Geometry;
- using TriangleNet.IO;
- using TriangleNet.Meshing;
-
- ///
- /// Read and write JSON files.
- ///
- ///
- /// The JSON format:
- /// {
- /// "config": {
- /// "ver": 1,
- /// "type": "mesh" | "poly" | "points",
- /// "dim": 2
- /// },
- /// "points": {
- /// "data": [ p0.x, p0.y ... pn.x, pn.y ],
- /// "markers": [ ... ],
- /// "attributes": [ ... ]
- /// },
- /// "segments": {
- /// "data": [ s0(1), s0(2) ... sn(1), sn(2) ],
- /// "markers": [ ... ]
- /// },
- /// "holes": [ h0.x, h0.y ... hn.x, hn.y ],
- /// "triangles": {
- /// "data": [ t0(1), t0(2), t0(3) ... tn(1), tn(2), tn(3) ],
- /// "neighbors": [ t0.n1, t0.n2, t0.n3 ... tn.n1, tn.n2, tn.n3 ],
- /// "attributes": [ ... ]
- /// }
- /// }
- ///
- public class JsonFile : IMeshFile
- {
- string file;
- Dictionary json;
-
- ///
- /// Gets the supported file extensions.
- ///
- public string[] Extensions
- {
- get { return new string[] { ".json" }; }
- }
-
- public bool ContainsMeshData(string filename)
- {
- ParseJson(filename);
-
- if (this.json.ContainsKey("config"))
- {
- var config = this.json["config"] as Dictionary;
-
- if (config != null && config.ContainsKey("type"))
- {
- return config["type"].ToString() == "mesh";
- }
- }
-
- return false;
- }
-
- public bool IsSupported(string file)
- {
- throw new NotImplementedException();
- }
-
- public IMesh Import(string filename)
- {
- var geometry = (Polygon)this.Read(filename);
-
- List triangles = null;
-
- if (this.json.ContainsKey("triangles"))
- {
- var tri = this.json["triangles"] as Dictionary;
-
- if (tri != null)
- {
- triangles = ReadTriangles(tri, geometry.Points.Count);
- }
- }
-
- return Converter.ToMesh(geometry, triangles);
- }
-
- public void Write(IMesh mesh, string filename)
- {
- using (StreamWriter writer = new StreamWriter(filename))
- {
- int nv = mesh.Vertices.Count;
- int ns = mesh.Segments.Count;
- int nh = mesh.Holes.Count;
- int ne = mesh.Triangles.Count;
-
- writer.Write("{");
-
- // Config header
- writer.Write("\"config\":{");
- writer.Write("\"ver\":1,");
- writer.Write("\"type\":\"{0}\",", ne > 0 ? "mesh" : (ns > 0 ? "poly" : "points"));
- writer.Write("\"dim\":2");
- writer.Write("}");
-
- if (((Mesh)mesh).CurrentNumbering == NodeNumbering.None)
- {
- ((Mesh)mesh).Renumber(NodeNumbering.Linear);
- }
-
- // Write the coordinates
- if (nv > 0)
- {
- writer.Write(",");
- WritePoints((Mesh)mesh, writer, nv);
- }
-
- // Write the segments
- if (ns > 0)
- {
- writer.Write(",");
- WriteSegments(mesh.Segments, writer, ns);
- }
-
- // Write the holes
- if (nh > 0)
- {
- writer.Write(",");
- WriteHoles(mesh.Holes, writer, nh);
- }
-
- // Write the elements
- if (ne > 0)
- {
- writer.Write(",");
- WriteTriangles(mesh.Triangles, writer, ne);
- }
-
- writer.Write("}");
- }
- }
-
- public void Write(IMesh mesh, Stream stream)
- {
- throw new NotImplementedException();
- }
-
- ///
- ///
- ///
- ///
- ///
- public IPolygon Read(string filename)
- {
- ParseJson(filename);
-
- var data = new Polygon();
-
- if (json == null)
- {
- // TODO: Exception?
- return data;
- }
-
- if (json.ContainsKey("config"))
- {
-
- }
-
- int count = 0;
-
- if (json.ContainsKey("points"))
- {
- var points = json["points"] as Dictionary;
-
- if (points != null)
- {
- ReadPoints(data, points, ref count);
- }
- else
- {
- // TODO: Exception?
- return data;
- }
- }
-
- if (json.ContainsKey("segments"))
- {
- var segments = json["segments"] as Dictionary;
-
- if (segments != null)
- {
- ReadSegments(data, segments, count);
- }
- }
-
- if (json.ContainsKey("holes"))
- {
- var holes = json["holes"] as ArrayList;
-
- if (holes != null)
- {
- ReadHoles(data, holes);
- }
- }
-
- return data;
- }
-
- public void Write(IPolygon polygon, string filename)
- {
- throw new NotImplementedException();
- }
-
- public void Write(IPolygon polygon, Stream stream)
- {
- throw new NotImplementedException();
- }
-
- private void ParseJson(string filename)
- {
- if (this.json == null || this.file != filename)
- {
- this.file = filename;
-
- string content = File.ReadAllText(filename);
-
- JsonParser parser = new JsonParser(content);
- this.json = parser.Decode() as Dictionary;
- }
- }
-
- #region Read helpers
-
- private void ReadPoints(Polygon geometry, Dictionary points, ref int count)
- {
- ArrayList data = points["data"] as ArrayList;
-
- ArrayList markers = null;
- ArrayList attributes = null;
-
- if (points.ContainsKey("markers"))
- {
- markers = points["markers"] as ArrayList;
- }
-
- if (points.ContainsKey("attributes"))
- {
- attributes = points["attributes"] as ArrayList;
- }
-
- if (data != null)
- {
- int mark, n = data.Count;
-
- if (n % 2 != 0)
- {
- throw new Exception("JSON format error (points).");
- }
-
- // Number of points
- count = n / 2;
-
- for (int i = 0; i < n; i += 2)
- {
- mark = 0;
-
- if (markers != null && markers.Count == count)
- {
- mark = int.Parse(markers[i / 2].ToString());
- }
-
- geometry.Add(new Vertex(
- double.Parse(data[i].ToString(), Util.Nfi),
- double.Parse(data[i + 1].ToString(), Util.Nfi),
- mark
- ));
- }
- }
- }
-
- private void ReadSegments(Polygon geometry, Dictionary segments, int count)
- {
- ArrayList data = segments["data"] as ArrayList;
-
- ArrayList markers = null;
-
- if (segments.ContainsKey("markers"))
- {
- markers = segments["markers"] as ArrayList;
- }
-
- if (data != null)
- {
- int mark, n = data.Count;
-
- if (n % 2 != 0)
- {
- throw new Exception("JSON format error (segments).");
- }
-
- int p0, p1;
-
- throw new NotImplementedException();
- // TODO: Fix JSON format
-
- for (int i = 0; i < n; i += 2)
- {
- mark = 0;
-
- if (markers != null && markers.Count == n)
- {
- mark = int.Parse(markers[i / 2].ToString());
- }
-
- p0 = int.Parse(data[i].ToString());
- p1 = int.Parse(data[i + 1].ToString());
-
- if (p0 < 0 || p0 >= count || p1 < 0 || p1 >= count)
- {
- throw new Exception("JSON format error (segment index).");
- }
-
- //geometry.Add(new Edge(p0, p1, mark));
- }
- }
- }
-
- private void ReadHoles(Polygon geometry, ArrayList holes)
- {
- int n = holes.Count;
-
- if (n % 2 != 0)
- {
- throw new Exception("JSON format error (holes).");
- }
-
- for (int i = 0; i < n; i += 2)
- {
- geometry.Holes.Add(new Point(
- double.Parse(holes[i].ToString(), Util.Nfi),
- double.Parse(holes[i + 1].ToString(), Util.Nfi)
- ));
- }
- }
-
- private List ReadTriangles(Dictionary triangles, int points)
- {
- ArrayList data = triangles["data"] as ArrayList;
-
- ArrayList neighbors = null;
- ArrayList attributes = null;
-
- if (triangles.ContainsKey("neighbors"))
- {
- neighbors = triangles["neighbors"] as ArrayList;
- }
-
- if (triangles.ContainsKey("attributes"))
- {
- attributes = triangles["attributes"] as ArrayList;
- }
-
- List output = null;
-
- if (data != null)
- {
- int n = data.Count;
-
- if (n % 3 != 0)
- {
- throw new Exception("JSON format error (triangles).");
- }
-
- output = new List(n / 3);
-
- int p0, p1, p2, n0, n1, n2;
-
- for (int i = 0; i < n; i += 3)
- {
- p0 = int.Parse(data[i].ToString());
- p1 = int.Parse(data[i + 1].ToString());
- p2 = int.Parse(data[i + 2].ToString());
-
- n0 = n1 = n2 = -1;
-
- if (p0 < 0 || p0 >= points || p1 < 0 || p1 >= points || p2 < 0 || p2 >= points)
- {
- throw new Exception("JSON format error (triangle index).");
- }
-
- if (neighbors.Count == n)
- {
- n0 = int.Parse(neighbors[i].ToString());
- n1 = int.Parse(neighbors[i + 1].ToString());
- n2 = int.Parse(neighbors[i + 2].ToString());
- }
-
- // TODO: Set neighbors
- output.Add(new InputTriangle(p0, p1, p2));
- }
- }
-
- return output;
- }
-
- #endregion
-
- #region Write helpers
-
- private void WritePoints(Mesh mesh, StreamWriter writer, int nv)
- {
- bool useMarkers = false;
-
- StringBuilder markers;
-
- writer.Write("\"points\":{\"data\":[");
-
- if (mesh.CurrentNumbering == NodeNumbering.Linear)
- {
- markers = WritePoints(mesh.Vertices, writer, nv, useMarkers);
- }
- else
- {
- Vertex[] nodes = new Vertex[mesh.Vertices.Count];
-
- foreach (var node in mesh.Vertices)
- {
- nodes[node.ID] = node;
- }
-
- markers = WritePoints(nodes, writer, nv, useMarkers);
- }
-
- writer.Write("]");
- if (useMarkers)
- {
- writer.Write(",\"markers\":[" + markers.ToString() + "]");
- }
-
- // TODO: writer.Write(",\"attributes\":[]");
- writer.Write("}");
- }
-
- private static StringBuilder WritePoints(IEnumerable data, StreamWriter writer, int nv, bool useMarkers)
- {
- StringBuilder markers = new StringBuilder();
-
- int i = 0;
- string seperator;
- foreach (var item in data)
- {
- seperator = (i == nv - 1) ? String.Empty : ", ";
-
- writer.Write("{0},{1}{2}",
- item.X.ToString(Util.Nfi),
- item.Y.ToString(Util.Nfi), seperator);
-
- if (item.Label > 0)
- {
- useMarkers = true;
- }
-
- markers.AppendFormat("{0}{1}", item.Label, seperator);
-
- i++;
- }
-
- return markers;
- }
-
- private void WriteHoles(IEnumerable data, StreamWriter writer, int nh)
- {
- int i = 0;
-
- writer.Write("\"holes\":[");
- foreach (var item in data)
- {
- writer.Write("{0},{1}{2}",
- item.X.ToString(Util.Nfi),
- item.Y.ToString(Util.Nfi), (i == nh - 1) ? String.Empty : ", ");
-
- i++;
- }
-
- writer.Write("]");
- }
-
- private void WriteSegments(IEnumerable data, StreamWriter writer, int ns)
- {
- int i = 0;
-
- StringBuilder markers = new StringBuilder();
- bool useMarkers = false;
-
- string seperator;
-
- writer.Write("\"segments\":{\"data\":[");
- foreach (var item in data)
- {
- seperator = (i == ns - 1) ? String.Empty : ", ";
-
- writer.Write("{0},{1}{2}",
- item.P0, item.P1, seperator);
-
- if (item.Label > 0)
- {
- useMarkers = true;
- }
-
- markers.AppendFormat("{0}{1}", item.Label, seperator);
-
- i++;
- }
-
- writer.Write("]");
-
- if (useMarkers)
- {
- writer.Write(",\"markers\":[" + markers.ToString() + "]");
- }
-
- writer.Write("}");
- }
-
- private void WriteTriangles(IEnumerable data, StreamWriter writer, int ne)
- {
- int i = 0;
-
- StringBuilder neighbors = new StringBuilder();
-
- string seperator;
-
- writer.Write("\"triangles\":{\"data\":[");
- foreach (var item in data)
- {
- seperator = (i == ne - 1) ? String.Empty : ", ";
-
- writer.Write("{0},{1},{2}{3}",
- item.GetVertexID(0),
- item.GetVertexID(1),
- item.GetVertexID(2),
- seperator);
-
- neighbors.AppendFormat("{0},{1},{2}{3}",
- item.GetNeighborID(0),
- item.GetNeighborID(1),
- item.GetNeighborID(2),
- seperator);
-
- i++;
- }
- writer.Write("]");
- writer.Write(",\"neighbors\":[" + neighbors.ToString() + "]");
- writer.Write("}");
- }
-
- #endregion
- }
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+//
+// -----------------------------------------------------------------------
+
+namespace MeshExplorer.IO.Formats
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Text;
+ using TriangleNet;
+ using TriangleNet.Topology;
+ using TriangleNet.Geometry;
+ using TriangleNet.IO;
+ using TriangleNet.Meshing;
+
+ ///
+ /// Read and write JSON files.
+ ///
+ ///
+ /// The JSON format:
+ /// {
+ /// "config": {
+ /// "ver": 1,
+ /// "type": "mesh" | "poly" | "points",
+ /// "dim": 2
+ /// },
+ /// "points": {
+ /// "data": [ p0.x, p0.y ... pn.x, pn.y ],
+ /// "markers": [ ... ],
+ /// "attributes": [ ... ]
+ /// },
+ /// "segments": {
+ /// "data": [ s0(1), s0(2) ... sn(1), sn(2) ],
+ /// "markers": [ ... ]
+ /// },
+ /// "holes": [ h0.x, h0.y ... hn.x, hn.y ],
+ /// "triangles": {
+ /// "data": [ t0(1), t0(2), t0(3) ... tn(1), tn(2), tn(3) ],
+ /// "neighbors": [ t0.n1, t0.n2, t0.n3 ... tn.n1, tn.n2, tn.n3 ],
+ /// "attributes": [ ... ]
+ /// }
+ /// }
+ ///
+ public class JsonFile : IMeshFile
+ {
+ string file;
+ Dictionary json;
+
+ ///
+ /// Gets the supported file extensions.
+ ///
+ public string[] Extensions
+ {
+ get { return new string[] { ".json" }; }
+ }
+
+ public bool ContainsMeshData(string filename)
+ {
+ ParseJson(filename);
+
+ if (this.json.ContainsKey("config"))
+ {
+ var config = this.json["config"] as Dictionary;
+
+ if (config != null && config.ContainsKey("type"))
+ {
+ return config["type"].ToString() == "mesh";
+ }
+ }
+
+ return false;
+ }
+
+ public bool IsSupported(string file)
+ {
+ throw new NotImplementedException();
+ }
+
+ public IMesh Import(string filename)
+ {
+ var geometry = (Polygon)this.Read(filename);
+
+ List triangles = null;
+
+ if (this.json.ContainsKey("triangles"))
+ {
+ var tri = this.json["triangles"] as Dictionary;
+
+ if (tri != null)
+ {
+ triangles = ReadTriangles(tri, geometry.Points.Count);
+ }
+ }
+
+ return Converter.Instance.ToMesh(geometry, triangles);
+ }
+
+ public void Write(IMesh mesh, string filename)
+ {
+ using (StreamWriter writer = new StreamWriter(filename))
+ {
+ int nv = mesh.Vertices.Count;
+ int ns = mesh.Segments.Count;
+ int nh = mesh.Holes.Count;
+ int ne = mesh.Triangles.Count;
+
+ writer.Write("{");
+
+ // Config header
+ writer.Write("\"config\":{");
+ writer.Write("\"ver\":1,");
+ writer.Write("\"type\":\"{0}\",", ne > 0 ? "mesh" : (ns > 0 ? "poly" : "points"));
+ writer.Write("\"dim\":2");
+ writer.Write("}");
+
+ if (((Mesh)mesh).CurrentNumbering == NodeNumbering.None)
+ {
+ ((Mesh)mesh).Renumber(NodeNumbering.Linear);
+ }
+
+ // Write the coordinates
+ if (nv > 0)
+ {
+ writer.Write(",");
+ WritePoints((Mesh)mesh, writer, nv);
+ }
+
+ // Write the segments
+ if (ns > 0)
+ {
+ writer.Write(",");
+ WriteSegments(mesh.Segments, writer, ns);
+ }
+
+ // Write the holes
+ if (nh > 0)
+ {
+ writer.Write(",");
+ WriteHoles(mesh.Holes, writer, nh);
+ }
+
+ // Write the elements
+ if (ne > 0)
+ {
+ writer.Write(",");
+ WriteTriangles(mesh.Triangles, writer, ne);
+ }
+
+ writer.Write("}");
+ }
+ }
+
+ public void Write(IMesh mesh, Stream stream)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public IPolygon Read(string filename)
+ {
+ ParseJson(filename);
+
+ var data = new Polygon();
+
+ if (json == null)
+ {
+ // TODO: Exception?
+ return data;
+ }
+
+ if (json.ContainsKey("config"))
+ {
+
+ }
+
+ int count = 0;
+
+ if (json.ContainsKey("points"))
+ {
+ var points = json["points"] as Dictionary;
+
+ if (points != null)
+ {
+ ReadPoints(data, points, ref count);
+ }
+ else
+ {
+ // TODO: Exception?
+ return data;
+ }
+ }
+
+ if (json.ContainsKey("segments"))
+ {
+ var segments = json["segments"] as Dictionary;
+
+ if (segments != null)
+ {
+ ReadSegments(data, segments, count);
+ }
+ }
+
+ if (json.ContainsKey("holes"))
+ {
+ var holes = json["holes"] as ArrayList;
+
+ if (holes != null)
+ {
+ ReadHoles(data, holes);
+ }
+ }
+
+ return data;
+ }
+
+ public void Write(IPolygon polygon, string filename)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Write(IPolygon polygon, Stream stream)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ParseJson(string filename)
+ {
+ if (this.json == null || this.file != filename)
+ {
+ this.file = filename;
+
+ string content = File.ReadAllText(filename);
+
+ JsonParser parser = new JsonParser(content);
+ this.json = parser.Decode() as Dictionary;
+ }
+ }
+
+ #region Read helpers
+
+ private void ReadPoints(Polygon geometry, Dictionary points, ref int count)
+ {
+ ArrayList data = points["data"] as ArrayList;
+
+ ArrayList markers = null;
+ ArrayList attributes = null;
+
+ if (points.ContainsKey("markers"))
+ {
+ markers = points["markers"] as ArrayList;
+ }
+
+ if (points.ContainsKey("attributes"))
+ {
+ attributes = points["attributes"] as ArrayList;
+ }
+
+ if (data != null)
+ {
+ int mark, n = data.Count;
+
+ if (n % 2 != 0)
+ {
+ throw new Exception("JSON format error (points).");
+ }
+
+ // Number of points
+ count = n / 2;
+
+ for (int i = 0; i < n; i += 2)
+ {
+ mark = 0;
+
+ if (markers != null && markers.Count == count)
+ {
+ mark = int.Parse(markers[i / 2].ToString());
+ }
+
+ geometry.Add(new Vertex(
+ double.Parse(data[i].ToString(), Util.Nfi),
+ double.Parse(data[i + 1].ToString(), Util.Nfi),
+ mark
+ ));
+ }
+ }
+ }
+
+ private void ReadSegments(Polygon geometry, Dictionary segments, int count)
+ {
+ ArrayList data = segments["data"] as ArrayList;
+
+ ArrayList markers = null;
+
+ if (segments.ContainsKey("markers"))
+ {
+ markers = segments["markers"] as ArrayList;
+ }
+
+ if (data != null)
+ {
+ int mark, n = data.Count;
+
+ if (n % 2 != 0)
+ {
+ throw new Exception("JSON format error (segments).");
+ }
+
+ int p0, p1;
+
+ throw new NotImplementedException();
+ // TODO: Fix JSON format
+
+ for (int i = 0; i < n; i += 2)
+ {
+ mark = 0;
+
+ if (markers != null && markers.Count == n)
+ {
+ mark = int.Parse(markers[i / 2].ToString());
+ }
+
+ p0 = int.Parse(data[i].ToString());
+ p1 = int.Parse(data[i + 1].ToString());
+
+ if (p0 < 0 || p0 >= count || p1 < 0 || p1 >= count)
+ {
+ throw new Exception("JSON format error (segment index).");
+ }
+
+ //geometry.Add(new Edge(p0, p1, mark));
+ }
+ }
+ }
+
+ private void ReadHoles(Polygon geometry, ArrayList holes)
+ {
+ int n = holes.Count;
+
+ if (n % 2 != 0)
+ {
+ throw new Exception("JSON format error (holes).");
+ }
+
+ for (int i = 0; i < n; i += 2)
+ {
+ geometry.Holes.Add(new Point(
+ double.Parse(holes[i].ToString(), Util.Nfi),
+ double.Parse(holes[i + 1].ToString(), Util.Nfi)
+ ));
+ }
+ }
+
+ private List ReadTriangles(Dictionary triangles, int points)
+ {
+ ArrayList data = triangles["data"] as ArrayList;
+
+ ArrayList neighbors = null;
+ ArrayList attributes = null;
+
+ if (triangles.ContainsKey("neighbors"))
+ {
+ neighbors = triangles["neighbors"] as ArrayList;
+ }
+
+ if (triangles.ContainsKey("attributes"))
+ {
+ attributes = triangles["attributes"] as ArrayList;
+ }
+
+ List output = null;
+
+ if (data != null)
+ {
+ int n = data.Count;
+
+ if (n % 3 != 0)
+ {
+ throw new Exception("JSON format error (triangles).");
+ }
+
+ output = new List(n / 3);
+
+ int p0, p1, p2, n0, n1, n2;
+
+ for (int i = 0; i < n; i += 3)
+ {
+ p0 = int.Parse(data[i].ToString());
+ p1 = int.Parse(data[i + 1].ToString());
+ p2 = int.Parse(data[i + 2].ToString());
+
+ n0 = n1 = n2 = -1;
+
+ if (p0 < 0 || p0 >= points || p1 < 0 || p1 >= points || p2 < 0 || p2 >= points)
+ {
+ throw new Exception("JSON format error (triangle index).");
+ }
+
+ if (neighbors.Count == n)
+ {
+ n0 = int.Parse(neighbors[i].ToString());
+ n1 = int.Parse(neighbors[i + 1].ToString());
+ n2 = int.Parse(neighbors[i + 2].ToString());
+ }
+
+ // TODO: Set neighbors
+ output.Add(new InputTriangle(p0, p1, p2));
+ }
+ }
+
+ return output;
+ }
+
+ #endregion
+
+ #region Write helpers
+
+ private void WritePoints(Mesh mesh, StreamWriter writer, int nv)
+ {
+ bool useMarkers = false;
+
+ StringBuilder markers;
+
+ writer.Write("\"points\":{\"data\":[");
+
+ if (mesh.CurrentNumbering == NodeNumbering.Linear)
+ {
+ markers = WritePoints(mesh.Vertices, writer, nv, useMarkers);
+ }
+ else
+ {
+ Vertex[] nodes = new Vertex[mesh.Vertices.Count];
+
+ foreach (var node in mesh.Vertices)
+ {
+ nodes[node.ID] = node;
+ }
+
+ markers = WritePoints(nodes, writer, nv, useMarkers);
+ }
+
+ writer.Write("]");
+ if (useMarkers)
+ {
+ writer.Write(",\"markers\":[" + markers.ToString() + "]");
+ }
+
+ // TODO: writer.Write(",\"attributes\":[]");
+ writer.Write("}");
+ }
+
+ private static StringBuilder WritePoints(IEnumerable data, StreamWriter writer, int nv, bool useMarkers)
+ {
+ StringBuilder markers = new StringBuilder();
+
+ int i = 0;
+ string seperator;
+ foreach (var item in data)
+ {
+ seperator = (i == nv - 1) ? String.Empty : ", ";
+
+ writer.Write("{0},{1}{2}",
+ item.X.ToString(Util.Nfi),
+ item.Y.ToString(Util.Nfi), seperator);
+
+ if (item.Label > 0)
+ {
+ useMarkers = true;
+ }
+
+ markers.AppendFormat("{0}{1}", item.Label, seperator);
+
+ i++;
+ }
+
+ return markers;
+ }
+
+ private void WriteHoles(IEnumerable data, StreamWriter writer, int nh)
+ {
+ int i = 0;
+
+ writer.Write("\"holes\":[");
+ foreach (var item in data)
+ {
+ writer.Write("{0},{1}{2}",
+ item.X.ToString(Util.Nfi),
+ item.Y.ToString(Util.Nfi), (i == nh - 1) ? String.Empty : ", ");
+
+ i++;
+ }
+
+ writer.Write("]");
+ }
+
+ private void WriteSegments(IEnumerable data, StreamWriter writer, int ns)
+ {
+ int i = 0;
+
+ StringBuilder markers = new StringBuilder();
+ bool useMarkers = false;
+
+ string seperator;
+
+ writer.Write("\"segments\":{\"data\":[");
+ foreach (var item in data)
+ {
+ seperator = (i == ns - 1) ? String.Empty : ", ";
+
+ writer.Write("{0},{1}{2}",
+ item.P0, item.P1, seperator);
+
+ if (item.Label > 0)
+ {
+ useMarkers = true;
+ }
+
+ markers.AppendFormat("{0}{1}", item.Label, seperator);
+
+ i++;
+ }
+
+ writer.Write("]");
+
+ if (useMarkers)
+ {
+ writer.Write(",\"markers\":[" + markers.ToString() + "]");
+ }
+
+ writer.Write("}");
+ }
+
+ private void WriteTriangles(IEnumerable data, StreamWriter writer, int ne)
+ {
+ int i = 0;
+
+ StringBuilder neighbors = new StringBuilder();
+
+ string seperator;
+
+ writer.Write("\"triangles\":{\"data\":[");
+ foreach (var item in data)
+ {
+ seperator = (i == ne - 1) ? String.Empty : ", ";
+
+ writer.Write("{0},{1},{2}{3}",
+ item.GetVertexID(0),
+ item.GetVertexID(1),
+ item.GetVertexID(2),
+ seperator);
+
+ neighbors.AppendFormat("{0},{1},{2}{3}",
+ item.GetNeighborID(0),
+ item.GetNeighborID(1),
+ item.GetNeighborID(2),
+ seperator);
+
+ i++;
+ }
+ writer.Write("]");
+ writer.Write(",\"neighbors\":[" + neighbors.ToString() + "]");
+ writer.Write("}");
+ }
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/Triangle.NET/TestApp/IO/Formats/TriangleFile.cs b/src/Triangle.Viewer/IO/Formats/TriangleFile.cs
similarity index 96%
rename from Triangle.NET/TestApp/IO/Formats/TriangleFile.cs
rename to src/Triangle.Viewer/IO/Formats/TriangleFile.cs
index ae60afa..be6c56a 100644
--- a/Triangle.NET/TestApp/IO/Formats/TriangleFile.cs
+++ b/src/Triangle.Viewer/IO/Formats/TriangleFile.cs
@@ -1,83 +1,83 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace MeshExplorer.IO.Formats
-{
- using System;
- using System.IO;
- using TriangleNet.Geometry;
- using TriangleNet.IO;
- using TriangleNet.Meshing;
-
- ///
- /// Read and write files defined in classic Triangle format.
- ///
- public class TriangleFile : IMeshFile
- {
- TriangleFormat format = new TriangleFormat();
-
- ///
- /// Gets the supported file extensions.
- ///
- public string[] Extensions
- {
- get { return new string[] { ".node", ".poly", ".ele" }; }
- }
-
- public bool ContainsMeshData(string filename)
- {
- string ext = Path.GetExtension(filename);
-
- if (ext == ".node" || ext == ".poly")
- {
- if (File.Exists(Path.ChangeExtension(filename, ".ele")))
- {
- return true;
- }
- }
-
- return (ext == ".ele");
- }
-
- public bool IsSupported(string file)
- {
- throw new NotImplementedException();
- }
-
- public IPolygon Read(string filename)
- {
- return format.Read(filename);
- }
-
- public void Write(IPolygon polygon, string filename)
- {
- format.Write(polygon, filename);
- }
-
- public void Write(IPolygon polygon, Stream stream)
- {
- format.Write(polygon, stream);
- }
-
- public IMesh Import(string filename)
- {
- return format.Import(filename);
- }
-
- public void Write(IMesh mesh, string filename)
- {
- if (mesh.Vertices.Count > 0)
- {
- format.Write(mesh, filename);
- }
- }
-
- public void Write(IMesh mesh, Stream stream)
- {
- format.Write(mesh, stream);
- }
- }
-}
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+//
+// -----------------------------------------------------------------------
+
+namespace MeshExplorer.IO.Formats
+{
+ using System;
+ using System.IO;
+ using TriangleNet.Geometry;
+ using TriangleNet.IO;
+ using TriangleNet.Meshing;
+
+ ///
+ /// Read and write files defined in classic Triangle format.
+ ///
+ public class TriangleFile : IMeshFile
+ {
+ TriangleFormat format = new TriangleFormat();
+
+ ///
+ /// Gets the supported file extensions.
+ ///
+ public string[] Extensions
+ {
+ get { return new string[] { ".node", ".poly", ".ele" }; }
+ }
+
+ public bool ContainsMeshData(string filename)
+ {
+ string ext = Path.GetExtension(filename);
+
+ if (ext == ".node" || ext == ".poly")
+ {
+ if (File.Exists(Path.ChangeExtension(filename, ".ele")))
+ {
+ return true;
+ }
+ }
+
+ return (ext == ".ele");
+ }
+
+ public bool IsSupported(string file)
+ {
+ throw new NotImplementedException();
+ }
+
+ public IPolygon Read(string filename)
+ {
+ return format.Read(filename);
+ }
+
+ public void Write(IPolygon polygon, string filename)
+ {
+ format.Write(polygon, filename);
+ }
+
+ public void Write(IPolygon polygon, Stream stream)
+ {
+ format.Write(polygon, stream);
+ }
+
+ public IMesh Import(string filename)
+ {
+ return format.Import(filename);
+ }
+
+ public void Write(IMesh mesh, string filename)
+ {
+ if (mesh.Vertices.Count > 0)
+ {
+ format.Write(mesh, filename);
+ }
+ }
+
+ public void Write(IMesh mesh, Stream stream)
+ {
+ format.Write(mesh, stream);
+ }
+ }
+}
diff --git a/Triangle.NET/TestApp/IO/IMeshFile.cs b/src/Triangle.Viewer/IO/IMeshFile.cs
similarity index 85%
rename from Triangle.NET/TestApp/IO/IMeshFile.cs
rename to src/Triangle.Viewer/IO/IMeshFile.cs
index 35e55cb..47f0092 100644
--- a/Triangle.NET/TestApp/IO/IMeshFile.cs
+++ b/src/Triangle.Viewer/IO/IMeshFile.cs
@@ -1,33 +1,28 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace MeshExplorer.IO
-{
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using TriangleNet;
- using TriangleNet.IO;
-
- ///
- /// Defines an interface for mesh file formats.
- ///
- public interface IMeshFile : IPolygonFormat, IMeshFormat
- {
- ///
- /// The supported file extensions.
- ///
- string[] Extensions { get; }
-
- ///
- /// Return true, if a (previously saved) mesh is associated with the given file.
- ///
- /// The file name.
- /// True, if a mesh is associated with the given file.
- bool ContainsMeshData(string filename);
- }
-}
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+//
+// -----------------------------------------------------------------------
+
+namespace MeshExplorer.IO
+{
+ using TriangleNet.IO;
+
+ ///
+ /// Defines an interface for mesh file formats.
+ ///
+ public interface IMeshFile : IPolygonFormat, IMeshFormat
+ {
+ ///
+ /// The supported file extensions.
+ ///
+ string[] Extensions { get; }
+
+ ///
+ /// Return true, if a (previously saved) mesh is associated with the given file.
+ ///
+ /// The file name.
+ /// True, if a mesh is associated with the given file.
+ bool ContainsMeshData(string filename);
+ }
+}
diff --git a/Triangle.NET/TestApp/IO/ImageWriter.cs b/src/Triangle.Viewer/IO/ImageWriter.cs
similarity index 96%
rename from Triangle.NET/TestApp/IO/ImageWriter.cs
rename to src/Triangle.Viewer/IO/ImageWriter.cs
index e1e764d..b0a265d 100644
--- a/Triangle.NET/TestApp/IO/ImageWriter.cs
+++ b/src/Triangle.Viewer/IO/ImageWriter.cs
@@ -1,88 +1,88 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace MeshExplorer.IO
-{
- using System.IO;
- using System.IO.Compression;
- using TriangleNet;
- using TriangleNet.Rendering.GDI;
- using TriangleNet.Rendering.Text;
-
- ///
- /// Writes an image of the mesh to disk.
- ///
- public class ImageWriter
- {
- ///
- /// Export the mesh to PNG format.
- ///
- /// The current mesh.
- /// The PNG filename.
- /// Image type (0 = png, 1 = eps, 2 = svg).
- /// The desired width of the image.
- /// Use GZip compression (only eps or svg).
- public void Export(Mesh mesh, string filename, int type, int width, bool compress)
- {
- if (type == 1)
- {
- ExportEps(mesh, filename, width, compress);
- }
- else if (type == 2)
- {
- ExportSvg(mesh, filename, width, compress);
- }
- else
- {
- ImageRenderer.Save(mesh, filename, width);
- }
- }
-
- private void ExportEps(Mesh mesh, string filename, int width, bool compress)
- {
- var eps = new EpsImage();
-
- eps.Export(mesh, filename, width);
-
- if (compress)
- {
- CompressFile(filename, true);
- }
- }
-
- private void ExportSvg(Mesh mesh, string filename, int width, bool compress)
- {
- var svg = new SvgImage();
-
- svg.Export(mesh, filename, width);
-
- if (compress)
- {
- CompressFile(filename, true);
- }
- }
-
- private void CompressFile(string filename, bool cleanup)
- {
- if (!File.Exists(filename))
- {
- return;
- }
-
- using (var input = File.OpenRead(filename))
- using (var output = File.Create(filename + ".gz"))
- using (var gzip = new GZipStream(output, CompressionMode.Compress))
- {
- input.CopyTo(gzip);
- }
-
- if (cleanup)
- {
- File.Delete(filename);
- }
- }
- }
-}
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+//
+// -----------------------------------------------------------------------
+
+namespace MeshExplorer.IO
+{
+ using System.IO;
+ using System.IO.Compression;
+ using TriangleNet;
+ using TriangleNet.Rendering.GDI;
+ using TriangleNet.Rendering.Text;
+
+ ///
+ /// Writes an image of the mesh to disk.
+ ///
+ public class ImageWriter
+ {
+ ///
+ /// Export the mesh to PNG format.
+ ///
+ /// The current mesh.
+ /// The PNG filename.
+ /// Image type (0 = png, 1 = eps, 2 = svg).
+ /// The desired width of the image.
+ /// Use GZip compression (only eps or svg).
+ public void Export(Mesh mesh, string filename, int type, int width, bool compress)
+ {
+ if (type == 1)
+ {
+ ExportEps(mesh, filename, width, compress);
+ }
+ else if (type == 2)
+ {
+ ExportSvg(mesh, filename, width, compress);
+ }
+ else
+ {
+ ImageRenderer.Save(mesh, filename, width);
+ }
+ }
+
+ private void ExportEps(Mesh mesh, string filename, int width, bool compress)
+ {
+ var eps = new EpsImage();
+
+ eps.Export(mesh, filename, width);
+
+ if (compress)
+ {
+ CompressFile(filename, true);
+ }
+ }
+
+ private void ExportSvg(Mesh mesh, string filename, int width, bool compress)
+ {
+ var svg = new SvgImage();
+
+ svg.Export(mesh, filename, width);
+
+ if (compress)
+ {
+ CompressFile(filename, true);
+ }
+ }
+
+ private void CompressFile(string filename, bool cleanup)
+ {
+ if (!File.Exists(filename))
+ {
+ return;
+ }
+
+ using (var input = File.OpenRead(filename))
+ using (var output = File.Create(filename + ".gz"))
+ using (var gzip = new GZipStream(output, CompressionMode.Compress))
+ {
+ input.CopyTo(gzip);
+ }
+
+ if (cleanup)
+ {
+ File.Delete(filename);
+ }
+ }
+ }
+}
diff --git a/Triangle.NET/TestApp/IO/JsonParser.cs b/src/Triangle.Viewer/IO/JsonParser.cs
similarity index 96%
rename from Triangle.NET/TestApp/IO/JsonParser.cs
rename to src/Triangle.Viewer/IO/JsonParser.cs
index ced3436..99cfebd 100644
--- a/Triangle.NET/TestApp/IO/JsonParser.cs
+++ b/src/Triangle.Viewer/IO/JsonParser.cs
@@ -1,408 +1,408 @@
-// -----------------------------------------------------------------------
-//
-// fastJSON - http://fastjson.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace MeshExplorer.IO
-{
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Globalization;
- using System.Text;
-
- ///
- /// This class encodes and decodes JSON strings.
- /// Spec. details, see http://www.json.org/
- ///
- /// JSON uses Arrays and Objects. These correspond here to the datatypes ArrayList and Hashtable.
- /// All numbers are parsed to doubles.
- ///
- internal class JsonParser
- {
- enum Token
- {
- None = -1, // Used to denote no Lookahead available
- Curly_Open,
- Curly_Close,
- Squared_Open,
- Squared_Close,
- Colon,
- Comma,
- String,
- Number,
- True,
- False,
- Null
- }
-
- readonly char[] json;
- readonly StringBuilder s = new StringBuilder();
- Token lookAheadToken = Token.None;
- int index;
-
- public JsonParser(string json)
- {
- this.json = json.ToCharArray();
- }
-
- public object Decode()
- {
- return ParseValue();
- }
-
- private Dictionary ParseObject()
- {
- Dictionary table = new Dictionary();
-
- ConsumeToken(); // {
-
- while (true)
- {
- switch (LookAhead())
- {
-
- case Token.Comma:
- ConsumeToken();
- break;
-
- case Token.Curly_Close:
- ConsumeToken();
- return table;
-
- default:
- {
-
- // name
- string name = ParseString();
-
- // :
- if (NextToken() != Token.Colon)
- {
- throw new Exception("Expected colon at index " + index);
- }
-
- // value
- object value = ParseValue();
-
- table[name] = value;
- }
- break;
- }
- }
- }
-
- private ArrayList ParseArray()
- {
- ArrayList array = new ArrayList();
-
- ConsumeToken(); // [
-
- while (true)
- {
- switch (LookAhead())
- {
-
- case Token.Comma:
- ConsumeToken();
- break;
-
- case Token.Squared_Close:
- ConsumeToken();
- return array;
-
- default:
- {
- array.Add(ParseValue());
- }
- break;
- }
- }
- }
-
- private object ParseValue()
- {
- switch (LookAhead())
- {
- case Token.Number:
- return ParseNumber();
-
- case Token.String:
- return ParseString();
-
- case Token.Curly_Open:
- return ParseObject();
-
- case Token.Squared_Open:
- return ParseArray();
-
- case Token.True:
- ConsumeToken();
- return true;
-
- case Token.False:
- ConsumeToken();
- return false;
-
- case Token.Null:
- ConsumeToken();
- return null;
- }
-
- throw new Exception("Unrecognized token at index" + index);
- }
-
- private string ParseString()
- {
- ConsumeToken(); // "
-
- s.Length = 0;
-
- int runIndex = -1;
-
- while (index < json.Length)
- {
- var c = json[index++];
-
- if (c == '"')
- {
- if (runIndex != -1)
- {
- if (s.Length == 0)
- return new string(json, runIndex, index - runIndex - 1);
-
- s.Append(json, runIndex, index - runIndex - 1);
- }
- return s.ToString();
- }
-
- if (c != '\\')
- {
- if (runIndex == -1)
- runIndex = index - 1;
-
- continue;
- }
-
- if (index == json.Length) break;
-
- if (runIndex != -1)
- {
- s.Append(json, runIndex, index - runIndex - 1);
- runIndex = -1;
- }
-
- switch (json[index++])
- {
- case '"':
- s.Append('"');
- break;
-
- case '\\':
- s.Append('\\');
- break;
-
- case '/':
- s.Append('/');
- break;
-
- case 'b':
- s.Append('\b');
- break;
-
- case 'f':
- s.Append('\f');
- break;
-
- case 'n':
- s.Append('\n');
- break;
-
- case 'r':
- s.Append('\r');
- break;
-
- case 't':
- s.Append('\t');
- break;
-
- case 'u':
- {
- int remainingLength = json.Length - index;
- if (remainingLength < 4) break;
-
- // parse the 32 bit hex into an integer codepoint
- uint codePoint = ParseUnicode(json[index], json[index + 1], json[index + 2], json[index + 3]);
- s.Append((char)codePoint);
-
- // skip 4 chars
- index += 4;
- }
- break;
- }
- }
-
- throw new Exception("Unexpectedly reached end of string");
- }
-
- private uint ParseSingleChar(char c1, uint multipliyer)
- {
- uint p1 = 0;
- if (c1 >= '0' && c1 <= '9')
- p1 = (uint)(c1 - '0') * multipliyer;
- else if (c1 >= 'A' && c1 <= 'F')
- p1 = (uint)((c1 - 'A') + 10) * multipliyer;
- else if (c1 >= 'a' && c1 <= 'f')
- p1 = (uint)((c1 - 'a') + 10) * multipliyer;
- return p1;
- }
-
- private uint ParseUnicode(char c1, char c2, char c3, char c4)
- {
- uint p1 = ParseSingleChar(c1, 0x1000);
- uint p2 = ParseSingleChar(c2, 0x100);
- uint p3 = ParseSingleChar(c3, 0x10);
- uint p4 = ParseSingleChar(c4, 1);
-
- return p1 + p2 + p3 + p4;
- }
-
- private string ParseNumber()
- {
- ConsumeToken();
-
- // Need to start back one place because the first digit is also a token and would have been consumed
- var startIndex = index - 1;
-
- do
- {
- var c = json[index];
-
- if ((c >= '0' && c <= '9') || c == '.' || c == '-' || c == '+' || c == 'e' || c == 'E')
- {
- if (++index == json.Length) throw new Exception("Unexpected end of string whilst parsing number");
- continue;
- }
-
- break;
- } while (true);
-
- return new string(json, startIndex, index - startIndex);
- }
-
- private Token LookAhead()
- {
- if (lookAheadToken != Token.None) return lookAheadToken;
-
- return lookAheadToken = NextTokenCore();
- }
-
- private void ConsumeToken()
- {
- lookAheadToken = Token.None;
- }
-
- private Token NextToken()
- {
- var result = lookAheadToken != Token.None ? lookAheadToken : NextTokenCore();
-
- lookAheadToken = Token.None;
-
- return result;
- }
-
- private Token NextTokenCore()
- {
- char c;
-
- // Skip past whitespace
- do
- {
- c = json[index];
-
- if (c > ' ') break;
- if (c != ' ' && c != '\t' && c != '\n' && c != '\r') break;
-
- } while (++index < json.Length);
-
- if (index == json.Length)
- {
- throw new Exception("Reached end of string unexpectedly");
- }
-
- c = json[index];
-
- index++;
-
- //if (c >= '0' && c <= '9')
- // return Token.Number;
-
- switch (c)
- {
- case '{':
- return Token.Curly_Open;
-
- case '}':
- return Token.Curly_Close;
-
- case '[':
- return Token.Squared_Open;
-
- case ']':
- return Token.Squared_Close;
-
- case ',':
- return Token.Comma;
-
- case '"':
- return Token.String;
-
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- case '-': case '+': case '.':
- return Token.Number;
-
- case ':':
- return Token.Colon;
-
- case 'f':
- if (json.Length - index >= 4 &&
- json[index + 0] == 'a' &&
- json[index + 1] == 'l' &&
- json[index + 2] == 's' &&
- json[index + 3] == 'e')
- {
- index += 4;
- return Token.False;
- }
- break;
-
- case 't':
- if (json.Length - index >= 3 &&
- json[index + 0] == 'r' &&
- json[index + 1] == 'u' &&
- json[index + 2] == 'e')
- {
- index += 3;
- return Token.True;
- }
- break;
-
- case 'n':
- if (json.Length - index >= 3 &&
- json[index + 0] == 'u' &&
- json[index + 1] == 'l' &&
- json[index + 2] == 'l')
- {
- index += 3;
- return Token.Null;
- }
- break;
-
- }
-
- throw new Exception("Could not find token at index " + --index);
- }
- }
-}
+// -----------------------------------------------------------------------
+//
+// fastJSON - http://fastjson.codeplex.com/
+//
+// -----------------------------------------------------------------------
+
+namespace MeshExplorer.IO
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Globalization;
+ using System.Text;
+
+ ///
+ /// This class encodes and decodes JSON strings.
+ /// Spec. details, see http://www.json.org/
+ ///
+ /// JSON uses Arrays and Objects. These correspond here to the datatypes ArrayList and Hashtable.
+ /// All numbers are parsed to doubles.
+ ///
+ internal class JsonParser
+ {
+ enum Token
+ {
+ None = -1, // Used to denote no Lookahead available
+ Curly_Open,
+ Curly_Close,
+ Squared_Open,
+ Squared_Close,
+ Colon,
+ Comma,
+ String,
+ Number,
+ True,
+ False,
+ Null
+ }
+
+ readonly char[] json;
+ readonly StringBuilder s = new StringBuilder();
+ Token lookAheadToken = Token.None;
+ int index;
+
+ public JsonParser(string json)
+ {
+ this.json = json.ToCharArray();
+ }
+
+ public object Decode()
+ {
+ return ParseValue();
+ }
+
+ private Dictionary ParseObject()
+ {
+ Dictionary table = new Dictionary();
+
+ ConsumeToken(); // {
+
+ while (true)
+ {
+ switch (LookAhead())
+ {
+
+ case Token.Comma:
+ ConsumeToken();
+ break;
+
+ case Token.Curly_Close:
+ ConsumeToken();
+ return table;
+
+ default:
+ {
+
+ // name
+ string name = ParseString();
+
+ // :
+ if (NextToken() != Token.Colon)
+ {
+ throw new Exception("Expected colon at index " + index);
+ }
+
+ // value
+ object value = ParseValue();
+
+ table[name] = value;
+ }
+ break;
+ }
+ }
+ }
+
+ private ArrayList ParseArray()
+ {
+ ArrayList array = new ArrayList();
+
+ ConsumeToken(); // [
+
+ while (true)
+ {
+ switch (LookAhead())
+ {
+
+ case Token.Comma:
+ ConsumeToken();
+ break;
+
+ case Token.Squared_Close:
+ ConsumeToken();
+ return array;
+
+ default:
+ {
+ array.Add(ParseValue());
+ }
+ break;
+ }
+ }
+ }
+
+ private object ParseValue()
+ {
+ switch (LookAhead())
+ {
+ case Token.Number:
+ return ParseNumber();
+
+ case Token.String:
+ return ParseString();
+
+ case Token.Curly_Open:
+ return ParseObject();
+
+ case Token.Squared_Open:
+ return ParseArray();
+
+ case Token.True:
+ ConsumeToken();
+ return true;
+
+ case Token.False:
+ ConsumeToken();
+ return false;
+
+ case Token.Null:
+ ConsumeToken();
+ return null;
+ }
+
+ throw new Exception("Unrecognized token at index" + index);
+ }
+
+ private string ParseString()
+ {
+ ConsumeToken(); // "
+
+ s.Length = 0;
+
+ int runIndex = -1;
+
+ while (index < json.Length)
+ {
+ var c = json[index++];
+
+ if (c == '"')
+ {
+ if (runIndex != -1)
+ {
+ if (s.Length == 0)
+ return new string(json, runIndex, index - runIndex - 1);
+
+ s.Append(json, runIndex, index - runIndex - 1);
+ }
+ return s.ToString();
+ }
+
+ if (c != '\\')
+ {
+ if (runIndex == -1)
+ runIndex = index - 1;
+
+ continue;
+ }
+
+ if (index == json.Length) break;
+
+ if (runIndex != -1)
+ {
+ s.Append(json, runIndex, index - runIndex - 1);
+ runIndex = -1;
+ }
+
+ switch (json[index++])
+ {
+ case '"':
+ s.Append('"');
+ break;
+
+ case '\\':
+ s.Append('\\');
+ break;
+
+ case '/':
+ s.Append('/');
+ break;
+
+ case 'b':
+ s.Append('\b');
+ break;
+
+ case 'f':
+ s.Append('\f');
+ break;
+
+ case 'n':
+ s.Append('\n');
+ break;
+
+ case 'r':
+ s.Append('\r');
+ break;
+
+ case 't':
+ s.Append('\t');
+ break;
+
+ case 'u':
+ {
+ int remainingLength = json.Length - index;
+ if (remainingLength < 4) break;
+
+ // parse the 32 bit hex into an integer codepoint
+ uint codePoint = ParseUnicode(json[index], json[index + 1], json[index + 2], json[index + 3]);
+ s.Append((char)codePoint);
+
+ // skip 4 chars
+ index += 4;
+ }
+ break;
+ }
+ }
+
+ throw new Exception("Unexpectedly reached end of string");
+ }
+
+ private uint ParseSingleChar(char c1, uint multipliyer)
+ {
+ uint p1 = 0;
+ if (c1 >= '0' && c1 <= '9')
+ p1 = (uint)(c1 - '0') * multipliyer;
+ else if (c1 >= 'A' && c1 <= 'F')
+ p1 = (uint)((c1 - 'A') + 10) * multipliyer;
+ else if (c1 >= 'a' && c1 <= 'f')
+ p1 = (uint)((c1 - 'a') + 10) * multipliyer;
+ return p1;
+ }
+
+ private uint ParseUnicode(char c1, char c2, char c3, char c4)
+ {
+ uint p1 = ParseSingleChar(c1, 0x1000);
+ uint p2 = ParseSingleChar(c2, 0x100);
+ uint p3 = ParseSingleChar(c3, 0x10);
+ uint p4 = ParseSingleChar(c4, 1);
+
+ return p1 + p2 + p3 + p4;
+ }
+
+ private string ParseNumber()
+ {
+ ConsumeToken();
+
+ // Need to start back one place because the first digit is also a token and would have been consumed
+ var startIndex = index - 1;
+
+ do
+ {
+ var c = json[index];
+
+ if ((c >= '0' && c <= '9') || c == '.' || c == '-' || c == '+' || c == 'e' || c == 'E')
+ {
+ if (++index == json.Length) throw new Exception("Unexpected end of string whilst parsing number");
+ continue;
+ }
+
+ break;
+ } while (true);
+
+ return new string(json, startIndex, index - startIndex);
+ }
+
+ private Token LookAhead()
+ {
+ if (lookAheadToken != Token.None) return lookAheadToken;
+
+ return lookAheadToken = NextTokenCore();
+ }
+
+ private void ConsumeToken()
+ {
+ lookAheadToken = Token.None;
+ }
+
+ private Token NextToken()
+ {
+ var result = lookAheadToken != Token.None ? lookAheadToken : NextTokenCore();
+
+ lookAheadToken = Token.None;
+
+ return result;
+ }
+
+ private Token NextTokenCore()
+ {
+ char c;
+
+ // Skip past whitespace
+ do
+ {
+ c = json[index];
+
+ if (c > ' ') break;
+ if (c != ' ' && c != '\t' && c != '\n' && c != '\r') break;
+
+ } while (++index < json.Length);
+
+ if (index == json.Length)
+ {
+ throw new Exception("Reached end of string unexpectedly");
+ }
+
+ c = json[index];
+
+ index++;
+
+ //if (c >= '0' && c <= '9')
+ // return Token.Number;
+
+ switch (c)
+ {
+ case '{':
+ return Token.Curly_Open;
+
+ case '}':
+ return Token.Curly_Close;
+
+ case '[':
+ return Token.Squared_Open;
+
+ case ']':
+ return Token.Squared_Close;
+
+ case ',':
+ return Token.Comma;
+
+ case '"':
+ return Token.String;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case '-': case '+': case '.':
+ return Token.Number;
+
+ case ':':
+ return Token.Colon;
+
+ case 'f':
+ if (json.Length - index >= 4 &&
+ json[index + 0] == 'a' &&
+ json[index + 1] == 'l' &&
+ json[index + 2] == 's' &&
+ json[index + 3] == 'e')
+ {
+ index += 4;
+ return Token.False;
+ }
+ break;
+
+ case 't':
+ if (json.Length - index >= 3 &&
+ json[index + 0] == 'r' &&
+ json[index + 1] == 'u' &&
+ json[index + 2] == 'e')
+ {
+ index += 3;
+ return Token.True;
+ }
+ break;
+
+ case 'n':
+ if (json.Length - index >= 3 &&
+ json[index + 0] == 'u' &&
+ json[index + 1] == 'l' &&
+ json[index + 2] == 'l')
+ {
+ index += 3;
+ return Token.Null;
+ }
+ break;
+
+ }
+
+ throw new Exception("Could not find token at index " + --index);
+ }
+ }
+}
diff --git a/Triangle.NET/TestApp/Program.cs b/src/Triangle.Viewer/Program.cs
similarity index 95%
rename from Triangle.NET/TestApp/Program.cs
rename to src/Triangle.Viewer/Program.cs
index 928c59e..b01de2e 100644
--- a/Triangle.NET/TestApp/Program.cs
+++ b/src/Triangle.Viewer/Program.cs
@@ -1,21 +1,21 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Windows.Forms;
-
-namespace MeshExplorer
-{
- static class Program
- {
- ///
- /// The main entry point for the application.
- ///
- [STAThread]
- static void Main()
- {
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
- Application.Run(new FormMain());
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Forms;
+
+namespace MeshExplorer
+{
+ static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new FormMain());
+ }
+ }
+}
diff --git a/Triangle.NET/TestApp/Settings.cs b/src/Triangle.Viewer/Settings.cs
similarity index 97%
rename from Triangle.NET/TestApp/Settings.cs
rename to src/Triangle.Viewer/Settings.cs
index e21d9b0..04f59af 100644
--- a/Triangle.NET/TestApp/Settings.cs
+++ b/src/Triangle.Viewer/Settings.cs
@@ -1,78 +1,78 @@
-// -----------------------------------------------------------------------
-//
-// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace MeshExplorer
-{
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.IO;
- using System.Windows.Forms;
-
- ///
- /// Stores some of the data used in the main application.
- ///
- public class Settings
- {
- // String resources
- public static string ImportString = "The selected file has associated mesh information. " +
- "You can choose to import the mesh or just read the geometry.";
-
- public static string VoronoiString = "Make sure you use the \"Confoming Delaunay\" option " +
- "when building the Voronoi diagram from a constrained mesh.";
-
- // Open file dialog
- public string OfdDirectory { get; set; }
- public string OfdFilter { get; set; }
- public int OfdFilterIndex{ get; set; }
-
- // Save file dialog
- public string SfdDirectory { get; set; }
- public string SfdFilter { get; set; }
- public int SfdFilterIndex { get; set; }
-
- public string CurrentFile { get; set; }
-
- public bool RefineMode { get; set; }
- public bool ExceptionThrown { get; set; }
-
- public Settings()
- {
- if (Directory.Exists(@"..\..\..\Data\"))
- {
- OfdDirectory = Path.GetFullPath(@"..\..\..\Data\");
- }
- else if (Directory.Exists(@"Data\"))
- {
- OfdDirectory = Path.GetFullPath(@"Data\");
- }
- else
- {
- //System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase;
- OfdDirectory = Application.StartupPath;
- }
-
- SfdDirectory = OfdDirectory;
- SfdFilter = "Triangle file (*.node;*.poly)|*.node;*.poly";
- SfdFilter += "|Triangle.NET JSON (*.json)|*.json";
- SfdFilterIndex = 1;
-
- OfdFilter = SfdFilter;
- //OfdFilter += "|Polygon data (*.dat)|*.dat";
- //OfdFilter += "|COMSOL mesh (*.mphtxt)|*.mphtxt";
- //OfdFilter += "|AVS UCD data (*.ucd)|*.ucd";
- //OfdFilter += "|VTK data (*.vtk)|*.vtk";
-
- OfdFilterIndex = 0;
-
- CurrentFile = "";
-
- RefineMode = false;
- ExceptionThrown = false;
- }
- }
-}
+// -----------------------------------------------------------------------
+//
+// Christian Woltering, Triangle.NET, http://triangle.codeplex.com/
+//
+// -----------------------------------------------------------------------
+
+namespace MeshExplorer
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using System.IO;
+ using System.Windows.Forms;
+
+ ///
+ /// Stores some of the data used in the main application.
+ ///
+ public class Settings
+ {
+ // String resources
+ public static string ImportString = "The selected file has associated mesh information. " +
+ "You can choose to import the mesh or just read the geometry.";
+
+ public static string VoronoiString = "Make sure you use the \"Confoming Delaunay\" option " +
+ "when building the Voronoi diagram from a constrained mesh.";
+
+ // Open file dialog
+ public string OfdDirectory { get; set; }
+ public string OfdFilter { get; set; }
+ public int OfdFilterIndex{ get; set; }
+
+ // Save file dialog
+ public string SfdDirectory { get; set; }
+ public string SfdFilter { get; set; }
+ public int SfdFilterIndex { get; set; }
+
+ public string CurrentFile { get; set; }
+
+ public bool RefineMode { get; set; }
+ public bool ExceptionThrown { get; set; }
+
+ public Settings()
+ {
+ if (Directory.Exists(@"..\..\..\Data\"))
+ {
+ OfdDirectory = Path.GetFullPath(@"..\..\..\Data\");
+ }
+ else if (Directory.Exists(@"Data\"))
+ {
+ OfdDirectory = Path.GetFullPath(@"Data\");
+ }
+ else
+ {
+ //System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase;
+ OfdDirectory = Application.StartupPath;
+ }
+
+ SfdDirectory = OfdDirectory;
+ SfdFilter = "Triangle file (*.node;*.poly)|*.node;*.poly";
+ SfdFilter += "|Triangle.NET JSON (*.json)|*.json";
+ SfdFilterIndex = 1;
+
+ OfdFilter = SfdFilter;
+ //OfdFilter += "|Polygon data (*.dat)|*.dat";
+ //OfdFilter += "|COMSOL mesh (*.mphtxt)|*.mphtxt";
+ //OfdFilter += "|AVS UCD data (*.ucd)|*.ucd";
+ //OfdFilter += "|VTK data (*.vtk)|*.vtk";
+
+ OfdFilterIndex = 0;
+
+ CurrentFile = "";
+
+ RefineMode = false;
+ ExceptionThrown = false;
+ }
+ }
+}
diff --git a/Triangle.NET/TestApp/Topology/TopologyControlView.Designer.cs b/src/Triangle.Viewer/Topology/TopologyControlView.Designer.cs
similarity index 97%
rename from Triangle.NET/TestApp/Topology/TopologyControlView.Designer.cs
rename to src/Triangle.Viewer/Topology/TopologyControlView.Designer.cs
index bdb22e1..128d58b 100644
--- a/Triangle.NET/TestApp/Topology/TopologyControlView.Designer.cs
+++ b/src/Triangle.Viewer/Topology/TopologyControlView.Designer.cs
@@ -1,359 +1,359 @@
-namespace MeshExplorer.Topology
-{
- partial class TopologyControlView
- {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Component Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- this.lbS2 = new System.Windows.Forms.Label();
- this.lbS1 = new System.Windows.Forms.Label();
- this.lbS0 = new System.Windows.Forms.Label();
- this.label6 = new System.Windows.Forms.Label();
- this.lbN2 = new System.Windows.Forms.Label();
- this.lbN1 = new System.Windows.Forms.Label();
- this.lbN0 = new System.Windows.Forms.Label();
- this.label5 = new System.Windows.Forms.Label();
- this.lbPosition = new System.Windows.Forms.Label();
- this.lbV2 = new System.Windows.Forms.Label();
- this.lbV1 = new System.Windows.Forms.Label();
- this.lbV0 = new System.Windows.Forms.Label();
- this.label4 = new System.Windows.Forms.Label();
- this.label1 = new System.Windows.Forms.Label();
- this.label2 = new System.Windows.Forms.Label();
- this.lbTriangle = new System.Windows.Forms.Label();
- this.darkButton9 = new MeshExplorer.Controls.DarkButton();
- this.darkButton7 = new MeshExplorer.Controls.DarkButton();
- this.darkButton5 = new MeshExplorer.Controls.DarkButton();
- this.darkButton3 = new MeshExplorer.Controls.DarkButton();
- this.darkButton8 = new MeshExplorer.Controls.DarkButton();
- this.darkButton6 = new MeshExplorer.Controls.DarkButton();
- this.darkButton4 = new MeshExplorer.Controls.DarkButton();
- this.darkButton2 = new MeshExplorer.Controls.DarkButton();
- this.darkButton1 = new MeshExplorer.Controls.DarkButton();
- this.SuspendLayout();
- //
- // lbS2
- //
- this.lbS2.Location = new System.Drawing.Point(137, 122);
- this.lbS2.Name = "lbS2";
- this.lbS2.Size = new System.Drawing.Size(53, 13);
- this.lbS2.TabIndex = 1;
- this.lbS2.Text = "-";
- this.lbS2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
- //
- // lbS1
- //
- this.lbS1.Location = new System.Drawing.Point(137, 107);
- this.lbS1.Name = "lbS1";
- this.lbS1.Size = new System.Drawing.Size(53, 13);
- this.lbS1.TabIndex = 1;
- this.lbS1.Text = "-";
- this.lbS1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
- //
- // lbS0
- //
- this.lbS0.Location = new System.Drawing.Point(137, 92);
- this.lbS0.Name = "lbS0";
- this.lbS0.Size = new System.Drawing.Size(53, 13);
- this.lbS0.TabIndex = 1;
- this.lbS0.Text = "-";
- this.lbS0.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
- //
- // label6
- //
- this.label6.ImageAlign = System.Drawing.ContentAlignment.MiddleRight;
- this.label6.Location = new System.Drawing.Point(134, 71);
- this.label6.Name = "label6";
- this.label6.Size = new System.Drawing.Size(57, 13);
- this.label6.TabIndex = 1;
- this.label6.Text = "Segments";
- //
- // lbN2
- //
- this.lbN2.Location = new System.Drawing.Point(66, 122);
- this.lbN2.Name = "lbN2";
- this.lbN2.Size = new System.Drawing.Size(57, 13);
- this.lbN2.TabIndex = 1;
- this.lbN2.Text = "-";
- this.lbN2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
- //
- // lbN1
- //
- this.lbN1.Location = new System.Drawing.Point(66, 107);
- this.lbN1.Name = "lbN1";
- this.lbN1.Size = new System.Drawing.Size(57, 13);
- this.lbN1.TabIndex = 1;
- this.lbN1.Text = "-";
- this.lbN1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
- //
- // lbN0
- //
- this.lbN0.Location = new System.Drawing.Point(66, 92);
- this.lbN0.Name = "lbN0";
- this.lbN0.Size = new System.Drawing.Size(57, 13);
- this.lbN0.TabIndex = 1;
- this.lbN0.Text = "-";
- this.lbN0.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
- //
- // label5
- //
- this.label5.ImageAlign = System.Drawing.ContentAlignment.MiddleRight;
- this.label5.Location = new System.Drawing.Point(63, 71);
- this.label5.Name = "label5";
- this.label5.Size = new System.Drawing.Size(61, 13);
- this.label5.TabIndex = 1;
- this.label5.Text = "Neighbors";
- //
- // lbPosition
- //
- this.lbPosition.AutoSize = true;
- this.lbPosition.Location = new System.Drawing.Point(70, 15);
- this.lbPosition.Name = "lbPosition";
- this.lbPosition.Size = new System.Drawing.Size(11, 13);
- this.lbPosition.TabIndex = 1;
- this.lbPosition.Text = "-";
- //
- // lbV2
- //
- this.lbV2.Location = new System.Drawing.Point(16, 122);
- this.lbV2.Name = "lbV2";
- this.lbV2.Size = new System.Drawing.Size(38, 13);
- this.lbV2.TabIndex = 1;
- this.lbV2.Text = "-";
- this.lbV2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
- //
- // lbV1
- //
- this.lbV1.Location = new System.Drawing.Point(16, 107);
- this.lbV1.Name = "lbV1";
- this.lbV1.Size = new System.Drawing.Size(38, 13);
- this.lbV1.TabIndex = 1;
- this.lbV1.Text = "-";
- this.lbV1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
- //
- // lbV0
- //
- this.lbV0.Location = new System.Drawing.Point(16, 92);
- this.lbV0.Name = "lbV0";
- this.lbV0.Size = new System.Drawing.Size(38, 13);
- this.lbV0.TabIndex = 1;
- this.lbV0.Text = "-";
- this.lbV0.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
- //
- // label4
- //
- this.label4.ImageAlign = System.Drawing.ContentAlignment.MiddleRight;
- this.label4.Location = new System.Drawing.Point(8, 71);
- this.label4.Name = "label4";
- this.label4.Size = new System.Drawing.Size(47, 13);
- this.label4.TabIndex = 1;
- this.label4.Text = "Vertices";
- //
- // label1
- //
- this.label1.AutoSize = true;
- this.label1.Location = new System.Drawing.Point(6, 15);
- this.label1.Name = "label1";
- this.label1.Size = new System.Drawing.Size(52, 13);
- this.label1.TabIndex = 1;
- this.label1.Text = "Position:";
- //
- // label2
- //
- this.label2.AutoSize = true;
- this.label2.Location = new System.Drawing.Point(7, 37);
- this.label2.Name = "label2";
- this.label2.Size = new System.Drawing.Size(51, 13);
- this.label2.TabIndex = 1;
- this.label2.Text = "Triangle:";
- //
- // lbTriangle
- //
- this.lbTriangle.AutoSize = true;
- this.lbTriangle.Location = new System.Drawing.Point(70, 37);
- this.lbTriangle.Name = "lbTriangle";
- this.lbTriangle.Size = new System.Drawing.Size(11, 13);
- this.lbTriangle.TabIndex = 1;
- this.lbTriangle.Text = "-";
- //
- // darkButton9
- //
- this.darkButton9.Location = new System.Drawing.Point(99, 367);
- this.darkButton9.Name = "darkButton9";
- this.darkButton9.Size = new System.Drawing.Size(78, 23);
- this.darkButton9.TabIndex = 10;
- this.darkButton9.Text = "Rprev";
- this.darkButton9.UseVisualStyleBackColor = true;
- this.darkButton9.Click += new System.EventHandler(this.btnPrimitive_Click);
- //
- // darkButton7
- //
- this.darkButton7.Location = new System.Drawing.Point(99, 338);
- this.darkButton7.Name = "darkButton7";
- this.darkButton7.Size = new System.Drawing.Size(78, 23);
- this.darkButton7.TabIndex = 8;
- this.darkButton7.Text = "Dprev";
- this.darkButton7.UseVisualStyleBackColor = true;
- this.darkButton7.Click += new System.EventHandler(this.btnPrimitive_Click);
- //
- // darkButton5
- //
- this.darkButton5.Location = new System.Drawing.Point(99, 309);
- this.darkButton5.Name = "darkButton5";
- this.darkButton5.Size = new System.Drawing.Size(78, 23);
- this.darkButton5.TabIndex = 6;
- this.darkButton5.Text = "Oprev";
- this.darkButton5.UseVisualStyleBackColor = true;
- this.darkButton5.Click += new System.EventHandler(this.btnPrimitive_Click);
- //
- // darkButton3
- //
- this.darkButton3.Location = new System.Drawing.Point(99, 280);
- this.darkButton3.Name = "darkButton3";
- this.darkButton3.Size = new System.Drawing.Size(78, 23);
- this.darkButton3.TabIndex = 4;
- this.darkButton3.Text = "Lprev";
- this.darkButton3.UseVisualStyleBackColor = true;
- this.darkButton3.Click += new System.EventHandler(this.btnPrimitive_Click);
- //
- // darkButton8
- //
- this.darkButton8.Location = new System.Drawing.Point(11, 367);
- this.darkButton8.Name = "darkButton8";
- this.darkButton8.Size = new System.Drawing.Size(78, 23);
- this.darkButton8.TabIndex = 9;
- this.darkButton8.Text = "Rnext";
- this.darkButton8.UseVisualStyleBackColor = true;
- this.darkButton8.Click += new System.EventHandler(this.btnPrimitive_Click);
- //
- // darkButton6
- //
- this.darkButton6.Location = new System.Drawing.Point(11, 338);
- this.darkButton6.Name = "darkButton6";
- this.darkButton6.Size = new System.Drawing.Size(78, 23);
- this.darkButton6.TabIndex = 7;
- this.darkButton6.Text = "Dnext";
- this.darkButton6.UseVisualStyleBackColor = true;
- this.darkButton6.Click += new System.EventHandler(this.btnPrimitive_Click);
- //
- // darkButton4
- //
- this.darkButton4.Location = new System.Drawing.Point(11, 309);
- this.darkButton4.Name = "darkButton4";
- this.darkButton4.Size = new System.Drawing.Size(78, 23);
- this.darkButton4.TabIndex = 5;
- this.darkButton4.Text = "Onext";
- this.darkButton4.UseVisualStyleBackColor = true;
- this.darkButton4.Click += new System.EventHandler(this.btnPrimitive_Click);
- //
- // darkButton2
- //
- this.darkButton2.Location = new System.Drawing.Point(11, 280);
- this.darkButton2.Name = "darkButton2";
- this.darkButton2.Size = new System.Drawing.Size(78, 23);
- this.darkButton2.TabIndex = 3;
- this.darkButton2.Text = "Lnext";
- this.darkButton2.UseVisualStyleBackColor = true;
- this.darkButton2.Click += new System.EventHandler(this.btnPrimitive_Click);
- //
- // darkButton1
- //
- this.darkButton1.Location = new System.Drawing.Point(11, 251);
- this.darkButton1.Name = "darkButton1";
- this.darkButton1.Size = new System.Drawing.Size(166, 23);
- this.darkButton1.TabIndex = 2;
- this.darkButton1.Text = "Sym";
- this.darkButton1.UseVisualStyleBackColor = true;
- this.darkButton1.Click += new System.EventHandler(this.btnPrimitive_Click);
- //
- // TopologyControlView
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(76)))), ((int)(((byte)(76)))), ((int)(((byte)(76)))));
- this.Controls.Add(this.darkButton9);
- this.Controls.Add(this.darkButton7);
- this.Controls.Add(this.darkButton5);
- this.Controls.Add(this.darkButton3);
- this.Controls.Add(this.darkButton8);
- this.Controls.Add(this.darkButton6);
- this.Controls.Add(this.darkButton4);
- this.Controls.Add(this.darkButton2);
- this.Controls.Add(this.darkButton1);
- this.Controls.Add(this.lbS2);
- this.Controls.Add(this.lbS1);
- this.Controls.Add(this.lbS0);
- this.Controls.Add(this.label6);
- this.Controls.Add(this.lbN2);
- this.Controls.Add(this.lbN1);
- this.Controls.Add(this.lbN0);
- this.Controls.Add(this.label5);
- this.Controls.Add(this.lbTriangle);
- this.Controls.Add(this.lbPosition);
- this.Controls.Add(this.lbV2);
- this.Controls.Add(this.lbV1);
- this.Controls.Add(this.lbV0);
- this.Controls.Add(this.label4);
- this.Controls.Add(this.label2);
- this.Controls.Add(this.label1);
- this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.ForeColor = System.Drawing.Color.White;
- this.Name = "TopologyControlView";
- this.Size = new System.Drawing.Size(195, 439);
- this.ResumeLayout(false);
- this.PerformLayout();
-
- }
-
- #endregion
-
- private System.Windows.Forms.Label lbS2;
- private System.Windows.Forms.Label lbS1;
- private System.Windows.Forms.Label lbS0;
- private System.Windows.Forms.Label label6;
- private System.Windows.Forms.Label lbN2;
- private System.Windows.Forms.Label lbN1;
- private System.Windows.Forms.Label lbN0;
- private System.Windows.Forms.Label label5;
- private System.Windows.Forms.Label lbPosition;
- private System.Windows.Forms.Label lbV2;
- private System.Windows.Forms.Label lbV1;
- private System.Windows.Forms.Label lbV0;
- private System.Windows.Forms.Label label4;
- private System.Windows.Forms.Label label1;
- private System.Windows.Forms.Label label2;
- private System.Windows.Forms.Label lbTriangle;
- private Controls.DarkButton darkButton9;
- private Controls.DarkButton darkButton7;
- private Controls.DarkButton darkButton5;
- private Controls.DarkButton darkButton3;
- private Controls.DarkButton darkButton8;
- private Controls.DarkButton darkButton6;
- private Controls.DarkButton darkButton4;
- private Controls.DarkButton darkButton2;
- private Controls.DarkButton darkButton1;
- }
-}
+namespace MeshExplorer.Topology
+{
+ partial class TopologyControlView
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.lbS2 = new System.Windows.Forms.Label();
+ this.lbS1 = new System.Windows.Forms.Label();
+ this.lbS0 = new System.Windows.Forms.Label();
+ this.label6 = new System.Windows.Forms.Label();
+ this.lbN2 = new System.Windows.Forms.Label();
+ this.lbN1 = new System.Windows.Forms.Label();
+ this.lbN0 = new System.Windows.Forms.Label();
+ this.label5 = new System.Windows.Forms.Label();
+ this.lbPosition = new System.Windows.Forms.Label();
+ this.lbV2 = new System.Windows.Forms.Label();
+ this.lbV1 = new System.Windows.Forms.Label();
+ this.lbV0 = new System.Windows.Forms.Label();
+ this.label4 = new System.Windows.Forms.Label();
+ this.label1 = new System.Windows.Forms.Label();
+ this.label2 = new System.Windows.Forms.Label();
+ this.lbTriangle = new System.Windows.Forms.Label();
+ this.darkButton9 = new MeshExplorer.Controls.DarkButton();
+ this.darkButton7 = new MeshExplorer.Controls.DarkButton();
+ this.darkButton5 = new MeshExplorer.Controls.DarkButton();
+ this.darkButton3 = new MeshExplorer.Controls.DarkButton();
+ this.darkButton8 = new MeshExplorer.Controls.DarkButton();
+ this.darkButton6 = new MeshExplorer.Controls.DarkButton();
+ this.darkButton4 = new MeshExplorer.Controls.DarkButton();
+ this.darkButton2 = new MeshExplorer.Controls.DarkButton();
+ this.darkButton1 = new MeshExplorer.Controls.DarkButton();
+ this.SuspendLayout();
+ //
+ // lbS2
+ //
+ this.lbS2.Location = new System.Drawing.Point(137, 122);
+ this.lbS2.Name = "lbS2";
+ this.lbS2.Size = new System.Drawing.Size(53, 13);
+ this.lbS2.TabIndex = 1;
+ this.lbS2.Text = "-";
+ this.lbS2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // lbS1
+ //
+ this.lbS1.Location = new System.Drawing.Point(137, 107);
+ this.lbS1.Name = "lbS1";
+ this.lbS1.Size = new System.Drawing.Size(53, 13);
+ this.lbS1.TabIndex = 1;
+ this.lbS1.Text = "-";
+ this.lbS1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // lbS0
+ //
+ this.lbS0.Location = new System.Drawing.Point(137, 92);
+ this.lbS0.Name = "lbS0";
+ this.lbS0.Size = new System.Drawing.Size(53, 13);
+ this.lbS0.TabIndex = 1;
+ this.lbS0.Text = "-";
+ this.lbS0.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // label6
+ //
+ this.label6.ImageAlign = System.Drawing.ContentAlignment.MiddleRight;
+ this.label6.Location = new System.Drawing.Point(134, 71);
+ this.label6.Name = "label6";
+ this.label6.Size = new System.Drawing.Size(57, 13);
+ this.label6.TabIndex = 1;
+ this.label6.Text = "Segments";
+ //
+ // lbN2
+ //
+ this.lbN2.Location = new System.Drawing.Point(66, 122);
+ this.lbN2.Name = "lbN2";
+ this.lbN2.Size = new System.Drawing.Size(57, 13);
+ this.lbN2.TabIndex = 1;
+ this.lbN2.Text = "-";
+ this.lbN2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // lbN1
+ //
+ this.lbN1.Location = new System.Drawing.Point(66, 107);
+ this.lbN1.Name = "lbN1";
+ this.lbN1.Size = new System.Drawing.Size(57, 13);
+ this.lbN1.TabIndex = 1;
+ this.lbN1.Text = "-";
+ this.lbN1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // lbN0
+ //
+ this.lbN0.Location = new System.Drawing.Point(66, 92);
+ this.lbN0.Name = "lbN0";
+ this.lbN0.Size = new System.Drawing.Size(57, 13);
+ this.lbN0.TabIndex = 1;
+ this.lbN0.Text = "-";
+ this.lbN0.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // label5
+ //
+ this.label5.ImageAlign = System.Drawing.ContentAlignment.MiddleRight;
+ this.label5.Location = new System.Drawing.Point(63, 71);
+ this.label5.Name = "label5";
+ this.label5.Size = new System.Drawing.Size(61, 13);
+ this.label5.TabIndex = 1;
+ this.label5.Text = "Neighbors";
+ //
+ // lbPosition
+ //
+ this.lbPosition.AutoSize = true;
+ this.lbPosition.Location = new System.Drawing.Point(70, 15);
+ this.lbPosition.Name = "lbPosition";
+ this.lbPosition.Size = new System.Drawing.Size(11, 13);
+ this.lbPosition.TabIndex = 1;
+ this.lbPosition.Text = "-";
+ //
+ // lbV2
+ //
+ this.lbV2.Location = new System.Drawing.Point(16, 122);
+ this.lbV2.Name = "lbV2";
+ this.lbV2.Size = new System.Drawing.Size(38, 13);
+ this.lbV2.TabIndex = 1;
+ this.lbV2.Text = "-";
+ this.lbV2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // lbV1
+ //
+ this.lbV1.Location = new System.Drawing.Point(16, 107);
+ this.lbV1.Name = "lbV1";
+ this.lbV1.Size = new System.Drawing.Size(38, 13);
+ this.lbV1.TabIndex = 1;
+ this.lbV1.Text = "-";
+ this.lbV1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // lbV0
+ //
+ this.lbV0.Location = new System.Drawing.Point(16, 92);
+ this.lbV0.Name = "lbV0";
+ this.lbV0.Size = new System.Drawing.Size(38, 13);
+ this.lbV0.TabIndex = 1;
+ this.lbV0.Text = "-";
+ this.lbV0.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // label4
+ //
+ this.label4.ImageAlign = System.Drawing.ContentAlignment.MiddleRight;
+ this.label4.Location = new System.Drawing.Point(8, 71);
+ this.label4.Name = "label4";
+ this.label4.Size = new System.Drawing.Size(47, 13);
+ this.label4.TabIndex = 1;
+ this.label4.Text = "Vertices";
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(6, 15);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(52, 13);
+ this.label1.TabIndex = 1;
+ this.label1.Text = "Position:";
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(7, 37);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(51, 13);
+ this.label2.TabIndex = 1;
+ this.label2.Text = "Triangle:";
+ //
+ // lbTriangle
+ //
+ this.lbTriangle.AutoSize = true;
+ this.lbTriangle.Location = new System.Drawing.Point(70, 37);
+ this.lbTriangle.Name = "lbTriangle";
+ this.lbTriangle.Size = new System.Drawing.Size(11, 13);
+ this.lbTriangle.TabIndex = 1;
+ this.lbTriangle.Text = "-";
+ //
+ // darkButton9
+ //
+ this.darkButton9.Location = new System.Drawing.Point(99, 367);
+ this.darkButton9.Name = "darkButton9";
+ this.darkButton9.Size = new System.Drawing.Size(78, 23);
+ this.darkButton9.TabIndex = 10;
+ this.darkButton9.Text = "Rprev";
+ this.darkButton9.UseVisualStyleBackColor = true;
+ this.darkButton9.Click += new System.EventHandler(this.btnPrimitive_Click);
+ //
+ // darkButton7
+ //
+ this.darkButton7.Location = new System.Drawing.Point(99, 338);
+ this.darkButton7.Name = "darkButton7";
+ this.darkButton7.Size = new System.Drawing.Size(78, 23);
+ this.darkButton7.TabIndex = 8;
+ this.darkButton7.Text = "Dprev";
+ this.darkButton7.UseVisualStyleBackColor = true;
+ this.darkButton7.Click += new System.EventHandler(this.btnPrimitive_Click);
+ //
+ // darkButton5
+ //
+ this.darkButton5.Location = new System.Drawing.Point(99, 309);
+ this.darkButton5.Name = "darkButton5";
+ this.darkButton5.Size = new System.Drawing.Size(78, 23);
+ this.darkButton5.TabIndex = 6;
+ this.darkButton5.Text = "Oprev";
+ this.darkButton5.UseVisualStyleBackColor = true;
+ this.darkButton5.Click += new System.EventHandler(this.btnPrimitive_Click);
+ //
+ // darkButton3
+ //
+ this.darkButton3.Location = new System.Drawing.Point(99, 280);
+ this.darkButton3.Name = "darkButton3";
+ this.darkButton3.Size = new System.Drawing.Size(78, 23);
+ this.darkButton3.TabIndex = 4;
+ this.darkButton3.Text = "Lprev";
+ this.darkButton3.UseVisualStyleBackColor = true;
+ this.darkButton3.Click += new System.EventHandler(this.btnPrimitive_Click);
+ //
+ // darkButton8
+ //
+ this.darkButton8.Location = new System.Drawing.Point(11, 367);
+ this.darkButton8.Name = "darkButton8";
+ this.darkButton8.Size = new System.Drawing.Size(78, 23);
+ this.darkButton8.TabIndex = 9;
+ this.darkButton8.Text = "Rnext";
+ this.darkButton8.UseVisualStyleBackColor = true;
+ this.darkButton8.Click += new System.EventHandler(this.btnPrimitive_Click);
+ //
+ // darkButton6
+ //
+ this.darkButton6.Location = new System.Drawing.Point(11, 338);
+ this.darkButton6.Name = "darkButton6";
+ this.darkButton6.Size = new System.Drawing.Size(78, 23);
+ this.darkButton6.TabIndex = 7;
+ this.darkButton6.Text = "Dnext";
+ this.darkButton6.UseVisualStyleBackColor = true;
+ this.darkButton6.Click += new System.EventHandler(this.btnPrimitive_Click);
+ //
+ // darkButton4
+ //
+ this.darkButton4.Location = new System.Drawing.Point(11, 309);
+ this.darkButton4.Name = "darkButton4";
+ this.darkButton4.Size = new System.Drawing.Size(78, 23);
+ this.darkButton4.TabIndex = 5;
+ this.darkButton4.Text = "Onext";
+ this.darkButton4.UseVisualStyleBackColor = true;
+ this.darkButton4.Click += new System.EventHandler(this.btnPrimitive_Click);
+ //
+ // darkButton2
+ //
+ this.darkButton2.Location = new System.Drawing.Point(11, 280);
+ this.darkButton2.Name = "darkButton2";
+ this.darkButton2.Size = new System.Drawing.Size(78, 23);
+ this.darkButton2.TabIndex = 3;
+ this.darkButton2.Text = "Lnext";
+ this.darkButton2.UseVisualStyleBackColor = true;
+ this.darkButton2.Click += new System.EventHandler(this.btnPrimitive_Click);
+ //
+ // darkButton1
+ //
+ this.darkButton1.Location = new System.Drawing.Point(11, 251);
+ this.darkButton1.Name = "darkButton1";
+ this.darkButton1.Size = new System.Drawing.Size(166, 23);
+ this.darkButton1.TabIndex = 2;
+ this.darkButton1.Text = "Sym";
+ this.darkButton1.UseVisualStyleBackColor = true;
+ this.darkButton1.Click += new System.EventHandler(this.btnPrimitive_Click);
+ //
+ // TopologyControlView
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(76)))), ((int)(((byte)(76)))), ((int)(((byte)(76)))));
+ this.Controls.Add(this.darkButton9);
+ this.Controls.Add(this.darkButton7);
+ this.Controls.Add(this.darkButton5);
+ this.Controls.Add(this.darkButton3);
+ this.Controls.Add(this.darkButton8);
+ this.Controls.Add(this.darkButton6);
+ this.Controls.Add(this.darkButton4);
+ this.Controls.Add(this.darkButton2);
+ this.Controls.Add(this.darkButton1);
+ this.Controls.Add(this.lbS2);
+ this.Controls.Add(this.lbS1);
+ this.Controls.Add(this.lbS0);
+ this.Controls.Add(this.label6);
+ this.Controls.Add(this.lbN2);
+ this.Controls.Add(this.lbN1);
+ this.Controls.Add(this.lbN0);
+ this.Controls.Add(this.label5);
+ this.Controls.Add(this.lbTriangle);
+ this.Controls.Add(this.lbPosition);
+ this.Controls.Add(this.lbV2);
+ this.Controls.Add(this.lbV1);
+ this.Controls.Add(this.lbV0);
+ this.Controls.Add(this.label4);
+ this.Controls.Add(this.label2);
+ this.Controls.Add(this.label1);
+ this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.ForeColor = System.Drawing.Color.White;
+ this.Name = "TopologyControlView";
+ this.Size = new System.Drawing.Size(195, 439);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Label lbS2;
+ private System.Windows.Forms.Label lbS1;
+ private System.Windows.Forms.Label lbS0;
+ private System.Windows.Forms.Label label6;
+ private System.Windows.Forms.Label lbN2;
+ private System.Windows.Forms.Label lbN1;
+ private System.Windows.Forms.Label lbN0;
+ private System.Windows.Forms.Label label5;
+ private System.Windows.Forms.Label lbPosition;
+ private System.Windows.Forms.Label lbV2;
+ private System.Windows.Forms.Label lbV1;
+ private System.Windows.Forms.Label lbV0;
+ private System.Windows.Forms.Label label4;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.Label lbTriangle;
+ private Controls.DarkButton darkButton9;
+ private Controls.DarkButton darkButton7;
+ private Controls.DarkButton darkButton5;
+ private Controls.DarkButton darkButton3;
+ private Controls.DarkButton darkButton8;
+ private Controls.DarkButton darkButton6;
+ private Controls.DarkButton darkButton4;
+ private Controls.DarkButton darkButton2;
+ private Controls.DarkButton darkButton1;
+ }
+}
diff --git a/Triangle.NET/TestApp/Topology/TopologyControlView.cs b/src/Triangle.Viewer/Topology/TopologyControlView.cs
similarity index 91%
rename from Triangle.NET/TestApp/Topology/TopologyControlView.cs
rename to src/Triangle.Viewer/Topology/TopologyControlView.cs
index 69563e3..351684e 100644
--- a/Triangle.NET/TestApp/Topology/TopologyControlView.cs
+++ b/src/Triangle.Viewer/Topology/TopologyControlView.cs
@@ -1,83 +1,83 @@
-using System;
-using System.Drawing;
-using System.Globalization;
-using System.Windows.Forms;
-using TriangleNet.Geometry;
-
-namespace MeshExplorer.Topology
-{
- public partial class TopologyControlView : UserControl
- {
- public event EventHandler> PrimitiveCommandInvoked;
-
- public TopologyControlView()
- {
- InitializeComponent();
- }
-
- public void SetPosition(PointF p)
- {
- var nfi = NumberFormatInfo.InvariantInfo;
-
- lbPosition.Text = String.Format(nfi, "X: {0:0.0}, Y: {1:0.0}", p.X, p.Y);
- }
-
- public void SetTriangle(ITriangle tri)
- {
- if (tri != null)
- {
- lbTriangle.Text = tri.ID.ToString();
-
- lbV0.Text = tri.GetVertexID(0).ToString();
- lbV1.Text = tri.GetVertexID(1).ToString();
- lbV2.Text = tri.GetVertexID(2).ToString();
-
- lbN0.Text = tri.GetNeighborID(0).ToString();
- lbN1.Text = tri.GetNeighborID(1).ToString();
- lbN2.Text = tri.GetNeighborID(2).ToString();
-
- lbS0.Text = GetSegmentString(tri.GetSegment(0));
- lbS1.Text = GetSegmentString(tri.GetSegment(1));
- lbS2.Text = GetSegmentString(tri.GetSegment(2));
- }
- else
- {
- lbTriangle.Text = "-";
-
- lbV0.Text = "-";
- lbV1.Text = "-";
- lbV2.Text = "-";
-
- lbN0.Text = "-";
- lbN1.Text = "-";
- lbN2.Text = "-";
-
- lbS0.Text = "-";
- lbS1.Text = "-";
- lbS2.Text = "-";
- }
- }
-
- private string GetSegmentString(ISegment seg)
- {
- return seg == null ? "-" : "[" + seg.P0 + " - " + seg.P1 + "]";
- }
-
- private void btnPrimitive_Click(object sender, EventArgs e)
- {
- var button = sender as Button;
-
- if (button != null)
- {
- var name = button.Text.ToLowerInvariant();
-
- var handler = PrimitiveCommandInvoked;
-
- if (handler != null)
- {
- handler(this, new GenericEventArgs(name));
- }
- }
- }
- }
-}
+using System;
+using System.Drawing;
+using System.Globalization;
+using System.Windows.Forms;
+using TriangleNet.Geometry;
+
+namespace MeshExplorer.Topology
+{
+ public partial class TopologyControlView : UserControl
+ {
+ public event EventHandler> PrimitiveCommandInvoked;
+
+ public TopologyControlView()
+ {
+ InitializeComponent();
+ }
+
+ public void SetPosition(double x, double y)
+ {
+ var nfi = NumberFormatInfo.InvariantInfo;
+
+ lbPosition.Text = string.Format(nfi, "X: {0:0.0}, Y: {1:0.0}", x, y);
+ }
+
+ public void SetTriangle(ITriangle tri)
+ {
+ if (tri != null)
+ {
+ lbTriangle.Text = tri.ID.ToString();
+
+ lbV0.Text = tri.GetVertexID(0).ToString();
+ lbV1.Text = tri.GetVertexID(1).ToString();
+ lbV2.Text = tri.GetVertexID(2).ToString();
+
+ lbN0.Text = tri.GetNeighborID(0).ToString();
+ lbN1.Text = tri.GetNeighborID(1).ToString();
+ lbN2.Text = tri.GetNeighborID(2).ToString();
+
+ lbS0.Text = GetSegmentString(tri.GetSegment(0));
+ lbS1.Text = GetSegmentString(tri.GetSegment(1));
+ lbS2.Text = GetSegmentString(tri.GetSegment(2));
+ }
+ else
+ {
+ lbTriangle.Text = "-";
+
+ lbV0.Text = "-";
+ lbV1.Text = "-";
+ lbV2.Text = "-";
+
+ lbN0.Text = "-";
+ lbN1.Text = "-";
+ lbN2.Text = "-";
+
+ lbS0.Text = "-";
+ lbS1.Text = "-";
+ lbS2.Text = "-";
+ }
+ }
+
+ private string GetSegmentString(ISegment seg)
+ {
+ return seg == null ? "-" : "[" + seg.P0 + " - " + seg.P1 + "]";
+ }
+
+ private void btnPrimitive_Click(object sender, EventArgs e)
+ {
+ var button = sender as Button;
+
+ if (button != null)
+ {
+ var name = button.Text.ToLowerInvariant();
+
+ var handler = PrimitiveCommandInvoked;
+
+ if (handler != null)
+ {
+ handler(this, new GenericEventArgs(name));
+ }
+ }
+ }
+ }
+}
diff --git a/Triangle.NET/TestApp/Topology/TopologyControlView.resx b/src/Triangle.Viewer/Topology/TopologyControlView.resx
similarity index 97%
rename from Triangle.NET/TestApp/Topology/TopologyControlView.resx
rename to src/Triangle.Viewer/Topology/TopologyControlView.resx
index 29dcb1b..1af7de1 100644
--- a/Triangle.NET/TestApp/Topology/TopologyControlView.resx
+++ b/src/Triangle.Viewer/Topology/TopologyControlView.resx
@@ -1,120 +1,120 @@
-
-
-
-
-
-
-