├── .gitattributes
├── .github
└── FUNDING.yml
├── .gitignore
├── Heron.sln
├── Heron
├── Components
│ ├── Deprecated
│ │ ├── ExportVector_DEPRECATED20240729.cs
│ │ ├── ImportLAZ_DEPRECATED20250120.cs
│ │ ├── ImportSHP_DEPRECATED.cs
│ │ ├── ImportTopo_DEPRECATED.cs
│ │ ├── ImportVectorSRS_DEPRECATED20230506.cs
│ │ ├── ImportVector_DEPRECATED20220730.cs
│ │ ├── MapboxRaster_DEPRECATED20211114.cs
│ │ ├── MultiSDiff_DEPRECATED20230910.cs
│ │ ├── RESTLayer_DEPRECATED.cs
│ │ ├── RESTRaster_DEPRECATED20220730.cs
│ │ ├── RESTTOSM_DEPRECATED20240128.cs
│ │ ├── RESTTopo_DEPRECATED20250119.cs
│ │ ├── RESTVector_DEPRECATED.cs
│ │ ├── RESTVector_DEPRECATED20220730.cs
│ │ ├── SetEAP_DEPRECATED20220416.cs
│ │ ├── SetSRS_DEPRECATED20240811.cs
│ │ └── SlippyRaster_DEPRECATED2021114.cs
│ ├── GIS API
│ │ ├── MapboxIsochrone.cs
│ │ ├── MapboxIsochroneSpeckle.cs
│ │ ├── MapboxRaster.cs
│ │ ├── MapboxTopo.cs
│ │ ├── MapboxVector.cs
│ │ ├── SlippyRaster.cs
│ │ ├── SlippyRasterCustom.cs
│ │ ├── SlippyTiles.cs
│ │ ├── SlippyViewport.cs
│ │ └── Yelp.cs
│ ├── GIS Import-Export
│ │ ├── ExportVector.cs
│ │ ├── ImportLAZ.cs
│ │ ├── ImportOSM.cs
│ │ ├── ImportOSMLite.cs
│ │ ├── ImportRaster.cs
│ │ ├── ImportTopo.cs
│ │ ├── ImportTopoLite.cs
│ │ ├── ImportVectorLite.cs
│ │ └── ImportVectorSRS.cs
│ ├── GIS REST
│ │ ├── RESTGeocode.cs
│ │ ├── RESTLayer.cs
│ │ ├── RESTOSM.cs
│ │ ├── RESTRasterSRS.cs
│ │ ├── RESTRevGeo.cs
│ │ ├── RESTTopo.cs
│ │ └── RESTVectorSRS.cs
│ ├── GIS Tools
│ │ ├── CoordinateTransformation.cs
│ │ ├── DDtoXY.cs
│ │ ├── DMStoDD.cs
│ │ ├── GdalBuffer.cs
│ │ ├── GdalConcaveHull.cs
│ │ ├── GdalConvexHull.cs
│ │ ├── GdalFillNoData.cs
│ │ ├── GdalInfo.cs
│ │ ├── GdalOGR2OGR.cs
│ │ ├── GdalPoligonize.cs
│ │ ├── GdalTranslate.cs
│ │ ├── GdalWarp.cs
│ │ ├── OgrInfo.cs
│ │ ├── SetEAP.cs
│ │ ├── SetSRS.cs
│ │ └── XYtoDD.cs
│ └── Utilities
│ │ ├── ColorToHex.cs
│ │ ├── DecimateTopoFromPoint.cs
│ │ ├── GdalDetails.cs
│ │ ├── HexToColor.cs
│ │ ├── ImageCubeMap.cs
│ │ ├── ImageCubeMapPlus.cs
│ │ ├── ImageCubeToEqui.cs
│ │ ├── ImageFilterColors.cs
│ │ ├── ImageFlip.cs
│ │ ├── ImageRotate.cs
│ │ ├── ImageTopColors.cs
│ │ ├── MultiMeshPatch.cs
│ │ ├── MultiMoveToTopo.cs
│ │ ├── MultiSDiff.cs
│ │ ├── TopiaryFlatten.cs
│ │ └── VisualCenter.cs
├── Convert.cs
├── GdalConfiguration.cs
├── Heron.csproj
├── HeronBoxPreviewComponent.cs
├── HeronComponent.cs
├── HeronConfiguration.cs
├── HeronInfo.cs
├── HeronRasterPreviewComponent.cs
├── HeronSRS.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── Resources
│ ├── Demo.png
│ ├── HeronServiceEndpoints.json
│ ├── Icon.png
│ ├── ddtoxy.png
│ ├── eap.png
│ ├── geocode.png
│ ├── heron-favicon.png
│ ├── heron-icon.png
│ ├── img.png
│ ├── layer-01.png
│ ├── layer.png
│ ├── raster.png
│ ├── revgeocode.png
│ ├── shp.png
│ ├── vector.png
│ └── xytodd.png
├── SpeckleAsync
│ ├── GH_AsyncComponent.cs
│ └── WorkerInstance.cs
├── app.config
├── appsettings.json
└── packages.config
├── HeronServiceEndpoints.json
├── LICENSE
├── Packages.dgml
└── README.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: herongis
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | project.fragment.lock.json
46 | artifacts/
47 |
48 | *_i.c
49 | *_p.c
50 | *_i.h
51 | *.ilk
52 | *.meta
53 | *.obj
54 | *.pch
55 | *.pdb
56 | *.pgc
57 | *.pgd
58 | *.rsp
59 | *.sbr
60 | *.tlb
61 | *.tli
62 | *.tlh
63 | *.tmp
64 | *.tmp_proj
65 | *.log
66 | *.vspscc
67 | *.vssscc
68 | .builds
69 | *.pidb
70 | *.svclog
71 | *.scc
72 |
73 | # Chutzpah Test files
74 | _Chutzpah*
75 |
76 | # Visual C++ cache files
77 | ipch/
78 | *.aps
79 | *.ncb
80 | *.opendb
81 | *.opensdf
82 | *.sdf
83 | *.cachefile
84 | *.VC.db
85 | *.VC.VC.opendb
86 |
87 | # Visual Studio profiler
88 | *.psess
89 | *.vsp
90 | *.vspx
91 | *.sap
92 |
93 | # TFS 2012 Local Workspace
94 | $tf/
95 |
96 | # Guidance Automation Toolkit
97 | *.gpState
98 |
99 | # ReSharper is a .NET coding add-in
100 | _ReSharper*/
101 | *.[Rr]e[Ss]harper
102 | *.DotSettings.user
103 |
104 | # JustCode is a .NET coding add-in
105 | .JustCode
106 |
107 | # TeamCity is a build add-in
108 | _TeamCity*
109 |
110 | # DotCover is a Code Coverage Tool
111 | *.dotCover
112 |
113 | # NCrunch
114 | _NCrunch_*
115 | .*crunch*.local.xml
116 | nCrunchTemp_*
117 |
118 | # MightyMoose
119 | *.mm.*
120 | AutoTest.Net/
121 |
122 | # Web workbench (sass)
123 | .sass-cache/
124 |
125 | # Installshield output folder
126 | [Ee]xpress/
127 |
128 | # DocProject is a documentation generator add-in
129 | DocProject/buildhelp/
130 | DocProject/Help/*.HxT
131 | DocProject/Help/*.HxC
132 | DocProject/Help/*.hhc
133 | DocProject/Help/*.hhk
134 | DocProject/Help/*.hhp
135 | DocProject/Help/Html2
136 | DocProject/Help/html
137 |
138 | # Click-Once directory
139 | publish/
140 |
141 | # Publish Web Output
142 | *.[Pp]ublish.xml
143 | *.azurePubxml
144 | # TODO: Comment the next line if you want to checkin your web deploy settings
145 | # but database connection strings (with potential passwords) will be unencrypted
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
150 | # checkin your Azure Web App publish settings, but sensitive information contained
151 | # in these scripts will be unencrypted
152 | PublishScripts/
153 |
154 | # NuGet Packages
155 | *.nupkg
156 | # The packages folder can be ignored because of Package Restore
157 | **/packages/*
158 | # except build/, which is used as an MSBuild target.
159 | !**/packages/build/
160 | # Uncomment if necessary however generally it will be regenerated when needed
161 | #!**/packages/repositories.config
162 | # NuGet v3's project.json files produces more ignoreable files
163 | *.nuget.props
164 | *.nuget.targets
165 |
166 | # Microsoft Azure Build Output
167 | csx/
168 | *.build.csdef
169 |
170 | # Microsoft Azure Emulator
171 | ecf/
172 | rcf/
173 |
174 | # Windows Store app package directories and files
175 | AppPackages/
176 | BundleArtifacts/
177 | Package.StoreAssociation.xml
178 | _pkginfo.txt
179 |
180 | # Visual Studio cache files
181 | # files ending in .cache can be ignored
182 | *.[Cc]ache
183 | # but keep track of directories ending in .cache
184 | !*.[Cc]ache/
185 |
186 | # Others
187 | ClientBin/
188 | ~$*
189 | *~
190 | *.dbmdl
191 | *.dbproj.schemaview
192 | *.jfm
193 | *.pfx
194 | *.publishsettings
195 | node_modules/
196 | orleans.codegen.cs
197 |
198 | # Since there are multiple workflows, uncomment next line to ignore bower_components
199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
200 | #bower_components/
201 |
202 | # RIA/Silverlight projects
203 | Generated_Code/
204 |
205 | # Backup & report files from converting an old project file
206 | # to a newer Visual Studio version. Backup files are not needed,
207 | # because we have git ;-)
208 | _UpgradeReport_Files/
209 | Backup*/
210 | UpgradeLog*.XML
211 | UpgradeLog*.htm
212 |
213 | # SQL Server files
214 | *.mdf
215 | *.ldf
216 |
217 | # Business Intelligence projects
218 | *.rdl.data
219 | *.bim.layout
220 | *.bim_*.settings
221 |
222 | # Microsoft Fakes
223 | FakesAssemblies/
224 |
225 | # GhostDoc plugin setting file
226 | *.GhostDoc.xml
227 |
228 | # Node.js Tools for Visual Studio
229 | .ntvs_analysis.dat
230 |
231 | # Visual Studio 6 build log
232 | *.plg
233 |
234 | # Visual Studio 6 workspace options file
235 | *.opt
236 |
237 | # Visual Studio LightSwitch build output
238 | **/*.HTMLClient/GeneratedArtifacts
239 | **/*.DesktopClient/GeneratedArtifacts
240 | **/*.DesktopClient/ModelManifest.xml
241 | **/*.Server/GeneratedArtifacts
242 | **/*.Server/ModelManifest.xml
243 | _Pvt_Extensions
244 |
245 | # Paket dependency manager
246 | .paket/paket.exe
247 | paket-files/
248 |
249 | # FAKE - F# Make
250 | .fake/
251 |
252 | # JetBrains Rider
253 | .idea/
254 | *.sln.iml
255 |
256 | # CodeRush
257 | .cr/
258 |
259 | # Python Tools for Visual Studio (PTVS)
260 | __pycache__/
261 | *.pyc
--------------------------------------------------------------------------------
/Heron.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.31613.86
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Heron", "Heron\Heron.csproj", "{A3CC60C1-0145-4237-8E81-1E96326B62A2}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {A3CC60C1-0145-4237-8E81-1E96326B62A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {A3CC60C1-0145-4237-8E81-1E96326B62A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {A3CC60C1-0145-4237-8E81-1E96326B62A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {A3CC60C1-0145-4237-8E81-1E96326B62A2}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {50125008-9BD8-47A9-9FC7-BC762A783683}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Heron/Components/Deprecated/MultiSDiff_DEPRECATED20230910.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Grasshopper.Kernel;
5 | using Grasshopper.Kernel.Data;
6 | using Grasshopper.Kernel.Types;
7 | using Rhino.Geometry;
8 |
9 | namespace Heron
10 | {
11 | public class MultiSDiff_DEPRECATED20230910_OBSOLETE : HeronComponent
12 | {
13 | ///
14 | /// Initializes a new instance of the MultiSDiff class.
15 | ///
16 | public MultiSDiff_DEPRECATED20230910_OBSOLETE()
17 | : base("Multi SDiff", "MSDiff",
18 | "This multithreaded boolean solid difference (SDiff) component spreads the branches of input over threads for the boolean operation. " +
19 | "Any failed difference breps will be discarded to the Bad Breps output. " +
20 | "An example use would be to differnce shapes from panels where each panel and the shapes to be cut are on the same relative branches in a tree. " +
21 | "Of the available threads, one thread is always reserved for the GUI.",
22 | "Utilities")
23 | {
24 | }
25 |
26 | ///Retiring this component to add faster boolean difference algo
27 | public override Grasshopper.Kernel.GH_Exposure Exposure
28 | {
29 | get { return GH_Exposure.hidden; }
30 | }
31 |
32 | ///
33 | /// Registers all the input parameters for this component.
34 | ///
35 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
36 | {
37 | pManager.AddBrepParameter("Solids", "S", "Solid breps from which to difference.", GH_ParamAccess.tree);
38 | pManager.AddBrepParameter("Diffs", "D", "Solid breps of which to remove.", GH_ParamAccess.tree);
39 | }
40 |
41 | ///
42 | /// Registers all the output parameters for this component.
43 | ///
44 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
45 | {
46 | pManager.AddBrepParameter("Results", "R", "Results of boolean difference operation.", GH_ParamAccess.tree);
47 | pManager.AddBrepParameter("Bad Breps", "BB", "Differnce breps that failed in the boolean operation", GH_ParamAccess.tree);
48 | }
49 |
50 | ///
51 | /// This is the method that actually does the work.
52 | ///
53 | /// The DA object is used to retrieve from inputs and store in outputs.
54 | protected override void SolveInstance(IGH_DataAccess DA)
55 | {
56 | GH_Structure sBreps = new GH_Structure();
57 | DA.GetDataTree(0, out sBreps);
58 |
59 | GH_Structure dBreps = new GH_Structure();
60 | DA.GetDataTree(1, out dBreps);
61 |
62 | double tol = DocumentTolerance();
63 |
64 | ///Reserve one processor for GUI
65 | int totalMaxConcurrancy = System.Environment.ProcessorCount - 1;
66 |
67 | ///Tells us how many threads were using
68 | Message = totalMaxConcurrancy + " threads";
69 |
70 | ///Declare dictionaries that work in parallel to hold the successful boolean results and
71 | ///the unsuccessful boolean cutters
72 | var mainBrepsMT = new System.Collections.Concurrent.ConcurrentDictionary();
73 | var badBrepsMT = new System.Collections.Concurrent.ConcurrentDictionary>();
74 |
75 | ///Start of the parallel engine
76 | ///Cast to GH_Brep to Brep and back in parallel engine to avoid speed hit when casting all at once later
77 | System.Threading.Tasks.Parallel.ForEach(sBreps.Paths, new System.Threading.Tasks.ParallelOptions
78 | { MaxDegreeOfParallelism = totalMaxConcurrancy },
79 | pth =>
80 | {
81 |
82 | List badBrep = new List();
83 |
84 | Brep mainBrep = new Brep();
85 | GH_Convert.ToBrep(sBreps.get_Branch(pth)[0], ref mainBrep, 0);
86 | List diffBreps = new List();
87 | foreach (var d_GH in dBreps.get_Branch(pth))
88 | {
89 | Brep d_Rhino = new Brep();
90 | GH_Convert.ToBrep(d_GH, ref d_Rhino, 0);
91 | diffBreps.Add(d_Rhino);
92 | }
93 |
94 | ///Look into boolean first with lists, then if fails, revert to one-by-one
95 | ///https://discourse.mcneel.com/t/boolean-difference-in-gh-much-slower-than-in-rhino/97985/19
96 |
97 | ///Difference one cutter brep at a time from the main brep in the branch.
98 | ///This allows the boolean operation to continue without failing
99 | ///and bad cutter breps can be discarded to a list that can be used for troubleshooting
100 | ///haven't noticed a hit big hit on performance
101 | foreach (Brep b in diffBreps)
102 | {
103 | Brep[] breps = new Brep[] { };
104 | breps = Brep.CreateBooleanDifference(mainBrep, b, tol);
105 | if ((breps == null) || (breps.Length < 1))
106 | {
107 | badBrep.Add(new GH_Brep(b));
108 | }
109 | else
110 | {
111 | mainBrep = breps[0];
112 | }
113 | }
114 | mainBrepsMT[pth] = new GH_Brep(mainBrep);
115 | badBrepsMT[pth] = badBrep;
116 | });
117 | ///End of the parallel engine
118 | ///
119 |
120 | //convert dictionaries to regular old data trees
121 | GH_Structure mainBreps = new GH_Structure();
122 | GH_Structure badBreps = new GH_Structure();
123 |
124 | foreach (KeyValuePair p in mainBrepsMT)
125 | {
126 | mainBreps.Append(p.Value, p.Key);
127 | }
128 |
129 | foreach (KeyValuePair> b in badBrepsMT)
130 | {
131 | badBreps.AppendRange(b.Value, b.Key);
132 | }
133 |
134 | DA.SetDataTree(0, mainBreps);
135 | DA.SetDataTree(1, badBreps);
136 |
137 | }
138 |
139 | ///
140 | /// Provides an Icon for the component.
141 | ///
142 | protected override System.Drawing.Bitmap Icon
143 | {
144 | get
145 | {
146 | //You can add image files to your project resources and access them like this:
147 | // return Resources.IconForThisComponent;
148 | return Properties.Resources.shp;
149 | }
150 | }
151 |
152 | ///
153 | /// Gets the unique ID for this component. Do not change this ID after release.
154 | ///
155 | public override Guid ComponentGuid
156 | {
157 | get { return new Guid("94a1165e-7fed-45a7-8c08-449bea06d503"); }
158 | }
159 | }
160 | }
--------------------------------------------------------------------------------
/Heron/Components/Deprecated/RESTLayer_DEPRECATED.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Xml;
4 | using System.Xml.Linq;
5 | using System.Linq;
6 | using System.Data;
7 | using System.Drawing;
8 | using System.Reflection;
9 | using System.Collections;
10 | using System.Collections.Generic;
11 | using System.Runtime.InteropServices;
12 | using System.Text;
13 | using System.Threading.Tasks;
14 | using System.Windows.Forms;
15 | using Grasshopper;
16 | using Grasshopper.Kernel;
17 | using Grasshopper.Kernel.Data;
18 | using Grasshopper.Kernel.Types;
19 | using Grasshopper.Kernel.Special;
20 | using Rhino.Geometry;
21 | using GH_IO;
22 | using GH_IO.Serialization;
23 |
24 | using Newtonsoft.Json.Bson;
25 | using Newtonsoft.Json;
26 | using Newtonsoft.Json.Converters;
27 | using Newtonsoft.Json.Linq;
28 | using Newtonsoft.Json.Schema;
29 | using Newtonsoft.Json.Serialization;
30 |
31 | namespace Heron
32 | {
33 | public class RESTLayer_DEPRECATED_OBSOLETE : HeronComponent
34 | {
35 | //Class Constructor
36 | public RESTLayer_DEPRECATED_OBSOLETE() : base("Get REST Service Layers DEPRECATED", "RESTLayer_D", "Discover ArcGIS REST Service Layers", "GIS REST")
37 | {
38 |
39 | }
40 |
41 | ///Retiring this component in to update the outputs to include urls
42 | public override Grasshopper.Kernel.GH_Exposure Exposure
43 | {
44 | get { return GH_Exposure.hidden; }
45 | }
46 |
47 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
48 | {
49 | pManager.AddTextParameter("Service URL", "serviceURL", "Service URL string", GH_ParamAccess.item);
50 |
51 | }
52 |
53 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
54 | {
55 | pManager.AddTextParameter("Map Description", "mapDescription", "Description of the REST Service", GH_ParamAccess.item);
56 | pManager.AddTextParameter("Map Layer", "mapLayers", "Names of available Service Layers", GH_ParamAccess.list);
57 | pManager.AddIntegerParameter("Map Integer", "mapIndex", "Index of available Service Layers", GH_ParamAccess.list);
58 |
59 | }
60 |
61 | protected override void SolveInstance(IGH_DataAccess DA)
62 | {
63 | string URL = string.Empty;
64 |
65 | DA.GetData("Service URL", ref URL);
66 |
67 | //get json from rest service
68 | string restquery = URL + "?f=pjson";
69 |
70 | System.Net.HttpWebRequest req = System.Net.WebRequest.Create(restquery) as System.Net.HttpWebRequest;
71 | string result = null;
72 |
73 | using (System.Net.HttpWebResponse resp = req.GetResponse() as System.Net.HttpWebResponse)
74 | {
75 | System.IO.StreamReader reader = new System.IO.StreamReader(resp.GetResponseStream());
76 | result = reader.ReadToEnd();
77 | reader.Close();
78 | }
79 |
80 | //parse json into a description and list of layer values
81 | JObject j = JObject.Parse(result);
82 | List layerKey = new List();
83 | List layerInt = new List();
84 |
85 | Dictionary d = new Dictionary();
86 |
87 | for (int i = 1; i < j["layers"].Children()["name"].Count(); i++)
88 | {
89 | d[(string)j["layers"][i]["name"]] = (int)j["layers"][i]["id"];
90 | layerKey.Add((string)j["layers"][i]["name"]);
91 | layerInt.Add((int)j["layers"][i]["id"]);
92 | }
93 |
94 | DA.SetData("Map Description", (string)j["description"]);
95 | //mapDescription = (string) j["description"];
96 | DA.SetDataList("Map Layer", layerKey);
97 | //mapLayer = layerKey;
98 | DA.SetDataList("Map Integer", layerInt);
99 | //mapInt = layerInt;
100 |
101 | }
102 |
103 |
104 |
105 |
106 |
107 | private JObject vectorJson = JObject.Parse(Heron.Convert.GetEnpoints());
108 |
109 | ///
110 | /// Adds to the context menu an option to create a pre-populated list of common REST Vector sources
111 | ///
112 | ///
113 | /// https://discourse.mcneel.com/t/generated-valuelist-not-working/79406/6?u=hypar
114 | public override void AppendAdditionalMenuItems(ToolStripDropDown menu)
115 | {
116 | var rasterSourcesJson = vectorJson["REST Vector"].Select(x => x["source"]).Distinct();
117 | List rasterSources = rasterSourcesJson.Values().ToList();
118 | foreach (var src in rasterSourcesJson)
119 | {
120 | ToolStripMenuItem root = GH_DocumentObject.Menu_AppendItem(menu, "Create " + src.ToString() + " Source List", CreateRasterList);
121 | root.ToolTipText = "Click this to create a pre-populated list of some " + src.ToString() + " sources.";
122 | base.AppendAdditionalMenuItems(menu);
123 | }
124 | }
125 |
126 | ///
127 | /// Creates a value list pre-populated with possible accent colors and adds it to the Grasshopper Document, located near the component pivot.
128 | ///
129 | /// The sender.
130 | /// The instance containing the event data.
131 | private void CreateRasterList(object sender, System.EventArgs e)
132 | {
133 | string source = sender.ToString();
134 | source = source.Replace("Create ", "");
135 | source = source.Replace(" Source List", "");
136 |
137 | GH_DocumentIO docIO = new GH_DocumentIO();
138 | docIO.Document = new GH_Document();
139 |
140 | ///Initialize object
141 | GH_ValueList vl = new GH_ValueList();
142 |
143 | ///Clear default contents
144 | vl.ListItems.Clear();
145 |
146 | foreach (var service in vectorJson["REST Vector"])
147 | {
148 | if (service["source"].ToString() == source)
149 | {
150 | GH_ValueListItem vi = new GH_ValueListItem(service["service"].ToString(), String.Format("\"{0}\"", service["url"].ToString()));
151 | vl.ListItems.Add(vi);
152 | }
153 | }
154 |
155 | ///Set component nickname
156 | vl.NickName = source;
157 |
158 | ///Get active GH doc
159 | GH_Document doc = OnPingDocument();
160 | if (docIO.Document == null) return;
161 |
162 | ///Place the object
163 | docIO.Document.AddObject(vl, false, 1);
164 |
165 | ///Get the pivot of the "URL" param
166 | PointF currPivot = Params.Input[0].Attributes.Pivot;
167 |
168 | ///Set the pivot of the new object
169 | vl.Attributes.Pivot = new PointF(currPivot.X - 400, currPivot.Y - 11);
170 |
171 | docIO.Document.SelectAll();
172 | docIO.Document.ExpireSolution();
173 | docIO.Document.MutateAllIds();
174 | IEnumerable objs = docIO.Document.Objects;
175 | doc.DeselectAll();
176 | doc.UndoUtil.RecordAddObjectEvent("Create REST Vector Source List", objs);
177 | doc.MergeDocument(docIO.Document);
178 | }
179 |
180 | protected override System.Drawing.Bitmap Icon
181 | {
182 | get
183 | {
184 | return Properties.Resources.layer;
185 | }
186 | }
187 |
188 | public override Guid ComponentGuid
189 | {
190 | get { return new Guid("{AD3A9FBB-AD30-4C95-BDD4-44D804895120}"); }
191 | }
192 | }
193 | }
194 |
--------------------------------------------------------------------------------
/Heron/Components/Deprecated/SetEAP_DEPRECATED20220416.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Xml;
4 | using System.Xml.Linq;
5 | using System.Linq;
6 | using System.Data;
7 | using System.Drawing;
8 | using System.Reflection;
9 | using System.Collections;
10 | using System.Collections.Generic;
11 | using System.Runtime.InteropServices;
12 | using System.Text;
13 | using System.Threading.Tasks;
14 | using Grasshopper;
15 | using Grasshopper.Kernel;
16 | using Grasshopper.Kernel.Data;
17 | using Grasshopper.Kernel.Types;
18 | using Rhino;
19 | using Rhino.Geometry;
20 | using Rhino.DocObjects;
21 | using Rhino.Collections;
22 | using GH_IO;
23 | using GH_IO.Serialization;
24 |
25 | using Newtonsoft.Json.Bson;
26 | using Newtonsoft.Json;
27 | using Newtonsoft.Json.Converters;
28 | using Newtonsoft.Json.Linq;
29 | using Newtonsoft.Json.Schema;
30 | using Newtonsoft.Json.Serialization;
31 |
32 | namespace Heron
33 | {
34 | public class SetEAP_DEPRECATED20220416_OBSOLETE : HeronComponent
35 | {
36 | //Class Constructor
37 | public SetEAP_DEPRECATED20220416_OBSOLETE() : base("Set EarthAnchorPoint", "SetEAP", "Set the Rhino EarthAnchorPoint", "GIS Tools")
38 | {
39 |
40 | }
41 |
42 | ///Retiring this component to add point of interest and DMS formatted lat/lon as input
43 | public override Grasshopper.Kernel.GH_Exposure Exposure
44 | {
45 | get { return GH_Exposure.hidden; }
46 | }
47 |
48 |
49 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
50 | {
51 | pManager.AddBooleanParameter("Set EAP", "set", "Set the EarthAnchorPoint", GH_ParamAccess.item, false);
52 | pManager.AddNumberParameter("Latitude", "LAT", "Decimal Degree Latitude", GH_ParamAccess.item);
53 | pManager.AddNumberParameter("Longitude", "LON", "Decimal Degree Longitude", GH_ParamAccess.item);
54 | pManager[1].Optional = true;
55 | pManager[2].Optional = true;
56 | }
57 |
58 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
59 | {
60 | pManager.AddTextParameter("Earth Anchor Point", "EAP", "EarthAnchorPoint Longitude/Latitude", GH_ParamAccess.item);
61 | }
62 |
63 | protected override void SolveInstance(IGH_DataAccess DA)
64 | {
65 | double lat = -1;
66 | double lon = -1;
67 | bool EAP = false;
68 | string lonlatString = string.Empty;
69 |
70 | //check if EAP has been set and if so what is it
71 | if (!Rhino.RhinoDoc.ActiveDoc.EarthAnchorPoint.EarthLocationIsSet())
72 | {
73 | lonlatString = "The Earth Anchor Point has not been set yet";
74 | AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "EAP has not been set yet");
75 | }
76 |
77 | else lonlatString = "Longitude: " + Rhino.RhinoDoc.ActiveDoc.EarthAnchorPoint.EarthBasepointLongitude.ToString() +
78 | " / Latitude: " + Rhino.RhinoDoc.ActiveDoc.EarthAnchorPoint.EarthBasepointLatitude.ToString();
79 |
80 | DA.GetData("Set EAP", ref EAP);
81 | DA.GetData("Latitude", ref lat);
82 | DA.GetData("Longitude", ref lon);
83 |
84 | if (EAP == true)
85 | {
86 | EarthAnchorPoint ePt = new EarthAnchorPoint();
87 | ePt.EarthBasepointLatitude = lat;
88 | ePt.EarthBasepointLongitude = lon;
89 |
90 | //set new EAP
91 | Rhino.RhinoDoc.ActiveDoc.EarthAnchorPoint = ePt;
92 |
93 | //new EAP to string for output
94 | lonlatString = "Longitude: " + Rhino.RhinoDoc.ActiveDoc.EarthAnchorPoint.EarthBasepointLongitude.ToString() +
95 | " / Latitude: " + Rhino.RhinoDoc.ActiveDoc.EarthAnchorPoint.EarthBasepointLatitude.ToString();
96 | }
97 |
98 |
99 | DA.SetData("Earth Anchor Point", lonlatString);
100 | }
101 |
102 | protected override System.Drawing.Bitmap Icon
103 | {
104 | get
105 | {
106 | return Properties.Resources.eap;
107 | }
108 | }
109 |
110 | public override Guid ComponentGuid
111 | {
112 | get { return new Guid("{6577DC68-200C-4B3C-ADB4-78DE61D76870}"); }
113 | }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/Heron/Components/GIS API/SlippyTiles.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 |
5 | using Grasshopper.Kernel;
6 | using Grasshopper.Kernel.Data;
7 | using Grasshopper.Kernel.Types;
8 | using Rhino.Geometry;
9 |
10 | namespace Heron
11 | {
12 | public class SlippyTiles : HeronComponent
13 | {
14 | ///
15 | /// Initializes a new instance of the SlippyTiles class.
16 | ///
17 | public SlippyTiles()
18 | : base("Slippy Tiles", "SlippyTiles",
19 | "Visualize boundaries of slippy map tiles within a given boundary at a given zoom level. See https://en.wikipedia.org/wiki/Tiled_web_map for more information about map tiles.",
20 | "GIS API")
21 | {
22 | }
23 |
24 | ///
25 | /// Registers all the input parameters for this component.
26 | ///
27 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
28 | {
29 | pManager.AddCurveParameter("Boundary", "boundary", "Boundary curve for map tiles", GH_ParamAccess.item);
30 | pManager.AddIntegerParameter("Zoom Level", "zoom", "Slippy map zoom level. Higher zoom level is higher resolution.", GH_ParamAccess.item);
31 | }
32 |
33 | ///
34 | /// Registers all the output parameters for this component.
35 | ///
36 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
37 | {
38 | pManager.AddCurveParameter("Tile Extents", "tiles", "Map tile boundaries for each tile", GH_ParamAccess.list);
39 | pManager.AddTextParameter("Tile ID", "id", "Map tile ID. The tile ID is formatted 'Z-X-Y' where Z is zoom level, X is the column and Y the row.", GH_ParamAccess.list);
40 | }
41 |
42 | ///
43 | /// This is the method that actually does the work.
44 | ///
45 | /// The DA object is used to retrieve from inputs and store in outputs.
46 | protected override void SolveInstance(IGH_DataAccess DA)
47 | {
48 | Curve boundary = null;
49 | DA.GetData(0, ref boundary);
50 |
51 | int zoom = -1;
52 | DA.GetData(1, ref zoom);
53 |
54 | ///Get image frame for given boundary
55 | if (!boundary.GetBoundingBox(true).IsValid)
56 | {
57 | AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Boundary is not valid.");
58 | return;
59 | }
60 | BoundingBox boundaryBox = boundary.GetBoundingBox(true);
61 |
62 | ///Tile bounding box array
63 | List boxPtList = new List();
64 |
65 | ///Get the tile coordinates for all tiles within boundary
66 | var ranges = Convert.GetTileRange(boundaryBox, zoom);
67 | var x_range = ranges.XRange;
68 | var y_range = ranges.YRange;
69 |
70 | if (x_range.Length > 100 || y_range.Length > 100)
71 | {
72 | AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "This tile range is too big (more than 100 tiles in the x or y direction). Check your units.");
73 | return;
74 | }
75 |
76 | ///Cycle through tiles to get bounding box
77 | List tileExtents = new List();
78 | List tileID = new List();
79 |
80 | for (int y = (int)y_range.Min; y <= y_range.Max; y++)
81 | {
82 | for (int x = (int)x_range.Min; x <= x_range.Max; x++)
83 | {
84 | string tileString = zoom + "-" + x + "-" + y;
85 | tileID.Add(tileString);
86 | Polyline tileExtent = Heron.Convert.GetTileAsPolygon(zoom, y, x);
87 | tileExtents.Add(tileExtent);
88 | double tileHeight = tileExtent[1].DistanceTo(tileExtent[2]);
89 |
90 | if (!string.IsNullOrWhiteSpace(tileString))
91 | {
92 | _text.Add(tileString);
93 | _point.Add(tileExtent.CenterPoint());
94 | _size.Add(tileHeight / 20);
95 | _tile.Add(tileExtent);
96 | }
97 | }
98 | }
99 |
100 | DA.SetDataList(0, tileExtents);
101 | DA.SetDataList(1, tileID);
102 | }
103 |
104 | ///Preview text and tile polylines
105 | ///https://www.grasshopper3d.com/forum/topics/drawing-a-text-tag-from-a-c-component?commentId=2985220%3AComment%3A1024697
106 |
107 | private readonly List _text = new List();
108 | private readonly List _point = new List();
109 | private readonly List _size = new List();
110 | private readonly List _tile = new List();
111 |
112 | protected override void BeforeSolveInstance()
113 | {
114 | _text.Clear();
115 | _point.Clear();
116 | _size.Clear();
117 | _tile.Clear();
118 | }
119 |
120 | public override void DrawViewportWires(IGH_PreviewArgs args)
121 | {
122 | if (_text.Count == 0)
123 | return;
124 |
125 | //Plane plane;
126 | //args.Viewport.GetFrustumFarPlane(out plane);
127 |
128 | for (int i = 0; i < _text.Count; i++)
129 | {
130 | string text = _text[i];
131 | Point3d point = _point[i];
132 | double size = _size[i];
133 | Polyline tile = _tile[i];
134 |
135 | Plane plane;
136 | args.Viewport.GetFrustumFarPlane(out plane);
137 | plane.Origin = point;
138 |
139 | Rhino.Display.Text3d drawText = new Rhino.Display.Text3d(text, plane, size);
140 | args.Display.Draw3dText(text, Color.Black, plane, size, null, false, false, Rhino.DocObjects.TextHorizontalAlignment.Center, Rhino.DocObjects.TextVerticalAlignment.Middle);
141 | args.Display.DrawPolyline(tile, Color.Black, 2);
142 | drawText.Dispose();
143 | }
144 | }
145 |
146 |
147 | ///
148 | /// Provides an Icon for the component.
149 | ///
150 | protected override System.Drawing.Bitmap Icon
151 | {
152 | get
153 | {
154 | //You can add image files to your project resources and access them like this:
155 | // return Resources.IconForThisComponent;
156 | return Properties.Resources.vector;
157 | }
158 | }
159 |
160 | ///
161 | /// Gets the unique ID for this component. Do not change this ID after release.
162 | ///
163 | public override Guid ComponentGuid
164 | {
165 | get { return new Guid("ae47ba29-49ae-4bbe-b76c-7335e725e91e"); }
166 | }
167 | }
168 | }
--------------------------------------------------------------------------------
/Heron/Components/GIS API/SlippyViewport.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | using Grasshopper.Kernel;
6 | using Rhino.Geometry;
7 |
8 | namespace Heron
9 | {
10 | public class SlippyViewport : HeronComponent
11 | {
12 | ///
13 | /// Initializes a new instance of the SlippyViewport class.
14 | ///
15 | public SlippyViewport()
16 | : base("Slippy Viewport", "SlippyVP", "Projects the boundary of a given Viewport to the World XY plane and calculates a good Zoom level for use with tile-based map components.", "GIS API")
17 | {
18 | }
19 |
20 | ///
21 | /// Registers all the input parameters for this component.
22 | ///
23 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
24 | {
25 | pManager.AddTextParameter("Named Viewport", "view", "Provide the name of the viewport to be used.", GH_ParamAccess.item, "Top");
26 | }
27 |
28 | ///
29 | /// Registers all the output parameters for this component.
30 | ///
31 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
32 | {
33 | pManager.AddCurveParameter("Viewport Boundary", "boundary", "The boundary of the given viewport projected onto the World XY plane", GH_ParamAccess.item);
34 | pManager.AddNumberParameter("Zoom Level", "zoom", "A good zoom level to be used with a Raster API componenet given the extents of viewport boundary. Max zoom level is set to 21", GH_ParamAccess.item);
35 | }
36 |
37 | ///
38 | /// This is the method that actually does the work.
39 | ///
40 | /// The DA object is used to retrieve from inputs and store in outputs.
41 | protected override void SolveInstance(IGH_DataAccess DA)
42 | {
43 | List pProjected = new List();
44 |
45 | string view = string.Empty;
46 | DA.GetData(0, ref view);
47 | viewportName = view;
48 | ///Get viewport boundary
49 | Rhino.Display.RhinoView[] rvList = Rhino.RhinoDoc.ActiveDoc.Views.GetViewList(true, false);
50 | Rhino.Display.RhinoView rv = Rhino.RhinoDoc.ActiveDoc.Views.Find(view, true);
51 |
52 | if (!rvList.Contains(rv))
53 | {
54 | rv = Rhino.RhinoDoc.ActiveDoc.Views.ActiveView;
55 | AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Viewport name is not valid. Using active viewport " + rv.ActiveViewport.Name);
56 | }
57 |
58 |
59 | Rhino.Display.RhinoViewport vp = rv.MainViewport;
60 | Point3d[] pNear = rv.MainViewport.GetNearRect();
61 | Point3d[] pFar = rv.MainViewport.GetFarRect();
62 |
63 | ///Project viewport boundary to a plane
64 | for (int i = 0; i < pNear.Length; i++)
65 | {
66 | Vector3d tVec = pFar[i] - pNear[i];
67 | Transform trans = Transform.ProjectAlong(Plane.WorldXY, tVec);
68 | pNear[i].Transform(trans);
69 | pProjected.Add(pNear[i]);
70 | }
71 |
72 | ///Create polyline from project viewport boundary
73 | Polyline pL = new Polyline();
74 | pL.Add(pProjected[2]);
75 | pL.Add(pProjected[3]);
76 | pL.Add(pProjected[1]);
77 | pL.Add(pProjected[0]);
78 | pL.Add(pProjected[2]);
79 |
80 |
81 | ///Calculate recommended zoom level from viewport size
82 | BoundingBox bb = pL.BoundingBox;
83 | Vector3d dia = bb.Diagonal;
84 | Double maxDim = Math.Max(dia.X, dia.Y) * Rhino.RhinoMath.UnitScale(Rhino.RhinoDoc.ActiveDoc.ModelUnitSystem, Rhino.UnitSystem.Meters);
85 | Double maxPix = Math.Max(vp.Size.Height, vp.Size.Width);
86 |
87 |
88 | ///https://gis.stackexchange.com/questions/19632/how-to-calculate-the-optimal-zoom-level-to-display-two-or-more-points-on-a-map
89 | ///diameter of earth at equator is approx 40,000km
90 | ///resolution = (512px*distance)/40,075,000 meters * 2^zoom
91 | ///2^zoom = (resolution * 40,000,000) / (512px * distance)
92 | Double a = (maxPix * 40075000) / (512 * maxDim * 1.2);
93 |
94 | ///Solve for zoom
95 | ///https://stackoverflow.com/questions/4016213/whats-the-opposite-of-javascripts-math-pow
96 | Double z = Math.Log(a) / Math.Log(2);
97 |
98 |
99 | ///make sure zoom doesn't get too ridiculous levels
100 | DA.SetData(0, pL);
101 | DA.SetData(1, Math.Min(z, 21));
102 | }
103 |
104 | public override bool IsPreviewCapable => true;
105 |
106 | private int updateFrequencyMS = 300;
107 | private Point3d lastCameraLocation = default(Point3d);
108 | private string viewportName = null;
109 |
110 | public override void DrawViewportWires(IGH_PreviewArgs args)
111 | {
112 | if (args.Display.Viewport.Name == viewportName)
113 | {
114 | var delta = args.Display.Viewport.CameraLocation.DistanceToSquared(lastCameraLocation);
115 | if (delta > 1) // if it's moved
116 | {
117 | lastCameraLocation = args.Display.Viewport.CameraLocation;
118 | OnPingDocument().ScheduleSolution(updateFrequencyMS, (doc) =>
119 | {
120 | ExpireSolution(false);
121 | });
122 | }
123 | }
124 | base.DrawViewportWires(args);
125 | }
126 |
127 | ///
128 | /// Provides an Icon for the component.
129 | ///
130 | protected override System.Drawing.Bitmap Icon
131 | {
132 | get
133 | {
134 | //You can add image files to your project resources and access them like this:
135 | // return Resources.IconForThisComponent;
136 | return Properties.Resources.vector;
137 | }
138 | }
139 |
140 | ///
141 | /// Gets the unique ID for this component. Do not change this ID after release.
142 | ///
143 | public override Guid ComponentGuid
144 | {
145 | get { return new Guid("76082489-C7F2-403A-9490-BC52374C4F2B"); }
146 | }
147 | }
148 | }
--------------------------------------------------------------------------------
/Heron/Components/GIS REST/RESTGeocode.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Xml;
4 | using System.Xml.Linq;
5 | using System.Linq;
6 | using System.Data;
7 | using System.Drawing;
8 | using System.Reflection;
9 | using System.Collections;
10 | using System.Collections.Generic;
11 | using System.Runtime.InteropServices;
12 | using System.Text;
13 | using System.Threading.Tasks;
14 | using Grasshopper;
15 | using Grasshopper.Kernel;
16 | using Grasshopper.Kernel.Data;
17 | using Grasshopper.Kernel.Types;
18 | using Rhino.Geometry;
19 | using GH_IO;
20 | using GH_IO.Serialization;
21 |
22 | using Newtonsoft.Json.Bson;
23 | using Newtonsoft.Json;
24 | using Newtonsoft.Json.Converters;
25 | using Newtonsoft.Json.Linq;
26 | using Newtonsoft.Json.Schema;
27 | using Newtonsoft.Json.Serialization;
28 |
29 | namespace Heron
30 | {
31 | public class RESTGeocode : HeronComponent
32 | {
33 | //Class Constructor
34 | public RESTGeocode() : base("ESRI REST Service Geocode", "RESTGeocode", "Get coordinates based on a Point-of-Interest or Address using the ESRI geocode service.", "GIS REST")
35 | {
36 |
37 | }
38 |
39 |
40 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
41 | {
42 | pManager.AddTextParameter("Addresses", "addresses", "POI or Address string(s) to geocode", GH_ParamAccess.tree);
43 |
44 | }
45 |
46 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
47 | {
48 | pManager.AddTextParameter("Candidates", "Candidates", "List of Candidate locations", GH_ParamAccess.tree);
49 | pManager.AddTextParameter("Latitude", "LAT", "Latitude of Candidate location", GH_ParamAccess.tree);
50 | pManager.AddTextParameter("Longitude", "LON", "Longitude of Candidate location", GH_ParamAccess.tree);
51 |
52 | }
53 |
54 | protected override void SolveInstance(IGH_DataAccess DA)
55 | {
56 | GH_Structure Addresses = new GH_Structure();
57 |
58 | DA.GetDataTree("Addresses", out Addresses);
59 |
60 | GH_Structure addr = new GH_Structure();
61 | GH_Structure latx = new GH_Structure();
62 | GH_Structure lony = new GH_Structure();
63 |
64 | for (int a = 0; a < Addresses.Branches.Count; a++)
65 | {
66 | IList branch = Addresses.Branches[a];
67 | GH_Path path = Addresses.Paths[a];
68 | int count = 0;
69 | foreach (GH_String addressString in branch)
70 | {
71 | string address = System.Net.WebUtility.UrlEncode(addressString.Value);
72 | string output = GetData("https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/findAddressCandidates?Address=" + address + "&f=pjson");
73 | JObject ja = JObject.Parse(output);
74 |
75 | if (ja["candidates"].Count() < 1)
76 | {
77 | addr.Append(new GH_String("No Cadidate location found for this address"), path);
78 | lony.Append(new GH_String(""), path);
79 | latx.Append(new GH_String(""), path);
80 | }
81 | else
82 | {
83 | for (int i = 0; i < ja["candidates"].Count(); i++)
84 | {
85 | if (ja["candidates"][i]["score"].Value() > 99)
86 | {
87 | addr.Append(new GH_String(ja["candidates"][i]["address"].ToString()), new GH_Path(path[count], i));
88 | addr.Append(new GH_String("LON: " + ja["candidates"][i]["location"]["x"].ToString()), new GH_Path(path[count], i));
89 | addr.Append(new GH_String("LAT: " + ja["candidates"][i]["location"]["y"].ToString()), new GH_Path(path[count], i));
90 | lony.Append(new GH_String(ja["candidates"][i]["location"]["y"].ToString()), new GH_Path(path[count], i));
91 | latx.Append(new GH_String(ja["candidates"][i]["location"]["x"].ToString()), new GH_Path(path[count], i));
92 | }
93 | }
94 | }
95 | }
96 | }
97 |
98 | if (addr == null)
99 | {
100 | AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "No Candidate locations found");
101 | return;
102 | }
103 | else
104 | {
105 | DA.SetDataTree(0, addr);
106 | DA.SetDataTree(1, lony);
107 | DA.SetDataTree(2, latx);
108 | }
109 |
110 |
111 | }
112 |
113 | public static string GetData(string qst)
114 | {
115 | System.Net.HttpWebRequest req = System.Net.WebRequest.Create(qst) as System.Net.HttpWebRequest;
116 | string result = null;
117 | try
118 | {
119 | using (System.Net.HttpWebResponse resp = req.GetResponse() as System.Net.HttpWebResponse)
120 | {
121 | System.IO.StreamReader reader = new System.IO.StreamReader(resp.GetResponseStream());
122 | result = reader.ReadToEnd();
123 | reader.Close();
124 | }
125 | }
126 | catch
127 | {
128 | return "Something went wrong getting data from the Service";
129 | }
130 | return result;
131 | }
132 |
133 |
134 | protected override System.Drawing.Bitmap Icon
135 | {
136 | get
137 | {
138 | return Properties.Resources.geocode;
139 | }
140 | }
141 |
142 | public override Guid ComponentGuid
143 | {
144 | get { return new Guid("{019FCF0D-08A1-4CB0-A0D7-EDD6F840378E}"); }
145 | }
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/Heron/Components/GIS REST/RESTLayer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Xml;
4 | using System.Xml.Linq;
5 | using System.Linq;
6 | using System.Data;
7 | using System.Drawing;
8 | using System.Reflection;
9 | using System.Collections;
10 | using System.Collections.Generic;
11 | using System.Runtime.InteropServices;
12 | using System.Text;
13 | using System.Threading.Tasks;
14 | using System.Windows.Forms;
15 | using Grasshopper;
16 | using Grasshopper.Kernel;
17 | using Grasshopper.Kernel.Data;
18 | using Grasshopper.Kernel.Types;
19 | using Grasshopper.Kernel.Special;
20 | using Rhino.Geometry;
21 | using GH_IO;
22 | using GH_IO.Serialization;
23 |
24 | using Newtonsoft.Json.Bson;
25 | using Newtonsoft.Json;
26 | using Newtonsoft.Json.Converters;
27 | using Newtonsoft.Json.Linq;
28 | using Newtonsoft.Json.Schema;
29 | using Newtonsoft.Json.Serialization;
30 |
31 | namespace Heron
32 | {
33 | public class RESTLayer : HeronComponent
34 | {
35 | //Class Constructor
36 | public RESTLayer() : base("Get REST Service Layers", "RESTLayer", "Discover ArcGIS REST Service Layers", "GIS REST")
37 | {
38 |
39 | }
40 |
41 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
42 | {
43 | pManager.AddTextParameter("Service URL", "serviceURL", "Service URL string", GH_ParamAccess.item);
44 |
45 | }
46 |
47 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
48 | {
49 | pManager.AddTextParameter("Map Description", "mapDescription", "Description of the REST Service", GH_ParamAccess.item);
50 | pManager.AddTextParameter("Map Layers", "mapLayers", "Names of available Service Layers", GH_ParamAccess.list);
51 | pManager.AddIntegerParameter("Map Integers", "mapIndexes", "Indexes of available Service Layers", GH_ParamAccess.list);
52 | pManager.AddTextParameter("Map Layer URLs", "URLs", "URLs of available Service Layers", GH_ParamAccess.list);
53 |
54 | }
55 |
56 | protected override void SolveInstance(IGH_DataAccess DA)
57 | {
58 | string URL = string.Empty;
59 |
60 | DA.GetData("Service URL", ref URL);
61 | if (!URL.EndsWith(@"/")) { URL = URL + "/"; }
62 |
63 | //get json from rest service
64 | string restquery = URL + "?f=pjson";
65 |
66 | System.Net.HttpWebRequest req = System.Net.WebRequest.Create(restquery) as System.Net.HttpWebRequest;
67 | string result = null;
68 |
69 | using (System.Net.HttpWebResponse resp = req.GetResponse() as System.Net.HttpWebResponse)
70 | {
71 | System.IO.StreamReader reader = new System.IO.StreamReader(resp.GetResponseStream());
72 | result = reader.ReadToEnd();
73 | reader.Close();
74 | }
75 |
76 | //parse json into a description and list of layer values
77 | JObject j = JObject.Parse(result);
78 | List layerKey = new List();
79 | List layerInt = new List();
80 | List layerUrl = new List();
81 |
82 | Dictionary d = new Dictionary();
83 |
84 | for (int i = 1; i < j["layers"].Children()["name"].Count(); i++)
85 | {
86 | d[(string)j["layers"][i]["name"]] = (int)j["layers"][i]["id"];
87 | layerKey.Add((string)j["layers"][i]["name"]);
88 | layerInt.Add((int)j["layers"][i]["id"]);
89 | layerUrl.Add(URL + j["layers"][i]["id"].ToString() + "/");
90 | }
91 |
92 | DA.SetData(0, (string)j["description"]);
93 | //mapDescription = (string) j["description"];
94 | DA.SetDataList(1, layerKey);
95 | //mapLayer = layerKey;
96 | DA.SetDataList(2, layerInt);
97 | //mapInt = layerInt;
98 | DA.SetDataList(3, layerUrl);
99 |
100 | }
101 |
102 |
103 |
104 |
105 |
106 | private JObject vectorJson = JObject.Parse(Heron.Convert.GetEnpoints());
107 |
108 | ///
109 | /// Adds to the context menu an option to create a pre-populated list of common REST Vector sources
110 | ///
111 | ///
112 | /// https://discourse.mcneel.com/t/generated-valuelist-not-working/79406/6?u=hypar
113 | public override void AppendAdditionalMenuItems(ToolStripDropDown menu)
114 | {
115 | var rasterSourcesJson = vectorJson["REST Vector"].Select(x => x["source"]).Distinct();
116 | List rasterSources = rasterSourcesJson.Values().ToList();
117 | foreach (var src in rasterSourcesJson)
118 | {
119 | ToolStripMenuItem root = GH_DocumentObject.Menu_AppendItem(menu, "Create " + src.ToString() + " Source List", CreateRasterList);
120 | root.ToolTipText = "Click this to create a pre-populated list of some " + src.ToString() + " sources.";
121 | base.AppendAdditionalMenuItems(menu);
122 | }
123 | }
124 |
125 | ///
126 | /// Creates a value list pre-populated with possible accent colors and adds it to the Grasshopper Document, located near the component pivot.
127 | ///
128 | /// The sender.
129 | /// The instance containing the event data.
130 | private void CreateRasterList(object sender, System.EventArgs e)
131 | {
132 | string source = sender.ToString();
133 | source = source.Replace("Create ", "");
134 | source = source.Replace(" Source List", "");
135 |
136 | GH_DocumentIO docIO = new GH_DocumentIO();
137 | docIO.Document = new GH_Document();
138 |
139 | ///Initialize object
140 | GH_ValueList vl = new GH_ValueList();
141 |
142 | ///Clear default contents
143 | vl.ListItems.Clear();
144 |
145 | foreach (var service in vectorJson["REST Vector"])
146 | {
147 | if (service["source"].ToString() == source)
148 | {
149 | GH_ValueListItem vi = new GH_ValueListItem(service["service"].ToString(), String.Format("\"{0}\"", service["url"].ToString()));
150 | vl.ListItems.Add(vi);
151 | }
152 | }
153 |
154 | ///Set component nickname
155 | vl.NickName = source;
156 |
157 | ///Get active GH doc
158 | GH_Document doc = OnPingDocument();
159 | if (docIO.Document == null) return;
160 |
161 | ///Place the object
162 | docIO.Document.AddObject(vl, false, 1);
163 |
164 | ///Get the pivot of the "URL" param
165 | PointF currPivot = Params.Input[0].Attributes.Pivot;
166 |
167 | ///Set the pivot of the new object
168 | vl.Attributes.Pivot = new PointF(currPivot.X - 400, currPivot.Y - 11);
169 |
170 | docIO.Document.SelectAll();
171 | docIO.Document.ExpireSolution();
172 | docIO.Document.MutateAllIds();
173 | IEnumerable objs = docIO.Document.Objects;
174 | doc.DeselectAll();
175 | doc.UndoUtil.RecordAddObjectEvent("Create REST Vector Source List", objs);
176 | doc.MergeDocument(docIO.Document);
177 | }
178 |
179 | protected override System.Drawing.Bitmap Icon
180 | {
181 | get
182 | {
183 | return Properties.Resources.layer;
184 | }
185 | }
186 |
187 | public override Guid ComponentGuid
188 | {
189 | get { return new Guid("{8F33D7B4-FF14-438A-B49B-7DF895890BDD}"); }
190 | }
191 | }
192 | }
193 |
--------------------------------------------------------------------------------
/Heron/Components/GIS Tools/CoordinateTransformation.cs:
--------------------------------------------------------------------------------
1 | using Grasshopper.Kernel;
2 | using Grasshopper.Kernel.Types;
3 | using Grasshopper.Kernel.Data;
4 | using Rhino.Geometry;
5 | using System;
6 | using System.Collections.Generic;
7 |
8 | using OSGeo.OGR;
9 |
10 | namespace Heron
11 | {
12 | public class CoordinateTransformation : HeronComponent
13 | {
14 | ///
15 | /// Initializes a new instance of the TranslateTo class.
16 | ///
17 | public CoordinateTransformation()
18 | : base("Coordinate Transformation", "CT",
19 | "Transform points from a source SRS to a destination SRS. The source points should be in the coordinate system of the source SRS.",
20 | "GIS Tools")
21 | {
22 | }
23 |
24 | ///
25 | /// Registers all the input parameters for this component.
26 | ///
27 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
28 | {
29 | pManager.AddPointParameter("Source Points", "sourcePoints", "Points to transform.", GH_ParamAccess.tree);
30 | pManager.AddTextParameter("Source SRS", "sourceSRS", "Source spatial reference system from which to translate the points. " +
31 | "This can be a simple EPSG code (ie 'EPSG:4326') or a full projection string (ie text from a prj file).", GH_ParamAccess.item, "WGS84");
32 | pManager.AddTextParameter("Destination SRS", "destSRS", "Destination spatial reference system to which to translate the points. " +
33 | "This can be a simple EPSG code (ie 'EPSG:4326') or a full projection string (ie text from a prj file).", GH_ParamAccess.item, "WGS84");
34 | }
35 |
36 | ///
37 | /// Registers all the output parameters for this component.
38 | ///
39 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
40 | {
41 | pManager.AddPointParameter("Translated Points", "destPoints", "Translated points", GH_ParamAccess.tree);
42 | }
43 |
44 | ///
45 | /// This is the method that actually does the work.
46 | ///
47 | /// The DA object is used to retrieve from inputs and store in outputs.
48 | protected override void SolveInstance(IGH_DataAccess DA)
49 | {
50 | ///GDAL setup
51 | Heron.GdalConfiguration.ConfigureOgr();
52 |
53 | ///Working with data trees allows us to only call the osr coordinate transformation once, which seems to be expensive
54 | GH_Structure sourcePoints = new GH_Structure();
55 | DA.GetDataTree(0, out sourcePoints);
56 |
57 | GH_Structure destPoints = new GH_Structure();
58 |
59 | string sourceString = string.Empty;
60 | DA.GetData(1, ref sourceString);
61 | OSGeo.OSR.SpatialReference sourceSRS = new OSGeo.OSR.SpatialReference("");
62 | sourceSRS.SetFromUserInput(sourceString);
63 | if (sourceSRS.Validate()==1)
64 | {
65 | AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid Source SRS.");
66 | return;
67 | }
68 |
69 | string destString = string.Empty;
70 | DA.GetData(2, ref destString);
71 | OSGeo.OSR.SpatialReference destSRS = new OSGeo.OSR.SpatialReference("");
72 | destSRS.SetFromUserInput(destString);
73 | if (destSRS.Validate() == 1)
74 | {
75 | AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid Destination SRS.");
76 | return;
77 | }
78 |
79 | OSGeo.OSR.CoordinateTransformation trans = new OSGeo.OSR.CoordinateTransformation(sourceSRS, destSRS);
80 |
81 | foreach(var path in sourcePoints.Paths)
82 | {
83 | List branchPts = (List)sourcePoints.get_Branch(path);
84 | foreach (var sp in branchPts)
85 | {
86 | OSGeo.OGR.Geometry destOgrPoint = new OSGeo.OGR.Geometry(wkbGeometryType.wkbPoint);
87 | destOgrPoint.AddPoint(sp.Value.X, sp.Value.Y, sp.Value.Z);
88 | destOgrPoint.AssignSpatialReference(sourceSRS);
89 |
90 | destOgrPoint.Transform(trans);
91 | Point3d destPoint = new Point3d(destOgrPoint.GetX(0), destOgrPoint.GetY(0), destOgrPoint.GetZ(0));
92 |
93 | destPoints.Append(new GH_Point(destPoint),path);
94 | destOgrPoint.Dispose();
95 | }
96 | }
97 |
98 | DA.SetDataTree(0, destPoints);
99 |
100 |
101 | }
102 |
103 | ///
104 | /// Provides an Icon for the component.
105 | ///
106 | protected override System.Drawing.Bitmap Icon
107 | {
108 | get
109 | {
110 | //You can add image files to your project resources and access them like this:
111 | // return Resources.IconForThisComponent;
112 | return Properties.Resources.xytodd;
113 | }
114 | }
115 |
116 | ///
117 | /// Gets the unique ID for this component. Do not change this ID after release.
118 | ///
119 | public override Guid ComponentGuid
120 | {
121 | get { return new Guid("0c32eee6-1721-4a0b-bd68-a10b0a7b6ccb"); }
122 | }
123 | }
124 | }
--------------------------------------------------------------------------------
/Heron/Components/GIS Tools/DDtoXY.cs:
--------------------------------------------------------------------------------
1 | using Grasshopper.Kernel;
2 | using Rhino.Geometry;
3 | using System;
4 |
5 | namespace Heron
6 | {
7 | public class DDtoXY : HeronComponent
8 | {
9 | //Class Constructor
10 | public DDtoXY() : base("Decimal Degrees to XY", "DDtoXY", "Convert WGS84 Decimal Degrees Longitude/Latitude to X/Y", "GIS Tools")
11 | {
12 |
13 | }
14 |
15 |
16 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
17 | {
18 | pManager.AddNumberParameter("Latitude", "LAT", "Decimal Degree Latitude", GH_ParamAccess.item);
19 | pManager.AddNumberParameter("Longitude", "LON", "Decimal Degree Longitude", GH_ParamAccess.item);
20 | pManager[0].Optional = true;
21 | pManager[1].Optional = true;
22 | }
23 |
24 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
25 | {
26 | pManager.AddPointParameter("xyPoint", "xyPoint", "Longitude/Latitude translated to X/Y", GH_ParamAccess.item);
27 | pManager.AddTransformParameter("Transform", "xForm", "The transform from WGS to XYZ", GH_ParamAccess.item);
28 |
29 | }
30 |
31 | protected override void SolveInstance(IGH_DataAccess DA)
32 | {
33 | ///GDAL setup
34 | Heron.GdalConfiguration.ConfigureOgr();
35 |
36 | ///Set transform from input spatial reference to Heron spatial reference
37 | OSGeo.OSR.SpatialReference heronSRS = new OSGeo.OSR.SpatialReference("");
38 | heronSRS.SetFromUserInput(HeronSRS.Instance.SRS);
39 | OSGeo.OSR.SpatialReference wgsSRS = new OSGeo.OSR.SpatialReference("");
40 | wgsSRS.SetFromUserInput("WGS84");
41 | //AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Heron's Spatial Spatial Reference System (SRS): " + HeronSRS.Instance.SRS);
42 | int heronSRSInt = Int16.Parse(heronSRS.GetAuthorityCode(null));
43 | Message = "EPSG:" + heronSRSInt;
44 |
45 | ///Apply EAP to HeronSRS
46 | Transform userSRSToModelTransform = Heron.Convert.GetUserSRSToHeronSRSTransform(heronSRS);
47 | Transform wgsToHeronSRSTransform = Heron.Convert.GetUserSRSToHeronSRSTransform(wgsSRS);
48 |
49 | ///Set transforms between source and HeronSRS
50 | OSGeo.OSR.CoordinateTransformation coordTransform = new OSGeo.OSR.CoordinateTransformation(wgsSRS, heronSRS);
51 |
52 | ///Dump out the transform first
53 | DA.SetData("Transform", wgsToHeronSRSTransform);
54 |
55 |
56 | /// Then, we need to retrieve all data from the input parameters.
57 | /// We'll start by declaring variables and assigning them starting values.
58 | double lat = -1;
59 | double lon = -1;
60 |
61 | /// Then we need to access the input parameters individually.
62 | /// When data cannot be extracted from a parameter, we should abort this method.
63 | if (!DA.GetData("Latitude", ref lat)) return;
64 | if (!DA.GetData("Longitude", ref lon)) return;
65 |
66 | /// We should now validate the data and warn the user if invalid data is supplied.
67 | if (lat < -90.0 || lat > 90.0)
68 | {
69 | AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Latitude should be between -90.0 deg and 90.0 deg");
70 | return;
71 | }
72 | if (lon < -180.0 || lon > 180.0)
73 | {
74 | AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Longitude should be between -180.0 deg and 180.0 deg");
75 | return;
76 | }
77 |
78 | Point3d dd = Heron.Convert.OSRTransformPoint3dToPoint3d(new Point3d(lon, lat, 0), coordTransform);
79 | dd.Transform(userSRSToModelTransform);
80 | DA.SetData("xyPoint", dd);
81 |
82 | }
83 |
84 | protected override System.Drawing.Bitmap Icon
85 | {
86 | get
87 | {
88 | return Properties.Resources.ddtoxy;
89 | }
90 | }
91 |
92 | public override Guid ComponentGuid
93 | {
94 | get { return new Guid("{78543216-14B5-422C-85F8-BB575FBED3D2}"); }
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/Heron/Components/GIS Tools/DMStoDD.cs:
--------------------------------------------------------------------------------
1 | using Grasshopper.Kernel;
2 | using Rhino.Geometry;
3 | using System;
4 | using System.Collections.Generic;
5 |
6 | namespace Heron
7 | {
8 | public class DMStoDD : HeronComponent
9 | {
10 | ///
11 | /// Initializes a new instance of the DMStoDD class.
12 | ///
13 | public DMStoDD()
14 | : base("DMStoDD", "DMS to DD",
15 | "Convert Latitude and Longitude coordinates formatted in Degree Mintue Seconds (DMS) to Decimal Degree (DD) format." +
16 | "Valid Degree Minute Second formats are: 79°58′36″W | 079:56:55W | 079d 58′ 36″ W | 079 58 36.0 | 079 58 36.4 E",
17 | "GIS Tools")
18 | {
19 | }
20 |
21 | ///
22 | /// Registers all the input parameters for this component.
23 | ///
24 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
25 | {
26 | pManager.AddTextParameter("Latitude", "LAT", "Latitude in Degree Minute Second (DMS) format", GH_ParamAccess.item);
27 | pManager.AddTextParameter("Longitude", "LON", "Longitude in Degree Minute Second (DMS) format", GH_ParamAccess.item);
28 | }
29 |
30 | ///
31 | /// Registers all the output parameters for this component.
32 | ///
33 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
34 | {
35 | pManager.AddTextParameter("Latitude", "LAT", "Latitude in Decimal Degree (DD) format", GH_ParamAccess.item);
36 | pManager.AddTextParameter("Longitude", "LON", "Longitude in Decimal Degree (DD) format", GH_ParamAccess.item);
37 | }
38 |
39 | ///
40 | /// This is the method that actually does the work.
41 | ///
42 | /// The DA object is used to retrieve from inputs and store in outputs.
43 | protected override void SolveInstance(IGH_DataAccess DA)
44 | {
45 | string latString = string.Empty;
46 | string lonString = string.Empty;
47 | double lat = Double.NaN;
48 | double lon = Double.NaN;
49 |
50 | DA.GetData("Latitude", ref latString);
51 | DA.GetData("Longitude", ref lonString);
52 |
53 | lat = Heron.Convert.DMStoDDLat(latString);
54 | lon = Heron.Convert.DMStoDDLon(lonString);
55 |
56 | if (!Double.IsNaN(lat) && Double.IsNaN(lon))
57 | {
58 | DA.SetData("Latitude", lat);
59 | return;
60 | }
61 |
62 | else if (Double.IsNaN(lat) && !Double.IsNaN(lon))
63 | {
64 | DA.SetData("Longitude", lon);
65 | }
66 |
67 | else if (Double.IsNaN(lat) && Double.IsNaN(lon))
68 | {
69 | return;
70 | }
71 |
72 | else
73 | {
74 | DA.SetData("Latitude", lat);
75 | DA.SetData("Longitude", lon);
76 | }
77 | }
78 |
79 | ///
80 | /// Provides an Icon for the component.
81 | ///
82 | protected override System.Drawing.Bitmap Icon
83 | {
84 | get
85 | {
86 | return Properties.Resources.ddtoxy;
87 | }
88 | }
89 |
90 | ///
91 | /// Gets the unique ID for this component. Do not change this ID after release.
92 | ///
93 | public override Guid ComponentGuid
94 | {
95 | get { return new Guid("570bd625-a7c6-4ec5-a6bc-a4b6ad70e528"); }
96 | }
97 | }
98 | }
--------------------------------------------------------------------------------
/Heron/Components/GIS Tools/GdalConcaveHull.cs:
--------------------------------------------------------------------------------
1 | using Grasshopper.Kernel;
2 | using Grasshopper.Kernel.Data;
3 | using Grasshopper.Kernel.Types;
4 | using OSGeo.OGR;
5 | using Rhino.Geometry;
6 | using System;
7 | using System.Collections.Generic;
8 | using System.Linq;
9 |
10 | namespace Heron.Components.GIS_Tools
11 | {
12 | public class GdalConcaveHull : HeronComponent
13 | {
14 | ///
15 | /// Initializes a new instance of the MyComponent1 class.
16 | ///
17 | public GdalConcaveHull()
18 | : base("Gdal Concave Hull", "GCCH",
19 | "Create a concave hull around geometry using Gdal's concave hull function. GDAL concave hull only works in 2D, so the results will be on the XY plane.",
20 | "GIS Tools")
21 | {
22 | }
23 |
24 | public override Grasshopper.Kernel.GH_Exposure Exposure
25 | {
26 | get { return GH_Exposure.tertiary; }
27 | }
28 |
29 | ///
30 | /// Registers all the input parameters for this component.
31 | ///
32 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
33 | {
34 | pManager.AddGeometryParameter("Feature Geometry", "FG", "Geometry contained in the feature. Geometry can be point(s), polyline(s), mesh(es) or a combination of these.", GH_ParamAccess.tree);
35 | pManager.AddNumberParameter("Ratio", "R", "Ratio of the area of the convex hull and the concave hull. A value of 1 will result in the convex hull.", GH_ParamAccess.tree);
36 | }
37 |
38 | ///
39 | /// Registers all the output parameters for this component.
40 | ///
41 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
42 | {
43 | pManager.AddGeometryParameter("Hull Geometry", "H", "Hull geometry.", GH_ParamAccess.tree);
44 | }
45 |
46 | ///
47 | /// This is the method that actually does the work.
48 | ///
49 | /// The DA object is used to retrieve from inputs and store in outputs.
50 | protected override void SolveInstance(IGH_DataAccess DA)
51 | {
52 |
53 | GH_Structure gGoo = new GH_Structure();
54 | DA.GetDataTree("Feature Geometry", out gGoo);
55 |
56 | GH_Structure ratios = new GH_Structure();
57 | DA.GetDataTree("Ratio", out ratios);
58 |
59 | GH_Structure gGooHull = new GH_Structure();
60 |
61 | ///GDAL setup
62 | Heron.GdalConfiguration.ConfigureOgr();
63 |
64 | ///Use WGS84 spatial reference
65 | OSGeo.OSR.SpatialReference dst = new OSGeo.OSR.SpatialReference("");
66 | dst.SetWellKnownGeogCS("WGS84");
67 | Transform transform = new Transform(1);
68 | Transform revTransform = new Transform(1);
69 |
70 | ///Create virtual datasource to be converted later
71 | ///Using geojson as a flexiblle base file type which can be converted later with ogr2ogr
72 | OSGeo.OGR.Driver drv = Ogr.GetDriverByName("GeoJSON");
73 | DataSource ds = drv.CreateDataSource("/vsimem/out.geojson", null);
74 |
75 | ///Use OGR catch-all for geometry types
76 | var gtype = wkbGeometryType.wkbGeometryCollection;
77 |
78 | ///Create layer
79 | OSGeo.OGR.Layer layer = ds.CreateLayer("temp", dst, gtype, null);
80 | FeatureDefn def = layer.GetLayerDefn();
81 |
82 | var branchPaths = gGoo.Paths;
83 |
84 | for (int a = 0; a < gGoo.Branches.Count; a++)
85 | {
86 | ///create feature
87 | OSGeo.OGR.Feature feature = new OSGeo.OGR.Feature(def);
88 |
89 | ///Get geometry type(s) in branch
90 | var geomList = gGoo.Branches[a];
91 | List geomTypeList = geomList.Select(o => o.TypeName).ToList();
92 |
93 | var ratioList = ratios.Branches[a];
94 | GH_Convert.ToDouble(ratioList[0], out double ratio, GH_Conversion.Primary);
95 |
96 | ///Add geomtery to feature
97 | ///Create containers for translating from GH Goo
98 | Point3d pt = new Point3d();
99 | List pts = new List();
100 |
101 | Curve crv = null;
102 | List crvs = new List();
103 |
104 | Mesh mesh = new Mesh();
105 | Mesh multiMesh = new Mesh();
106 |
107 | OSGeo.OGR.Geometry geoCollection = new OSGeo.OGR.Geometry(wkbGeometryType.wkbGeometryCollection);
108 | for (int gInt = 0; gInt < geomList.Count; gInt++)
109 | {
110 | string geomTypeMixed = geomTypeList[gInt];
111 | switch (geomTypeMixed)
112 | {
113 | case "Point":
114 | geomList[gInt].CastTo(out pt);
115 | geoCollection.AddGeometry(Heron.Convert.Point3dToOgrPoint(pt, transform));
116 | break;
117 |
118 | case "Curve":
119 | geomList[gInt].CastTo(out crv);
120 | geoCollection.AddGeometry(Heron.Convert.CurveToOgrLinestring(crv, transform));
121 | break;
122 |
123 | case "Mesh":
124 | geomList[gInt].CastTo(out mesh);
125 | geoCollection.AddGeometry(Ogr.ForceToMultiPolygon(Heron.Convert.MeshToMultiPolygon(mesh, transform)));
126 | break;
127 |
128 | default:
129 | AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Not able to export " + geomTypeMixed + " geometry at branch " + gGoo.get_Path(a).ToString() +
130 | ". Geometry must be a Point, Curve or Mesh.");
131 | break;
132 | }
133 |
134 | }
135 |
136 | ///Need to wait until GEOS 3.11 is included with the GDAL nuget package
137 | var hullCol = geoCollection.ConcaveHull(ratio,true);
138 | gGooHull.AppendRange(Heron.Convert.OgrGeomToGHGoo(hullCol, revTransform), new GH_Path(a));
139 |
140 | }
141 |
142 | def.Dispose();
143 | layer.Dispose();
144 | ds.Dispose();
145 |
146 | DA.SetDataTree(0, gGooHull);
147 | }
148 |
149 | ///
150 | /// Provides an Icon for the component.
151 | ///
152 | protected override System.Drawing.Bitmap Icon
153 | {
154 | get
155 | {
156 | //You can add image files to your project resources and access them like this:
157 | // return Resources.IconForThisComponent;
158 | return Properties.Resources.shp;
159 | }
160 | }
161 |
162 | ///
163 | /// Gets the unique ID for this component. Do not change this ID after release.
164 | ///
165 | public override Guid ComponentGuid
166 | {
167 | get { return new Guid("C56FC98A-98DA-49F8-8621-8677E4520D90"); }
168 | }
169 | }
170 | }
--------------------------------------------------------------------------------
/Heron/Components/GIS Tools/GdalConvexHull.cs:
--------------------------------------------------------------------------------
1 | using Grasshopper.Kernel;
2 | using Grasshopper.Kernel.Data;
3 | using Grasshopper.Kernel.Types;
4 | using OSGeo.OGR;
5 | using Rhino.Geometry;
6 | using System;
7 | using System.Collections.Generic;
8 | using System.Linq;
9 |
10 | namespace Heron.Components.GIS_Tools
11 | {
12 | public class GdalConvexHull : HeronComponent
13 | {
14 | ///
15 | /// Initializes a new instance of the MyComponent1 class.
16 | ///
17 | public GdalConvexHull()
18 | : base("Gdal Convex Hull", "GCVH",
19 | "Create a convex hull around geometry using Gdal's convex hull function. GDAL convex hull only works in 2D, so the results will be on the XY plane.",
20 | "GIS Tools")
21 | {
22 | }
23 |
24 | public override Grasshopper.Kernel.GH_Exposure Exposure
25 | {
26 | get { return GH_Exposure.tertiary; }
27 | }
28 |
29 | ///
30 | /// Registers all the input parameters for this component.
31 | ///
32 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
33 | {
34 | pManager.AddGeometryParameter("Feature Geometry", "FG", "Geometry contained in the feature. Geometry can be point(s), polyline(s), mesh(es) or a combination of these.", GH_ParamAccess.tree);
35 | }
36 |
37 | ///
38 | /// Registers all the output parameters for this component.
39 | ///
40 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
41 | {
42 | pManager.AddGeometryParameter("Hull Geometry", "H", "Hull geometry.", GH_ParamAccess.tree);
43 | }
44 |
45 | ///
46 | /// This is the method that actually does the work.
47 | ///
48 | /// The DA object is used to retrieve from inputs and store in outputs.
49 | protected override void SolveInstance(IGH_DataAccess DA)
50 | {
51 |
52 | GH_Structure gGoo = new GH_Structure();
53 | DA.GetDataTree("Feature Geometry", out gGoo);
54 |
55 | GH_Structure gGooHull = new GH_Structure();
56 |
57 | ///GDAL setup
58 | Heron.GdalConfiguration.ConfigureOgr();
59 |
60 | ///Use WGS84 spatial reference
61 | OSGeo.OSR.SpatialReference dst = new OSGeo.OSR.SpatialReference("");
62 | dst.SetWellKnownGeogCS("WGS84");
63 | Transform transform = new Transform(1);
64 | Transform revTransform = new Transform(1);
65 |
66 | ///Create virtual datasource to be converted later
67 | ///Using geojson as a flexiblle base file type which can be converted later with ogr2ogr
68 | OSGeo.OGR.Driver drv = Ogr.GetDriverByName("GeoJSON");
69 | DataSource ds = drv.CreateDataSource("/vsimem/out.geojson", null);
70 |
71 | ///Use OGR catch-all for geometry types
72 | var gtype = wkbGeometryType.wkbGeometryCollection;
73 |
74 | ///Create layer
75 | OSGeo.OGR.Layer layer = ds.CreateLayer("temp", dst, gtype, null);
76 | FeatureDefn def = layer.GetLayerDefn();
77 |
78 | var branchPaths = gGoo.Paths;
79 |
80 | for (int a = 0; a < gGoo.Branches.Count; a++)
81 | {
82 | ///create feature
83 | OSGeo.OGR.Feature feature = new OSGeo.OGR.Feature(def);
84 |
85 | ///Get geometry type(s) in branch
86 | var geomList = gGoo.Branches[a];
87 |
88 | List geomTypeList = geomList.Select(o => o.TypeName).ToList();
89 |
90 | ///Add geomtery to feature
91 | ///Create containers for translating from GH Goo
92 | Point3d pt = new Point3d();
93 | List pts = new List();
94 |
95 | Curve crv = null;
96 | List crvs = new List();
97 |
98 | Mesh mesh = new Mesh();
99 | Mesh multiMesh = new Mesh();
100 |
101 |
102 | OSGeo.OGR.Geometry geoCollection = new OSGeo.OGR.Geometry(wkbGeometryType.wkbGeometryCollection);
103 | for (int gInt = 0; gInt < geomList.Count; gInt++)
104 | {
105 | string geomTypeMixed = geomTypeList[gInt];
106 | switch (geomTypeMixed)
107 | {
108 | case "Point":
109 | geomList[gInt].CastTo(out pt);
110 | geoCollection.AddGeometry(Heron.Convert.Point3dToOgrPoint(pt, transform));
111 | break;
112 |
113 | case "Curve":
114 | geomList[gInt].CastTo(out crv);
115 | geoCollection.AddGeometry(Heron.Convert.CurveToOgrLinestring(crv, transform));
116 | break;
117 |
118 | case "Mesh":
119 | geomList[gInt].CastTo(out mesh);
120 | geoCollection.AddGeometry(Ogr.ForceToMultiPolygon(Heron.Convert.MeshToMultiPolygon(mesh, transform)));
121 | break;
122 |
123 | default:
124 | AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Not able to export " + geomTypeMixed + " geometry at branch " + gGoo.get_Path(a).ToString() +
125 | ". Geometry must be a Point, Curve or Mesh.");
126 | break;
127 | }
128 |
129 | }
130 |
131 | var hullCol = geoCollection.ConvexHull();
132 | gGooHull.AppendRange(Heron.Convert.OgrGeomToGHGoo(hullCol, revTransform), new GH_Path(a));
133 |
134 | }
135 |
136 | def.Dispose();
137 | layer.Dispose();
138 | ds.Dispose();
139 |
140 | DA.SetDataTree(0, gGooHull);
141 | }
142 |
143 | ///
144 | /// Provides an Icon for the component.
145 | ///
146 | protected override System.Drawing.Bitmap Icon
147 | {
148 | get
149 | {
150 | //You can add image files to your project resources and access them like this:
151 | // return Resources.IconForThisComponent;
152 | return Properties.Resources.shp;
153 | }
154 | }
155 |
156 | ///
157 | /// Gets the unique ID for this component. Do not change this ID after release.
158 | ///
159 | public override Guid ComponentGuid
160 | {
161 | get { return new Guid("E09EE6ED-8126-4624-AE3B-B400C43DDDE0"); }
162 | }
163 | }
164 | }
--------------------------------------------------------------------------------
/Heron/Components/GIS Tools/GdalFillNoData.cs:
--------------------------------------------------------------------------------
1 | using Grasshopper.Kernel;
2 | using OSGeo.GDAL;
3 | using System;
4 | using System.IO;
5 |
6 | namespace Heron
7 | {
8 | public class GdalFillNoData : HeronComponent
9 | {
10 | ///
11 | /// Initializes a new instance of the GdalTranslate class.
12 | ///
13 | public GdalFillNoData()
14 | : base("Gdal Fill No Data", "GFND",
15 | "Fill raster regions that have no data by interpolation from edges with the GDAL FillNoData program. " +
16 | "More information can be found at https://gdal.org/programs/gdal_fillnodata.html.",
17 | "GIS Tools")
18 | {
19 | }
20 |
21 | public override Grasshopper.Kernel.GH_Exposure Exposure
22 | {
23 | get { return GH_Exposure.tertiary; }
24 | }
25 |
26 | ///
27 | /// Registers all the input parameters for this component.
28 | ///
29 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
30 | {
31 | pManager.AddTextParameter("Source dataset", "S", "File location for the source raster dataset.", GH_ParamAccess.item);
32 | pManager.AddTextParameter("Destination dataset", "D", "File location for the destination dataset.", GH_ParamAccess.item);
33 | pManager.AddIntegerParameter("Max Distance", "MD", "The maximum distance (in pixels) that the algorithm will search out for values to interpolate. " +
34 | "The default is 100 pixels.", GH_ParamAccess.item, 100);
35 | pManager.AddIntegerParameter("Smooth Iterations", "SI", "The number of 3x3 average filter smoothing iterations to run after the interpolation to dampen artifacts. " +
36 | "The default is zero smoothing iterations.", GH_ParamAccess.item, 0);
37 | pManager.AddIntegerParameter("Band", "B", "The band to operate on, by default the first band is operated on.", GH_ParamAccess.item, 1);
38 | pManager[2].Optional = true;
39 | pManager[3].Optional = true;
40 | pManager[4].Optional = true;
41 | }
42 |
43 | ///
44 | /// Registers all the output parameters for this component.
45 | ///
46 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
47 | {
48 | pManager.AddTextParameter("Destination File", "D", "File location of destination datasource.", GH_ParamAccess.item);
49 | }
50 |
51 | ///
52 | /// This is the method that actually does the work.
53 | ///
54 | /// The DA object is used to retrieve from inputs and store in outputs.
55 | protected override void SolveInstance(IGH_DataAccess DA)
56 | {
57 | string datasourceFileLocation = string.Empty;
58 | DA.GetData(0, ref datasourceFileLocation);
59 |
60 | string dstFileLocation = string.Empty;
61 | DA.GetData(1, ref dstFileLocation);
62 |
63 | int maxDistance = 100;
64 | DA.GetData(2, ref maxDistance);
65 |
66 | int smoothIterations = 0;
67 | DA.GetData(3, ref smoothIterations);
68 |
69 | int band = 1;
70 | DA.GetData(4, ref band);
71 |
72 | string dstOutput = string.Empty;
73 |
74 |
75 | Heron.GdalConfiguration.ConfigureGdal();
76 | OSGeo.GDAL.Gdal.AllRegister();
77 |
78 | AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Look for more information about options at:");
79 | AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "https://gdal.org/programs/gdal_fillnodata.html");
80 |
81 | if (!string.IsNullOrEmpty(datasourceFileLocation))
82 | {
83 | using (Dataset datasource = Gdal.Open(datasourceFileLocation, Access.GA_ReadOnly))
84 | {
85 | if (datasource == null)
86 | {
87 | throw new Exception("Can't open GDAL dataset: " + datasourceFileLocation);
88 | }
89 |
90 | if (!string.IsNullOrEmpty(dstFileLocation))
91 | {
92 | if(File.Exists(dstFileLocation))
93 | {
94 | File.Delete(dstFileLocation);
95 | }
96 | OSGeo.GDAL.Driver drv = datasource.GetDriver();
97 | Dataset dst = drv.CreateCopy(dstFileLocation, datasource, 0, null, null, null);
98 | int filled = Gdal.FillNodata(dst.GetRasterBand(band), null, (double)maxDistance, smoothIterations, null, null, null);
99 | dst.Dispose();
100 | dstOutput = dstFileLocation;
101 | }
102 | datasource.Dispose();
103 | }
104 | }
105 |
106 | DA.SetData(0, dstOutput);
107 |
108 | }
109 |
110 | ///
111 | /// Provides an Icon for the component.
112 | ///
113 | protected override System.Drawing.Bitmap Icon
114 | {
115 | get
116 | {
117 | return Properties.Resources.raster;
118 | }
119 | }
120 |
121 | ///
122 | /// Gets the unique ID for this component. Do not change this ID after release.
123 | ///
124 | public override Guid ComponentGuid
125 | {
126 | get { return new Guid("0E773376-BB1B-42DA-8366-D6273BDF8755"); }
127 | }
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/Heron/Components/GIS Tools/GdalInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Runtime;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Text.RegularExpressions;
7 |
8 | using Grasshopper.Kernel;
9 | using Rhino.Geometry;
10 |
11 | using OSGeo.GDAL;
12 | using OSGeo.OSR;
13 | using OSGeo.OGR;
14 |
15 | namespace Heron
16 | {
17 | public class GdalInfo : HeronComponent
18 | {
19 | ///
20 | /// Initializes a new instance of the GdalTranslate class.
21 | ///
22 | public GdalInfo()
23 | : base("Gdal Info", "GI",
24 | "Gdalinfo program lists various information about a GDAL supported raster dataset. " +
25 | "More information about Gdalinfo options can be found at https://gdal.org/programs/gdalinfo.html.",
26 | "GIS Tools")
27 | {
28 | }
29 |
30 | public override Grasshopper.Kernel.GH_Exposure Exposure
31 | {
32 | get { return GH_Exposure.tertiary; }
33 | }
34 |
35 | ///
36 | /// Registers all the input parameters for this component.
37 | ///
38 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
39 | {
40 | pManager.AddTextParameter("Source dataset", "S", "File location for the source raster dataset.", GH_ParamAccess.item);
41 | pManager.AddTextParameter("Options", "O", "String of options with a space separating each term. " +
42 | "For instance, to report histogram information for all bands, the options string would be '-hist'.", GH_ParamAccess.item);
43 | pManager[1].Optional = true;
44 | }
45 |
46 | ///
47 | /// Registers all the output parameters for this component.
48 | ///
49 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
50 | {
51 | pManager.AddTextParameter("Source Info", "I", "List of information about the source dataset.", GH_ParamAccess.item);
52 | }
53 |
54 | ///
55 | /// This is the method that actually does the work.
56 | ///
57 | /// The DA object is used to retrieve from inputs and store in outputs.
58 | protected override void SolveInstance(IGH_DataAccess DA)
59 | {
60 | string datasourceFileLocation = string.Empty;
61 | DA.GetData(0, ref datasourceFileLocation);
62 |
63 | string options = string.Empty;
64 | DA.GetData(1, ref options);
65 |
66 | var re = new System.Text.RegularExpressions.Regex("(?<=\")[^\"]*(?=\")|[^\" ]+");
67 | string[] infoOptions = re.Matches(options).Cast().Select(m => m.Value).ToArray();
68 |
69 | string datasourceInfo = string.Empty;
70 | string dstInfo = string.Empty;
71 | string dstOutput = string.Empty;
72 |
73 | Heron.GdalConfiguration.ConfigureGdal();
74 | OSGeo.GDAL.Gdal.AllRegister();
75 | ///Specific settings for getting WMS images
76 | OSGeo.GDAL.Gdal.SetConfigOption("GDAL_HTTP_UNSAFESSL", "YES");
77 | OSGeo.GDAL.Gdal.SetConfigOption("GDAL_SKIP", "WMS");
78 |
79 | AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Look for more information about options at:");
80 | AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "https://gdal.org/programs/gdalinfo.html");
81 |
82 | if (!string.IsNullOrEmpty(datasourceFileLocation))
83 | {
84 | //using (Dataset datasource = Gdal.OpenEx(datasourceFileLocation,0, null,null,null))
85 | using (Dataset datasource = Gdal.Open(datasourceFileLocation, Access.GA_ReadOnly))
86 | {
87 | if (datasource == null)
88 | {
89 | throw new Exception("Can't open GDAL dataset: " + datasourceFileLocation);
90 | }
91 |
92 | datasourceInfo = Gdal.GDALInfo(datasource, new GDALInfoOptions(infoOptions.ToArray()));
93 | datasource.Dispose();
94 | }
95 | }
96 |
97 | DA.SetData(0, datasourceInfo);
98 | }
99 |
100 | ///
101 | /// Provides an Icon for the component.
102 | ///
103 | protected override System.Drawing.Bitmap Icon
104 | {
105 | get
106 | {
107 | return Properties.Resources.raster;
108 | }
109 | }
110 |
111 | ///
112 | /// Gets the unique ID for this component. Do not change this ID after release.
113 | ///
114 | public override Guid ComponentGuid
115 | {
116 | get { return new Guid("35AF7648-AAAD-464F-8343-B7DA339788FB"); }
117 | }
118 | }
119 | }
--------------------------------------------------------------------------------
/Heron/Components/GIS Tools/GdalTranslate.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Runtime;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Text.RegularExpressions;
7 |
8 | using Grasshopper.Kernel;
9 | using Rhino.Geometry;
10 |
11 | using OSGeo.GDAL;
12 | using OSGeo.OSR;
13 | using OSGeo.OGR;
14 |
15 | namespace Heron
16 | {
17 | public class GdalTranslate : HeronComponent
18 | {
19 | ///
20 | /// Initializes a new instance of the GdalTranslate class.
21 | ///
22 | public GdalTranslate()
23 | : base("GdalTranslate", "GdalTranslate",
24 | "Manipulate raster data with the GDAL Translate program given a source dataset, a destination dataset and a list of options. " +
25 | "Formatting for the list of options should be a single string of text with a space separating each term " +
26 | "where '-' should preceed the option parameter and the next item in the list should be that parameter's value. " +
27 | "For instance, to convert raster data to PNG format the options string would be '-of PNG'. To clip a large raster data set " +
28 | "to a boundary of upper left x (ulx), upper left y (uly), lower right x (lrx) and lower right y (lry), the options string " +
29 | "would be '-projwin ulx uly lrx lry' where ulx, uly, lrx and lry are substituted with coordinate values. " +
30 | "More information about translate options can be found at https://gdal.org/programs/gdal_translate.html.",
31 | "GIS Tools")
32 | {
33 | }
34 |
35 | public override Grasshopper.Kernel.GH_Exposure Exposure
36 | {
37 | get { return GH_Exposure.tertiary; }
38 | }
39 |
40 | ///
41 | /// Registers all the input parameters for this component.
42 | ///
43 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
44 | {
45 | pManager.AddTextParameter("Source dataset", "source", "File location for the source raster dataset.", GH_ParamAccess.item);
46 | pManager.AddTextParameter("Destination dataset", "dest", "File location for the destination dataset.", GH_ParamAccess.item);
47 | pManager.AddTextParameter("Options", "options", "String of options with a space separating each term. " +
48 | "For instance, to convert raster data to PNG format the options string would be '-of PNG'.", GH_ParamAccess.item);
49 | pManager[0].Optional = true;
50 | pManager[1].Optional = true;
51 | pManager[2].Optional = true;
52 | }
53 |
54 | ///
55 | /// Registers all the output parameters for this component.
56 | ///
57 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
58 | {
59 | pManager.AddTextParameter("Source Info", "sourceInfo", "List of information about the source dataset.", GH_ParamAccess.item);
60 | pManager.AddTextParameter("Destination Info", "destInfo", "List of information about the destination dataset.", GH_ParamAccess.item);
61 | pManager.AddTextParameter("Destination File", "destFile", "File location of destination datasource.", GH_ParamAccess.item);
62 | }
63 |
64 | ///
65 | /// This is the method that actually does the work.
66 | ///
67 | /// The DA object is used to retrieve from inputs and store in outputs.
68 | protected override void SolveInstance(IGH_DataAccess DA)
69 | {
70 | string datasourceFileLocation = string.Empty;
71 | DA.GetData(0, ref datasourceFileLocation);
72 |
73 | string dstFileLocation = string.Empty;
74 | DA.GetData(1, ref dstFileLocation);
75 |
76 | string options = string.Empty;
77 | DA.GetData(2, ref options);
78 |
79 | var re = new System.Text.RegularExpressions.Regex("(?<=\")[^\"]*(?=\")|[^\" ]+");
80 | string[] translateOptions = re.Matches(options).Cast().Select(m => m.Value).ToArray();
81 |
82 | string datasourceInfo = string.Empty;
83 | string dstInfo = string.Empty;
84 | string dstOutput = string.Empty;
85 |
86 | Heron.GdalConfiguration.ConfigureGdal();
87 | OSGeo.GDAL.Gdal.AllRegister();
88 | ///Specific settings for getting WMS images
89 | OSGeo.GDAL.Gdal.SetConfigOption("GDAL_HTTP_UNSAFESSL", "YES");
90 | OSGeo.GDAL.Gdal.SetConfigOption("GDAL_SKIP", "WMS");
91 |
92 | AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Look for more information about options at:");
93 | AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "https://gdal.org/programs/gdal_translate.html");
94 |
95 | if (!string.IsNullOrEmpty(datasourceFileLocation))
96 | {
97 | using (Dataset datasource = Gdal.Open(datasourceFileLocation, Access.GA_ReadOnly))
98 | {
99 | if (datasource == null)
100 | {
101 | throw new Exception("Can't open GDAL dataset: " + datasourceFileLocation);
102 | }
103 |
104 | SpatialReference sr = new SpatialReference(datasource.GetProjection());
105 |
106 | ///Check if SRS needs to be converted from ESRI format to WKT to avoid error:
107 | ///"No translation for Lambert_Conformal_Conic to PROJ.4 format is known."
108 | ///https://gis.stackexchange.com/questions/128266/qgis-error-6-no-translation-for-lambert-conformal-conic-to-proj-4-format-is-kn
109 | SpatialReference srEsri = sr;
110 | srEsri.MorphFromESRI();
111 | string projEsri = string.Empty;
112 | srEsri.ExportToWkt(out projEsri, null);
113 |
114 | ///If no SRS exists, check Ground Control Points SRS
115 | SpatialReference srGCP = new SpatialReference(datasource.GetGCPProjection());
116 | string projGCP = string.Empty;
117 | srGCP.ExportToWkt(out projGCP, null);
118 |
119 | if (!string.IsNullOrEmpty(projEsri))
120 | {
121 | datasource.SetProjection(projEsri);
122 | sr = srEsri;
123 | AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Spatial Reference System (SRS) morphed form ESRI format.");
124 | }
125 | else if (!string.IsNullOrEmpty(projGCP))
126 | {
127 | datasource.SetProjection(projGCP);
128 | sr = srGCP;
129 | AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Spatial Reference System (SRS) set from Ground Control Points (GCPs).");
130 | }
131 | else
132 | {
133 | AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Spatial Reference System (SRS) is unknown or unsupported. " +
134 | "Try setting the SRS with the GdalWarp component using -t_srs EPSG:4326 for the option input.");
135 | //sr.SetWellKnownGeogCS("WGS84");
136 | }
137 |
138 | ///Get info about image
139 | List infoOptions = new List {
140 | "-stats"
141 | };
142 | datasourceInfo = Gdal.GDALInfo(datasource, new GDALInfoOptions(infoOptions.ToArray()));
143 |
144 | if (!string.IsNullOrEmpty(dstFileLocation))
145 | {
146 | if (string.IsNullOrEmpty(options) && File.Exists(dstFileLocation))
147 | {
148 | Dataset dst = Gdal.Open(dstFileLocation, Access.GA_ReadOnly);
149 | dstInfo = Gdal.GDALInfo(dst, null);
150 | dst.Dispose();
151 | dstOutput = dstFileLocation;
152 | }
153 | else
154 | {
155 | Dataset dst = Gdal.wrapper_GDALTranslate(dstFileLocation, datasource, new GDALTranslateOptions(translateOptions), null, null);
156 | dstInfo = Gdal.GDALInfo(dst, new GDALInfoOptions(infoOptions.ToArray()));
157 | dst.Dispose();
158 | dstOutput = dstFileLocation;
159 | }
160 | }
161 | datasource.Dispose();
162 | }
163 | }
164 |
165 | DA.SetData(0, datasourceInfo);
166 | DA.SetData(1, dstInfo);
167 | DA.SetData(2, dstOutput);
168 | }
169 |
170 | ///
171 | /// Provides an Icon for the component.
172 | ///
173 | protected override System.Drawing.Bitmap Icon
174 | {
175 | get
176 | {
177 | return Properties.Resources.raster;
178 | }
179 | }
180 |
181 | ///
182 | /// Gets the unique ID for this component. Do not change this ID after release.
183 | ///
184 | public override Guid ComponentGuid
185 | {
186 | get { return new Guid("c9056659-a5f8-4cc0-89f3-0e2f22b08afc"); }
187 | }
188 | }
189 | }
--------------------------------------------------------------------------------
/Heron/Components/GIS Tools/SetEAP.cs:
--------------------------------------------------------------------------------
1 | using Grasshopper.Kernel;
2 | using Newtonsoft.Json.Linq;
3 | using Rhino.DocObjects;
4 | using System;
5 | using System.Linq;
6 |
7 | namespace Heron
8 | {
9 | public class SetEAP : HeronComponent
10 | {
11 | //Class Constructor
12 | public SetEAP() : base("Set EarthAnchorPoint", "SetEAP", "Set the Rhino EarthAnchorPoint using either an address or Lat/Lon coordinates", "GIS Tools")
13 | {
14 |
15 | }
16 |
17 |
18 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
19 | {
20 | pManager.AddBooleanParameter("Set EAP", "set", "Set the EarthAnchorPoint", GH_ParamAccess.item, false);
21 | pManager.AddTextParameter("Point of Interest", "poi", "Point of interest or address with which to set the EarthAnchorPoint. " +
22 | "If a point of interest or address is supplied, this component will query the ESRI geolocation service and set the EAP to the first coordinates in the list of candidates.", GH_ParamAccess.item);
23 | pManager[1].Optional = true;
24 | pManager.AddTextParameter("Latitude", "LAT", "Latitude in either Decimal Degree (DD) or Degree Minute Second (DMS) format", GH_ParamAccess.item);
25 | pManager[2].Optional = true;
26 | pManager.AddTextParameter("Longitude", "LON", "Longitude in either Decimal Degree (DD) or Degree Minute Second (DMS) format", GH_ParamAccess.item);
27 | pManager[3].Optional = true;
28 | }
29 |
30 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
31 | {
32 | pManager.AddTextParameter("Earth Anchor Point", "EAP", "EarthAnchorPoint Longitude/Latitude", GH_ParamAccess.item);
33 | }
34 |
35 | protected override void SolveInstance(IGH_DataAccess DA)
36 | {
37 | string latString = string.Empty;
38 | string lonString = string.Empty;
39 | double lat = Double.NaN;
40 | double lon = Double.NaN;
41 | bool EAP = false;
42 | string address = string.Empty;
43 | string lonlatString = string.Empty;
44 | string addressString = string.Empty;
45 |
46 | DA.GetData("Set EAP", ref EAP);
47 | DA.GetData("Point of Interest", ref address);
48 | DA.GetData("Latitude", ref latString);
49 | DA.GetData("Longitude", ref lonString);
50 |
51 |
52 |
53 | if (EAP == true)
54 | {
55 | EarthAnchorPoint ePt = new EarthAnchorPoint();
56 |
57 | lat = Heron.Convert.DMStoDDLat(latString);
58 | lon = Heron.Convert.DMStoDDLon(lonString);
59 |
60 | if (Double.IsNaN(lat) && !string.IsNullOrEmpty(latString))
61 | {
62 | AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Latitude value is invalid. Please enter value in valid Decimal Degree format (-79.976666) " +
63 | "or valid Degree Minute Second format (79°58′36″W | 079:56:55W | 079d 58′ 36″ W | 079 58 36.0 | 079 58 36.4 E)");
64 | return;
65 | }
66 |
67 | if (Double.IsNaN(lon) && !string.IsNullOrEmpty(lonString))
68 | {
69 | AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Longitude value is invalid. Please enter value in valid Decimal Degree format (40.446388) " +
70 | "or valid Degree Minute Second format (40°26′47″N | 40:26:46N | 40d 26m 47s N | 40 26 47.1 | 40 26 47.4141 N)");
71 | return;
72 | }
73 |
74 | if (!string.IsNullOrEmpty(address) && string.IsNullOrEmpty(latString) && string.IsNullOrEmpty(lonString))
75 | {
76 | string output = Heron.Convert.HttpToJson("https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/findAddressCandidates?Address=" + address + "&f=pjson");
77 | JObject ja = JObject.Parse(output);
78 |
79 | if (ja["candidates"].Count() < 1)
80 | {
81 | AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "No Cadidate location found for this address");
82 | DA.SetData("Earth Anchor Point", lonlatString);
83 | return;
84 | }
85 | else
86 | {
87 | if (ja["candidates"][0]["score"].Value() > 99)
88 | {
89 | addressString = "EAP set to the following address: " + ja["candidates"][0]["address"].ToString() + "\r\n";
90 | ePt.EarthBasepointLatitude = (double)ja["candidates"][0]["location"]["y"];
91 | ePt.EarthBasepointLongitude = (double)ja["candidates"][0]["location"]["x"];
92 | }
93 | }
94 | }
95 |
96 | else
97 | {
98 | if (!Double.IsNaN(lat) && !Double.IsNaN(lon))
99 | {
100 | ePt.EarthBasepointLatitude = lat;
101 | ePt.EarthBasepointLongitude = lon;
102 | }
103 | }
104 |
105 | if ((ePt.EarthBasepointLatitude > -90) && (ePt.EarthBasepointLatitude < 90) && (ePt.EarthBasepointLongitude > -180) && (ePt.EarthBasepointLongitude < 180))
106 | {
107 | //set new EAP
108 | Rhino.RhinoDoc.ActiveDoc.EarthAnchorPoint = ePt;
109 | }
110 |
111 | }
112 |
113 | //check if EAP has been set and if so what is it
114 | if (!Rhino.RhinoDoc.ActiveDoc.EarthAnchorPoint.EarthLocationIsSet())
115 | {
116 | lonlatString = "The Earth Anchor Point has not been set yet";
117 | AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "EAP has not been set yet");
118 | }
119 |
120 | else lonlatString = "Longitude: " + Rhino.RhinoDoc.ActiveDoc.EarthAnchorPoint.EarthBasepointLongitude.ToString() +
121 | " / Latitude: " + Rhino.RhinoDoc.ActiveDoc.EarthAnchorPoint.EarthBasepointLatitude.ToString();
122 |
123 | DA.SetData("Earth Anchor Point", lonlatString);
124 |
125 | }
126 |
127 | protected override System.Drawing.Bitmap Icon
128 | {
129 | get
130 | {
131 | return Properties.Resources.eap;
132 | }
133 | }
134 |
135 | public override Guid ComponentGuid
136 | {
137 | get { return new Guid("3A9B1B9D-9DED-4B5B-9101-ED57F5239EC8"); }
138 | }
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/Heron/Components/GIS Tools/XYtoDD.cs:
--------------------------------------------------------------------------------
1 | using Grasshopper.Kernel;
2 | using Rhino.Geometry;
3 | using System;
4 |
5 | namespace Heron
6 | {
7 | public class XYtoDD : HeronComponent
8 | {
9 | //Class Constructor
10 | public XYtoDD() : base("XY to Decimal Degrees", "XYtoDD", "Convert X/Y to Decimal Degrees Longitude/Latitude in the WGS84 spatial reference system", "GIS Tools")
11 | {
12 |
13 | }
14 |
15 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
16 | {
17 | pManager.AddPointParameter("xyPoint", "xyPoint", "Point to translate to Longitude/Latitude", GH_ParamAccess.item);
18 | }
19 |
20 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
21 | {
22 | pManager.AddNumberParameter("Latitude", "LAT", "Decimal Degree Latitude", GH_ParamAccess.item);
23 | pManager.AddNumberParameter("Longitude", "LON", "Decimal Degree Longitude", GH_ParamAccess.item);
24 | pManager.AddTransformParameter("Transform", "xForm", "The transform from XYZ to WGS", GH_ParamAccess.item);
25 | }
26 |
27 | protected override void SolveInstance(IGH_DataAccess DA)
28 | {
29 | ///GDAL setup
30 | Heron.GdalConfiguration.ConfigureOgr();
31 |
32 | ///Set transform from input spatial reference to Heron spatial reference
33 | OSGeo.OSR.SpatialReference heronSRS = new OSGeo.OSR.SpatialReference("");
34 | heronSRS.SetFromUserInput(HeronSRS.Instance.SRS);
35 | OSGeo.OSR.SpatialReference wgsSRS = new OSGeo.OSR.SpatialReference("");
36 | wgsSRS.SetFromUserInput("WGS84");
37 | //AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Heron's Spatial Spatial Reference System (SRS): " + HeronSRS.Instance.SRS);
38 | int heronSRSInt = Int16.Parse(heronSRS.GetAuthorityCode(null));
39 | Message = "EPSG:" + heronSRSInt;
40 |
41 | ///Apply EAP to HeronSRS
42 | Transform heronToUserSRSTransform = Heron.Convert.GetHeronSRSToUserSRSTransform(heronSRS);
43 | Transform heronToWgsSRSTransform = Heron.Convert.GetHeronSRSToUserSRSTransform(wgsSRS);
44 |
45 | ///Set transforms between source and HeronSRS
46 | OSGeo.OSR.CoordinateTransformation revTransform = new OSGeo.OSR.CoordinateTransformation(heronSRS, wgsSRS);
47 |
48 | ///Dump out the transform first
49 | DA.SetData("Transform", heronToWgsSRSTransform);
50 |
51 |
52 | Point3d xyPt = new Point3d();
53 | if (!DA.GetData("xyPoint", ref xyPt)) return;
54 |
55 | xyPt.Transform(heronToUserSRSTransform);
56 | Point3d dd = Heron.Convert.OSRTransformPoint3dToPoint3d(xyPt, revTransform);
57 |
58 | DA.SetData("Latitude", dd.Y);
59 | DA.SetData("Longitude", dd.X);
60 | }
61 |
62 | protected override System.Drawing.Bitmap Icon
63 | {
64 | get
65 | {
66 | return Properties.Resources.xytodd;
67 | }
68 | }
69 |
70 | public override Guid ComponentGuid
71 | {
72 | get { return new Guid("{0B461B47-632B-4145-AA06-157AAFAC1DDA}"); }
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/Heron/Components/Utilities/ColorToHex.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using Grasshopper.Kernel;
5 | using Rhino.Geometry;
6 |
7 | namespace Heron
8 | {
9 | public class ColorToHex : HeronComponent
10 | {
11 | ///
12 | /// Initializes a new instance of the ColorToHex class.
13 | ///
14 | public ColorToHex()
15 | : base("Color to Hex", "C2H", "Convert an RGBA color to hexidecimal format.", "Utilities")
16 | {
17 | }
18 | public override Grasshopper.Kernel.GH_Exposure Exposure
19 | {
20 | get { return GH_Exposure.quarternary; }
21 | }
22 |
23 |
24 | ///
25 | /// Registers all the input parameters for this component.
26 | ///
27 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
28 | {
29 | pManager.AddColourParameter("colorRGBA", "colorRGBA", "RGBA color to convert to hexidecimal format", GH_ParamAccess.item);
30 | }
31 |
32 | ///
33 | /// Registers all the output parameters for this component.
34 | ///
35 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
36 | {
37 | pManager.AddTextParameter("colorHexidecmial", "colorHex", "Hexidecimal color converted from RGBA", GH_ParamAccess.item);
38 | }
39 |
40 | ///
41 | /// This is the method that actually does the work.
42 | ///
43 | /// The DA object is used to retrieve from inputs and store in outputs.
44 | protected override void SolveInstance(IGH_DataAccess DA)
45 | {
46 | Color color = Color.Empty;
47 | DA.GetData(0, ref color);
48 | string hex = String.Format("#{0:X2}{1:X2}{2:X2}{3:X2}", color.R, color.G, color.B, color.A);
49 | DA.SetData(0, hex);
50 | }
51 |
52 | ///
53 | /// Provides an Icon for the component.
54 | ///
55 | protected override System.Drawing.Bitmap Icon
56 | {
57 | get
58 | {
59 | //You can add image files to your project resources and access them like this:
60 | // return Resources.IconForThisComponent;
61 | return Properties.Resources.raster;
62 | }
63 | }
64 |
65 | ///
66 | /// Gets the unique ID for this component. Do not change this ID after release.
67 | ///
68 | public override Guid ComponentGuid
69 | {
70 | get { return new Guid("5fd79e04-c146-4b3e-9e96-b1c0ec66310f"); }
71 | }
72 | }
73 | }
--------------------------------------------------------------------------------
/Heron/Components/Utilities/DecimateTopoFromPoint.cs:
--------------------------------------------------------------------------------
1 | using Grasshopper.Kernel;
2 | using Grasshopper.Kernel.Geometry;
3 | using Rhino.Geometry;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Runtime;
8 |
9 | namespace Heron.Components.Utilities
10 | {
11 | public class DecimateTopoFromPoint : HeronComponent
12 | {
13 | ///
14 | /// Initializes a new instance of the DecimateTopoFromPoint class.
15 | ///
16 | public DecimateTopoFromPoint()
17 | : base("Decimate Topography From Point", "DTP",
18 | "Reduce the number of vertexes of a topo mesh the farther they are from a given point.",
19 | "Utilities")
20 | {
21 | }
22 |
23 | public override Grasshopper.Kernel.GH_Exposure Exposure
24 | {
25 | get { return GH_Exposure.tertiary; }
26 | }
27 |
28 | ///
29 | /// Registers all the input parameters for this component.
30 | ///
31 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
32 | {
33 | pManager.AddPointParameter("View Point", "V", "The point from which to decimate the mesh. " +
34 | "The farther from this point a mesh vertex is, the more likely it will be eliminated from the mesh.", GH_ParamAccess.item);
35 | pManager.AddMeshParameter("Topography Mesh", "M", "The topographic (2.5D) mesh to be decimated.", GH_ParamAccess.item);
36 | pManager.AddNumberParameter("Distance Increments", "D", "List of distance increments for which to apply the corresponding percent reduction. " +
37 | "The number of distance and percent increments must match.", GH_ParamAccess.list);
38 | pManager[2].Optional = true;
39 | pManager.AddNumberParameter("Percent Increments", "P", "List of increments (from 0-1) by which to randomly reduce the mesh within each corresponding distance increment. " +
40 | "Numbers less than 0 and more than 1 will be clamped back to the 0-1 range. " +
41 | "The number of percent and distance increments must match.", GH_ParamAccess.list);
42 | pManager[3].Optional = true;
43 | pManager.AddIntegerParameter("Random Seed", "S", "Random seed used for randomly reducing the vertexes.", GH_ParamAccess.item, 1);
44 | }
45 |
46 | ///
47 | /// Registers all the output parameters for this component.
48 | ///
49 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
50 | {
51 | pManager.AddMeshParameter("Decimated Mesh", "M", "The decimated mesh, a 2.5D Delaunay triagulation of the decimated vertexes.", GH_ParamAccess.item);
52 | }
53 |
54 | ///
55 | /// This is the method that actually does the work.
56 | ///
57 | /// The DA object is used to retrieve from inputs and store in outputs.
58 | protected override void SolveInstance(IGH_DataAccess DA)
59 | {
60 | Point3d p = new Point3d();
61 | DA.GetData("View Point", ref p);
62 |
63 | Mesh topoMesh = new Mesh();
64 | DA.GetData("Topography Mesh", ref topoMesh);
65 |
66 | List distanceIncrements = new List();
67 | DA.GetDataList("Distance Increments", distanceIncrements);
68 |
69 | List percentIncrements = new List();
70 | DA.GetDataList("Percent Increments", percentIncrements);
71 |
72 | int seed = 1;
73 | DA.GetData("Random Seed", ref seed);
74 |
75 | BoundingBox bbox = topoMesh.GetBoundingBox(false);
76 | double diagonal = bbox.Diagonal.Length;
77 |
78 | ///Default ranges
79 | var distRanges = new List() { diagonal * 0.1 / 2, diagonal * 0.2 / 2, diagonal * 0.3 / 2, diagonal * 0.4 / 2 };
80 | var pctRanges = new List() { 0.5, 0.8, 0.9, 0.99 };
81 |
82 | ///Clamp values of user input
83 | if(distanceIncrements.Count != 0) { distRanges = distanceIncrements.Select(x => Math.Max(x,0.0)).ToList(); }
84 | if(percentIncrements.Count != 0) { pctRanges = percentIncrements.Select(x => Math.Min(Math.Max(x, 0.0), 1.0)).ToList(); }
85 |
86 |
87 | if (distRanges.Count != pctRanges.Count)
88 | {
89 | AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "The number of Distance Increments does not match the number of Percent Increments. The default is 4 increments.");
90 | return;
91 | }
92 |
93 | pctRanges.Insert(0, 0.0);
94 |
95 |
96 | List vertexPoints = topoMesh.Vertices.ToPoint3dArray().ToList();
97 | List nakedVerts = new List();
98 | List clothedVerts = new List();
99 |
100 | ///Allow maintaining of naked vertexes
101 | bool keepNakedVerts = true;
102 | if (keepNakedVerts)
103 | {
104 | bool[] nakedArray = topoMesh.GetNakedEdgePointStatus();
105 | for (int v = 0; v < nakedArray.Length; v++)
106 | {
107 | if (!nakedArray[v]) { clothedVerts.Add(vertexPoints[v]); }
108 | else { nakedVerts.Add(vertexPoints[v]); }
109 | }
110 |
111 | vertexPoints = clothedVerts;
112 | }
113 |
114 |
115 | ///Points grouped by distance
116 | var pointGroups = vertexPoints.GroupBy(x => distRanges.FirstOrDefault(r => r > Math.Sqrt(x.DistanceToSquared(p))))
117 | .OrderBy(grp => grp.First().DistanceToSquared(p))
118 | .Select(x => new List(x))
119 | .ToList();
120 |
121 | ///Randomly reduce points in a group based on user provided percentages
122 | var delPoints = new List();
123 | for (int i=0; i rnd.Next()).Take(count));
128 | }
129 |
130 | ///Create a Delaunay triangulated mesh
131 | delPoints.AddRange(nakedVerts);
132 | Mesh delMesh = DelaunayPoints(delPoints);
133 | delMesh.Faces.ConvertTrianglesToQuads(0, 0);
134 |
135 | DA.SetData(0, delMesh);
136 | }
137 |
138 |
139 | /// From https://discourse.mcneel.com/t/3d-delaunay/126194
140 | public Mesh DelaunayPoints(List pts)
141 | {
142 | //code from http://james-ramsden.com/create-2d-delaunay-triangulation-mesh-with-c-in-grasshopper/
143 |
144 | //convert point3d to node2
145 | //grasshopper requres that nodes are saved within a Node2List for Delaunay
146 | var nodes = new Node2List();
147 | for (int i = 0; i < pts.Count; i++)
148 | {
149 | //notice how we only read in the X and Y coordinates
150 | // this is why points should be mapped onto the XY plane
151 | nodes.Append(new Node2(pts[i].X, pts[i].Y));
152 | }
153 |
154 | //solve Delaunay
155 | var delMesh = new Mesh();
156 | var faces = new List();
157 |
158 | faces = Grasshopper.Kernel.Geometry.Delaunay.Solver.Solve_Faces(nodes, DocumentTolerance());
159 |
160 | //output
161 | delMesh = Grasshopper.Kernel.Geometry.Delaunay.Solver.Solve_Mesh(nodes, DocumentTolerance(), ref faces);
162 | for (int i = 0; i < pts.Count; i++)
163 | {
164 | delMesh.Vertices.SetVertex(i, pts[i]);
165 | }
166 |
167 | return delMesh;
168 | }
169 |
170 | ///
171 | /// Provides an Icon for the component.
172 | ///
173 | protected override System.Drawing.Bitmap Icon
174 | {
175 | get
176 | {
177 | //You can add image files to your project resources and access them like this:
178 | // return Resources.IconForThisComponent;
179 | return null;
180 | }
181 | }
182 |
183 | ///
184 | /// Gets the unique ID for this component. Do not change this ID after release.
185 | ///
186 | public override Guid ComponentGuid
187 | {
188 | get { return new Guid("0c6c5f78-9b7a-4e53-8d3c-4e8f6c1c2632"); }
189 | }
190 | }
191 | }
--------------------------------------------------------------------------------
/Heron/Components/Utilities/GdalDetails.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Reflection;
6 | using System.Runtime.InteropServices;
7 | using Gdal = OSGeo.GDAL.Gdal;
8 | using Ogr = OSGeo.OGR.Ogr;
9 | using System.Linq;
10 |
11 | using Grasshopper;
12 | using Grasshopper.Kernel;
13 | using Rhino.Geometry;
14 |
15 | namespace Heron
16 | {
17 | public class GdalDetails : HeronComponent
18 | {
19 | ///
20 | /// Each implementation of GH_Component must provide a public
21 | /// constructor without any arguments.
22 | /// Category represents the Tab in which the component will appear,
23 | /// Subcategory the panel. If you use non-existing tab or panel names,
24 | /// new tabs/panels will automatically be created.
25 | ///
26 | public GdalDetails()
27 | : base("GDAL Details", "GD",
28 | "This component enumerates the current version of GDAL and it's available raster and vector drivers.",
29 | "Utilities")
30 | {
31 | }
32 |
33 | ///
34 | /// Registers all the input parameters for this component.
35 | ///
36 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
37 | {
38 | }
39 |
40 | ///
41 | /// Registers all the output parameters for this component.
42 | ///
43 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
44 | {
45 | pManager.AddTextParameter("D", "GDAL Details", "", GH_ParamAccess.list);
46 | }
47 |
48 | ///
49 | /// This is the method that actually does the work.
50 | ///
51 | /// The DA object can be used to retrieve data from input parameters and
52 | /// to store data in output parameters.
53 | protected override void SolveInstance(IGH_DataAccess DA)
54 | {
55 | var info = new List();
56 |
57 | Heron.GdalConfiguration.ConfigureGdal();
58 | Heron.GdalConfiguration.ConfigureOgr();
59 |
60 | string gdalVersion = Gdal.VersionInfo("");
61 | info.Add("Gdal Version: " + gdalVersion);
62 |
63 | //string heronVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
64 | info.Add("Heron Version: " + HeronVersion.AssemblyFileVer);
65 | //string executingAssemblyFileMac = new Uri(Assembly.GetExecutingAssembly().GetName().CodeBase).LocalPath;
66 |
67 |
68 | //string executingDirectory = Path.GetDirectoryName(executingAssemblyFileMac);
69 | string executingDirectory = HeronLocation.GetHeronFolder();
70 | info.Add("Heron Location: " + executingDirectory);
71 |
72 | string osxPlatform = "";
73 | var arch = RuntimeInformation.ProcessArchitecture;
74 | var isOSX = RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
75 | if (arch == Architecture.X64 && isOSX == true) { osxPlatform = "osx-64"; }
76 | if (arch == Architecture.Arm64 && isOSX == true) { osxPlatform = "osx-Arm64"; }
77 |
78 | string gdalPath = Path.Combine(executingDirectory, "gdal");
79 | string nativePath = Path.Combine(gdalPath, osxPlatform);
80 |
81 | //info.Add("Gdal Path: " + gdalPath);
82 | //info.Add(nativePath);
83 |
84 | string envGdalDriverPath = Environment.GetEnvironmentVariable("GDAL_DRIVER_PATH");
85 | //info.Add("GDAL Driver Path: " + envGdalDriverPath);
86 |
87 | ///Add Gdal driver info
88 | Gdal.AllRegister();
89 | var driverCount = Gdal.GetDriverCount();
90 | List gdrivers = new List();
91 | info.Add("----------");
92 | info.Add("GDAL drivers (" + driverCount + "):");
93 |
94 | for (int drv = 0; drv < Gdal.GetDriverCount(); drv++)
95 | {
96 | gdrivers.Add(Gdal.GetDriver(drv).ShortName + " (" + Gdal.GetDriver(drv).LongName + ")");
97 | }
98 | gdrivers.Sort();
99 | info.AddRange(gdrivers);
100 |
101 | ///Add Ogr driver info
102 | Ogr.RegisterAll();
103 | var ogrDriverCount = Ogr.GetDriverCount();
104 | List odrivers = new List();
105 | info.Add("----------");
106 | info.Add("OGR drivers (" + ogrDriverCount + ") :");
107 | for (int odrv = 0; odrv < Ogr.GetDriverCount(); odrv++)
108 | {
109 | odrivers.Add(Ogr.GetDriver(odrv).GetName());
110 | }
111 | odrivers.Sort();
112 | info.AddRange(odrivers);
113 |
114 | ///Get Environment Variables for troublshooting
115 | var d = Environment.GetEnvironmentVariables();
116 | List ks = Environment.GetEnvironmentVariables().Keys.OfType().ToList();
117 | ks.Sort();
118 | //info.Add("----------");
119 | //info.Add("Environment Variables:");
120 | foreach (var key in ks)
121 | {
122 | string k = key;
123 | string v = (string)d[key];
124 | //info.Add(k + " : " + v);
125 | }
126 |
127 |
128 | DA.SetDataList(0, info);
129 | }
130 |
131 | ///
132 | /// Provides an Icon for every component that will be visible in the User Interface.
133 | /// Icons need to be 24x24 pixels.
134 | ///
135 | protected override System.Drawing.Bitmap Icon
136 | {
137 | get
138 | {
139 | // You can add image files to your project resources and access them like this:
140 | //return Resources.IconForThisComponent;
141 | return Properties.Resources.heron_favicon;
142 | }
143 | }
144 |
145 | ///
146 | /// Each component must have a unique Guid to identify it.
147 | /// It is vital this Guid doesn't change otherwise old ghx files
148 | /// that use the old ID will partially fail during loading.
149 | ///
150 | public override Guid ComponentGuid
151 | {
152 | get { return new Guid("bf25d013-6042-4b5d-a20f-8ba37c96a24c"); }
153 | }
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/Heron/Components/Utilities/HexToColor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Text.RegularExpressions;
5 | using Grasshopper.Kernel;
6 | using Rhino.Geometry;
7 |
8 | namespace Heron
9 | {
10 | public class HexToColor : HeronComponent
11 | {
12 | ///
13 | /// Initializes a new instance of the ColorToHex class.
14 | ///
15 | public HexToColor()
16 | : base("Hex to Color", "H2C", "Convert a hexidecimal color to RGBA format.", "Utilities")
17 | {
18 | }
19 | public override Grasshopper.Kernel.GH_Exposure Exposure
20 | {
21 | get { return GH_Exposure.quarternary; }
22 | }
23 |
24 |
25 | ///
26 | /// Registers all the input parameters for this component.
27 | ///
28 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
29 | {
30 | pManager.AddTextParameter("colorHexidecmial", "colorHex", "Hexidecimal color converted from RGBA", GH_ParamAccess.item);
31 | }
32 |
33 | ///
34 | /// Registers all the output parameters for this component.
35 | ///
36 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
37 | {
38 | pManager.AddColourParameter("colorRGBA", "colorRGBA", "RGBA color to convert to hexidecimal format", GH_ParamAccess.item);
39 |
40 | }
41 |
42 | ///
43 | /// This is the method that actually does the work.
44 | ///
45 | /// The DA object is used to retrieve from inputs and store in outputs.
46 | protected override void SolveInstance(IGH_DataAccess DA)
47 | {
48 | //Color color = Color.Empty;
49 | string hex = string.Empty;
50 | DA.GetData(0, ref hex);
51 | //string hex = String.Format("#{0:X2}{1:X2}{2:X2}{3:X2}", color.R, color.G, color.B, color.A);
52 | Regex reg = new Regex("^#(?:[0-9a-fA-F]{3,4}){1,2}$");
53 |
54 | if (!reg.IsMatch(hex))
55 | {
56 | AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "colorHex input string is not in a hexidecimal format.");
57 | return;
58 | }
59 |
60 | ///Parsing hex string from Stack Overflow
61 | ///https://stackoverflow.com/questions/2109756/how-do-i-get-the-color-from-a-hexadecimal-color-code-using-net?rq=1
62 |
63 | hex = hex.TrimStart('#');
64 |
65 | Color color;
66 | if (hex.Length == 6)
67 | color = Color.FromArgb(255, // hardcoded opaque
68 | int.Parse(hex.Substring(0, 2), System.Globalization.NumberStyles.HexNumber),
69 | int.Parse(hex.Substring(2, 2), System.Globalization.NumberStyles.HexNumber),
70 | int.Parse(hex.Substring(4, 2), System.Globalization.NumberStyles.HexNumber));
71 | else
72 | color = Color.FromArgb(
73 | int.Parse(hex.Substring(6, 2), System.Globalization.NumberStyles.HexNumber),
74 | int.Parse(hex.Substring(0, 2), System.Globalization.NumberStyles.HexNumber),
75 | int.Parse(hex.Substring(2, 2), System.Globalization.NumberStyles.HexNumber),
76 | int.Parse(hex.Substring(4, 2), System.Globalization.NumberStyles.HexNumber));
77 |
78 | DA.SetData(0, color);
79 | }
80 |
81 | ///
82 | /// Provides an Icon for the component.
83 | ///
84 | protected override System.Drawing.Bitmap Icon
85 | {
86 | get
87 | {
88 | //You can add image files to your project resources and access them like this:
89 | // return Resources.IconForThisComponent;
90 | return Properties.Resources.raster;
91 | }
92 | }
93 |
94 | ///
95 | /// Gets the unique ID for this component. Do not change this ID after release.
96 | ///
97 | public override Guid ComponentGuid
98 | {
99 | get { return new Guid("190F4F13-49C0-41F9-88BA-B13D2317F4BD"); }
100 | }
101 | }
102 | }
--------------------------------------------------------------------------------
/Heron/Components/Utilities/ImageFilterColors.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 | using System.Drawing;
5 | using System.Linq;
6 |
7 | using Grasshopper.Kernel;
8 | using Grasshopper.Kernel.Data;
9 | using Grasshopper.Kernel.Types;
10 | using GH_IO.Serialization;
11 |
12 | using Rhino;
13 | using Rhino.Geometry;
14 |
15 | namespace Heron
16 | {
17 | public class ImageFilterColors : GH_TaskCapableComponent
18 | {
19 | ///parallel processing based on code from https://github.com/mcneel/rhino-developer-samples/blob/6/grasshopper/cs/SampleGhTaskCapable/Components/SampleGhTaskCapableComponent.cs
20 | ///no need to worry about data trees, concurrent dictionaries or max concurrency, gh takes care of it!
21 | ///just think of what inputs you need per branch
22 |
23 | ///
24 | /// Initializes a new instance of the ImageColors class.
25 | ///
26 | public ImageFilterColors()
27 | : base("Image Filtered Colors", "ImageFC",
28 | "Get a filtered pixel count of colors contained in an image based on color list.",
29 | "Heron", "Utilities")
30 | {
31 | }
32 |
33 | ///
34 | /// Registers all the input parameters for this component.
35 | ///
36 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
37 | {
38 | pManager.AddTextParameter("Image File Location", "fileLoc", "File location(s) of the image(s).", GH_ParamAccess.item);
39 | pManager.AddColourParameter("Color Filter", "colors", "Filter the image for specific colors. If no filter colors are provided, all colors in the image will be included.", GH_ParamAccess.list);
40 | pManager[1].Optional = true;
41 | }
42 |
43 | ///
44 | /// Registers all the output parameters for this component.
45 | ///
46 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
47 | {
48 | pManager.AddIntegerParameter("Pixel Count", "PC", "Number of pixels in the image.", GH_ParamAccess.item);
49 | pManager.AddColourParameter("Top Colors", "TC", "Sorted list of colors in image.", GH_ParamAccess.list);
50 | pManager.AddPointParameter("Color Coordinates", "CC", "Coordinates of pixels in image of color.", GH_ParamAccess.tree);
51 | //pManager.AddPointParameter("Color Location", "CL", "Pixel locations grouped by color.", GH_ParamAccess.tree);
52 | }
53 |
54 | public class SolveResults
55 | {
56 | public GH_Integer PixCount { get; set; }
57 | public List TopColors { get; set; }
58 | public GH_Structure ColorLocation { get; set; }
59 | }
60 |
61 | SolveResults Compute (string fileLoc, List colors, int tskId)
62 | {
63 | var rc = new SolveResults();
64 | bool filterColors = colors.Any();
65 |
66 | List topCols = new List();
67 | List colCount = new List();
68 | GH_Structure colLocation = new GH_Structure();
69 |
70 |
71 | try
72 | {
73 | using (Bitmap bitmap = new Bitmap(fileLoc))
74 | {
75 | GH_Integer pixCount = new GH_Integer();
76 | GH_Convert.ToGHInteger(bitmap.Height * bitmap.Width,0,ref pixCount);
77 | rc.PixCount = pixCount;
78 |
79 | ///https://www.grasshopper3d.com/forum/topics/unsafe?page=1&commentId=2985220%3AComment%3A808291&x=1#2985220Comment808291
80 | GH_MemoryBitmap sampler = new GH_MemoryBitmap(bitmap);
81 |
82 | Color col = Color.Transparent;
83 | for (int x = 0; x < bitmap.Width; x++)
84 | {
85 | for (int y = 0; y < bitmap.Height; y++)
86 | {
87 | ///GH_MemoryBitmap Sample is faster than GetPixel
88 | //col = bitmap.GetPixel(x, y);
89 | if (sampler.Sample(x,y,ref col))
90 | {
91 | if (colors.Contains(col))
92 | {
93 | GH_Path path = new GH_Path(tskId, colors.IndexOf(col));
94 | colLocation.Append(new GH_Point(new Point3d(x,y,0)), path);
95 | }
96 | else if (!filterColors)
97 | {
98 | colors.Add(col);
99 | GH_Path path = new GH_Path(tskId, colors.IndexOf(col));
100 | colLocation.Append(new GH_Point(new Point3d(x, y, 0)), path);
101 | }
102 |
103 | }
104 |
105 | }
106 | }
107 |
108 | sampler.Release(false);
109 | bitmap.Dispose();
110 | }
111 |
112 | }
113 |
114 | catch
115 | {
116 | AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Could not load image from file path: "+fileLoc);
117 | }
118 |
119 | List ghColors = new List();
120 | foreach (var c in colors)
121 | {
122 | ghColors.Add(new GH_Colour(c));
123 | }
124 |
125 | rc.TopColors = ghColors;
126 | rc.ColorLocation = colLocation;
127 |
128 | return rc;
129 |
130 | }
131 |
132 | ///
133 | /// This is the method that actually does the work.
134 | ///
135 | /// The DA object is used to retrieve from inputs and store in outputs.
136 | protected override void SolveInstance(IGH_DataAccess DA)
137 | {
138 | if (InPreSolve)
139 | {
140 | ///First pass; collect data and construct tasks
141 | ///
142 | string fileLocList = "";
143 | List colors = new List();
144 | Task tsk = null;
145 |
146 | if(DA.GetData(0,ref fileLocList))
147 | {
148 | DA.GetDataList(1, colors);
149 | tsk = Task.Run(() => Compute(fileLocList, colors, tsk.Id), CancelToken);
150 | }
151 |
152 | ///Add a null task even if data collection fails. This keeps the list size in sync with the iterations
153 | TaskList.Add(tsk);
154 | return;
155 | }
156 |
157 | if(!GetSolveResults(DA, out var results))
158 | {
159 | ///Compute right here, right now.
160 | ///1. Collect
161 | ///
162 | string fileLocList = "";
163 | List colors = new List();
164 | int tskId = 0;
165 |
166 | if (!DA.GetData(0, ref fileLocList)) { return; }
167 | if(!DA.GetDataList(1, colors)) { return; }
168 |
169 | ///2. Compute
170 | ///
171 | results = Compute(fileLocList, colors, tskId);
172 | }
173 |
174 | ///3. Set
175 | ///
176 | if (results != null)
177 | {
178 | DA.SetData(0, results.PixCount);
179 | DA.SetDataList(1, results.TopColors);
180 | DA.SetDataTree(2, results.ColorLocation);
181 | //DA.SetDataTree(3, results.ColorLocation);
182 | }
183 | }
184 |
185 | ///
186 | /// Provides an Icon for the component.
187 | ///
188 | protected override System.Drawing.Bitmap Icon
189 | {
190 | get
191 | {
192 | //You can add image files to your project resources and access them like this:
193 | // return Resources.IconForThisComponent;
194 | return Properties.Resources.raster;
195 | }
196 | }
197 |
198 | ///
199 | /// Gets the unique ID for this component. Do not change this ID after release.
200 | ///
201 | public override Guid ComponentGuid
202 | {
203 | get { return new Guid("DB0FE3BC-2471-45C3-BAAC-4BC0C83CB654"); }
204 | }
205 | }
206 | }
--------------------------------------------------------------------------------
/Heron/Components/Utilities/ImageFlip.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Drawing.Imaging;
5 | using System.IO;
6 | using System.Windows.Forms;
7 |
8 | using Grasshopper.Kernel;
9 | using GH_IO.Serialization;
10 | using Rhino.Geometry;
11 |
12 | namespace Heron
13 | {
14 | public class ImageFlip : HeronComponent
15 | {
16 | ///
17 | /// Initializes a new instance of the FlipImage class.
18 | ///
19 | public ImageFlip()
20 | : base("Flip Image", "FlipImage", "Flip an image along its vertical, horizontal axis or both.",
21 | "Utilities")
22 | {
23 | }
24 |
25 | ///
26 | /// Registers all the input parameters for this component.
27 | ///
28 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
29 | {
30 | pManager.AddTextParameter("Original Image", "image", "File path for the image to be flipped.", GH_ParamAccess.item);
31 | pManager.AddTextParameter("Suffix", "suffix", "Suffix to add the end of the original image. If none is provided, a '_flipped' suffix will be added. " +
32 | "An existing flipped image path will be overwritten.", GH_ParamAccess.item, "_flipped");
33 | pManager.AddBooleanParameter("Run", "run", "Flip the image. An existing flipped image path will be overwritten.", GH_ParamAccess.item, false);
34 | pManager[1].Optional = true;
35 | Message = flipStatus;
36 |
37 | }
38 |
39 | ///
40 | /// Registers all the output parameters for this component.
41 | ///
42 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
43 | {
44 | pManager.AddTextParameter("Flipped Image", "flipped", "File path for the flipped image.", GH_ParamAccess.item);
45 | }
46 |
47 | ///
48 | /// This is the method that actually does the work.
49 | ///
50 | /// The DA object is used to retrieve from inputs and store in outputs.
51 | protected override void SolveInstance(IGH_DataAccess DA)
52 | {
53 | string originalPath = string.Empty;
54 | DA.GetData(0, ref originalPath);
55 | if (!File.Exists(originalPath)) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Cannot find the original image."); }
56 | string fDir = Path.GetDirectoryName(originalPath);
57 | string fName = Path.GetFileNameWithoutExtension(originalPath);
58 | string fExt = Path.GetExtension(originalPath);
59 |
60 | string suffix = string.Empty;
61 | DA.GetData(1, ref suffix);
62 |
63 | string fOut = Path.Combine(fDir, fName + suffix + fExt);
64 | if (!File.Exists(fOut)) { fOut = string.Empty; }
65 |
66 | bool run = false;
67 | DA.GetData("Run", ref run);
68 |
69 | Bitmap originalBitmap = new Bitmap(originalPath, true);
70 | ImageFormat imgFormat = originalBitmap.RawFormat;
71 |
72 | if (run)
73 | {
74 | Bitmap finalImage = new Bitmap(originalBitmap);
75 | originalBitmap.Dispose();
76 |
77 | fOut = Path.Combine(fDir, fName + suffix + fExt);
78 | if (File.Exists(fOut)) { File.Delete(fOut); }
79 |
80 | switch (flipStatus)
81 | {
82 | case "None":
83 | break;
84 | case "Flip X":
85 | finalImage.RotateFlip(RotateFlipType.RotateNoneFlipX);
86 | break;
87 | case "Flip Y":
88 | finalImage.RotateFlip(RotateFlipType.RotateNoneFlipY);
89 | break;
90 | case "Flip X and Y":
91 | finalImage.RotateFlip(RotateFlipType.RotateNoneFlipXY);
92 | break;
93 | }
94 |
95 | finalImage.Save(fOut, imgFormat);
96 | finalImage.Dispose();
97 | }
98 |
99 | DA.SetData(0, fOut);
100 |
101 | }
102 |
103 |
104 | ////////////////////////////
105 | //Menu Items
106 |
107 | private bool IsFlipSelected(string flipString)
108 | {
109 | return flipString.Equals(flipStatus);
110 | }
111 | protected override void AppendAdditionalComponentMenuItems(ToolStripDropDown menu)
112 | {
113 | ToolStripMenuItem fN = new ToolStripMenuItem("No Flip");
114 | fN.Tag = "No Flip";
115 | fN.Checked = IsFlipSelected("No Flip");
116 | fN.ToolTipText = "Do not flip the image";
117 | fN.Click += FlipItemOnClick;
118 | menu.Items.Add(fN);
119 |
120 | ToolStripMenuItem fX = new ToolStripMenuItem("Flip X");
121 | fX.Tag = "Flip X";
122 | fX.Checked = IsFlipSelected("Flip X");
123 | fX.ToolTipText = "Flip image along its vertical axis (left becomes right).";
124 | fX.Click += FlipItemOnClick;
125 | menu.Items.Add(fX);
126 |
127 | ToolStripMenuItem fY = new ToolStripMenuItem("Flip Y");
128 | fY.Tag = "Flip Y";
129 | fY.Checked = IsFlipSelected("Flip Y");
130 | fY.ToolTipText = "Flip image along its horizontal axis (top becomes bottom).";
131 | fY.Click += FlipItemOnClick;
132 | menu.Items.Add(fY);
133 |
134 | ToolStripMenuItem fXY = new ToolStripMenuItem("Flip X and Y");
135 | fXY.Tag = "Flip X and Y";
136 | fXY.Checked = IsFlipSelected("Flip X and Y");
137 | fXY.ToolTipText = "Flip image along both X and Y axises.";
138 | fXY.Click += FlipItemOnClick;
139 | menu.Items.Add(fXY);
140 |
141 | base.AppendAdditionalComponentMenuItems(menu);
142 | }
143 |
144 | private void FlipItemOnClick(object sender, EventArgs e)
145 | {
146 | ToolStripMenuItem item = sender as ToolStripMenuItem;
147 | if (item == null)
148 | return;
149 |
150 | string code = (string)item.Tag;
151 | if (IsFlipSelected(code))
152 | return;
153 |
154 | RecordUndoEvent("FlipStatus");
155 |
156 | flipStatus = code;
157 | Message = flipStatus;
158 |
159 | ExpireSolution(true);
160 | }
161 |
162 | ////////////////////////////
163 | //Sticky Parameters
164 |
165 | private string flipStatus = "Flip Y";
166 |
167 | public string FlipStatus
168 | {
169 | get { return flipStatus; }
170 | set
171 | {
172 | flipStatus = value;
173 | Message = flipStatus;
174 | }
175 | }
176 |
177 | public override bool Write (GH_IWriter writer)
178 | {
179 | writer.SetString("FlipStatus", FlipStatus);
180 | return base.Write(writer);
181 | }
182 |
183 | public override bool Read(GH_IReader reader)
184 | {
185 | FlipStatus = reader.GetString("FlipStatus");
186 | return base.Read(reader);
187 | }
188 |
189 | ///
190 | /// Provides an Icon for the component.
191 | ///
192 | protected override System.Drawing.Bitmap Icon
193 | {
194 | get
195 | {
196 | return Properties.Resources.raster;
197 | }
198 | }
199 |
200 | ///
201 | /// Gets the unique ID for this component. Do not change this ID after release.
202 | ///
203 | public override Guid ComponentGuid
204 | {
205 | get { return new Guid("f1e9c8ad-2500-48de-9692-54e7d6f6379d"); }
206 | }
207 | }
208 | }
--------------------------------------------------------------------------------
/Heron/Components/Utilities/ImageRotate.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Drawing.Imaging;
5 | using System.IO;
6 | using System.Windows.Forms;
7 |
8 | using Grasshopper.Kernel;
9 | using GH_IO.Serialization;
10 | using Rhino.Geometry;
11 |
12 | namespace Heron
13 | {
14 | public class ImageRotate : HeronComponent
15 | {
16 | ///
17 | /// Initializes a new instance of the FlipImage class.
18 | ///
19 | public ImageRotate()
20 | : base("Rotate Image", "RotateImage", "Roate an image 90, 180 or 270 degrees.",
21 | "Utilities")
22 | {
23 | }
24 |
25 | ///
26 | /// Registers all the input parameters for this component.
27 | ///
28 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
29 | {
30 | pManager.AddTextParameter("Original Image", "image", "File path for the image to be rotated.", GH_ParamAccess.item);
31 | pManager.AddTextParameter("Suffix", "suffix", "Suffix to add the end of the original image. If none is provided, a '_rotated' suffix will be added. " +
32 | "An existing flipped image path will be overwritten.", GH_ParamAccess.item, "_rotated");
33 | pManager.AddBooleanParameter("Run", "run", "Rotate the image. An existing rotated image path will be overwritten.", GH_ParamAccess.item, false);
34 | pManager[1].Optional = true;
35 | Message = rotateStatus;
36 |
37 | }
38 |
39 | ///
40 | /// Registers all the output parameters for this component.
41 | ///
42 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
43 | {
44 | pManager.AddTextParameter("Rotated Image", "rotated", "File path for the rotated image.", GH_ParamAccess.item);
45 | }
46 |
47 | ///
48 | /// This is the method that actually does the work.
49 | ///
50 | /// The DA object is used to retrieve from inputs and store in outputs.
51 | protected override void SolveInstance(IGH_DataAccess DA)
52 | {
53 | string originalPath = string.Empty;
54 | DA.GetData(0, ref originalPath);
55 | if (!File.Exists(originalPath)) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Cannot find the original image."); }
56 | string fDir = Path.GetDirectoryName(originalPath);
57 | string fName = Path.GetFileNameWithoutExtension(originalPath);
58 | string fExt = Path.GetExtension(originalPath);
59 |
60 | string suffix = string.Empty;
61 | DA.GetData(1, ref suffix);
62 |
63 | string fOut = Path.Combine(fDir, fName + suffix + fExt);
64 | if (!File.Exists(fOut)) { fOut = string.Empty; }
65 |
66 | bool run = false;
67 | DA.GetData("Run", ref run);
68 |
69 | Bitmap originalBitmap = new Bitmap(originalPath, true);
70 | ImageFormat imgFormat = originalBitmap.RawFormat;
71 |
72 | if (run)
73 | {
74 | Bitmap finalImage = new Bitmap(originalBitmap);
75 | originalBitmap.Dispose();
76 |
77 | fOut = Path.Combine(fDir, fName + suffix + fExt);
78 | if (File.Exists(fOut)) { File.Delete(fOut); }
79 |
80 | switch (rotateStatus)
81 | {
82 | case "None":
83 | break;
84 | case "Rotate 90":
85 | finalImage.RotateFlip(RotateFlipType.Rotate90FlipNone);
86 | break;
87 | case "Rotate 180":
88 | finalImage.RotateFlip(RotateFlipType.Rotate180FlipNone);
89 | break;
90 | case "Rotate 270":
91 | finalImage.RotateFlip(RotateFlipType.Rotate270FlipNone);
92 | break;
93 | }
94 |
95 | finalImage.Save(fOut, imgFormat);
96 | finalImage.Dispose();
97 | }
98 |
99 | DA.SetData(0, fOut);
100 |
101 | }
102 |
103 |
104 | ////////////////////////////
105 | //Menu Items
106 |
107 | private bool IsFlipSelected(string rotateString)
108 | {
109 | return rotateString.Equals(rotateStatus);
110 | }
111 | protected override void AppendAdditionalComponentMenuItems(ToolStripDropDown menu)
112 | {
113 | ToolStripMenuItem sN = new ToolStripMenuItem("No Rotation");
114 | sN.Tag = "No Rotation";
115 | sN.Checked = IsFlipSelected("No Rotation");
116 | sN.ToolTipText = "Do not rotate the image";
117 | sN.Click += FlipItemOnClick;
118 | menu.Items.Add(sN);
119 |
120 | ToolStripMenuItem s90 = new ToolStripMenuItem("Rotate 90");
121 | s90.Tag = "Rotate 90";
122 | s90.Checked = IsFlipSelected("Rotate 90");
123 | s90.ToolTipText = "Rotate image 90 deg clockwise.";
124 | s90.Click += FlipItemOnClick;
125 | menu.Items.Add(s90);
126 |
127 | ToolStripMenuItem s180 = new ToolStripMenuItem("Rotate 180");
128 | s180.Tag = "Rotate 180";
129 | s180.Checked = IsFlipSelected("Rotate 180");
130 | s180.ToolTipText = "Rotate image 180 deg clockwise.";
131 | s180.Click += FlipItemOnClick;
132 | menu.Items.Add(s180);
133 |
134 | ToolStripMenuItem s270 = new ToolStripMenuItem("Rotate 270");
135 | s270.Tag = "Rotate 270";
136 | s270.Checked = IsFlipSelected("Rotate 270");
137 | s270.ToolTipText = "Rotate image 270 deg clockwise.";
138 | s270.Click += FlipItemOnClick;
139 | menu.Items.Add(s270);
140 |
141 | base.AppendAdditionalComponentMenuItems(menu);
142 | }
143 |
144 | private void FlipItemOnClick(object sender, EventArgs e)
145 | {
146 | ToolStripMenuItem item = sender as ToolStripMenuItem;
147 | if (item == null)
148 | return;
149 |
150 | string code = (string)item.Tag;
151 | if (IsFlipSelected(code))
152 | return;
153 |
154 | RecordUndoEvent("rotateStatus");
155 |
156 | rotateStatus = code;
157 | Message = rotateStatus;
158 |
159 | ExpireSolution(true);
160 | }
161 |
162 | ////////////////////////////
163 | //Sticky Parameters
164 |
165 | private string rotateStatus = "Rotate 270";
166 |
167 | public string RotateStatus
168 | {
169 | get { return rotateStatus; }
170 | set
171 | {
172 | rotateStatus = value;
173 | Message = rotateStatus;
174 | }
175 | }
176 |
177 | public override bool Write (GH_IWriter writer)
178 | {
179 | writer.SetString("rotateStatus", rotateStatus);
180 | return base.Write(writer);
181 | }
182 |
183 | public override bool Read(GH_IReader reader)
184 | {
185 | rotateStatus = reader.GetString("rotateStatus");
186 | return base.Read(reader);
187 | }
188 |
189 | ///
190 | /// Provides an Icon for the component.
191 | ///
192 | protected override System.Drawing.Bitmap Icon
193 | {
194 | get
195 | {
196 | return Properties.Resources.raster;
197 | }
198 | }
199 |
200 | ///
201 | /// Gets the unique ID for this component. Do not change this ID after release.
202 | ///
203 | public override Guid ComponentGuid
204 | {
205 | get { return new Guid("AA4281C3-74E4-46A8-A37D-F095F9EC1570"); }
206 | }
207 | }
208 | }
--------------------------------------------------------------------------------
/Heron/Components/Utilities/TopiaryFlatten.cs:
--------------------------------------------------------------------------------
1 | using Grasshopper.Kernel;
2 | using Grasshopper.Kernel.Data;
3 | using Grasshopper.Kernel.Types;
4 | using Rhino.Geometry;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 |
9 | namespace Heron
10 | {
11 | public class TopiaryFlatten : HeronComponent
12 | {
13 |
14 | public TopiaryFlatten()
15 | : base("Topiary Flatten", "TF", "Flatten branches by a set depth from the deepest path in a data tree. " +
16 | "The resulting tree will look more like a topiary. This can be useful for data trees with uneven path depths.", "Utilities")
17 | {
18 | }
19 |
20 | ///
21 | /// Registers all the input parameters for this component.
22 | ///
23 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
24 | {
25 | pManager.AddGenericParameter("Data Tree", "DT", "Data tree to flatten to a topiary.", GH_ParamAccess.tree);
26 | pManager.AddIntegerParameter("Number of Branches", "N", "The number of branches to merge from the deepest path branch count. " +
27 | "For instance, if N=2 and the path with the most branches is 4, any path in the tree with a depth greater than 2 will be flattened up into 2.", GH_ParamAccess.item);
28 | }
29 |
30 | ///
31 | /// Registers all the output parameters for this component.
32 | ///
33 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
34 | {
35 | pManager.AddGenericParameter("Pruned Tree", "PT", "Pruned tree.", GH_ParamAccess.tree);
36 | }
37 |
38 | ///
39 | /// This is the method that actually does the work.
40 | ///
41 | /// The DA object is used to retrieve from inputs and store in outputs.
42 | protected override void SolveInstance(IGH_DataAccess DA)
43 | {
44 | GH_Structure treeIn = new GH_Structure();
45 | DA.GetDataTree(0, out treeIn);
46 |
47 | int pruneDepth = 0;
48 | DA.GetData(1, ref pruneDepth);
49 |
50 | GH_Structure treeOut = new GH_Structure();
51 |
52 | ///Create list of path strings
53 | var pathStrings = treeIn.Paths.Select(x => x.ToString());
54 | ///Find the deepest path in the tree
55 | var maxDepthPath = pathStrings.Aggregate((max, cur) => max.Split(';').Length > cur.Split(';').Length ? max : cur);
56 | ///Get number of branches for deepest path
57 | var maxDepthInt = maxDepthPath.Split(';').Length;
58 |
59 | foreach (var path in treeIn.Paths)
60 | {
61 | ///Determine number of branches to prune if any
62 | GH_Path.SplitPathLikeString(path.ToString(), out string[] path_segments, out string index_segment);
63 | var numBranchesToRemove = path_segments.Length - (maxDepthInt - pruneDepth);
64 |
65 | var newPath = path;
66 |
67 | if (numBranchesToRemove > 0 && maxDepthInt - pruneDepth > 0)
68 | {
69 | ///Remove pruned branches from path string
70 | path_segments = path_segments.Take(path_segments.Count() - numBranchesToRemove).ToArray();
71 | int[] path_args = path_segments.Select(int.Parse).ToArray();
72 |
73 | newPath = new GH_Path(path_args);
74 | }
75 |
76 | treeOut.AppendRange(treeIn[path],newPath);
77 | }
78 |
79 | DA.SetDataTree(0, treeOut);
80 | }
81 |
82 |
83 | ///
84 | /// Provides an Icon for the component.
85 | ///
86 | protected override System.Drawing.Bitmap Icon
87 | {
88 | get
89 | {
90 | return Properties.Resources.shp;
91 | }
92 | }
93 |
94 | ///
95 | /// Gets the unique ID for this component. Do not change this ID after release.
96 | ///
97 | public override Guid ComponentGuid
98 | {
99 | get { return new Guid("a3499421-1bcb-4877-9c68-4afca606c3f7"); }
100 | }
101 | }
102 | }
--------------------------------------------------------------------------------
/Heron/HeronBoxPreviewComponent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Grasshopper.Kernel;
8 | using Rhino.Display;
9 | using Rhino.DocObjects;
10 | using Rhino.Geometry;
11 | using Rhino.Render;
12 |
13 | namespace Heron
14 | {
15 | internal struct HeronBoxPreviewItem
16 | {
17 | public BoundingBox bbox;
18 | public PointCloud pointCloud;
19 | public double radius;
20 | }
21 |
22 | public abstract class HeronBoxPreviewComponent : HeronComponent
23 | {
24 | private List _previewItems;
25 | private BoundingBox _box;
26 |
27 | public HeronBoxPreviewComponent(string name, string nickName, string description, string subCategory) : base(name, nickName, description, subCategory)
28 | {
29 | _previewItems = new List();
30 | }
31 |
32 | protected override void BeforeSolveInstance()
33 | {
34 | _previewItems.Clear();
35 | }
36 |
37 | public override bool IsPreviewCapable => true;
38 |
39 |
40 | internal void AddPreviewItem(BoundingBox bbox)
41 | {
42 | _previewItems.Add(new HeronBoxPreviewItem()
43 | {
44 | bbox = bbox
45 | });
46 | }
47 |
48 | internal void AddPreviewItem(PointCloud pointCloud, double radius)
49 | {
50 | _previewItems.Add(new HeronBoxPreviewItem()
51 | {
52 | pointCloud = pointCloud,
53 | radius = radius,
54 | });
55 | }
56 |
57 | public override void DrawViewportWires(IGH_PreviewArgs args)
58 | {
59 | foreach (var item in _previewItems)
60 | {
61 | if (item.bbox.IsValid) args.Display.DrawBox(item.bbox, Color.Red); //args.Display.DrawLines(item.bbox.GetEdges(), Color.Red);
62 | if (item.pointCloud != null) args.Display.DrawPointCloud(item.pointCloud, (float) item.radius);
63 | }
64 |
65 | base.DrawViewportWires(args);
66 | }
67 |
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/Heron/HeronComponent.cs:
--------------------------------------------------------------------------------
1 | using Grasshopper.Kernel;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 |
9 | namespace Heron
10 | {
11 | public abstract class HeronComponent : GH_Component
12 | {
13 | public HeronComponent(string name, string nickName, string description, string subCategory) : base(name, nickName, description, "Heron", subCategory)
14 | {
15 |
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Heron/HeronInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Grasshopper;
8 | using Grasshopper.Kernel;
9 |
10 | namespace Heron
11 | {
12 | public class HeronInfo : GH_AssemblyInfo
13 | {
14 | public override string Name
15 | {
16 | get
17 | {
18 | return "Heron";
19 | }
20 | }
21 | public override string AuthorName
22 | {
23 | get
24 | {
25 | return "Brian Washburn";
26 | }
27 | }
28 |
29 | public override string Version
30 | {
31 | get
32 | {
33 | return HeronVersion.AssemblyFileVer;
34 | }
35 | }
36 |
37 | public override string AuthorContact
38 | {
39 | get
40 | {
41 | return "blueheronGIS@gmail.com";
42 | }
43 | }
44 |
45 | public override Guid Id
46 | {
47 | get
48 | {
49 | return new System.Guid("{94830583-1656-43FB-8415-6FD290548DD1}");
50 | }
51 | }
52 |
53 | public override Bitmap Icon
54 | {
55 | get
56 | {
57 | return Properties.Resources.heron_favicon;
58 | }
59 | }
60 | }
61 |
62 | ///
63 | /// https://discourse.mcneel.com/t/add-a-custom-icon-image-to-grasshopper-plugin-tabs/61777/14
64 | ///
65 | public class HeronCategoryIcon : Grasshopper.Kernel.GH_AssemblyPriority
66 | {
67 | public override Grasshopper.Kernel.GH_LoadingInstruction PriorityLoad()
68 | {
69 | Grasshopper.Instances.ComponentServer.AddCategoryIcon("Heron", Properties.Resources.heron_favicon);
70 | Grasshopper.Instances.ComponentServer.AddCategorySymbolName("Heron", 'H');
71 | return Grasshopper.Kernel.GH_LoadingInstruction.Proceed;
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/Heron/HeronRasterPreviewComponent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Grasshopper.Kernel;
7 | using Rhino.Display;
8 | using Rhino.DocObjects;
9 | using Rhino.Geometry;
10 | using Rhino.Render;
11 |
12 | namespace Heron
13 | {
14 | internal struct HeronRasterPreviewItem
15 | {
16 | public DisplayMaterial mat;
17 | public Mesh mesh;
18 | }
19 |
20 | public abstract class HeronRasterPreviewComponent : HeronComponent
21 | {
22 | private List _previewItems;
23 | private BoundingBox _boundingBox;
24 | public HeronRasterPreviewComponent(string name, string nickName, string description, string subCategory) : base(name, nickName, description, subCategory)
25 | {
26 | _previewItems = new List();
27 | }
28 |
29 | protected override void BeforeSolveInstance()
30 | {
31 | _previewItems.Clear();
32 | _boundingBox = BoundingBox.Empty;
33 | }
34 |
35 | internal static Rectangle3d BBoxToRect(BoundingBox imageBox)
36 | {
37 | var xInterval = new Interval(imageBox.Min.X, imageBox.Max.X);
38 | var yInterval = new Interval(imageBox.Min.Y, imageBox.Max.Y);
39 | var rect = new Rectangle3d(Plane.WorldXY, xInterval, yInterval);
40 | return rect;
41 | }
42 |
43 | public override bool IsPreviewCapable => true;
44 |
45 | internal void AddPreviewItem(string bitmap, Rectangle3d rect)
46 | {
47 | AddPreviewItem(bitmap, rect.ToNurbsCurve(), rect);
48 | }
49 |
50 | internal void AddPreviewItem(string bitmap, Curve c, Rectangle3d rect)
51 | {
52 | var mesh = Mesh.CreateFromPlanarBoundary(c, MeshingParameters.FastRenderMesh, 0.1);
53 | TextureMapping tm = TextureMapping.CreatePlaneMapping(rect.Plane, rect.X, rect.Y, new Interval(-1, 1));
54 | mesh.SetTextureCoordinates(tm, Transform.Identity, true);
55 | var mat = new DisplayMaterial(System.Drawing.Color.White);
56 |
57 | ///Force bitmap to redraw
58 | //string docBitmapName = string.Empty;
59 | //var docBitmap = Rhino.RhinoDoc.ActiveDoc.Bitmaps.Find(bitmap, true, out docBitmapName);
60 | //mat.SetBitmapTexture(docBitmapName, true);
61 |
62 | mat.SetBitmapTexture(bitmap, true);
63 |
64 | _previewItems.Add(new HeronRasterPreviewItem()
65 | {
66 | mesh = mesh,
67 | mat = mat
68 | });
69 |
70 | ///Use Wait to refresh images
71 | ///https://discourse.mcneel.com/t/wish-list-set-bitmap-texture-from-memory-stream/105158/5
72 | ///https://mcneel.myjetbrains.com/youtrack/issue/RH-59416
73 | Rhino.RhinoApp.Wait();
74 | }
75 |
76 | public override void DrawViewportMeshes(IGH_PreviewArgs args)
77 | {
78 | foreach (var item in _previewItems)
79 | {
80 | args.Display.DrawMeshShaded(item.mesh, item.mat);
81 | }
82 | base.DrawViewportMeshes(args);
83 | }
84 |
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/Heron/HeronSRS.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Heron
8 | {
9 | ///
10 | /// https://discourse.mcneel.com/t/defining-plugin-wide-variables-for-grasshopper-plugin/67582/2
11 | ///
12 | public sealed class HeronSRS
13 | {
14 | private static HeronSRS _instance;
15 | private HeronSRS() { } // private constructor, should only access through Instance. Any necessary initialization here, too.
16 | public static HeronSRS Instance
17 | {
18 | get
19 | {
20 | if (_instance == null)
21 | _instance = new HeronSRS();
22 |
23 | return _instance;
24 | }
25 | }
26 |
27 | public string SRS { get; set; } = "WGS84"; // initialize to min value of int. Can use any valid value here. Or init in the private constructor.
28 | }
29 | }
--------------------------------------------------------------------------------
/Heron/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using Grasshopper.Kernel;
2 | using System.Reflection;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 |
6 | // General Information about an assembly is controlled through the following
7 | // set of attributes. Change these attribute values to modify the information
8 | // associated with an assembly.
9 | [assembly: AssemblyTitle("Heron")]
10 | [assembly: AssemblyDescription("")]
11 | [assembly: AssemblyConfiguration("")]
12 | [assembly: AssemblyCompany("")]
13 | [assembly: AssemblyProduct("Heron")]
14 | [assembly: AssemblyCopyright("Copyright © 2025")]
15 | [assembly: AssemblyTrademark("")]
16 | [assembly: AssemblyCulture("")]
17 |
18 | //[assembly: GH_Loading(GH_LoadingDemand.ForceDirect)]
19 |
20 | // Setting ComVisible to false makes the types in this assembly not visible
21 | // to COM components. If you need to access a type in this assembly from
22 | // COM, set the ComVisible attribute to true on that type.
23 | [assembly: ComVisible(false)]
24 |
25 | // The following GUID is for the ID of the typelib if this project is exposed to COM
26 | [assembly: Guid("ac46f274-cd33-445b-9347-1dd45a437f88")]
27 |
28 | // Version information for an assembly consists of the following four values:
29 | //
30 | // Major Version
31 | // Minor Version
32 | // Build Number
33 | // Revision
34 | //
35 | // You can specify all the values or you can default the Build and Revision Numbers
36 | // by using the '*' as shown below:
37 | // [assembly: AssemblyVersion("1.0.*")]
38 | [assembly: AssemblyVersion(Heron.HeronVersion.AssemblyVer)]
39 | [assembly: AssemblyFileVersion(Heron.HeronVersion.AssemblyFileVer)]
40 |
--------------------------------------------------------------------------------
/Heron/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace Heron.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Heron.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Looks up a localized resource of type System.Drawing.Bitmap.
65 | ///
66 | internal static System.Drawing.Bitmap ddtoxy {
67 | get {
68 | object obj = ResourceManager.GetObject("ddtoxy", resourceCulture);
69 | return ((System.Drawing.Bitmap)(obj));
70 | }
71 | }
72 |
73 | ///
74 | /// Looks up a localized resource of type System.Drawing.Bitmap.
75 | ///
76 | internal static System.Drawing.Bitmap Demo {
77 | get {
78 | object obj = ResourceManager.GetObject("Demo", resourceCulture);
79 | return ((System.Drawing.Bitmap)(obj));
80 | }
81 | }
82 |
83 | ///
84 | /// Looks up a localized resource of type System.Drawing.Bitmap.
85 | ///
86 | internal static System.Drawing.Bitmap eap {
87 | get {
88 | object obj = ResourceManager.GetObject("eap", resourceCulture);
89 | return ((System.Drawing.Bitmap)(obj));
90 | }
91 | }
92 |
93 | ///
94 | /// Looks up a localized resource of type System.Drawing.Bitmap.
95 | ///
96 | internal static System.Drawing.Bitmap geocode {
97 | get {
98 | object obj = ResourceManager.GetObject("geocode", resourceCulture);
99 | return ((System.Drawing.Bitmap)(obj));
100 | }
101 | }
102 |
103 | ///
104 | /// Looks up a localized resource of type System.Drawing.Bitmap.
105 | ///
106 | internal static System.Drawing.Bitmap heron_favicon {
107 | get {
108 | object obj = ResourceManager.GetObject("heron_favicon", resourceCulture);
109 | return ((System.Drawing.Bitmap)(obj));
110 | }
111 | }
112 |
113 | ///
114 | /// Looks up a localized resource of type System.Drawing.Bitmap.
115 | ///
116 | internal static System.Drawing.Bitmap heron_icon {
117 | get {
118 | object obj = ResourceManager.GetObject("heron_icon", resourceCulture);
119 | return ((System.Drawing.Bitmap)(obj));
120 | }
121 | }
122 |
123 | ///
124 | /// Looks up a localized resource of type System.Byte[].
125 | ///
126 | internal static byte[] HeronServiceEndpoints {
127 | get {
128 | object obj = ResourceManager.GetObject("HeronServiceEndpoints", resourceCulture);
129 | return ((byte[])(obj));
130 | }
131 | }
132 |
133 | ///
134 | /// Looks up a localized resource of type System.Drawing.Bitmap.
135 | ///
136 | internal static System.Drawing.Bitmap img {
137 | get {
138 | object obj = ResourceManager.GetObject("img", resourceCulture);
139 | return ((System.Drawing.Bitmap)(obj));
140 | }
141 | }
142 |
143 | ///
144 | /// Looks up a localized resource of type System.Drawing.Bitmap.
145 | ///
146 | internal static System.Drawing.Bitmap layer {
147 | get {
148 | object obj = ResourceManager.GetObject("layer", resourceCulture);
149 | return ((System.Drawing.Bitmap)(obj));
150 | }
151 | }
152 |
153 | ///
154 | /// Looks up a localized resource of type System.Drawing.Bitmap.
155 | ///
156 | internal static System.Drawing.Bitmap raster {
157 | get {
158 | object obj = ResourceManager.GetObject("raster", resourceCulture);
159 | return ((System.Drawing.Bitmap)(obj));
160 | }
161 | }
162 |
163 | ///
164 | /// Looks up a localized resource of type System.Drawing.Bitmap.
165 | ///
166 | internal static System.Drawing.Bitmap revgeocode {
167 | get {
168 | object obj = ResourceManager.GetObject("revgeocode", resourceCulture);
169 | return ((System.Drawing.Bitmap)(obj));
170 | }
171 | }
172 |
173 | ///
174 | /// Looks up a localized resource of type System.Drawing.Bitmap.
175 | ///
176 | internal static System.Drawing.Bitmap shp {
177 | get {
178 | object obj = ResourceManager.GetObject("shp", resourceCulture);
179 | return ((System.Drawing.Bitmap)(obj));
180 | }
181 | }
182 |
183 | ///
184 | /// Looks up a localized resource of type System.Drawing.Bitmap.
185 | ///
186 | internal static System.Drawing.Bitmap vector {
187 | get {
188 | object obj = ResourceManager.GetObject("vector", resourceCulture);
189 | return ((System.Drawing.Bitmap)(obj));
190 | }
191 | }
192 |
193 | ///
194 | /// Looks up a localized resource of type System.Drawing.Bitmap.
195 | ///
196 | internal static System.Drawing.Bitmap xytodd {
197 | get {
198 | object obj = ResourceManager.GetObject("xytodd", resourceCulture);
199 | return ((System.Drawing.Bitmap)(obj));
200 | }
201 | }
202 | }
203 | }
204 |
--------------------------------------------------------------------------------
/Heron/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 | ..\Resources\ddtoxy.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
123 |
124 |
125 | ..\Resources\Demo.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
126 |
127 |
128 | ..\Resources\eap.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
129 |
130 |
131 | ..\Resources\geocode.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
132 |
133 |
134 | ..\Resources\img.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
135 |
136 |
137 | ..\Resources\layer.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
138 |
139 |
140 | ..\Resources\raster.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
141 |
142 |
143 | ..\Resources\shp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
144 |
145 |
146 | ..\Resources\vector.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
147 |
148 |
149 | ..\Resources\revgeocode.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
150 |
151 |
152 | ..\Resources\xytodd.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
153 |
154 |
155 | ..\Resources\heron-favicon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
156 |
157 |
158 | ..\Resources\heron-icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
159 |
160 |
161 | ..\Resources\HeronServiceEndpoints.json;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
162 |
163 |
--------------------------------------------------------------------------------
/Heron/Resources/Demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blueherongis/Heron/a267da8aa014bcd6bfa3658cf2a1f67ec258905d/Heron/Resources/Demo.png
--------------------------------------------------------------------------------
/Heron/Resources/Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blueherongis/Heron/a267da8aa014bcd6bfa3658cf2a1f67ec258905d/Heron/Resources/Icon.png
--------------------------------------------------------------------------------
/Heron/Resources/ddtoxy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blueherongis/Heron/a267da8aa014bcd6bfa3658cf2a1f67ec258905d/Heron/Resources/ddtoxy.png
--------------------------------------------------------------------------------
/Heron/Resources/eap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blueherongis/Heron/a267da8aa014bcd6bfa3658cf2a1f67ec258905d/Heron/Resources/eap.png
--------------------------------------------------------------------------------
/Heron/Resources/geocode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blueherongis/Heron/a267da8aa014bcd6bfa3658cf2a1f67ec258905d/Heron/Resources/geocode.png
--------------------------------------------------------------------------------
/Heron/Resources/heron-favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blueherongis/Heron/a267da8aa014bcd6bfa3658cf2a1f67ec258905d/Heron/Resources/heron-favicon.png
--------------------------------------------------------------------------------
/Heron/Resources/heron-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blueherongis/Heron/a267da8aa014bcd6bfa3658cf2a1f67ec258905d/Heron/Resources/heron-icon.png
--------------------------------------------------------------------------------
/Heron/Resources/img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blueherongis/Heron/a267da8aa014bcd6bfa3658cf2a1f67ec258905d/Heron/Resources/img.png
--------------------------------------------------------------------------------
/Heron/Resources/layer-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blueherongis/Heron/a267da8aa014bcd6bfa3658cf2a1f67ec258905d/Heron/Resources/layer-01.png
--------------------------------------------------------------------------------
/Heron/Resources/layer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blueherongis/Heron/a267da8aa014bcd6bfa3658cf2a1f67ec258905d/Heron/Resources/layer.png
--------------------------------------------------------------------------------
/Heron/Resources/raster.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blueherongis/Heron/a267da8aa014bcd6bfa3658cf2a1f67ec258905d/Heron/Resources/raster.png
--------------------------------------------------------------------------------
/Heron/Resources/revgeocode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blueherongis/Heron/a267da8aa014bcd6bfa3658cf2a1f67ec258905d/Heron/Resources/revgeocode.png
--------------------------------------------------------------------------------
/Heron/Resources/shp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blueherongis/Heron/a267da8aa014bcd6bfa3658cf2a1f67ec258905d/Heron/Resources/shp.png
--------------------------------------------------------------------------------
/Heron/Resources/vector.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blueherongis/Heron/a267da8aa014bcd6bfa3658cf2a1f67ec258905d/Heron/Resources/vector.png
--------------------------------------------------------------------------------
/Heron/Resources/xytodd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/blueherongis/Heron/a267da8aa014bcd6bfa3658cf2a1f67ec258905d/Heron/Resources/xytodd.png
--------------------------------------------------------------------------------
/Heron/SpeckleAsync/GH_AsyncComponent.cs:
--------------------------------------------------------------------------------
1 | using Grasshopper.Kernel;
2 | using System;
3 | using System.Collections.Concurrent;
4 | using System.Collections.Generic;
5 | using System.Diagnostics;
6 | using System.Linq;
7 | using System.Threading;
8 | using System.Threading.Tasks;
9 | using Timer = System.Timers.Timer;
10 |
11 | namespace GrasshopperAsyncComponent
12 | {
13 | ///
14 | /// Inherit your component from this class to make all the async goodness available.
15 | ///
16 | public abstract class GH_AsyncComponent : GH_Component
17 | {
18 | public override Guid ComponentGuid => throw new Exception("ComponentGuid should be overriden in any descendant of GH_AsyncComponent!");
19 |
20 | //List<(string, GH_RuntimeMessageLevel)> Errors;
21 |
22 | Action ReportProgress;
23 |
24 | public ConcurrentDictionary ProgressReports;
25 |
26 | Action Done;
27 |
28 | Timer DisplayProgressTimer;
29 |
30 | int State = 0;
31 |
32 | int SetData = 0;
33 |
34 | public List Workers;
35 |
36 | List Tasks;
37 |
38 | public readonly List CancellationSources;
39 |
40 | ///
41 | /// Set this property inside the constructor of your derived component.
42 | ///
43 | public WorkerInstance BaseWorker { get; set; }
44 |
45 | ///
46 | /// Optional: if you have opinions on how the default system task scheduler should treat your workers, set it here.
47 | ///
48 | public TaskCreationOptions? TaskCreationOptions { get; set; } = null;
49 |
50 | protected GH_AsyncComponent(string name, string nickname, string description, string category, string subCategory) : base(name, nickname, description, category, subCategory)
51 | {
52 |
53 | DisplayProgressTimer = new Timer(333) { AutoReset = false };
54 | DisplayProgressTimer.Elapsed += DisplayProgress;
55 |
56 | ReportProgress = (id, value) =>
57 | {
58 | ProgressReports[id] = value;
59 | if (!DisplayProgressTimer.Enabled)
60 | {
61 | DisplayProgressTimer.Start();
62 | }
63 | };
64 |
65 | Done = () =>
66 | {
67 | Interlocked.Increment(ref State);
68 | if (State == Workers.Count && SetData == 0)
69 | {
70 | Interlocked.Exchange(ref SetData, 1);
71 |
72 | // We need to reverse the workers list to set the outputs in the same order as the inputs.
73 | Workers.Reverse();
74 |
75 | Rhino.RhinoApp.InvokeOnUiThread((Action)delegate
76 | {
77 | ExpireSolution(true);
78 | });
79 | }
80 | };
81 |
82 | ProgressReports = new ConcurrentDictionary();
83 |
84 | Workers = new List();
85 | CancellationSources = new List();
86 | Tasks = new List();
87 | }
88 |
89 | public virtual void DisplayProgress(object sender, System.Timers.ElapsedEventArgs e)
90 | {
91 | if (Workers.Count == 0 || ProgressReports.Values.Count == 0)
92 | {
93 | return;
94 | }
95 |
96 | if (Workers.Count == 1)
97 | {
98 | Message = ProgressReports.Values.Last().ToString("0.00%");
99 | }
100 | else
101 | {
102 | double total = 0;
103 | foreach (var kvp in ProgressReports)
104 | {
105 | total += kvp.Value;
106 | }
107 |
108 | Message = (total / Workers.Count).ToString("0.00%");
109 | }
110 |
111 | Rhino.RhinoApp.InvokeOnUiThread((Action)delegate
112 | {
113 | OnDisplayExpired(true);
114 | });
115 | }
116 |
117 | protected override void BeforeSolveInstance()
118 | {
119 | if (State != 0 && SetData == 1)
120 | {
121 | return;
122 | }
123 |
124 | Debug.WriteLine("Killing");
125 |
126 | foreach (var source in CancellationSources)
127 | {
128 | source.Cancel();
129 | }
130 |
131 | CancellationSources.Clear();
132 | Workers.Clear();
133 | ProgressReports.Clear();
134 | Tasks.Clear();
135 |
136 | Interlocked.Exchange(ref State, 0);
137 | }
138 |
139 | protected override void AfterSolveInstance()
140 | {
141 | System.Diagnostics.Debug.WriteLine("After solve instance was called " + State + " ? " + Workers.Count);
142 | // We need to start all the tasks as close as possible to each other.
143 | if (State == 0 && Tasks.Count > 0 && SetData == 0)
144 | {
145 | System.Diagnostics.Debug.WriteLine("After solve INVOKATIONM");
146 | foreach (var task in Tasks)
147 | {
148 | task.Start();
149 | }
150 | }
151 | }
152 |
153 | protected override void ExpireDownStreamObjects()
154 | {
155 | // Prevents the flash of null data until the new solution is ready
156 | if (SetData == 1)
157 | {
158 | base.ExpireDownStreamObjects();
159 | }
160 | }
161 |
162 | protected override void SolveInstance(IGH_DataAccess DA)
163 | {
164 | //return;
165 | if (State == 0)
166 | {
167 | if (BaseWorker == null)
168 | {
169 | AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Worker class not provided.");
170 | return;
171 | }
172 |
173 | var currentWorker = BaseWorker.Duplicate();
174 | if (currentWorker == null)
175 | {
176 | AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Could not get a worker instance.");
177 | return;
178 | }
179 |
180 | // Let the worker collect data.
181 | currentWorker.GetData(DA, Params);
182 |
183 | // Create the task
184 | var tokenSource = new CancellationTokenSource();
185 | currentWorker.CancellationToken = tokenSource.Token;
186 | currentWorker.Id = $"Worker-{DA.Iteration}";
187 |
188 | var currentRun = TaskCreationOptions != null
189 | ? new Task(() => currentWorker.DoWork(ReportProgress, Done), tokenSource.Token, (TaskCreationOptions)TaskCreationOptions)
190 | : new Task(() => currentWorker.DoWork(ReportProgress, Done), tokenSource.Token);
191 |
192 | // Add cancellation source to our bag
193 | CancellationSources.Add(tokenSource);
194 |
195 | // Add the worker to our list
196 | Workers.Add(currentWorker);
197 |
198 | Tasks.Add(currentRun);
199 |
200 | return;
201 | }
202 |
203 | if (SetData == 0)
204 | {
205 | return;
206 | }
207 |
208 | if (Workers.Count > 0)
209 | {
210 | Interlocked.Decrement(ref State);
211 | Workers[State].SetData(DA);
212 | }
213 |
214 | if (State != 0)
215 | {
216 | return;
217 | }
218 |
219 | CancellationSources.Clear();
220 | Workers.Clear();
221 | ProgressReports.Clear();
222 | Tasks.Clear();
223 |
224 | Interlocked.Exchange(ref SetData, 0);
225 |
226 | Message = "Done";
227 | OnDisplayExpired(true);
228 | }
229 |
230 | public void RequestCancellation()
231 | {
232 | foreach (var source in CancellationSources)
233 | {
234 | source.Cancel();
235 | }
236 |
237 | CancellationSources.Clear();
238 | Workers.Clear();
239 | ProgressReports.Clear();
240 | Tasks.Clear();
241 |
242 | Interlocked.Exchange(ref State, 0);
243 | Interlocked.Exchange(ref SetData, 0);
244 | Message = "Cancelled";
245 | OnDisplayExpired(true);
246 | }
247 |
248 | }
249 | }
250 |
--------------------------------------------------------------------------------
/Heron/SpeckleAsync/WorkerInstance.cs:
--------------------------------------------------------------------------------
1 | using Grasshopper.Kernel;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 |
9 | namespace GrasshopperAsyncComponent
10 | {
11 |
12 | ///
13 | /// A class that holds the actual compute logic and encapsulates the state it needs. Every needs to have one.
14 | ///
15 | public abstract class WorkerInstance
16 | {
17 |
18 | ///
19 | /// The parent component. Useful for passing state back to the host component.
20 | ///
21 | public GH_Component Parent { get; set; }
22 |
23 | ///
24 | /// This token is set by the parent .
25 | ///
26 | public CancellationToken CancellationToken { get; set; }
27 |
28 | ///
29 | /// This is set by the parent . You can set it yourself, but it's not really worth it.
30 | ///
31 | public string Id { get; set; }
32 |
33 | protected WorkerInstance(GH_Component _parent)
34 | {
35 | Parent = _parent;
36 | }
37 |
38 | ///
39 | /// This is a "factory" method. It should return a fresh instance of this class, but with all the necessary state that you might have passed on directly from your component.
40 | ///
41 | ///
42 | public abstract WorkerInstance Duplicate();
43 |
44 | ///
45 | /// This method is where the actual calculation/computation/heavy lifting should be done.
46 | /// Make sure you always check as frequently as you can if is cancelled. For an example, see the .
47 | ///
48 | /// Call this to report progress up to the parent component.
49 | /// Call this when everything is done. It will tell the parent component that you're ready to .
50 | public abstract void DoWork(Action ReportProgress, Action Done);
51 |
52 | ///
53 | /// Write your data setting logic here. Do not call this function directly from this class. It will be invoked by the parent after you've called `Done` in the function.
54 | ///
55 | ///
56 | public abstract void SetData(IGH_DataAccess DA);
57 |
58 | ///
59 | /// Write your data collection logic here. Do not call this method directly. It will be invoked by the parent .
60 | ///
61 | ///
62 | ///
63 | public abstract void GetData(IGH_DataAccess DA, GH_ComponentParamServer Params);
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/Heron/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/Heron/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Heron.HeronConfiguration": {
3 | "HeronOpenTopographyAPI": "<>"
4 | }
5 | }
--------------------------------------------------------------------------------
/Heron/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Brian Washburn
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Packages.dgml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
14 |
15 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Heron
2 | Heron is a Grasshopper add-on which enables the import and export of GIS data into the Rhino 3d/Grasshopper environment, located, scaled and cropped based on Rhino's EarthAnchorPoint and a clipping polygon. Heron is built on GDAL libraries and can import many GIS vector, raster and topographic file types, export vector GIS data and consume GIS REST services over the web.
3 |
4 | The add-on includes components in five categories.
5 |
6 | 
7 | #
8 | ### GIS Import | Export
9 | Components for importing and exporting GIS data.
10 | - **Import Vector**: Import vector GIS data clipped to a boundary, including SHP, GeoJSON, OSM, KML, MVT, GDB folders and HTTP sources.
11 | - **Import Topo**: Create a topographic mesh from a raster file (IMG, HGT, ASCII, DEM, TIF, etc) clipped to a boundary.
12 | - **Import Raster**: Import georeferenced raster data.
13 | - **Import OSM**: Import vector OpenStreetMap data clipped to a boundary. Nodes, Ways and Relations are organized onto their own branches in the output. Building massing will also be included if it exists in the OSM data.
14 | - **Import LAZ**: Import LAS & LAZ files. Built on laszip.net.
15 | - **Export Vector**: Export Grasshopper geometry to Shapefile, GeoJSON, KML and GML file formats in the WGS84 (EPSG:4326) spatial reference system.
16 | #
17 | ### GIS Tools
18 | Components for translating between Rhino and GIS coordinates and processing GIS data with GDAL programs.
19 | - **Set EarthAnchorPoint**: Set the Rhino EarthAnchorPoint. Setting the EAP is necessary for most Heron components to work properly.
20 | - **XY to Decimal Degrees**: Convert XY to Decimal Degrees Longitude/Latitude in the WGS84 spatial reference system.
21 | - **Decimal Degrees to XY**: Convert WGS84 Decimal Degrees Longitude/Latitude to X/Y.
22 | - **Coordinate Transformation**: Transform points from a source SRS to a destination SRS. The source points should be in the coordinate system of the source SRS.
23 | - **Gdal Ogr2Ogr**: Manipulate vector data with the GDAL OGR2OGR program given a source dataset, a destination dataset and a list of options. Information about conversion options can be found at https://gdal.org/programs/ogr2ogr.html.
24 | - **Gdal Warp**: Manipulate raster data with the GDAL Warp program given a source dataset, a destination dataset and a list of options. Information about Warp options can be found at https://gdal.org/programs/gdalwarp.html.
25 | - **Gdal Translate**: Manipulate raster data with the GDAL Translate program given a source dataset, a destination dataset and a list of options. Information about Translate options can be found at https://gdal.org/programs/gdal_translate.html.
26 | #
27 | ### GIS REST
28 | Components for interacting with REST web services.
29 | - **ESRI REST Service Geocode**: Get coordinates based on a Point-of-Interest or Address using the ESRI geocode service.
30 | - **ESRI REST Service Reverse Geocode**: Get the closest addresses to XY coordinates using the ESRI reverse geocode service.
31 | - **Get REST Service Layers**: Discover ArcGIS REST Service Layers.
32 | - **Get REST Vector**: Get vector data from ArcGIS REST Services.
33 | - **Get REST Topo**: Get STRM, ALOS and GMRT topographic data from web services. These services include global coverage from the Shuttle Radar Topography Mission (SRTM GL3 90m and SRTM GL1 30m), Advanced Land Observing Satellite (ALOS World 3D - 30m) and Global Multi-Resolution Topography (GMRT including bathymetry). Sources are opentopography.org and gmrt.org.
34 | - **Get REST Raster**: Get raster imagery from ArcGIS REST Services.
35 | - **Get REST OSM**: Get an OSM vector file within a boundary from web services such as the Overpass API. Use a search term to filter results and increase speed.
36 | #
37 | ### GIS API
38 | Components for interacting with tile-based services and services requiring a token.
39 | - **Slippy Viewport**: Projects the boundary of a given Viewport to the World XY plane and calculates a good Zoom level for use with tile-based map components.
40 | - **Slippy Tiles**: Visualize boundaries of slippy map tiles within a given boundary at a given zoom level. See https://en.wikipedia.org/wiki/Tiled_web_map for more information about map tiles.
41 | - **Slippy Raster**: Get raster imagery from a tile-based map service. Use the component menu to select the service.
42 | - **Mapbox Vector**: Get vector data from a Mapbox service. Requires a Mapbox Token.
43 | - **Mapbox Raster**: Get raster imagery from a Mapbox service. Requires a Mapbox Token.
44 | - **Mapbox Topo**: Get mesh topography from a Mapbox service. Requires a Mapbox Token.
45 | #
46 | ### Utilities
47 | Non-GIS components
48 | - **Cubemap from View**: Generate a cubemap from a given plane using the specified display mode.
49 | - **Cubemap from View Plus**: Generate a cubemap from a given plane using the specified display mode. This component is also able to visualize ray casting based on colors in the cubemap.
50 | - **Cubemap to Equirectangular**: Convert a cube map panorama to an equirectangular panorama.
51 | - **Image Filtered Colors**: Get a filtered pixel count of colors contained in an image based on color list.
52 | - **Image Top Colors**: Get a sorted list of the top colors contained in an image.
53 | - **Flip Image**: Flip an image along its vertical, horizontal axis or both.
54 | - **Rotate Image**: Roate an image 90, 180 or 270 degrees.
55 | - **Multi Mesh Patch**: Multithreaded creation of mesh patches from planar polylines. The first polyine in a branch will be considered the outer boundary, any others will be considered holes and should be completely within the outer boundary.
56 | - **Multi SDiff**: This multithreaded boolean solid difference (SDiff) component spreads the branches of input over threads for the boolean operation.
57 | - **Multi Move to Topo**: Move breps, surfaces, meshes, polylines and points to a topography mesh. Breps and closed meshes will be moved to the lowest point on the topography mesh within their footprint. Vertexes of curves and open meshes and control points of surfaces will be moved to the topography mesh. Geometry on a branch will be moved together as a group, but can be moved independently by deselecting 'Group' from the component menu. For a slower, but more detailed projection where curves and open meshes take on the vertexes of the topography mesh, select 'Detailed' from the component menu.
58 | - **Color to Hex**: Convert an RGBA color to hexidecimal format.
59 | - **Hex to Color**: Convert a hexidecimal color to RGBA format.
60 | - **Visual Center**: Find the visual center of closed planar curves. The resulting point will lie within the boundary of the curve and multiple curves on a branch will be treated as a surface with holes.
61 |
--------------------------------------------------------------------------------