diff --git a/Microsoft.VisualBasic.Core/src/Language/StringHelpers.vb b/Microsoft.VisualBasic.Core/src/Language/StringHelpers.vb
index fd2a5f15b..cfa92d4c2 100644
--- a/Microsoft.VisualBasic.Core/src/Language/StringHelpers.vb
+++ b/Microsoft.VisualBasic.Core/src/Language/StringHelpers.vb
@@ -65,8 +65,21 @@ Namespace Language
'''
Public Module FormatHelpers
+ '''
+ ''' Removes all leading and trailing occurrences of a set of characters specified
+ ''' in an array from the current string.
+ '''
+ '''
+ ''' An array of Unicode characters to remove, or null.
+ '''
+ ''' The string that remains after all occurrences of the characters in the trimChars
+ ''' parameter are removed from the start and end of the current string. If trimChars
+ ''' is null or an empty array, white-space characters are removed instead. If no
+ ''' characters can be trimmed from the current instance, the method returns the current
+ ''' instance unchanged.
+ '''
- Public Function Trim(str As Value(Of String), c As Char()) As String
+ Public Function Trim(str As Value(Of String), ParamArray c As Char()) As String
If str Is Nothing OrElse str.Value Is Nothing Then
Return ""
Else
diff --git a/Microsoft.VisualBasic.Core/src/Language/Value/ByRefValueExtensions.vb b/Microsoft.VisualBasic.Core/src/Language/Value/ByRefValueExtensions.vb
index a23ef1f9f..ecfc0e642 100644
--- a/Microsoft.VisualBasic.Core/src/Language/Value/ByRefValueExtensions.vb
+++ b/Microsoft.VisualBasic.Core/src/Language/Value/ByRefValueExtensions.vb
@@ -89,10 +89,22 @@ Namespace Language.Values
Return list.Value.First
End Function
+ '''
+ ''' get the first char
+ '''
+ '''
+ '''
Public Function First(str As ByRefString) As Char
- Return str.Value.First
+ If str Is Nothing OrElse
+ str.Value Is Nothing OrElse
+ str.Value.Length = 0 Then
+
+ Return Nothing
+ Else
+ Return str.Value.First
+ End If
End Function
diff --git a/gr/Landscape/3DBuilder/XML/models.vb b/gr/Landscape/3DBuilder/XML/models.vb
index 9e193c8bb..c0820cf99 100644
--- a/gr/Landscape/3DBuilder/XML/models.vb
+++ b/gr/Landscape/3DBuilder/XML/models.vb
@@ -119,6 +119,9 @@ Namespace Vendor_3mf.XML
End Function
End Class
+ '''
+ ''' 3 vertex index to create a triangle of the surface model data
+ '''
Public Class triangle
Public Property v1 As Integer
diff --git a/gr/Landscape/PLY/Header.vb b/gr/Landscape/PLY/Header.vb
index d91986136..d293d5f4f 100644
--- a/gr/Landscape/PLY/Header.vb
+++ b/gr/Landscape/PLY/Header.vb
@@ -1,73 +1,69 @@
#Region "Microsoft.VisualBasic::050e16ba84ef1932bc43eda21a2e551e, sciBASIC#\gr\Landscape\PLY\Header.vb"
- ' Author:
- '
- ' asuka (amethyst.asuka@gcmodeller.org)
- ' xie (genetics@smrucc.org)
- ' xieguigang (xie.guigang@live.com)
- '
- ' Copyright (c) 2018 GPL3 Licensed
- '
- '
- ' GNU GENERAL PUBLIC LICENSE (GPL3)
- '
- '
- ' This program is free software: you can redistribute it and/or modify
- ' it under the terms of the GNU General Public License as published by
- ' the Free Software Foundation, either version 3 of the License, or
- ' (at your option) any later version.
- '
- ' This program is distributed in the hope that it will be useful,
- ' but WITHOUT ANY WARRANTY; without even the implied warranty of
- ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ' GNU General Public License for more details.
- '
- ' You should have received a copy of the GNU General Public License
- ' along with this program. If not, see .
-
-
-
- ' /********************************************************************************/
-
- ' Summaries:
-
-
- ' Code Statistics:
-
- ' Total Lines: 94
- ' Code Lines: 76
- ' Comment Lines: 0
- ' Blank Lines: 18
- ' File Size: 3.52 KB
-
-
- ' Class Header
- '
- ' Properties: comment, element_face, element_vertex, properties
- '
- ' Sub: WriteAsciiText
- '
- ' Module SimplePlyWriter
- '
- ' Function: WriteAsciiText
- '
- ' Class PointCloud
- '
- ' Properties: color, intensity, x, y, z
- '
- ' Function: ToString
- '
- '
- ' /********************************************************************************/
+' Author:
+'
+' asuka (amethyst.asuka@gcmodeller.org)
+' xie (genetics@smrucc.org)
+' xieguigang (xie.guigang@live.com)
+'
+' Copyright (c) 2018 GPL3 Licensed
+'
+'
+' GNU GENERAL PUBLIC LICENSE (GPL3)
+'
+'
+' This program is free software: you can redistribute it and/or modify
+' it under the terms of the GNU General Public License as published by
+' the Free Software Foundation, either version 3 of the License, or
+' (at your option) any later version.
+'
+' This program is distributed in the hope that it will be useful,
+' but WITHOUT ANY WARRANTY; without even the implied warranty of
+' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+' GNU General Public License for more details.
+'
+' You should have received a copy of the GNU General Public License
+' along with this program. If not, see .
+
+
+
+' /********************************************************************************/
+
+' Summaries:
+
+
+' Code Statistics:
+
+' Total Lines: 94
+' Code Lines: 76
+' Comment Lines: 0
+' Blank Lines: 18
+' File Size: 3.52 KB
+
+
+' Class Header
+'
+' Properties: comment, element_face, element_vertex, properties
+'
+' Sub: WriteAsciiText
+'
+' Module SimplePlyWriter
+'
+' Function: WriteAsciiText
+'
+' Class PointCloud
+'
+' Properties: color, intensity, x, y, z
+'
+' Function: ToString
+'
+'
+' /********************************************************************************/
#End Region
-Imports System.Drawing
Imports System.IO
-Imports System.Text
Imports Microsoft.VisualBasic.ComponentModel.DataSourceModel
-Imports Microsoft.VisualBasic.ComponentModel.Ranges.Model
-Imports Microsoft.VisualBasic.Imaging.Drawing2D.Colors
Namespace Ply
@@ -91,68 +87,5 @@ Namespace Ply
Call file.WriteLine($"end_header")
End Sub
-
- End Class
-
- Public Module SimplePlyWriter
-
- Public Function WriteAsciiText(pointCloud As IEnumerable(Of PointCloud),
- buffer As Stream,
- Optional colors As ScalerPalette = ScalerPalette.turbo,
- Optional levels As Integer = 200) As Boolean
-
- Using file As New StreamWriter(buffer, Encoding.ASCII) With {
- .AutoFlush = True,
- .NewLine = vbLf
- }
- Dim vertex As PointCloud() = pointCloud.ToArray
- Dim header As New Header With {
- .comment = "Point Cloud Model",
- .element_face = -1,
- .element_vertex = vertex.Length,
- .properties = {
- New NamedValue(Of String)("x", "float"),
- New NamedValue(Of String)("y", "float"),
- New NamedValue(Of String)("z", "float"),
- New NamedValue(Of String)("intensity", "float"),
- New NamedValue(Of String)("color", "string")
- }
- }
- Dim colorSet As String() = Designer _
- .GetColors(colors.Description, levels) _
- .Select(Function(c) c.ToHtmlColor) _
- .ToArray
- Dim scale As New DoubleRange(From v As PointCloud In vertex Select v.intensity)
- Dim i As Integer
- Dim index As New DoubleRange(0, levels - 1)
- Dim clr As String
-
- Call header.WriteAsciiText(file)
- Call file.Flush()
-
- For Each point As PointCloud In vertex
- i = scale.ScaleMapping(point.intensity, index)
- clr = colorSet(i)
-
- Call file.WriteLine($"{point.x.ToString("F3")} {point.y.ToString("F3")} {point.z.ToString("F3")} {point.intensity} {clr}")
- Next
- End Using
-
- Return True
- End Function
- End Module
-
- Public Class PointCloud
-
- Public Property x As Double
- Public Property y As Double
- Public Property z As Double
- Public Property color As String
- Public Property intensity As Double
-
- Public Overrides Function ToString() As String
- Return $"[{x},{y},{z}] {intensity}"
- End Function
-
End Class
End Namespace
diff --git a/gr/Landscape/PLY/PointCloud.vb b/gr/Landscape/PLY/PointCloud.vb
new file mode 100644
index 000000000..833a8ad61
--- /dev/null
+++ b/gr/Landscape/PLY/PointCloud.vb
@@ -0,0 +1,16 @@
+Namespace Ply
+
+ Public Class PointCloud
+
+ Public Property x As Double
+ Public Property y As Double
+ Public Property z As Double
+ Public Property color As String
+ Public Property intensity As Double
+
+ Public Overrides Function ToString() As String
+ Return $"[{x},{y},{z}] {intensity}"
+ End Function
+
+ End Class
+End Namespace
\ No newline at end of file
diff --git a/gr/Landscape/PLY/SimplePlyWriter.vb b/gr/Landscape/PLY/SimplePlyWriter.vb
new file mode 100644
index 000000000..595e2bf3b
--- /dev/null
+++ b/gr/Landscape/PLY/SimplePlyWriter.vb
@@ -0,0 +1,56 @@
+Imports Microsoft.VisualBasic.ComponentModel.DataSourceModel
+Imports Microsoft.VisualBasic.ComponentModel.Ranges.Model
+Imports Microsoft.VisualBasic.Imaging.Drawing2D.Colors
+Imports System.IO
+Imports System.Text
+
+Namespace Ply
+
+ Public Module SimplePlyWriter
+
+ Public Function WriteAsciiText(pointCloud As IEnumerable(Of PointCloud),
+ buffer As Stream,
+ Optional colors As ScalerPalette = ScalerPalette.turbo,
+ Optional levels As Integer = 200) As Boolean
+
+ Using file As New StreamWriter(buffer, Encoding.ASCII) With {
+ .AutoFlush = True,
+ .NewLine = vbLf
+ }
+ Dim vertex As PointCloud() = pointCloud.ToArray
+ Dim header As New Header With {
+ .comment = "Point Cloud Model",
+ .element_face = -1,
+ .element_vertex = vertex.Length,
+ .properties = {
+ New NamedValue(Of String)("x", "float"),
+ New NamedValue(Of String)("y", "float"),
+ New NamedValue(Of String)("z", "float"),
+ New NamedValue(Of String)("intensity", "float"),
+ New NamedValue(Of String)("color", "string")
+ }
+ }
+ Dim colorSet As String() = Designer _
+ .GetColors(colors.Description, levels) _
+ .Select(Function(c) c.ToHtmlColor) _
+ .ToArray
+ Dim scale As New DoubleRange(From v As PointCloud In vertex Select v.intensity)
+ Dim i As Integer
+ Dim index As New DoubleRange(0, levels - 1)
+ Dim clr As String
+
+ Call header.WriteAsciiText(file)
+ Call file.Flush()
+
+ For Each point As PointCloud In vertex
+ i = scale.ScaleMapping(point.intensity, index)
+ clr = colorSet(i)
+
+ Call file.WriteLine($"{point.x.ToString("F3")} {point.y.ToString("F3")} {point.z.ToString("F3")} {point.intensity} {clr}")
+ Next
+ End Using
+
+ Return True
+ End Function
+ End Module
+End Namespace
\ No newline at end of file
diff --git a/gr/Landscape/Wavefront/FileName.vb b/gr/Landscape/Wavefront/FileName.vb
new file mode 100644
index 000000000..c64edbcba
--- /dev/null
+++ b/gr/Landscape/Wavefront/FileName.vb
@@ -0,0 +1,10 @@
+Namespace Wavefront
+
+ Public Class Triangle
+
+ Public Property v3 As Integer()
+ Public Property vn3 As Integer()
+ Public Property comment As String
+
+ End Class
+End Namespace
\ No newline at end of file
diff --git a/gr/Landscape/Wavefront/OBJ.vb b/gr/Landscape/Wavefront/OBJ.vb
new file mode 100644
index 000000000..8e8006a7d
--- /dev/null
+++ b/gr/Landscape/Wavefront/OBJ.vb
@@ -0,0 +1,49 @@
+Imports System.IO
+Imports System.Runtime.CompilerServices
+Imports Microsoft.VisualBasic.Imaging.Drawing3D
+Imports Microsoft.VisualBasic.Language
+
+Namespace Wavefront
+
+ Public Class OBJ
+
+ '''
+ ''' lib file name of mtl data
+ '''
+ '''
+ Public Property mtllib As String
+ Public Property parts As ObjectPart()
+ Public Property comment As String
+
+
+
+ Public Shared Function ReadFile(file As StreamReader) As OBJ
+ Return TextParser.ParseFile(file)
+ End Function
+
+ End Class
+
+ Public Class ObjectPart
+
+ Public Property g As String
+ Public Property vertex As Point3D()
+ Public Property vn As Point3D()
+ Public Property usemtl As String
+ Public Property f As Triangle()
+
+ Public ReadOnly Property IsEmpty As Boolean
+ Get
+ Return g.StringEmpty AndAlso
+ vertex.IsNullOrEmpty AndAlso
+ vn.IsNullOrEmpty AndAlso
+ usemtl.StringEmpty AndAlso
+ f.IsNullOrEmpty
+ End Get
+ End Property
+
+ Public Overrides Function ToString() As String
+ Return $"{g Or "no_label".AsDefault}: {vertex.Length} vertexs and {f.Length} triangles"
+ End Function
+
+ End Class
+End Namespace
\ No newline at end of file
diff --git a/gr/Landscape/Wavefront/TextParser.vb b/gr/Landscape/Wavefront/TextParser.vb
new file mode 100644
index 000000000..10109476f
--- /dev/null
+++ b/gr/Landscape/Wavefront/TextParser.vb
@@ -0,0 +1,103 @@
+Imports System.IO
+Imports System.Runtime.CompilerServices
+Imports System.Text
+Imports Microsoft.VisualBasic.Imaging.Drawing3D
+Imports Microsoft.VisualBasic.Language
+Imports Microsoft.VisualBasic.Language.Values
+Imports Microsoft.VisualBasic.Linq
+
+Namespace Wavefront
+
+ Public Module TextParser
+
+
+ Public Function ParseFile(buf As StreamReader) As OBJ
+ Dim line As New Value(Of String)
+ Dim comments As New StringBuilder
+ Dim mtllib As String = Nothing
+ Dim parts As New List(Of ObjectPart)
+ Dim vertex As New List(Of Point3D)
+ Dim vn As New List(Of Point3D)
+ Dim g As String = Nothing
+ Dim usemtl As String = Nothing
+ Dim f As New List(Of Triangle)
+
+ Do While Not (line = buf.ReadLine) Is Nothing
+ If line.First = "#"c Then
+ comments.AppendLine(line.Trim("#"c, " "c))
+ ElseIf Not line.Value.StringEmpty Then
+ If line.StartsWith("mtllib") Then
+ mtllib = Mid(line.Value, "mtllib".Length + 1).Trim
+ Else
+ Dim tokens As String() = line.Split
+
+ Select Case tokens(Scan0)
+ Case "v"
+ Call vertex.Add(tokens.Skip(1).Select(AddressOf Val).ToArray.DoCall(Function(v) New Point3D(v)))
+ Case "vn"
+ Call vn.Add(tokens.Skip(1).Select(AddressOf Val).ToArray.DoCall(Function(v) New Point3D(v)))
+ Case "g"
+ g = tokens.Skip(1).JoinBy(" ")
+ Case "usemtl"
+ usemtl = tokens.Skip(1).JoinBy(" ")
+ Case "f"
+ Dim ints As Integer()() = tokens _
+ .Skip(1) _
+ .Take(3) _
+ .Select(Function(str)
+ Return str.Split("/"c).Select(Function(c) CInt(Val(c))).ToArray
+ End Function) _
+ .ToArray
+
+ f.Add(New Triangle With {
+ .v3 = ints.Select(Function(v) v(Scan0)).ToArray,
+ .vn3 = ints.Select(Function(v) v(2)).ToArray,
+ .comment = tokens(4)
+ })
+ Case Else
+ Throw New NotImplementedException(line)
+ End Select
+ End If
+ Else
+ Dim objPart As New ObjectPart With {
+ .vertex = vertex.ToArray,
+ .vn = vn.ToArray,
+ .g = g,
+ .usemtl = usemtl,
+ .f = f.ToArray
+ }
+
+ If Not objPart.IsEmpty Then
+ ' create new part
+ Call parts.Add(objPart)
+ End If
+
+ g = Nothing
+ usemtl = Nothing
+ f.Clear()
+ vertex.Clear()
+ vn.Clear()
+ End If
+ Loop
+
+ If vertex.Count > 0 Then
+ Dim objPart As New ObjectPart With {
+ .vertex = vertex.ToArray,
+ .vn = vn.ToArray,
+ .g = g,
+ .usemtl = usemtl,
+ .f = f.ToArray
+ }
+
+ ' create new part
+ parts.Add(objPart)
+ End If
+
+ Return New OBJ With {
+ .comment = comments.ToString,
+ .mtllib = mtllib,
+ .parts = parts.ToArray
+ }
+ End Function
+ End Module
+End Namespace
\ No newline at end of file
diff --git a/gr/Microsoft.VisualBasic.Imaging.sln b/gr/Microsoft.VisualBasic.Imaging.sln
index 347249476..21a9f3bc3 100644
--- a/gr/Microsoft.VisualBasic.Imaging.sln
+++ b/gr/Microsoft.VisualBasic.Imaging.sln
@@ -1,294 +1,385 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.29102.190
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.33326.253
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Microsoft.VisualBasic.Imaging", "Microsoft.VisualBasic.Imaging\Microsoft.VisualBasic.Imaging.vbproj", "{85E71B4B-9276-4EC8-AADC-C849205F1EA8}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "framework", "framework", "{E0DFA7E4-1D86-4239-A8F6-C3ECAE31EC3D}"
EndProject
-Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "47-dotnet_Microsoft.VisualBasic", "..\Microsoft.VisualBasic.Core\src\47-dotnet_Microsoft.VisualBasic.vbproj"", "{FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}"
+Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "Core", "..\Microsoft.VisualBasic.Core\src\Core.vbproj", "{14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}"
EndProject
-Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Test", "Microsoft.VisualBasic.Imaging\Test\Test.vbproj", "{1A566414-428F-403B-84A6-6B9F36FB1117}"
+Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "Math.NET5", "..\Data_science\Mathematica\Math\Math\Math.NET5.vbproj", "{7B55A6EC-7F70-4A03-8A3F-3705F01658D6}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{AFCC8068-49D2-4A75-80AB-22055703DD48}"
+Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "html_netcore5", "..\mime\text%html\html_netcore5.vbproj", "{A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}"
EndProject
-Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "MIME-htmls", "..\mime\text%html\MIME-htmls.vbproj", "{2DD4BE80-DDC3-4767-94A7-10F1C3395716}"
+Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "imaging.NET5", "Microsoft.VisualBasic.Imaging\imaging.NET5.vbproj", "{2CCC6428-7934-4B1D-BE0D-757F6AF14692}"
EndProject
-Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "math-core", "..\Data_science\Mathematica\Math\Math\math-core.vbproj", "{E3367B88-5D0C-495A-8273-331656D4B5AA}"
+Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "Landscape", "Landscape\Landscape.vbproj", "{3E100C21-5196-485E-9546-BB0DB4138AF7}"
EndProject
-Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Landscape", "Landscape\Landscape.vbproj", "{CCD693C3-EE09-473A-8344-26E05B373394}"
-EndProject
-Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "text.yaml", "..\mime\text%yaml\text.yaml.vbproj", "{FB637DE6-6BEB-4722-968A-F76DEB851DFC}"
-EndProject
-Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "physics", "physics\physics.vbproj", "{3291389C-EA87-4B33-A9A5-65A2D60BA3E2}"
+Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "test", "Microsoft.VisualBasic.Imaging\test\test.vbproj", "{1A566414-428F-403B-84A6-6B9F36FB1117}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
- docs|Any CPU = docs|Any CPU
- docs|x64 = docs|x64
- docs|x86 = docs|x86
- Publish|Any CPU = Publish|Any CPU
- Publish|x64 = Publish|x64
- Publish|x86 = Publish|x86
+ gcmodeller_desktop|Any CPU = gcmodeller_desktop|Any CPU
+ gcmodeller_desktop|x64 = gcmodeller_desktop|x64
+ gcmodeller_desktop|x86 = gcmodeller_desktop|x86
+ LipidSearch|Any CPU = LipidSearch|Any CPU
+ LipidSearch|x64 = LipidSearch|x64
+ LipidSearch|x86 = LipidSearch|x86
+ mzkit_win32|Any CPU = mzkit_win32|Any CPU
+ mzkit_win32|x64 = mzkit_win32|x64
+ mzkit_win32|x86 = mzkit_win32|x86
+ mzkit|Any CPU = mzkit|Any CPU
+ mzkit|x64 = mzkit|x64
+ mzkit|x86 = mzkit|x86
+ NPSearch|Any CPU = NPSearch|Any CPU
+ NPSearch|x64 = NPSearch|x64
+ NPSearch|x86 = NPSearch|x86
+ PlantMAT|Any CPU = PlantMAT|Any CPU
+ PlantMAT|x64 = PlantMAT|x64
+ PlantMAT|x86 = PlantMAT|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
- Release2|Any CPU = Release2|Any CPU
- Release2|x64 = Release2|x64
- Release2|x86 = Release2|x86
+ Rsharp_app_release|Any CPU = Rsharp_app_release|Any CPU
+ Rsharp_app_release|x64 = Rsharp_app_release|x64
+ Rsharp_app_release|x86 = Rsharp_app_release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.Debug|x64.ActiveCfg = Debug|x64
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.Debug|x64.Build.0 = Debug|x64
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.Debug|x86.ActiveCfg = Debug|x86
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.Debug|x86.Build.0 = Debug|x86
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.docs|Any CPU.ActiveCfg = docs|Any CPU
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.docs|Any CPU.Build.0 = docs|Any CPU
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.docs|x64.ActiveCfg = docs|x64
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.docs|x64.Build.0 = docs|x64
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.docs|x86.ActiveCfg = docs|x86
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.docs|x86.Build.0 = docs|x86
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.Publish|Any CPU.ActiveCfg = Publish|Any CPU
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.Publish|Any CPU.Build.0 = Publish|Any CPU
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.Publish|x64.ActiveCfg = Publish|x64
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.Publish|x64.Build.0 = Publish|x64
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.Publish|x86.ActiveCfg = Publish|x86
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.Publish|x86.Build.0 = Publish|x86
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.Release|Any CPU.Build.0 = Release|Any CPU
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.Release|x64.ActiveCfg = Release|x64
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.Release|x64.Build.0 = Release|x64
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.Release|x86.ActiveCfg = Release|Any CPU
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.Release|x86.Build.0 = Release|Any CPU
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.Release2|Any CPU.ActiveCfg = Release|Any CPU
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.Release2|Any CPU.Build.0 = Release|Any CPU
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.Release2|x64.ActiveCfg = Release|x64
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.Release2|x64.Build.0 = Release|x64
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.Release2|x86.ActiveCfg = Release|x86
- {85E71B4B-9276-4EC8-AADC-C849205F1EA8}.Release2|x86.Build.0 = Release|x86
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Debug|x64.ActiveCfg = Debug|x64
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Debug|x64.Build.0 = Debug|x64
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Debug|x86.ActiveCfg = Debug|x86
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Debug|x86.Build.0 = Debug|x86
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.docs|Any CPU.ActiveCfg = docs|Any CPU
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.docs|Any CPU.Build.0 = docs|Any CPU
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.docs|x64.ActiveCfg = docs|x64
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.docs|x64.Build.0 = docs|x64
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.docs|x86.ActiveCfg = docs|x86
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.docs|x86.Build.0 = docs|x86
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Publish|Any CPU.ActiveCfg = Publish|Any CPU
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Publish|Any CPU.Build.0 = Publish|Any CPU
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Publish|x64.ActiveCfg = Publish|x64
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Publish|x64.Build.0 = Publish|x64
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Publish|x86.ActiveCfg = Publish|x86
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Publish|x86.Build.0 = Publish|x86
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Release|Any CPU.Build.0 = Release|Any CPU
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Release|x64.ActiveCfg = Release|x64
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Release|x64.Build.0 = Release|x64
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Release|x86.ActiveCfg = Release|x86
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Release|x86.Build.0 = Release|x86
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Release2|Any CPU.ActiveCfg = Release|Any CPU
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Release2|Any CPU.Build.0 = Release|Any CPU
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Release2|x64.ActiveCfg = Release|x64
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Release2|x64.Build.0 = Release|x64
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Release2|x86.ActiveCfg = Release|x86
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99}.Release2|x86.Build.0 = Release|x86
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.Debug|x64.ActiveCfg = Debug|x64
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.Debug|x64.Build.0 = Debug|x64
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.Debug|x86.ActiveCfg = Debug|x86
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.Debug|x86.Build.0 = Debug|x86
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.gcmodeller_desktop|Any CPU.ActiveCfg = gcmodeller_desktop|Any CPU
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.gcmodeller_desktop|Any CPU.Build.0 = gcmodeller_desktop|Any CPU
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.gcmodeller_desktop|x64.ActiveCfg = gcmodeller_desktop|x64
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.gcmodeller_desktop|x64.Build.0 = gcmodeller_desktop|x64
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.gcmodeller_desktop|x86.ActiveCfg = gcmodeller_desktop|x86
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.gcmodeller_desktop|x86.Build.0 = gcmodeller_desktop|x86
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.LipidSearch|Any CPU.ActiveCfg = LipidSearch|Any CPU
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.LipidSearch|Any CPU.Build.0 = LipidSearch|Any CPU
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.LipidSearch|x64.ActiveCfg = LipidSearch|x64
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.LipidSearch|x64.Build.0 = LipidSearch|x64
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.LipidSearch|x86.ActiveCfg = LipidSearch|x86
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.LipidSearch|x86.Build.0 = LipidSearch|x86
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.mzkit_win32|Any CPU.ActiveCfg = mzkit_win32|Any CPU
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.mzkit_win32|Any CPU.Build.0 = mzkit_win32|Any CPU
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.mzkit_win32|x64.ActiveCfg = mzkit_win32|x64
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.mzkit_win32|x64.Build.0 = mzkit_win32|x64
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.mzkit_win32|x86.ActiveCfg = mzkit_win32|x86
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.mzkit_win32|x86.Build.0 = mzkit_win32|x86
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.mzkit|Any CPU.ActiveCfg = mzkit|Any CPU
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.mzkit|Any CPU.Build.0 = mzkit|Any CPU
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.mzkit|x64.ActiveCfg = mzkit|x64
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.mzkit|x64.Build.0 = mzkit|x64
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.mzkit|x86.ActiveCfg = mzkit|x86
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.mzkit|x86.Build.0 = mzkit|x86
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.NPSearch|Any CPU.ActiveCfg = NPSearch|Any CPU
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.NPSearch|Any CPU.Build.0 = NPSearch|Any CPU
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.NPSearch|x64.ActiveCfg = NPSearch|x64
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.NPSearch|x64.Build.0 = NPSearch|x64
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.NPSearch|x86.ActiveCfg = NPSearch|x86
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.NPSearch|x86.Build.0 = NPSearch|x86
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.PlantMAT|Any CPU.ActiveCfg = PlantMAT|Any CPU
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.PlantMAT|Any CPU.Build.0 = PlantMAT|Any CPU
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.PlantMAT|x64.ActiveCfg = PlantMAT|x64
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.PlantMAT|x64.Build.0 = PlantMAT|x64
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.PlantMAT|x86.ActiveCfg = PlantMAT|x86
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.PlantMAT|x86.Build.0 = PlantMAT|x86
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.Release|Any CPU.Build.0 = Release|Any CPU
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.Release|x64.ActiveCfg = Release|x64
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.Release|x64.Build.0 = Release|x64
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.Release|x86.ActiveCfg = Release|x86
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.Release|x86.Build.0 = Release|x86
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.Rsharp_app_release|Any CPU.ActiveCfg = Rsharp_app_release|Any CPU
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.Rsharp_app_release|Any CPU.Build.0 = Rsharp_app_release|Any CPU
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.Rsharp_app_release|x64.ActiveCfg = Rsharp_app_release|x64
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.Rsharp_app_release|x64.Build.0 = Rsharp_app_release|x64
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.Rsharp_app_release|x86.ActiveCfg = Rsharp_app_release|x86
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23}.Rsharp_app_release|x86.Build.0 = Rsharp_app_release|x86
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.Debug|x64.ActiveCfg = Debug|x64
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.Debug|x64.Build.0 = Debug|x64
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.Debug|x86.Build.0 = Debug|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.gcmodeller_desktop|Any CPU.ActiveCfg = gcmodeller_desktop|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.gcmodeller_desktop|Any CPU.Build.0 = gcmodeller_desktop|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.gcmodeller_desktop|x64.ActiveCfg = gcmodeller_desktop|x64
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.gcmodeller_desktop|x64.Build.0 = gcmodeller_desktop|x64
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.gcmodeller_desktop|x86.ActiveCfg = gcmodeller_desktop|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.gcmodeller_desktop|x86.Build.0 = gcmodeller_desktop|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.LipidSearch|Any CPU.ActiveCfg = LipidSearch|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.LipidSearch|Any CPU.Build.0 = LipidSearch|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.LipidSearch|x64.ActiveCfg = LipidSearch|x64
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.LipidSearch|x64.Build.0 = LipidSearch|x64
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.LipidSearch|x86.ActiveCfg = LipidSearch|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.LipidSearch|x86.Build.0 = LipidSearch|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.mzkit_win32|Any CPU.ActiveCfg = mzkit_win32|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.mzkit_win32|Any CPU.Build.0 = mzkit_win32|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.mzkit_win32|x64.ActiveCfg = mzkit_win32|x64
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.mzkit_win32|x64.Build.0 = mzkit_win32|x64
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.mzkit_win32|x86.ActiveCfg = mzkit_win32|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.mzkit_win32|x86.Build.0 = mzkit_win32|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.mzkit|Any CPU.ActiveCfg = mzkit|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.mzkit|Any CPU.Build.0 = mzkit|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.mzkit|x64.ActiveCfg = mzkit|x64
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.mzkit|x64.Build.0 = mzkit|x64
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.mzkit|x86.ActiveCfg = mzkit|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.mzkit|x86.Build.0 = mzkit|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.NPSearch|Any CPU.ActiveCfg = NPSearch|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.NPSearch|Any CPU.Build.0 = NPSearch|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.NPSearch|x64.ActiveCfg = NPSearch|x64
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.NPSearch|x64.Build.0 = NPSearch|x64
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.NPSearch|x86.ActiveCfg = NPSearch|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.NPSearch|x86.Build.0 = NPSearch|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.PlantMAT|Any CPU.ActiveCfg = PlantMAT|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.PlantMAT|Any CPU.Build.0 = PlantMAT|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.PlantMAT|x64.ActiveCfg = PlantMAT|x64
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.PlantMAT|x64.Build.0 = PlantMAT|x64
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.PlantMAT|x86.ActiveCfg = PlantMAT|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.PlantMAT|x86.Build.0 = PlantMAT|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.Release|x64.ActiveCfg = Release|x64
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.Release|x64.Build.0 = Release|x64
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.Release|x86.ActiveCfg = Release|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.Release|x86.Build.0 = Release|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.Rsharp_app_release|Any CPU.ActiveCfg = Rsharp_app_release|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.Rsharp_app_release|Any CPU.Build.0 = Rsharp_app_release|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.Rsharp_app_release|x64.ActiveCfg = Rsharp_app_release|x64
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.Rsharp_app_release|x64.Build.0 = Rsharp_app_release|x64
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.Rsharp_app_release|x86.ActiveCfg = Rsharp_app_release|Any CPU
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6}.Rsharp_app_release|x86.Build.0 = Rsharp_app_release|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.Debug|x64.ActiveCfg = Debug|x64
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.Debug|x64.Build.0 = Debug|x64
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.Debug|x86.Build.0 = Debug|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.gcmodeller_desktop|Any CPU.ActiveCfg = gcmodeller_desktop|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.gcmodeller_desktop|Any CPU.Build.0 = gcmodeller_desktop|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.gcmodeller_desktop|x64.ActiveCfg = gcmodeller_desktop|x64
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.gcmodeller_desktop|x64.Build.0 = gcmodeller_desktop|x64
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.gcmodeller_desktop|x86.ActiveCfg = gcmodeller_desktop|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.gcmodeller_desktop|x86.Build.0 = gcmodeller_desktop|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.LipidSearch|Any CPU.ActiveCfg = LipidSearch|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.LipidSearch|Any CPU.Build.0 = LipidSearch|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.LipidSearch|x64.ActiveCfg = LipidSearch|x64
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.LipidSearch|x64.Build.0 = LipidSearch|x64
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.LipidSearch|x86.ActiveCfg = LipidSearch|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.LipidSearch|x86.Build.0 = LipidSearch|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.mzkit_win32|Any CPU.ActiveCfg = mzkit_win32|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.mzkit_win32|Any CPU.Build.0 = mzkit_win32|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.mzkit_win32|x64.ActiveCfg = mzkit_win32|x64
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.mzkit_win32|x64.Build.0 = mzkit_win32|x64
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.mzkit_win32|x86.ActiveCfg = mzkit_win32|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.mzkit_win32|x86.Build.0 = mzkit_win32|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.mzkit|Any CPU.ActiveCfg = mzkit|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.mzkit|Any CPU.Build.0 = mzkit|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.mzkit|x64.ActiveCfg = mzkit|x64
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.mzkit|x64.Build.0 = mzkit|x64
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.mzkit|x86.ActiveCfg = mzkit|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.mzkit|x86.Build.0 = mzkit|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.NPSearch|Any CPU.ActiveCfg = NPSearch|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.NPSearch|Any CPU.Build.0 = NPSearch|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.NPSearch|x64.ActiveCfg = NPSearch|x64
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.NPSearch|x64.Build.0 = NPSearch|x64
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.NPSearch|x86.ActiveCfg = NPSearch|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.NPSearch|x86.Build.0 = NPSearch|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.PlantMAT|Any CPU.ActiveCfg = Debug|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.PlantMAT|Any CPU.Build.0 = Debug|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.PlantMAT|x64.ActiveCfg = Debug|x64
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.PlantMAT|x64.Build.0 = Debug|x64
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.PlantMAT|x86.ActiveCfg = Debug|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.PlantMAT|x86.Build.0 = Debug|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.Release|x64.ActiveCfg = Release|x64
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.Release|x64.Build.0 = Release|x64
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.Release|x86.ActiveCfg = Release|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.Release|x86.Build.0 = Release|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.Rsharp_app_release|Any CPU.ActiveCfg = Rsharp_app_release|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.Rsharp_app_release|Any CPU.Build.0 = Rsharp_app_release|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.Rsharp_app_release|x64.ActiveCfg = Rsharp_app_release|x64
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.Rsharp_app_release|x64.Build.0 = Rsharp_app_release|x64
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.Rsharp_app_release|x86.ActiveCfg = Rsharp_app_release|Any CPU
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59}.Rsharp_app_release|x86.Build.0 = Rsharp_app_release|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.Debug|x64.ActiveCfg = Debug|x64
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.Debug|x64.Build.0 = Debug|x64
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.Debug|x86.Build.0 = Debug|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.gcmodeller_desktop|Any CPU.ActiveCfg = gcmodeller_desktop|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.gcmodeller_desktop|Any CPU.Build.0 = gcmodeller_desktop|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.gcmodeller_desktop|x64.ActiveCfg = gcmodeller_desktop|x64
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.gcmodeller_desktop|x64.Build.0 = gcmodeller_desktop|x64
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.gcmodeller_desktop|x86.ActiveCfg = gcmodeller_desktop|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.gcmodeller_desktop|x86.Build.0 = gcmodeller_desktop|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.LipidSearch|Any CPU.ActiveCfg = LipidSearch|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.LipidSearch|Any CPU.Build.0 = LipidSearch|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.LipidSearch|x64.ActiveCfg = LipidSearch|x64
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.LipidSearch|x64.Build.0 = LipidSearch|x64
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.LipidSearch|x86.ActiveCfg = LipidSearch|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.LipidSearch|x86.Build.0 = LipidSearch|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.mzkit_win32|Any CPU.ActiveCfg = mzkit_win32|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.mzkit_win32|Any CPU.Build.0 = mzkit_win32|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.mzkit_win32|x64.ActiveCfg = mzkit_win32|x64
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.mzkit_win32|x64.Build.0 = mzkit_win32|x64
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.mzkit_win32|x86.ActiveCfg = mzkit_win32|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.mzkit_win32|x86.Build.0 = mzkit_win32|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.mzkit|Any CPU.ActiveCfg = mzkit|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.mzkit|Any CPU.Build.0 = mzkit|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.mzkit|x64.ActiveCfg = mzkit|x64
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.mzkit|x64.Build.0 = mzkit|x64
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.mzkit|x86.ActiveCfg = mzkit|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.mzkit|x86.Build.0 = mzkit|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.NPSearch|Any CPU.ActiveCfg = NPSearch|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.NPSearch|Any CPU.Build.0 = NPSearch|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.NPSearch|x64.ActiveCfg = NPSearch|x64
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.NPSearch|x64.Build.0 = NPSearch|x64
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.NPSearch|x86.ActiveCfg = NPSearch|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.NPSearch|x86.Build.0 = NPSearch|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.PlantMAT|Any CPU.ActiveCfg = Debug|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.PlantMAT|Any CPU.Build.0 = Debug|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.PlantMAT|x64.ActiveCfg = Debug|x64
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.PlantMAT|x64.Build.0 = Debug|x64
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.PlantMAT|x86.ActiveCfg = Debug|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.PlantMAT|x86.Build.0 = Debug|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.Release|x64.ActiveCfg = Release|x64
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.Release|x64.Build.0 = Release|x64
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.Release|x86.ActiveCfg = Release|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.Release|x86.Build.0 = Release|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.Rsharp_app_release|Any CPU.ActiveCfg = Rsharp_app_release|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.Rsharp_app_release|Any CPU.Build.0 = Rsharp_app_release|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.Rsharp_app_release|x64.ActiveCfg = Rsharp_app_release|x64
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.Rsharp_app_release|x64.Build.0 = Rsharp_app_release|x64
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.Rsharp_app_release|x86.ActiveCfg = Rsharp_app_release|Any CPU
+ {2CCC6428-7934-4B1D-BE0D-757F6AF14692}.Rsharp_app_release|x86.Build.0 = Rsharp_app_release|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.Debug|x64.ActiveCfg = Debug|x64
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.Debug|x64.Build.0 = Debug|x64
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.Debug|x86.Build.0 = Debug|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.gcmodeller_desktop|Any CPU.ActiveCfg = gcmodeller_desktop|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.gcmodeller_desktop|Any CPU.Build.0 = gcmodeller_desktop|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.gcmodeller_desktop|x64.ActiveCfg = gcmodeller_desktop|x64
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.gcmodeller_desktop|x64.Build.0 = gcmodeller_desktop|x64
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.gcmodeller_desktop|x86.ActiveCfg = gcmodeller_desktop|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.gcmodeller_desktop|x86.Build.0 = gcmodeller_desktop|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.LipidSearch|Any CPU.ActiveCfg = LipidSearch|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.LipidSearch|Any CPU.Build.0 = LipidSearch|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.LipidSearch|x64.ActiveCfg = LipidSearch|x64
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.LipidSearch|x64.Build.0 = LipidSearch|x64
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.LipidSearch|x86.ActiveCfg = LipidSearch|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.LipidSearch|x86.Build.0 = LipidSearch|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.mzkit_win32|Any CPU.ActiveCfg = mzkit_win32|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.mzkit_win32|Any CPU.Build.0 = mzkit_win32|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.mzkit_win32|x64.ActiveCfg = mzkit_win32|x64
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.mzkit_win32|x64.Build.0 = mzkit_win32|x64
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.mzkit_win32|x86.ActiveCfg = mzkit_win32|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.mzkit_win32|x86.Build.0 = mzkit_win32|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.mzkit|Any CPU.ActiveCfg = mzkit|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.mzkit|Any CPU.Build.0 = mzkit|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.mzkit|x64.ActiveCfg = mzkit|x64
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.mzkit|x64.Build.0 = mzkit|x64
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.mzkit|x86.ActiveCfg = mzkit|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.mzkit|x86.Build.0 = mzkit|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.NPSearch|Any CPU.ActiveCfg = NPSearch|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.NPSearch|Any CPU.Build.0 = NPSearch|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.NPSearch|x64.ActiveCfg = NPSearch|x64
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.NPSearch|x64.Build.0 = NPSearch|x64
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.NPSearch|x86.ActiveCfg = NPSearch|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.NPSearch|x86.Build.0 = NPSearch|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.PlantMAT|Any CPU.ActiveCfg = Debug|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.PlantMAT|Any CPU.Build.0 = Debug|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.PlantMAT|x64.ActiveCfg = Debug|x64
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.PlantMAT|x64.Build.0 = Debug|x64
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.PlantMAT|x86.ActiveCfg = Debug|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.PlantMAT|x86.Build.0 = Debug|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.Release|x64.ActiveCfg = Release|x64
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.Release|x64.Build.0 = Release|x64
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.Release|x86.ActiveCfg = Release|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.Release|x86.Build.0 = Release|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.Rsharp_app_release|Any CPU.ActiveCfg = Rsharp_app_release|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.Rsharp_app_release|Any CPU.Build.0 = Rsharp_app_release|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.Rsharp_app_release|x64.ActiveCfg = Rsharp_app_release|x64
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.Rsharp_app_release|x64.Build.0 = Rsharp_app_release|x64
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.Rsharp_app_release|x86.ActiveCfg = Rsharp_app_release|Any CPU
+ {3E100C21-5196-485E-9546-BB0DB4138AF7}.Rsharp_app_release|x86.Build.0 = Rsharp_app_release|Any CPU
{1A566414-428F-403B-84A6-6B9F36FB1117}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1A566414-428F-403B-84A6-6B9F36FB1117}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1A566414-428F-403B-84A6-6B9F36FB1117}.Debug|x64.ActiveCfg = Debug|x64
{1A566414-428F-403B-84A6-6B9F36FB1117}.Debug|x64.Build.0 = Debug|x64
{1A566414-428F-403B-84A6-6B9F36FB1117}.Debug|x86.ActiveCfg = Debug|x86
{1A566414-428F-403B-84A6-6B9F36FB1117}.Debug|x86.Build.0 = Debug|x86
- {1A566414-428F-403B-84A6-6B9F36FB1117}.docs|Any CPU.ActiveCfg = Debug|Any CPU
- {1A566414-428F-403B-84A6-6B9F36FB1117}.docs|Any CPU.Build.0 = Debug|Any CPU
- {1A566414-428F-403B-84A6-6B9F36FB1117}.docs|x64.ActiveCfg = Debug|x64
- {1A566414-428F-403B-84A6-6B9F36FB1117}.docs|x64.Build.0 = Debug|x64
- {1A566414-428F-403B-84A6-6B9F36FB1117}.docs|x86.ActiveCfg = Debug|x86
- {1A566414-428F-403B-84A6-6B9F36FB1117}.docs|x86.Build.0 = Debug|x86
- {1A566414-428F-403B-84A6-6B9F36FB1117}.Publish|Any CPU.ActiveCfg = Release|Any CPU
- {1A566414-428F-403B-84A6-6B9F36FB1117}.Publish|Any CPU.Build.0 = Release|Any CPU
- {1A566414-428F-403B-84A6-6B9F36FB1117}.Publish|x64.ActiveCfg = Release|x64
- {1A566414-428F-403B-84A6-6B9F36FB1117}.Publish|x64.Build.0 = Release|x64
- {1A566414-428F-403B-84A6-6B9F36FB1117}.Publish|x86.ActiveCfg = Release|x86
- {1A566414-428F-403B-84A6-6B9F36FB1117}.Publish|x86.Build.0 = Release|x86
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.gcmodeller_desktop|Any CPU.ActiveCfg = Debug|Any CPU
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.gcmodeller_desktop|Any CPU.Build.0 = Debug|Any CPU
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.gcmodeller_desktop|x64.ActiveCfg = Debug|x64
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.gcmodeller_desktop|x64.Build.0 = Debug|x64
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.gcmodeller_desktop|x86.ActiveCfg = Debug|x86
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.gcmodeller_desktop|x86.Build.0 = Debug|x86
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.LipidSearch|Any CPU.ActiveCfg = Debug|Any CPU
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.LipidSearch|Any CPU.Build.0 = Debug|Any CPU
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.LipidSearch|x64.ActiveCfg = Debug|x64
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.LipidSearch|x64.Build.0 = Debug|x64
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.LipidSearch|x86.ActiveCfg = Debug|x86
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.LipidSearch|x86.Build.0 = Debug|x86
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.mzkit_win32|Any CPU.ActiveCfg = Debug|Any CPU
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.mzkit_win32|Any CPU.Build.0 = Debug|Any CPU
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.mzkit_win32|x64.ActiveCfg = Debug|x64
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.mzkit_win32|x64.Build.0 = Debug|x64
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.mzkit_win32|x86.ActiveCfg = Debug|x86
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.mzkit_win32|x86.Build.0 = Debug|x86
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.mzkit|Any CPU.ActiveCfg = Debug|Any CPU
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.mzkit|Any CPU.Build.0 = Debug|Any CPU
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.mzkit|x64.ActiveCfg = Debug|x64
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.mzkit|x64.Build.0 = Debug|x64
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.mzkit|x86.ActiveCfg = Debug|x86
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.mzkit|x86.Build.0 = Debug|x86
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.NPSearch|Any CPU.ActiveCfg = Debug|Any CPU
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.NPSearch|Any CPU.Build.0 = Debug|Any CPU
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.NPSearch|x64.ActiveCfg = Debug|x64
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.NPSearch|x64.Build.0 = Debug|x64
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.NPSearch|x86.ActiveCfg = Debug|x86
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.NPSearch|x86.Build.0 = Debug|x86
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.PlantMAT|Any CPU.ActiveCfg = Debug|Any CPU
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.PlantMAT|Any CPU.Build.0 = Debug|Any CPU
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.PlantMAT|x64.ActiveCfg = Debug|x64
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.PlantMAT|x64.Build.0 = Debug|x64
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.PlantMAT|x86.ActiveCfg = Debug|x86
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.PlantMAT|x86.Build.0 = Debug|x86
{1A566414-428F-403B-84A6-6B9F36FB1117}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1A566414-428F-403B-84A6-6B9F36FB1117}.Release|Any CPU.Build.0 = Release|Any CPU
{1A566414-428F-403B-84A6-6B9F36FB1117}.Release|x64.ActiveCfg = Release|x64
{1A566414-428F-403B-84A6-6B9F36FB1117}.Release|x64.Build.0 = Release|x64
- {1A566414-428F-403B-84A6-6B9F36FB1117}.Release|x86.ActiveCfg = Release|Any CPU
- {1A566414-428F-403B-84A6-6B9F36FB1117}.Release|x86.Build.0 = Release|Any CPU
- {1A566414-428F-403B-84A6-6B9F36FB1117}.Release2|Any CPU.ActiveCfg = Release|Any CPU
- {1A566414-428F-403B-84A6-6B9F36FB1117}.Release2|Any CPU.Build.0 = Release|Any CPU
- {1A566414-428F-403B-84A6-6B9F36FB1117}.Release2|x64.ActiveCfg = Release|x64
- {1A566414-428F-403B-84A6-6B9F36FB1117}.Release2|x64.Build.0 = Release|x64
- {1A566414-428F-403B-84A6-6B9F36FB1117}.Release2|x86.ActiveCfg = Release|x86
- {1A566414-428F-403B-84A6-6B9F36FB1117}.Release2|x86.Build.0 = Release|x86
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.Debug|x64.ActiveCfg = Debug|x64
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.Debug|x64.Build.0 = Debug|x64
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.Debug|x86.ActiveCfg = Debug|x86
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.Debug|x86.Build.0 = Debug|x86
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.docs|Any CPU.ActiveCfg = docs|Any CPU
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.docs|Any CPU.Build.0 = docs|Any CPU
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.docs|x64.ActiveCfg = docs|x64
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.docs|x64.Build.0 = docs|x64
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.docs|x86.ActiveCfg = docs|x86
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.docs|x86.Build.0 = docs|x86
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.Publish|Any CPU.ActiveCfg = Publish|Any CPU
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.Publish|Any CPU.Build.0 = Publish|Any CPU
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.Publish|x64.ActiveCfg = Publish|x64
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.Publish|x64.Build.0 = Publish|x64
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.Publish|x86.ActiveCfg = Publish|x86
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.Publish|x86.Build.0 = Publish|x86
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.Release|Any CPU.Build.0 = Release|Any CPU
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.Release|x64.ActiveCfg = Release|x64
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.Release|x64.Build.0 = Release|x64
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.Release|x86.ActiveCfg = Release|x86
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.Release|x86.Build.0 = Release|x86
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.Release2|Any CPU.ActiveCfg = Release|Any CPU
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.Release2|Any CPU.Build.0 = Release|Any CPU
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.Release2|x64.ActiveCfg = Release|x64
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.Release2|x64.Build.0 = Release|x64
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.Release2|x86.ActiveCfg = Release|x86
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}.Release2|x86.Build.0 = Release|x86
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.Debug|x64.ActiveCfg = Debug|x64
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.Debug|x64.Build.0 = Debug|x64
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.Debug|x86.ActiveCfg = Debug|x86
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.Debug|x86.Build.0 = Debug|x86
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.docs|Any CPU.ActiveCfg = docs|Any CPU
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.docs|Any CPU.Build.0 = docs|Any CPU
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.docs|x64.ActiveCfg = docs|x64
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.docs|x64.Build.0 = docs|x64
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.docs|x86.ActiveCfg = docs|x86
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.docs|x86.Build.0 = docs|x86
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.Publish|Any CPU.ActiveCfg = Publish|Any CPU
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.Publish|Any CPU.Build.0 = Publish|Any CPU
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.Publish|x64.ActiveCfg = Publish|x64
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.Publish|x64.Build.0 = Publish|x64
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.Publish|x86.ActiveCfg = Publish|x86
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.Publish|x86.Build.0 = Publish|x86
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.Release|Any CPU.Build.0 = Release|Any CPU
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.Release|x64.ActiveCfg = Release|x64
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.Release|x64.Build.0 = Release|x64
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.Release|x86.ActiveCfg = Release|x86
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.Release|x86.Build.0 = Release|x86
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.Release2|Any CPU.ActiveCfg = Release|Any CPU
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.Release2|Any CPU.Build.0 = Release|Any CPU
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.Release2|x64.ActiveCfg = Release|x64
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.Release2|x64.Build.0 = Release|x64
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.Release2|x86.ActiveCfg = Release|x86
- {E3367B88-5D0C-495A-8273-331656D4B5AA}.Release2|x86.Build.0 = Release|x86
- {CCD693C3-EE09-473A-8344-26E05B373394}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.Debug|x64.ActiveCfg = Debug|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.Debug|x64.Build.0 = Debug|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.Debug|x86.ActiveCfg = Debug|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.Debug|x86.Build.0 = Debug|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.docs|Any CPU.ActiveCfg = Debug|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.docs|Any CPU.Build.0 = Debug|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.docs|x64.ActiveCfg = Debug|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.docs|x64.Build.0 = Debug|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.docs|x86.ActiveCfg = Debug|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.docs|x86.Build.0 = Debug|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.Publish|Any CPU.ActiveCfg = Release|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.Publish|Any CPU.Build.0 = Release|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.Publish|x64.ActiveCfg = Release|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.Publish|x64.Build.0 = Release|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.Publish|x86.ActiveCfg = Release|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.Publish|x86.Build.0 = Release|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.Release|Any CPU.Build.0 = Release|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.Release|x64.ActiveCfg = Release|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.Release|x64.Build.0 = Release|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.Release|x86.ActiveCfg = Release|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.Release|x86.Build.0 = Release|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.Release2|Any CPU.ActiveCfg = Release|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.Release2|Any CPU.Build.0 = Release|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.Release2|x64.ActiveCfg = Release|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.Release2|x64.Build.0 = Release|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.Release2|x86.ActiveCfg = Release|Any CPU
- {CCD693C3-EE09-473A-8344-26E05B373394}.Release2|x86.Build.0 = Release|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.Debug|x64.ActiveCfg = Debug|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.Debug|x64.Build.0 = Debug|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.Debug|x86.ActiveCfg = Debug|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.Debug|x86.Build.0 = Debug|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.docs|Any CPU.ActiveCfg = Debug|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.docs|Any CPU.Build.0 = Debug|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.docs|x64.ActiveCfg = Debug|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.docs|x64.Build.0 = Debug|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.docs|x86.ActiveCfg = Debug|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.docs|x86.Build.0 = Debug|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.Publish|Any CPU.ActiveCfg = Release|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.Publish|Any CPU.Build.0 = Release|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.Publish|x64.ActiveCfg = Release|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.Publish|x64.Build.0 = Release|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.Publish|x86.ActiveCfg = Release|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.Publish|x86.Build.0 = Release|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.Release|Any CPU.Build.0 = Release|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.Release|x64.ActiveCfg = Release|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.Release|x64.Build.0 = Release|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.Release|x86.ActiveCfg = Release|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.Release|x86.Build.0 = Release|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.Release2|Any CPU.ActiveCfg = Release|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.Release2|Any CPU.Build.0 = Release|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.Release2|x64.ActiveCfg = Release|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.Release2|x64.Build.0 = Release|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.Release2|x86.ActiveCfg = Release|Any CPU
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC}.Release2|x86.Build.0 = Release|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.Debug|x64.ActiveCfg = Debug|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.Debug|x64.Build.0 = Debug|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.Debug|x86.ActiveCfg = Debug|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.Debug|x86.Build.0 = Debug|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.docs|Any CPU.ActiveCfg = Debug|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.docs|Any CPU.Build.0 = Debug|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.docs|x64.ActiveCfg = Debug|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.docs|x64.Build.0 = Debug|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.docs|x86.ActiveCfg = Debug|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.docs|x86.Build.0 = Debug|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.Publish|Any CPU.ActiveCfg = Release|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.Publish|Any CPU.Build.0 = Release|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.Publish|x64.ActiveCfg = Release|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.Publish|x64.Build.0 = Release|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.Publish|x86.ActiveCfg = Release|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.Publish|x86.Build.0 = Release|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.Release|Any CPU.Build.0 = Release|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.Release|x64.ActiveCfg = Release|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.Release|x64.Build.0 = Release|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.Release|x86.ActiveCfg = Release|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.Release|x86.Build.0 = Release|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.Release2|Any CPU.ActiveCfg = Release|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.Release2|Any CPU.Build.0 = Release|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.Release2|x64.ActiveCfg = Release|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.Release2|x64.Build.0 = Release|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.Release2|x86.ActiveCfg = Release|Any CPU
- {3291389C-EA87-4B33-A9A5-65A2D60BA3E2}.Release2|x86.Build.0 = Release|Any CPU
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.Release|x86.ActiveCfg = Release|x86
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.Release|x86.Build.0 = Release|x86
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.Rsharp_app_release|Any CPU.ActiveCfg = Release|Any CPU
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.Rsharp_app_release|Any CPU.Build.0 = Release|Any CPU
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.Rsharp_app_release|x64.ActiveCfg = Release|x64
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.Rsharp_app_release|x64.Build.0 = Release|x64
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.Rsharp_app_release|x86.ActiveCfg = Release|x86
+ {1A566414-428F-403B-84A6-6B9F36FB1117}.Rsharp_app_release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
- {FECCE1FD-E1D4-49E3-A668-60BB5E7AED99} = {AFCC8068-49D2-4A75-80AB-22055703DD48}
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716} = {AFCC8068-49D2-4A75-80AB-22055703DD48}
- {E3367B88-5D0C-495A-8273-331656D4B5AA} = {AFCC8068-49D2-4A75-80AB-22055703DD48}
- {FB637DE6-6BEB-4722-968A-F76DEB851DFC} = {AFCC8068-49D2-4A75-80AB-22055703DD48}
+ {14589A8E-DEC0-4F3B-BBA3-F127B5A89B23} = {E0DFA7E4-1D86-4239-A8F6-C3ECAE31EC3D}
+ {7B55A6EC-7F70-4A03-8A3F-3705F01658D6} = {E0DFA7E4-1D86-4239-A8F6-C3ECAE31EC3D}
+ {A9CF5F42-84F0-4B92-922C-0F1CF08E0B59} = {E0DFA7E4-1D86-4239-A8F6-C3ECAE31EC3D}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6398F1C0-7A2F-4ABF-A31F-268FC9F34B72}
diff --git a/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Math3D/Polyhedron/.gitignore b/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Math3D/Polyhedron/.gitignore
new file mode 100644
index 000000000..e776c8500
--- /dev/null
+++ b/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Math3D/Polyhedron/.gitignore
@@ -0,0 +1,3 @@
+# Byte-compiled files.
+__pycache__/
+*.py[co]
diff --git a/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Math3D/Polyhedron/.travis.yml b/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Math3D/Polyhedron/.travis.yml
new file mode 100644
index 000000000..4a406a3c4
--- /dev/null
+++ b/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Math3D/Polyhedron/.travis.yml
@@ -0,0 +1,11 @@
+language: python
+python:
+ - 2.7
+ - 3.5
+ - 3.6
+ - pypy
+script:
+ - python -m unittest discover -v
+notifications:
+ email:
+ - dickinsm@gmail.com
diff --git a/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Math3D/Polyhedron/LICENSE b/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Math3D/Polyhedron/LICENSE
new file mode 100644
index 000000000..40cb3e8bf
--- /dev/null
+++ b/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Math3D/Polyhedron/LICENSE
@@ -0,0 +1,29 @@
+BSD 3-Clause License
+
+Copyright (c) 2019, Mark Dickinson
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Math3D/Polyhedron/README.rst b/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Math3D/Polyhedron/README.rst
new file mode 100644
index 000000000..eb7b26f47
--- /dev/null
+++ b/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Math3D/Polyhedron/README.rst
@@ -0,0 +1,17 @@
+.. image:: https://zenodo.org/badge/20797542.svg
+ :target: https://zenodo.org/badge/latestdoi/20797542
+
+Polyhedron
+==========
+
+This repository contains a pure Python implementation of a robust algorithm for
+point-in-polyhedron testing.
+
+See the docstring of the ``polyhedron`` module for details.
+
+License
+-------
+
+The ``polyhedron`` code is Copyright (c) 2019, Mark Dickinson.
+The code is released under the BSD 3-Clause License. See the ``LICENSE``
+file for details.
diff --git a/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Math3D/Polyhedron/polygon.py b/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Math3D/Polyhedron/polygon.py
new file mode 100644
index 000000000..7bcf0efe8
--- /dev/null
+++ b/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Math3D/Polyhedron/polygon.py
@@ -0,0 +1,120 @@
+"""Simple point-in-polygon algorithm based on winding number, with robustness
+depending only on the underlying arithmetic.
+
+We've got a closed, possibly non-simple polygon described as a list of vertices
+in R^2, and we're given a point that doesn't lie directly on the path of the
+polygon. We'd like to compute the winding number of the polygon around the
+point.
+
+There are two sources of difficulty: (1) dealing with numerical errors that
+might result in an incorrect answer, and (2) dealing with degenerate cases.
+We'll ignore the numerical issues for the moment.
+
+Strategy: without loss of generality, let's place the point at the origin.
+Divide the remainder of the plane (i.e., R^2 minus the origin) into two
+halves, L and R, defined as follows:
+
+ L = {(x, y) | x < 0 or x == 0 and y < 0}
+
+ R = {(x, y) | x > 0 or x == 0 and y > 0}
+
+That is, R contains all points with argument in the half-closed interval
+(-pi/2, pi/2], and L contains all others. Note that with these definitions, L
+and R are both convex: a line segment between two points in R lies entirely in
+R, and similarly for L. In particular, a line segment between two points can
+only pass through the origin if one of those points is in L and the other in R.
+
+Now the idea is that we follow the edges of the polygon, keeping track of how
+many times we move between L and R. For each move from L to R (or vice versa),
+we also need to compute whether the edge passes *above* or *below* the origin,
+to compute its contribution to the total winding number. From the comment
+above, we can safely ignore all edges that lie entirely within either L or R.
+
+"""
+
+
+def sign(x):
+ """
+ Return 1 if x is positive, -1 if it's negative, and 0 if it's zero.
+
+ """
+ if x > 0:
+ return 1
+ elif x < 0:
+ return -1
+ else:
+ return 0
+
+
+def vertex_sign(P, O):
+ result = sign(P[0] - O[0]) or sign(P[1] - O[1])
+ if not result:
+ raise ValueError("vertex coincides with origin")
+ return result
+
+
+def edge_sign(P, Q, O):
+ result = sign(
+ (P[0] - O[0]) * (Q[1] - O[1]) - (P[1] - O[1]) * (Q[0] - O[0]))
+ if not result:
+ raise ValueError("vertices collinear with origin")
+ return result
+
+
+def half_turn(point1, point2, origin):
+ """
+ Return the contribution to the total winding number about 'origin' from a
+ single edge, from point1 to point2.
+
+ """
+ edge_boundary = vertex_sign(point2, origin) - vertex_sign(point1, origin)
+ return 0 if not edge_boundary else edge_sign(point1, point2, origin)
+
+
+class Polygon(object):
+ def __init__(self, vertex_positions):
+ """
+ Initialize from list of vertex positions.
+
+ """
+ self.vertex_positions = vertex_positions
+
+ def edge_positions(self):
+ """
+ Pairs of vertex positions corresponding to the polygon edges.
+
+ """
+ points = self.vertex_positions
+ first_point = previous_point = points[0]
+ for point in points[1:]:
+ yield previous_point, point
+ previous_point = point
+ yield previous_point, first_point
+
+ def area(self):
+ """
+ Area enclosed by this polygon.
+
+ For simple counterclockwise-oriented polygons, return the area
+ enclosed by the polygon. More generally, return the integral
+ of the winding number of the polygon over R^2.
+
+ """
+ acc = 0.0
+ for p1, p2 in self.edge_positions():
+ acc += (p1[0] - p2[0]) * (p1[1] + p2[1])
+ return acc / 2.0
+
+ def winding_number(self, origin):
+ """
+ Compute the (counterclockwise) winding number of a polygon around a
+ point.
+
+ Raise ValueError if the point lies directly on the path
+ of the polygon.
+
+ """
+ return sum(
+ half_turn(point1, point2, origin)
+ for point1, point2 in self.edge_positions()
+ ) // 2
diff --git a/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Math3D/Polyhedron/polyhedron.py b/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Math3D/Polyhedron/polyhedron.py
new file mode 100644
index 000000000..18ab4ab8c
--- /dev/null
+++ b/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Math3D/Polyhedron/polyhedron.py
@@ -0,0 +1,372 @@
+"""Robust point-in-polyhedron test.
+
+Given an closed, oriented surface in R^3 described by a triangular mesh, the
+code below gives a robust algorithm for determining whether a given point is
+inside, on the boundary of, or outside, the surface. The algorithm should give
+correct results even in degenerate cases, and applies to disconnected
+polyhedra, non simply-connected surfaces, and so on. There are no requirements
+for the surface to be convex, simple, connected or simply-connected.
+
+More precisely, we give a method for computing the *winding number* of a closed
+oriented surface S around a point O that doesn't lie on S. Roughly speaking,
+the winding number of the closed oriented surface S around a point O not on S
+is the number of times that the surface encloses that point; for a simple
+outward-oriented surface (like that of a convex polyhedron, for example), the
+winding number will be 1 for points inside the surface and 0 for points
+outside.
+
+For a precise definition of winding number, we can turn to algebraic topology:
+our oriented surface is presented as a collection of combinatorial data
+defining abstract vertices, edges and triangles, together with a mapping of
+those vertices to R^3. The combinatorial data describe a simplicial complex C,
+and assuming that O doesn't lie on the surface, the mapping of the vertices to
+R^3 gives a continuous map from the geometric realization of C to R^3 - {O}.
+This in turn induces a map on second homology groups:
+
+ H^2(C, Z) -> H^2(R^3 - {O}, Z)
+
+and by taking the usual right-handed orientation in R^3 we identify H^2(R^3 -
+{O}, Z) with Z. The image of [S] under this map gives the winding number. In
+particular, the well-definedness of the winding number does not depend on
+topological properties of the embedding: it doesn't matter if the surface is
+self-intersecting, or has degenerate triangles. The only condition is that O
+does not lie on the surface S.
+
+Algorithm
+---------
+The algorithm is based around the usual method of ray-casting: we take a
+vertical line L through O and count the intersections of this line with the
+triangles of the surface, keeping track of orientations as we go. Let's ignore
+corner cases for a moment and assume that:
+
+(1) O does not lie on the surface, and
+(2) for each triangle T (thought of as a closed subset of R^3) touched by
+ our vertical line L, L meets the interior of T in exactly one point Q
+
+Then there are four possibilities for each such triangle T:
+
+1. T lies *above* O and is oriented *upwards* (*away* from O).
+2. T lies *above* O and is oriented *downwards* (*towards* O).
+3. T lies *below* O and is oriented *downwards* (*away* from O).
+4. T lies *below* O and is oriented *upwards* (*towards* O).
+
+Let's write N1, N2, N3 and N4 for the counts of triangles satisfying conditions
+1, 2, 3 and 4 respectively. Since we have a closed surface, these numbers
+are not independent; they satisfy the relation:
+
+ N1 + N4 == N2 + N3
+
+That is, the number of upward-facing triangles must match the number of
+downward-facing triangles. The winding number w is then given by:
+
+ w = N1 - N2 == N3 - N4
+
+In the code below, we simply compute 2*w = (N1 + N3) - (N2 + N4), so each
+triangle oriented away from O contributes 1 to 2w, while each triangle oriented
+towards O contributes -1.
+
+
+Making the algorithm robust
+---------------------------
+Now we describe how to augment the basic algorithm described above to include:
+
+- correct treatment of corner cases (vertical triangles, cases where L meets an
+ edge or vertex directly, etc.)
+
+- detection of the case where the point lies directly on the surface.
+
+It turns out that to make the algorithm robust, all we need to do is be careful
+and consistent about classifying vertices, edges and triangles. We do this as
+follows:
+
+- Each vertex of the surface that's not equal to O is considered *positive* if
+ its coordinates are lexicographically greater than O, and *negative*
+ otherwise.
+
+- For an edge PQ of the surface that's not collinear with O, we first describe
+ the classification in the case that P is negative and Q is positive, and
+ then extend to arbitrary PQ.
+
+ For P negative and Q positive, there are two cases:
+
+ 1. P and Q have distinct x coordinates. In that case we classify the edge
+ PQ by its intersection with the plane passing through O and parallel
+ to the yz-plane: the edge is *positive* if the intersection point is
+ positive, and *negative* otherwise.
+
+ 2. P and Q have the same x coordinate, in which case they must have
+ distinct y coordinates. (If the x and the y coordinates both match
+ then PQ passes through O.) We classify by the intersection of PQ
+ with the line parallel to the y-axis through O.
+
+ For P positive and Q negative, we classify as above but reverse the sign.
+ For like-signed P and Q, the classification isn't used.
+
+ Computationally, in case 1 above, the y-coordinate of the intersection
+ point is:
+
+ Py + (Qy - Py) * (Ox - Px) / (Qx - Px)
+
+ and this is greater than Oy iff
+
+ (Py - Oy) * (Qx - Ox) - (Px - Ox) * (Qy - Oy)
+
+ is positive, so the sign of the edge is the sign of the above expression.
+ Similarly, if this quantity is zero then we need to look at the z-coordinate
+ of the intersection, and the sign of the edge is given by
+
+ (Pz - Oz) * (Qx - Ox) - (Px - Ox) * (Qz - Oz)
+
+ In case 2, both of the above quantities are zero, and the sign of the edge is
+ the sign of
+
+ (Pz - Oz) * (Qy - Oy) - (Py - Oy) * (Qz - Oz)
+
+ Another way to look at this: if P, Q and O are not collinear then the
+ matrix
+
+ ( Px Qx Ox )
+ ( Py Qy Ox )
+ ( Pz Qz Ox )
+ ( 1 1 1 )
+
+ has rank 3. It follows that at least one of the three 3x3 minors
+
+ | Px Qx Ox | | Px Qx Ox | | Py Qy Oy |
+ | Py Qy Oy | | Pz Qz Oz | | Pz Qz Oz |
+ | 1 1 1 | | 1 1 1 | | 1 1 1 |
+
+ is nonzero. We define the sign of PQ to be the *negative* of the sign of the
+ first nonzero minor in that list.
+
+- Each triangle PQR of the surface that's not coplanar with O is considered
+ *positive* if its normal points away from O, and *negative* if its normal
+ points towards O.
+
+ Computationally, the sign of the triangle PQR is the sign of the 4x4
+ determinant
+
+ | Px Qx Rx Ox |
+ | Py Qy Ry Oy |
+ | Pz Qz Rz Oz |
+ | 1 1 1 1 |
+
+ or equivalently of the 3x3 determinant
+
+ | Px-Ox Qx-Ox Rx-Ox |
+ | Py-Oy Qy-Oy Ry-Oy |
+ | Pz-Oz Qz-Oz Rz-Oz |
+
+
+Now to compute the contribution of any given triangle to the total winding
+number:
+
+1. Classify the vertices of the triangle. At the same time, we can check that
+ none of the vertices is equal to O. If all vertices have the same sign,
+ then the winding number contribution is zero.
+
+2. Assuming that the vertices do not all have the same sign, two of the three
+ edges connect two differently-signed vertices. Classify both those edges
+ (and simultaneously check that they don't pass through O). If the edges
+ have opposite classification, then the winding number contribution is zero.
+
+3. Now two of the edges have the same sign: classify the triangle itself. If
+ the triangle is positive it contributes 1/2 to the winding number total; if
+ negative it contributes -1/2. In practice we count contributions of 1 and
+ -1, and halve the total at the end.
+
+Note that an edge between two like-signed vertices can never pass through O, so
+there's no need to check the third edge in step 2. Similarly, a triangle whose
+edge-cycle is trivial can't contain O in its interior.
+
+To understand what's going on above, it's helpful to step into the world of
+homology again. The homology of R^3 - {O} can be identified with that of the
+two-sphere S^2 by deformation retract, and we can decompose the two-sphere as a
+CW complex consisting of six cells, as follows:
+
+* 0-cells B and F, where B = (-1, 0, 0) and F = (1, 0, 0)
+* 1-cells L and R, where
+ L = {(cos t, sin t, 0) | -pi <= t <= 0 }
+ R = {(cos t, sin t, 0) | 0 <= t <= pi }
+* 2-cells U and D, where U is the top half of the sphere (z >= 0)
+ and D is the bottom half (z <= 0), both oriented outwards.
+
+And the homology of the CW complex is now representable in terms of cellular
+homology:
+
+ d d
+ Z[U] + Z[D] --> Z[L] + Z[R] --> Z[B] + Z[F]
+
+with boundary maps given by:
+
+ d[U] = [L] + [R]; d[D] = -[L] - [R]
+ d[R] = [B] - [F]; d[L] = [F] - [B]
+
+Now the original map C -> R^3 - {O} from the geometric realization of the
+simplicial complex is homotopic to a map C -> S^2 that sends:
+
+* each positive vertex to F and each negative vertex to B
+* each edge with boundary [F] - [B] to L if the edge is negative, and -R if the
+ edge is positive
+* each edge with boundary [B] - [F] to R if the edge is positive, and -L if the
+ edge is negative
+* all other edges to 0
+* each triangle whose boundary is [L] + [R] to either U or -D,
+ depending on whether the triangle is positive or negative
+* each triangle whose boundary is -[L] - [R] to either D or -U,
+ depending on whether the triangle is positive or negative
+* all other triangles to 0
+
+Mapping all of the triangles in the surface this way, and summing the results
+in second homology, we end up with (winding number)*([U] + [D]).
+
+"""
+
+
+def sign(x):
+ """
+ Return 1 if x is positive, -1 if it's negative, and 0 if it's zero.
+
+ """
+ if x > 0:
+ return 1
+ elif x < 0:
+ return -1
+ else:
+ return 0
+
+
+def vertex_sign(P, O):
+ """
+ Sign of the vertex P with respect to O, as defined above.
+
+ """
+ result = sign(P[0] - O[0]) or sign(P[1] - O[1]) or sign(P[2] - O[2])
+ if not result:
+ raise ValueError("vertex coincides with origin")
+ return result
+
+
+def edge_sign(P, Q, O):
+ """
+ Sign of the edge PQ with respect to O, as defined above.
+
+ """
+ result = (
+ sign((P[1] - O[1]) * (Q[0] - O[0]) - (P[0] - O[0]) * (Q[1] - O[1])) or
+ sign((P[2] - O[2]) * (Q[0] - O[0]) - (P[0] - O[0]) * (Q[2] - O[2])) or
+ sign((P[2] - O[2]) * (Q[1] - O[1]) - (P[1] - O[1]) * (Q[2] - O[2]))
+ )
+ if not result:
+ raise ValueError("vertices collinear with origin")
+ return result
+
+
+def triangle_sign(P, Q, R, O):
+ """
+ Sign of the triangle PQR with respect to O, as defined above.
+
+ """
+ m1_0 = P[0] - O[0]
+ m1_1 = P[1] - O[1]
+ m2_0 = Q[0] - O[0]
+ m2_1 = Q[1] - O[1]
+ m3_0 = R[0] - O[0]
+ m3_1 = R[1] - O[1]
+ result = sign(
+ (m1_0 * m2_1 - m1_1 * m2_0) * (R[2] - O[2]) +
+ (m2_0 * m3_1 - m2_1 * m3_0) * (P[2] - O[2]) +
+ (m3_0 * m1_1 - m3_1 * m1_0) * (Q[2] - O[2]))
+ if not result:
+ raise ValueError("vertices coplanar with origin")
+ return result
+
+
+def triangle_chain(v1, v2, v3, origin):
+ """
+ Return the contribution of this triangle to the winding number.
+
+ Raise ValueError if the face contains the origin.
+
+ """
+ v1sign = vertex_sign(v1, origin)
+ v2sign = vertex_sign(v2, origin)
+ v3sign = vertex_sign(v3, origin)
+
+ face_boundary = 0
+ if v1sign != v2sign:
+ face_boundary += edge_sign(v1, v2, origin)
+ if v2sign != v3sign:
+ face_boundary += edge_sign(v2, v3, origin)
+ if v3sign != v1sign:
+ face_boundary += edge_sign(v3, v1, origin)
+ if not face_boundary:
+ return 0
+
+ return triangle_sign(v1, v2, v3, origin)
+
+
+class Polyhedron(object):
+ def __init__(self, triangles, vertex_positions):
+ """
+ Initialize from list of triangles and vertex positions.
+
+ """
+ # Validate: check the combinatorial data.
+ edges = set()
+ vertices = set()
+ for triangle in triangles:
+ vertices.update(triangle)
+ P, Q, R = triangle
+ for edge in ((P, Q), (Q, R), (R, P)):
+ if edge[0] == edge[1]:
+ raise ValueError("Self edge: {!r}".format(edge))
+ if edge in edges:
+ raise ValueError("Duplicate edge: {!r}".format(edge))
+ edges.add(edge)
+
+ # For each edge that appears, the reverse edge should also appear.
+ for P, Q in edges:
+ if not (Q, P) in edges:
+ raise ValueError("Unmatched edge: {!r}".format((P, Q)))
+
+ # Vertex set should match indices in vertex_positions.
+ if vertices != set(range(len(vertex_positions))):
+ raise ValueError("Vertex set doesn't match position indices.")
+
+ # Vertex positions in R^3.
+ self.vertex_positions = vertex_positions
+ # Indices making up each triangle, counterclockwise
+ # around the outside of the face.
+ self.triangles = triangles
+
+ def triangle_positions(self):
+ """
+ Triples of vertex positions.
+
+ """
+ for triangle in self.triangles:
+ yield tuple(self.vertex_positions[vx] for vx in triangle)
+
+ def volume(self):
+ """
+ Return the volume of this polyhedron.
+
+ """
+ acc = 0
+ for p1, p2, p3 in self.triangle_positions():
+ # Twice the area of the projection onto the x-y plane.
+ det = ((p2[1] - p3[1]) * (p1[0] - p3[0]) -
+ (p2[0] - p3[0]) * (p1[1] - p3[1]))
+ # Three times the average height.
+ height = p1[2] + p2[2] + p3[2]
+ acc += det * height
+ return acc / 6.0
+
+ def winding_number(self, point):
+ """Determine the winding number of *self* around the given point.
+
+ """
+ return sum(
+ triangle_chain(v1, v2, v3, point)
+ for v1, v2, v3 in self.triangle_positions()) // 2
diff --git a/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Math3D/Polyhedron/test_polygon.py b/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Math3D/Polyhedron/test_polygon.py
new file mode 100644
index 000000000..23cc982e4
--- /dev/null
+++ b/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Math3D/Polyhedron/test_polygon.py
@@ -0,0 +1,146 @@
+"""
+Tests for Polygon.winding_number.
+
+"""
+import unittest
+
+try:
+ import numpy
+except ImportError:
+ NUMPY_AVAILABLE = False
+else:
+ NUMPY_AVAILABLE = True
+
+from polygon import Polygon
+
+
+class TestPolygon(unittest.TestCase):
+ def test_simple_square(self):
+ square = Polygon(
+ vertex_positions=[
+ (1.0, -1.0),
+ (1.0, 1.0),
+ (-1.0, 1.0),
+ (-1.0, -1.0),
+ ]
+ )
+ origin = (0.0, 0.0)
+ self.assertEqual(square.winding_number(origin), 1)
+ self.assertEqual(square.area(), 4.0)
+
+ def test_double_square(self):
+ square = Polygon(
+ vertex_positions=[
+ (1.0, -1.0),
+ (1.0, 1.0),
+ (-1.0, 1.0),
+ (-1.0, -1.0),
+ ] * 2
+ )
+ origin = (0.0, 0.0)
+ self.assertEqual(square.winding_number(origin), 2)
+ self.assertEqual(square.area(), 8.0)
+
+ def test_clockwise_square(self):
+ square = Polygon(
+ vertex_positions=[
+ (1.0, -1.0),
+ (1.0, 1.0),
+ (-1.0, 1.0),
+ (-1.0, -1.0),
+ ][::-1]
+ )
+ origin = (0.0, 0.0)
+ self.assertEqual(square.winding_number(origin), -1)
+ self.assertEqual(square.area(), -4.0)
+
+ def test_various_points_in_square(self):
+ square = Polygon(
+ vertex_positions=[
+ (1.0, -1.0),
+ (1.0, 1.0),
+ (-1.0, 1.0),
+ (-1.0, -1.0),
+ ]
+ )
+ test_points = []
+ for x in range(-3, 4):
+ for y in range(-3, 4):
+ test_points.append((0.5*x, 0.5*y))
+
+ for point in test_points:
+ x, y = point
+ if -1 < x < 1 and -1 < y < 1:
+ # Point is inside.
+ self.assertEqual(square.winding_number(point), 1)
+ elif x < -1 or x > 1 or y < -1 or y > 1:
+ # Point outside.
+ self.assertEqual(square.winding_number(point), 0)
+ else:
+ with self.assertRaises(ValueError):
+ square.winding_number(point)
+
+ def test_aitch(self):
+ aitch = Polygon(
+ vertex_positions=[
+ (0, 0),
+ (1, 0),
+ (1, 1),
+ (2, 1),
+ (2, 0),
+ (3, 0),
+ (3, 3),
+ (2, 3),
+ (2, 2),
+ (1, 2),
+ (1, 3),
+ (0, 3),
+ ]
+ )
+
+ test_points = [
+ (0.5*x, 0.5*y)
+ for y in range(-1, 8)
+ for x in range(-1, 8)
+ ]
+
+ # * for boundary, '.' for outside, 'o' for inside.
+ template = """\
+.........
+.***.***.
+.*o*.*o*.
+.*o***o*.
+.*ooooo*.
+.*o***o*.
+.*o*.*o*.
+.***.***.
+.........
+"""
+ expected = ''.join(template.strip().split())
+
+ assert len(expected) == len(test_points)
+ for point, point_type in zip(test_points, expected):
+ if point_type == '.':
+ self.assertEqual(aitch.winding_number(point), 0)
+ elif point_type == 'o':
+ self.assertEqual(aitch.winding_number(point), 1)
+ else:
+ with self.assertRaises(ValueError):
+ aitch.winding_number(point)
+
+ @unittest.skipUnless(NUMPY_AVAILABLE, "Test requires NumPy")
+ def test_numpy_compatibility(self):
+ square = Polygon(
+ vertex_positions=numpy.array(
+ [
+ [1.0, -1.0],
+ [1.0, 1.0],
+ [-1.0, 1.0],
+ [-1.0, -1.0],
+ ],
+ dtype=numpy.float64,
+ )
+ )
+ origin = numpy.array([0.0, 0.0], dtype=numpy.float64)
+ self.assertEqual(square.winding_number(origin), 1)
+ self.assertEqual(square.area(), 4.0)
diff --git a/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Math3D/Polyhedron/test_polyhedron.py b/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Math3D/Polyhedron/test_polyhedron.py
new file mode 100644
index 000000000..37ea97136
--- /dev/null
+++ b/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Math3D/Polyhedron/test_polyhedron.py
@@ -0,0 +1,666 @@
+"""
+Tests for Polyhedron winding number calculation.
+
+"""
+import unittest
+
+try:
+ import numpy
+except ImportError:
+ NUMPY_AVAILABLE = False
+else:
+ NUMPY_AVAILABLE = True
+
+from polyhedron import Polyhedron
+
+
+# Sample polyhedra ############################################################
+
+# Regular tetrahedron.
+tetrahedron = Polyhedron(
+ vertex_positions=[
+ (0, 0, 0),
+ (0, 1, 1),
+ (1, 0, 1),
+ (1, 1, 0),
+ ],
+ triangles=[
+ [0, 1, 3],
+ [0, 2, 1],
+ [0, 3, 2],
+ [1, 2, 3],
+ ],
+)
+
+
+def tetrahedron_classify(point):
+ x, y, z = point
+ if x + y + z < 2 and x + y > z and x + z > y and y + z > x:
+ return "inside"
+ if x + y + z <= 2 and x + y >= z and x + z >= y and y + z >= x:
+ return "boundary"
+ return "outside"
+
+
+# Regular octahedron, with vertices on the axes.
+octahedron = Polyhedron(
+ vertex_positions=[
+ (-1, 0, 0), (0, -1, 0), (0, 0, -1),
+ (1, 0, 0), (0, 1, 0), (0, 0, 1),
+ ],
+ triangles=[
+ [0, 2, 1], [0, 4, 2], [0, 1, 5], [0, 5, 4],
+ [3, 1, 2], [3, 5, 1], [3, 2, 4], [3, 4, 5],
+ ],
+)
+
+# Cube with vertices at (+-1, +-1, +-1).
+cube = Polyhedron(
+ vertex_positions=[
+ (-1, -1, -1), (-1, -1, +1), (-1, +1, -1), (-1, +1, +1),
+ (+1, -1, -1), (+1, -1, +1), (+1, +1, -1), (+1, +1, +1),
+ ],
+ triangles=[
+ [1, 3, 2], [1, 0, 4], [1, 5, 7],
+ [2, 0, 1], [2, 6, 4], [2, 3, 7],
+ [4, 5, 1], [4, 0, 2], [4, 6, 7],
+ [7, 3, 1], [7, 6, 2], [7, 5, 4],
+ ],
+)
+
+# Pair of cubes, sharing a common vertex at the origin.
+pair_of_cubes = Polyhedron(
+ vertex_positions=[
+ (-1, -1, -1), (-1, -1, 0), (-1, 0, -1), (-1, 0, 0),
+ (0, -1, -1), (0, -1, 0), (0, 0, -1), (0, 0, 0),
+ (0, 0, 1), (0, 1, 0), (0, 1, 1),
+ (1, 0, 0), (1, 0, 1), (1, 1, 0), (1, 1, 1),
+ ],
+ triangles=[
+ [1, 3, 2], [1, 0, 4], [1, 5, 7],
+ [2, 0, 1], [2, 6, 4], [2, 3, 7],
+ [4, 5, 1], [4, 0, 2], [4, 6, 7],
+ [7, 3, 1], [7, 6, 2], [7, 5, 4],
+ [8, 10, 9], [8, 7, 11], [8, 12, 14],
+ [9, 7, 8], [9, 13, 11], [9, 10, 14],
+ [11, 12, 8], [11, 7, 9], [11, 13, 14],
+ [14, 10, 8], [14, 13, 9], [14, 12, 11],
+ ],
+)
+
+# Two stacked cuboids, one directly above the other.
+aligned_stacked_cuboids = Polyhedron(
+ vertex_positions=[
+ (0, 0, 0), (0, 0, 1), (0, 3, 0), (0, 3, 1),
+ (3, 0, 0), (3, 0, 1), (3, 3, 0), (3, 3, 1),
+ (0, 0, 2), (0, 0, 3), (0, 3, 2), (0, 3, 3),
+ (3, 0, 2), (3, 0, 3), (3, 3, 2), (3, 3, 3),
+ ],
+ triangles=(
+ cube.triangles +
+ [[x+8, y+8, z+8] for x, y, z in cube.triangles]
+ ),
+)
+
+# Similar, but with the cuboids misaligned.
+
+misaligned_stacked_cuboids = Polyhedron(
+ vertex_positions=[
+ (0, 0, 0), (0, 0, 1), (0, 2, 0), (0, 2, 1),
+ (2, 0, 0), (2, 0, 1), (2, 2, 0), (2, 2, 1),
+ (1, 1, 2), (1, 1, 3), (1, 3, 2), (1, 3, 3),
+ (3, 1, 2), (3, 1, 3), (3, 3, 2), (3, 3, 3),
+ ],
+ triangles=(
+ cube.triangles +
+ [[x+8, y+8, z+8] for x, y, z in cube.triangles]
+ ),
+)
+
+# Hollow cube: surface consists of two cubes, one facing outwards
+# and one facing inwards.
+hollow_cube = Polyhedron(
+ vertex_positions=[
+ (0, 0, 0), (0, 0, 3), (0, 3, 0), (0, 3, 3),
+ (3, 0, 0), (3, 0, 3), (3, 3, 0), (3, 3, 3),
+ (1, 1, 1), (1, 1, 2), (1, 2, 1), (1, 2, 2),
+ (2, 1, 1), (2, 1, 2), (2, 2, 1), (2, 2, 2),
+ ],
+ triangles=(
+ # Outer cube.
+ cube.triangles +
+ # Inner cube: reverse orientation.
+ [[z+8, y+8, x+8] for x, y, z in cube.triangles]
+ ),
+)
+
+# Nested cubes: surface consists of two cubes, both facing
+# outwards. Points inside the inner cube should have a winding
+# number of 2.
+
+nested_cube = Polyhedron(
+ vertex_positions=[
+ (0, 0, 0), (0, 0, 3), (0, 3, 0), (0, 3, 3),
+ (3, 0, 0), (3, 0, 3), (3, 3, 0), (3, 3, 3),
+ (1, 1, 1), (1, 1, 2), (1, 2, 1), (1, 2, 2),
+ (2, 1, 1), (2, 1, 2), (2, 2, 1), (2, 2, 2),
+ ],
+ triangles=(
+ # Outer cube.
+ cube.triangles +
+ # Inner cube: same orientation as outer cube.
+ [[x+8, y+8, z+8] for x, y, z in cube.triangles]
+ ),
+)
+
+# Torus.
+torus = Polyhedron(
+ vertex_positions=[
+ # Outer square, bottom face.
+ (0, 0, 0), (0, 3, 0), (3, 0, 0), (3, 3, 0),
+ # Inner square, bottom face.
+ (1, 1, 0), (1, 2, 0), (2, 1, 0), (2, 2, 0),
+ # Outer square, top face.
+ (0, 0, 1), (0, 3, 1), (3, 0, 1), (3, 3, 1),
+ # Inner square, top face.
+ (1, 1, 1), (1, 2, 1), (2, 1, 1), (2, 2, 1),
+ ],
+ triangles=[
+ # Top face.
+ [8, 14, 12], [14, 8, 10], [10, 15, 14], [15, 10, 11],
+ [11, 13, 15], [13, 11, 9], [9, 12, 13], [12, 9, 8],
+ # Bottom face.
+ [4, 6, 0], [2, 0, 6], [6, 7, 2], [3, 2, 7],
+ [7, 5, 3], [1, 3, 5], [5, 4, 1], [0, 1, 4],
+ # Outer faces.
+ [0, 2, 10], [10, 8, 0], [2, 3, 11], [11, 10, 2],
+ [3, 1, 9], [9, 11, 3], [1, 0, 8], [8, 9, 1],
+ # Inner faces.
+ [4, 12, 14], [14, 6, 4], [6, 14, 15], [15, 7, 6],
+ [7, 15, 13], [13, 5, 7], [5, 13, 12], [12, 4, 5],
+ ],
+)
+
+
+# Empty surface
+empty = Polyhedron(
+ vertex_positions=[],
+ triangles=[],
+)
+
+
+# Double-sided triangle. This is the simplest valid nontrivial
+# surface.
+triangle = Polyhedron(
+ triangles=[
+ [0, 1, 2],
+ [2, 1, 0],
+ ],
+ vertex_positions=[
+ [1.0, 0.0, 0.0],
+ [0.0, 1.0, 0.0],
+ [0.0, 0.0, 1.0],
+ ],
+)
+
+
+# A hexadecahedron that's topologically equivalent to two octagonal pyramids
+# glued base-to-base, but with a mapping into R^3 that wraps the surface twice
+# around the origin, so that its image in R^3 looks like the surface of an
+# octahedron. All points inside the surface have winding number 2.
+twice_wrapped_octahedron = Polyhedron(
+ triangles=[
+ (0, 1, 2),
+ (0, 2, 3),
+ (0, 3, 4),
+ (0, 4, 5),
+ (0, 5, 6),
+ (0, 6, 7),
+ (0, 7, 8),
+ (0, 8, 1),
+ (9, 2, 1),
+ (9, 3, 2),
+ (9, 4, 3),
+ (9, 5, 4),
+ (9, 6, 5),
+ (9, 7, 6),
+ (9, 8, 7),
+ (9, 1, 8),
+ ],
+ vertex_positions=[
+ (0.0, 0.0, 1.0),
+ (1.0, 0.0, 0.0),
+ (0.0, 1.0, 0.0),
+ (-1.0, 0.0, 0.0),
+ (0.0, -1.0, 0.0),
+ (1.0, 0.0, 0.0),
+ (0.0, 1.0, 0.0),
+ (-1.0, 0.0, 0.0),
+ (0.0, -1.0, 0.0),
+ (0.0, 0.0, -1.0),
+ ],
+)
+
+
+class TestPolyhedron(unittest.TestCase):
+ def test_invalid_polyhedra(self):
+ with self.assertRaises(ValueError):
+ # Tetrahedron with one face incorrectly oriented.
+ Polyhedron(
+ vertex_positions=[
+ (0, 0, 0),
+ (0, 1, 1),
+ (1, 0, 1),
+ (1, 1, 0),
+ ],
+ triangles=[
+ [0, 1, 3],
+ [0, 1, 2],
+ [0, 3, 2],
+ [1, 2, 3],
+ ],
+ )
+
+ with self.assertRaises(ValueError):
+ # Tetrahedron with a duplicated face.
+ Polyhedron(
+ vertex_positions=[
+ (0, 0, 0),
+ (0, 1, 1),
+ (1, 0, 1),
+ (1, 1, 0),
+ ],
+ triangles=[
+ [0, 1, 3],
+ [0, 2, 1],
+ [0, 3, 2],
+ [1, 2, 3],
+ [1, 2, 3],
+ ],
+ )
+
+ with self.assertRaises(ValueError):
+ # Tetrahedron with a missing face.
+ Polyhedron(
+ vertex_positions=[
+ (0, 0, 0),
+ (0, 1, 1),
+ (1, 0, 1),
+ (1, 1, 0),
+ ],
+ triangles=[
+ [0, 1, 3],
+ [0, 2, 1],
+ [0, 3, 2],
+ ],
+ )
+
+ def test_tetrahedron(self):
+ xs = ys = zs = [0.25 * v for v in range(-1, 6)]
+ points = [(x, y, z) for x in xs for y in ys for z in zs]
+ for point in points:
+ class_ = tetrahedron_classify(point)
+ if class_ == "inside":
+ self.assertEqual(tetrahedron.winding_number(point), 1)
+ elif class_ == "outside":
+ self.assertEqual(tetrahedron.winding_number(point), 0)
+ elif class_ == "boundary":
+ # Point is on the boundary.
+ with self.assertRaises(ValueError):
+ tetrahedron.winding_number(point)
+ else:
+ assert False, "should never get here"
+
+ def test_cube(self):
+ # Check volume
+ self.assertEqual(cube.volume(), 8)
+
+ def classify(point):
+ x, y, z = point
+ if -1 < x < 1 and -1 < y < 1 and -1 < z < 1:
+ return "inside"
+ if -1 <= x <= 1 and -1 <= y <= 1 and -1 <= z <= 1:
+ return "boundary"
+ return "outside"
+
+ # Quarter-integer boundaries from -1.25 to 1.25 inclusive.
+ xs = ys = zs = [0.25 * v for v in range(-5, 6)]
+ points = [(x, y, z) for x in xs for y in ys for z in zs]
+ for point in points:
+ class_ = classify(point)
+ if class_ == "inside":
+ self.assertEqual(cube.winding_number(point), 1)
+ elif class_ == "outside":
+ self.assertEqual(cube.winding_number(point), 0)
+ elif class_ == "boundary":
+ # Point is on the boundary.
+ with self.assertRaises(ValueError):
+ cube.winding_number(point)
+ else:
+ assert False, "should never get here"
+
+ def test_octahedron(self):
+ self.assertEqual(octahedron.volume(), 4.0 / 3.0)
+
+ def classify(point):
+ x, y, z = point
+ s = abs(x) + abs(y) + abs(z)
+ if s < 1:
+ return "inside"
+ elif s == 1:
+ return "boundary"
+ else:
+ return "outside"
+
+ # Quarter-integer boundaries from -1.25 to 1.25 inclusive.
+ xs = ys = zs = [0.25 * v for v in range(-5, 6)]
+ points = [(x, y, z) for x in xs for y in ys for z in zs]
+ for point in points:
+ class_ = classify(point)
+ if class_ == "inside":
+ self.assertEqual(octahedron.winding_number(point), 1)
+ elif class_ == "outside":
+ self.assertEqual(octahedron.winding_number(point), 0)
+ elif class_ == "boundary":
+ # Point is on the boundary.
+ with self.assertRaises(ValueError):
+ octahedron.winding_number(point)
+ else:
+ assert False, "never get here"
+
+ def test_twice_wrapped_octahedron(self):
+ poly = twice_wrapped_octahedron
+
+ self.assertEqual(poly.volume(), 8.0 / 3.0)
+
+ def winding_number(point):
+ x, y, z = point
+ s = abs(x) + abs(y) + abs(z)
+ if s == 1:
+ raise ValueError("boundary")
+ return 2 if s < 1 else 0
+
+ xs = ys = zs = [0.25 * v for v in range(-5, 6)]
+ points = [(x, y, z) for x in xs for y in ys for z in zs]
+ for point in points:
+ try:
+ expected = winding_number(point)
+ except ValueError:
+ with self.assertRaises(ValueError):
+ poly.winding_number(point)
+ else:
+ self.assertEqual(poly.winding_number(point), expected)
+
+ def test_pair_of_cubes(self):
+ self.assertEqual(pair_of_cubes.volume(), 2.0)
+
+ def classify(point):
+ x, y, z = point
+ if -1 < x < 0 and -1 < y < 0 and -1 < z < 0:
+ return "inside"
+ if 0 < x < 1 and 0 < y < 1 and 0 < z < 1:
+ return "inside"
+ if -1 <= x <= 0 and -1 <= y <= 0 and -1 <= z <= 0:
+ return "boundary"
+ if 0 <= x <= 1 and 0 <= y <= 1 and 0 <= z <= 1:
+ return "boundary"
+ return "outside"
+
+ # Quarter-integer boundaries from -1.25 to 1.25 inclusive.
+ xs = ys = zs = [0.25 * v for v in range(-5, 6)]
+ points = [(x, y, z) for x in xs for y in ys for z in zs]
+ for point in points:
+ class_ = classify(point)
+ if class_ == "inside":
+ self.assertEqual(pair_of_cubes.winding_number(point), 1)
+ elif class_ == "boundary":
+ with self.assertRaises(ValueError):
+ pair_of_cubes.winding_number(point)
+ elif class_ == "outside":
+ self.assertEqual(pair_of_cubes.winding_number(point), 0)
+ else:
+ assert False, "never get here"
+
+ def test_hollow_cube(self):
+ self.assertEqual(hollow_cube.volume(), 26.0)
+
+ def classify(point):
+ x, y, z = point
+ if 1 < x < 2 and 1 < y < 2 and 1 < z < 2:
+ return "outside"
+ if 1 <= x <= 2 and 1 <= y <= 2 and 1 <= z <= 2:
+ return "boundary"
+ if 0 < x < 3 and 0 < y < 3 and 0 < z < 3:
+ return "inside"
+ if 0 <= x <= 3 and 0 <= y <= 3 and 0 <= z <= 3:
+ return "boundary"
+ return "outside"
+
+ xs = ys = zs = [0.25 * v for v in range(-1, 14)]
+ points = [(x, y, z) for x in xs for y in ys for z in zs]
+ for point in points:
+ class_ = classify(point)
+ if class_ == "inside":
+ self.assertEqual(hollow_cube.winding_number(point), 1)
+ elif class_ == "boundary":
+ with self.assertRaises(ValueError):
+ hollow_cube.winding_number(point)
+ elif class_ == "outside":
+ self.assertEqual(hollow_cube.winding_number(point), 0)
+ else:
+ assert False, "never get here"
+
+ def test_nested_cube(self):
+ # To make sense of the volume, think of it as the integral
+ # of the winding number: in effect, points inside the inner cube
+ # contribute to the volume *twice*.
+ self.assertEqual(nested_cube.volume(), 28.0)
+
+ def classify(point):
+ x, y, z = point
+ if 1 < x < 2 and 1 < y < 2 and 1 < z < 2:
+ return "doubled"
+ if 1 <= x <= 2 and 1 <= y <= 2 and 1 <= z <= 2:
+ return "boundary"
+ if 0 < x < 3 and 0 < y < 3 and 0 < z < 3:
+ return "inside"
+ if 0 <= x <= 3 and 0 <= y <= 3 and 0 <= z <= 3:
+ return "boundary"
+ return "outside"
+
+ xs = ys = zs = [0.25 * v for v in range(-1, 14)]
+ points = [(x, y, z) for x in xs for y in ys for z in zs]
+ for point in points:
+ class_ = classify(point)
+ if class_ == "inside":
+ self.assertEqual(nested_cube.winding_number(point), 1)
+ elif class_ == "boundary":
+ with self.assertRaises(ValueError):
+ nested_cube.winding_number(point)
+ elif class_ == "outside":
+ self.assertEqual(nested_cube.winding_number(point), 0)
+ elif class_ == "doubled":
+ self.assertEqual(nested_cube.winding_number(point), 2)
+ else:
+ assert False, "never get here"
+
+ def test_torus(self):
+ self.assertEqual(torus.volume(), 8.0)
+
+ def classify(point):
+ x, y, z = point
+ if 0 < z < 1 and (0 < x < 1 or 2 < x < 3) and 0 < y < 3:
+ return "inside"
+ if 0 < z < 1 and (0 < y < 1 or 2 < y < 3) and 0 < x < 3:
+ return "inside"
+ if 0 <= z <= 1 and (0 <= x <= 1 or 2 <= x <= 3) and 0 <= y <= 3:
+ return "boundary"
+ if 0 <= z <= 1 and (0 <= y <= 1 or 2 <= y <= 3) and 0 <= x <= 3:
+ return "boundary"
+ return "outside"
+
+ xs = ys = [0.25 * v for v in range(-1, 14)]
+ zs = [0.25 * v for v in range(-1, 6)]
+ points = [(x, y, z) for x in xs for y in ys for z in zs]
+ for point in points:
+ class_ = classify(point)
+ if class_ == "inside":
+ self.assertEqual(torus.winding_number(point), 1)
+ elif class_ == "boundary":
+ with self.assertRaises(ValueError):
+ torus.winding_number(point)
+ elif class_ == "outside":
+ self.assertEqual(torus.winding_number(point), 0)
+ else:
+ assert False, "never get here"
+
+ def test_aligned_stacked_cuboids(self):
+ self.assertEqual(aligned_stacked_cuboids.volume(), 18.0)
+
+ def classify(point):
+ x, y, z = point
+ if 0 < x < 3 and 0 < y < 3 and 0 < z < 1:
+ return "inside"
+ if 0 < x < 3 and 0 < y < 3 and 2 < z < 3:
+ return "inside"
+ if 0 <= x <= 3 and 0 <= y <= 3 and 0 <= z <= 1:
+ return "boundary"
+ if 0 <= x <= 3 and 0 <= y <= 3 and 2 <= z <= 3:
+ return "boundary"
+ return "outside"
+
+ xs = ys = zs = [0.25 * v for v in range(-1, 14)]
+ points = [(x, y, z) for x in xs for y in ys for z in zs]
+ for point in points:
+ class_ = classify(point)
+ if class_ == "inside":
+ self.assertEqual(
+ aligned_stacked_cuboids.winding_number(point), 1)
+ elif class_ == "boundary":
+ with self.assertRaises(ValueError):
+ aligned_stacked_cuboids.winding_number(point)
+ elif class_ == "outside":
+ self.assertEqual(
+ aligned_stacked_cuboids.winding_number(point), 0)
+ else:
+ assert False, "never get here"
+
+ def test_misaligned_stacked_cuboids(self):
+ self.assertEqual(misaligned_stacked_cuboids.volume(), 8.0)
+
+ def classify(point):
+ x, y, z = point
+ if 0 < x < 2 and 0 < y < 2 and 0 < z < 1:
+ return "inside"
+ if 1 < x < 3 and 1 < y < 3 and 2 < z < 3:
+ return "inside"
+ if 0 <= x <= 2 and 0 <= y <= 2 and 0 <= z <= 1:
+ return "boundary"
+ if 1 <= x <= 3 and 1 <= y <= 3 and 2 <= z <= 3:
+ return "boundary"
+ return "outside"
+
+ xs = ys = zs = [0.25 * v for v in range(-1, 14)]
+ points = [(x, y, z) for x in xs for y in ys for z in zs]
+ for point in points:
+ class_ = classify(point)
+ if class_ == "inside":
+ self.assertEqual(
+ misaligned_stacked_cuboids.winding_number(point), 1)
+ elif class_ == "boundary":
+ with self.assertRaises(ValueError):
+ misaligned_stacked_cuboids.winding_number(point)
+ elif class_ == "outside":
+ self.assertEqual(
+ misaligned_stacked_cuboids.winding_number(point), 0)
+ else:
+ assert False, "never get here"
+
+ def test_empty(self):
+ self.assertEqual(empty.volume(), 0.0)
+ xs = ys = zs = [0.25 * v for v in range(-1, 14)]
+ points = [(x, y, z) for x in xs for y in ys for z in zs]
+ for point in points:
+ self.assertEqual(empty.winding_number(point), 0)
+
+ @unittest.skipUnless(NUMPY_AVAILABLE, "Test requires NumPy")
+ def test_numpy_float64_compatibility(self):
+ # This is a repetition of test_cube, but using NumPy float64
+ # and int64 values in place of Python ints for vertices and triangles
+ # (respectively), and ndarrays in place of lists or tuples.
+ numpy_cube = Polyhedron(
+ triangles=numpy.array(cube.triangles, dtype=numpy.int64),
+ vertex_positions=numpy.array(
+ cube.vertex_positions, dtype=numpy.float64),
+ )
+
+ # Check volume
+ self.assertEqual(numpy_cube.volume(), 8)
+
+ def classify(point):
+ x, y, z = point
+ if -1 < x < 1 and -1 < y < 1 and -1 < z < 1:
+ return "inside"
+ if -1 <= x <= 1 and -1 <= y <= 1 and -1 <= z <= 1:
+ return "boundary"
+ return "outside"
+
+ # Quarter-integer boundaries from -1.25 to 1.25 inclusive.
+ xs = ys = zs = numpy.linspace(-1.25, 1.25, 11)
+
+ points = [(x, y, z) for x in xs for y in ys for z in zs]
+ for point in points:
+ class_ = classify(point)
+ if class_ == "inside":
+ self.assertEqual(numpy_cube.winding_number(point), 1)
+ elif class_ == "outside":
+ self.assertEqual(numpy_cube.winding_number(point), 0)
+ elif class_ == "boundary":
+ # Point is on the boundary.
+ with self.assertRaises(ValueError):
+ numpy_cube.winding_number(point)
+ else:
+ assert False, "should never get here"
+
+ @unittest.skipUnless(NUMPY_AVAILABLE, "Test requires NumPy")
+ def test_numpy_int64_compatibility(self):
+ # This is a repetition of test_cube, but using NumPy int64
+ # values in place of Python ints, and ndarrays in place
+ # of lists or tuples.
+ numpy_cube = Polyhedron(
+ triangles=numpy.array(cube.triangles, dtype=numpy.int64),
+ vertex_positions=numpy.array(
+ cube.vertex_positions, dtype=numpy.int64),
+ )
+
+ # Check volume
+ self.assertEqual(numpy_cube.volume(), 8)
+
+ def classify(point):
+ x, y, z = point
+ if -1 < x < 1 and -1 < y < 1 and -1 < z < 1:
+ return "inside"
+ if -1 <= x <= 1 and -1 <= y <= 1 and -1 <= z <= 1:
+ return "boundary"
+ return "outside"
+
+ # Quarter-integer boundaries from -1.25 to 1.25 inclusive.
+ xs = ys = zs = numpy.linspace(-1.25, 1.25, 11)
+
+ points = [(x, y, z) for x in xs for y in ys for z in zs]
+ for point in points:
+ class_ = classify(point)
+ if class_ == "inside":
+ self.assertEqual(numpy_cube.winding_number(point), 1)
+ elif class_ == "outside":
+ self.assertEqual(numpy_cube.winding_number(point), 0)
+ elif class_ == "boundary":
+ # Point is on the boundary.
+ with self.assertRaises(ValueError):
+ numpy_cube.winding_number(point)
+ else:
+ assert False, "should never get here"
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Point3D.vb b/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Point3D.vb
index ba3e8c37e..d81d0e6e7 100644
--- a/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Point3D.vb
+++ b/gr/Microsoft.VisualBasic.Imaging/Drawing3D/Point3D.vb
@@ -97,16 +97,28 @@ Namespace Drawing3D
Me.Z = z
End Sub
- Public Sub New(p As PointF, z!)
+
+ Public Sub New(p As PointF, Optional z! = 0.0)
Me.X = p.X
Me.Y = p.Y
Me.Z = z
End Sub
+
Public Sub New(p As Point)
Call Me.New(p.X, p.Y)
End Sub
+
+ Sub New(xyz As Double())
+ Call Me.New(xyz(0), xyz(1), xyz.ElementAtOrDefault(2))
+ End Sub
+
+
+ Sub New(xyz As Single())
+ Call Me.New(xyz(0), xyz(1), xyz.ElementAtOrDefault(2))
+ End Sub
+
Public Property X As Double Implements PointF3D.X
Public Property Y As Double Implements PointF3D.Y
Public Property Z As Double Implements PointF3D.Z
@@ -195,9 +207,10 @@ Namespace Drawing3D
Public Shared Operator -(p3D As Point3D, offset As Point3D) As Point3D
Return New Point3D(
- p3D.X - offset.X,
- p3D.Y - offset.Y,
- p3D.Z - offset.Z)
+ x:=p3D.X - offset.X,
+ y:=p3D.Y - offset.Y,
+ z:=p3D.Z - offset.Z
+ )
End Operator
'''
diff --git a/gr/Microsoft.VisualBasic.Imaging/test/hqx_test.vb b/gr/Microsoft.VisualBasic.Imaging/test/hqx_test.vb
index 1ff06e0f1..6c3d64627 100644
--- a/gr/Microsoft.VisualBasic.Imaging/test/hqx_test.vb
+++ b/gr/Microsoft.VisualBasic.Imaging/test/hqx_test.vb
@@ -50,7 +50,7 @@
#End Region
Imports System.Drawing
-Imports System.Drawing.Imaging
+Imports Microsoft.VisualBasic.Imaging
Imports Microsoft.VisualBasic.Imaging.BitmapImage
Imports Microsoft.VisualBasic.Imaging.Drawing2D.HeatMap
diff --git a/gr/Microsoft.VisualBasic.Imaging/test/objReaderTest.vb b/gr/Microsoft.VisualBasic.Imaging/test/objReaderTest.vb
new file mode 100644
index 000000000..ec64fae7e
--- /dev/null
+++ b/gr/Microsoft.VisualBasic.Imaging/test/objReaderTest.vb
@@ -0,0 +1,13 @@
+Imports System.IO
+Imports Microsoft.VisualBasic.Imaging.Landscape.Wavefront
+
+Module objReaderTest
+
+ Sub Main()
+ Using file As StreamReader = "E:\mzkit\Rscript\Library\MSI_app\data\Segmentation.obj".OpenReader
+ Dim obj As OBJ = OBJ.ReadFile(file)
+
+ Pause()
+ End Using
+ End Sub
+End Module
diff --git a/gr/Microsoft.VisualBasic.Imaging/test/test.vbproj b/gr/Microsoft.VisualBasic.Imaging/test/test.vbproj
index 72af95061..a54b9a48a 100644
--- a/gr/Microsoft.VisualBasic.Imaging/test/test.vbproj
+++ b/gr/Microsoft.VisualBasic.Imaging/test/test.vbproj
@@ -6,7 +6,7 @@
AnyCPU
{1A566414-428F-403B-84A6-6B9F36FB1117}
Exe
- Test.Project.imageSmoothTest
+ Test.Project.objReaderTest
Test.Project
Test.Project
512
@@ -118,6 +118,7 @@
+
@@ -128,6 +129,7 @@
+
@@ -169,21 +171,25 @@
-
- {e3367b88-5d0c-495a-8273-331656d4b5aa}
- math-core
+
+ {7b55a6ec-7f70-4a03-8a3f-3705f01658d6}
+ Math.NET5
-
- {fecce1fd-e1d4-49e3-a668-60bb5e7aed99}
- 47-dotnet_Microsoft.VisualBasic
+
+ {14589a8e-dec0-4f3b-bba3-f127b5a89b23}
+ Core
-
- {2DD4BE80-DDC3-4767-94A7-10F1C3395716}
- MIME-htmls
+
+ {a9cf5f42-84f0-4b92-922c-0f1cf08e0b59}
+ html_netcore5
-
- {85e71b4b-9276-4ec8-aadc-c849205f1ea8}
- Microsoft.VisualBasic.Imaging
+
+ {3e100c21-5196-485e-9546-bb0db4138af7}
+ Landscape
+
+
+ {2ccc6428-7934-4b1d-be0d-757f6af14692}
+ imaging.NET5
diff --git a/gr/Microsoft.VisualBasic.Imaging/test/test5.vbproj b/gr/Microsoft.VisualBasic.Imaging/test/test5.vbproj
deleted file mode 100644
index 1fa93065b..000000000
--- a/gr/Microsoft.VisualBasic.Imaging/test/test5.vbproj
+++ /dev/null
@@ -1,126 +0,0 @@
-
-
-
- Microsoft.VisualBasic.Imaging
- net6.0
- test
- AnyCPU;x64
- Debug;Release;LipidSearch;Rsharp_app_release;mzkit;NPSearch
- Exe
-
-
-
-
- netcore5=1,UNIX=1
- Microsoft.VisualBasic.Imaging.xml
- true
- true
- full
-
-
-
- netcore5=1
- Microsoft.VisualBasic.Imaging.xml
-
-
-
- true
- false
- true
- full
- false
- true
- netcore5=1,UNIX=1
- Microsoft.VisualBasic.Imaging.xml
-
-
-
- true
- false
- true
- full
- false
- true
- netcore5=1,UNIX=1
- Microsoft.VisualBasic.Imaging.xml
- D:\GCModeller\src\R-sharp\App\
-
-
-
- true
- false
- true
- full
- false
- true
- netcore5=1,UNIX=1
- Microsoft.VisualBasic.Imaging.xml
- D:\biodeep\biodeepdb_v3\metaCluster\NPSearch\assembly\
-
-
-
- true
- false
- true
- full
- false
- true
- netcore5=1,UNIX=1
- Microsoft.VisualBasic.Imaging.xml
- D:\GCModeller\src\R-sharp\App\
-
-
-
- Microsoft.VisualBasic.Imaging.xml
-
-
-
- Microsoft.VisualBasic.Imaging.xml
-
-
-
- Microsoft.VisualBasic.Imaging.xml
-
-
-
- Microsoft.VisualBasic.Imaging.xml
-
-
-
- Microsoft.VisualBasic.Imaging.xml
-
-
-
- Microsoft.VisualBasic.Imaging.xml
- true
- false
- true
- full
- false
- netcore5=1,UNIX=1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-