From 4824447d3f84c66aa79f515190f2f2c0f70b7fb2 Mon Sep 17 00:00:00 2001 From: Dan Patterson Date: Sun, 26 Nov 2023 18:32:07 -0500 Subject: [PATCH] Add files via upload updates for Nov 2023 --- arcpro_npg/npg/npg/npGeo.py | 60 +++++----- arcpro_npg/npg/npg/npgDocs.py | 15 ++- arcpro_npg/npg/npg/npg_analysis.py | 39 +++---- arcpro_npg/npg/npg/npg_arc_npg.py | 35 +++--- arcpro_npg/npg/npg/npg_bool_hlp.py | 46 ++++---- arcpro_npg/npg/npg/npg_clip_split.py | 17 +-- arcpro_npg/npg/npg/npg_create.py | 8 +- arcpro_npg/npg/npg/npg_erase.py | 13 ++- arcpro_npg/npg/npg/npg_geom.py | 35 +++--- arcpro_npg/npg/npg/npg_helpers.py | 65 ++++++----- arcpro_npg/npg/npg/npg_io.py | 166 +++++++++++++++------------ arcpro_npg/npg/npg/npg_overlay.py | 5 +- arcpro_npg/npg/npg/npg_plots.py | 9 +- arcpro_npg/npg/npg/npg_prn.py | 10 +- arcpro_npg/npg/npg/npg_table.py | 2 +- arcpro_npg/npg/npg/npg_utils.py | 69 ++++++++++- 16 files changed, 352 insertions(+), 242 deletions(-) diff --git a/arcpro_npg/npg/npg/npGeo.py b/arcpro_npg/npg/npg/npGeo.py index 089e41f..4274ed5 100644 --- a/arcpro_npg/npg/npg/npGeo.py +++ b/arcpro_npg/npg/npg/npGeo.py @@ -12,10 +12,11 @@ ---- """ -# pylint: disable=C0103,C0302,C0415 -# pylint: disable=E1101,E1121 -# pylint: disable=W0105,W0201,W0212,W0221,W0611,W0612,W0621 + +# pylint: disable=C0103,C0201,C0209,C0302,C0415 # pylint: disable=R0902,R0904,R0912,R0913,R0914,R0915 +# pylint: disable=W0105,W0201,W0212,W0221,W0611,W0612,W0613,W0621 +# pylint: disable=E0401,E0611,E1101,E1121 import sys from textwrap import indent, dedent, wrap @@ -24,8 +25,9 @@ from numpy.lib.recfunctions import unstructured_to_structured as uts from numpy.lib.recfunctions import repack_fields +import npg # noqa from npg import npg_geom as geom -from npg import (npg_helpers, npg_io, npg_prn) # npg_create) +from npg import npg_helpers, npg_io, npg_prn # npg_create) from npg import npg_min_circ as sc from npg.npg_helpers import ( @@ -53,10 +55,9 @@ TwoPI = np.pi * 2.0 __all__ = [ - 'Geo', 'is_Geo', - 'roll_coords', 'roll_arrays', 'array_IFT', 'arrays_to_Geo', + 'Geo', 'roll_coords', 'roll_arrays', 'array_IFT', 'arrays_to_Geo', 'Geo_to_arrays', 'Geo_to_lists', '_fill_float_array', - 'is_Geo', 'reindex_shapes', 'remove_seq_dupl', 'check_geometry', + 'remove_seq_dupl', 'check_geometry', 'is_Geo', 'reindex_shapes', 'dirr' ] @@ -167,14 +168,14 @@ def __array_finalize__(self, src_arr): self.UR = getattr(src_arr, 'UR', None) self.Z = getattr(src_arr, 'Z', None) self.SVG = getattr(src_arr, 'SVG', None) + return self def __array_wrap__(self, out_arr, context=None): """Wrap it up.""" return np.ndarray.__array_wrap__(self, out_arr, context) - # ---- ------------------------------------------------------------------ # ---- End of class definition ------------------------------------------- - # + # ---- ------------------------------------------------------------------ # ---- help : information @property def H(self): @@ -189,12 +190,8 @@ def facts(self): structure, and/or more records use the `prn_geo` method. """ info_ = self.IFT_str[:25] - frmt = """ - {}\nExtents :\n LL {}\n UR {} - Shapes :{:>6.0f} - Parts :{:>6.0f} - Points :{:>6.0f} - \nSp Ref : {} + frmt = """{}\nExtents :\n LL {}\n UR {}\nShapes :{:>6.0f}\ + \nParts :{:>6.0f}\nPoints :{:>6.0f}\nSp Ref : {} """ args = ["-" * 14, self.LL, self.UR, len(self.U), self.IFT.shape[0], self.IFT[-1, 2], self.SR] @@ -228,7 +225,7 @@ def geo_props(self): w = wrap(t, 79) print(">>> geo_info(geo_array)\n... Geo methods and properties.") for i in w: - print(indent("{}".format(i), prefix=" ")) + print(indent(f"{i}", prefix=" ")) print("\n... Geo base properties.") s0 = set(srt) s1 = set(Geo.__dict__.keys()) @@ -236,13 +233,13 @@ def geo_props(self): t = ", ".join([str(i) for i in s0s1]) w = wrap(t, 79) for i in w: - print(indent("{}".format(i), prefix=" ")) + print(indent(f"{i}", prefix=" ")) print("\n... Geo special.") s1s0 = sorted(list(s1.difference(s0))) t = ", ".join([str(i) for i in s1s0]) w = wrap(t, 79) for i in w: - print(indent("{}".format(i), prefix=" ")) + print(indent(f"{i}", prefix=" ")) # return # ---- --------------------------- @@ -499,7 +496,7 @@ def first_part(self, asGeo=True): Holes are retained. The IFT is altered to account for point removal. """ - info = "{} first part".format(self.Info) + info = f"{self.Info} first part" ift_s = self.IFT[self.PID == 1] a_2d = [self.XY[ft[0]:ft[1]] for ft in self.FT] if asGeo: @@ -591,7 +588,7 @@ def lengths(self, by_shape=True): def perimeters(self, by_shape=True): """Polyline lengths or polygon perimeter. Calls `lengths`.""" - return self.lengths(by_shape=True) + return self.lengths(by_shape) def centers(self, by_shape=True): """Return the center of outer ring points.""" @@ -879,7 +876,9 @@ def rotate(self, as_group=True, angle=0.0, clockwise=False): # def bounding_circles(self, angle=5, shift_back=False, return_xyr=False): """Bounding circles for features.""" - chk = False if len(self.IFT) > 1 else True + chk = True + if len(self.IFT) > 1: + chk = False chs = self.convex_hulls(chk, False, 50) # check for singlepart shapes xyr = [sc.small_circ(s) for s in chs.shapes] circs = [] @@ -979,7 +978,7 @@ def fill_holes(self): cs = np.cumsum(tmp_ft) id_too[1:, 0] = cs[:-1] id_too[:, 1] = cs - info = "{} fill_holes".format(self.Info) + info = f"{self.Info} fill_holes" tmp_ift[:, 1:3] = id_too return Geo(a_2d, IFT=tmp_ift, Kind=2, Extent=self.XT, Info=info) @@ -1164,8 +1163,7 @@ def segment_pnt_ids(self): def to_segments(self, ignore_holes=True): """Segment poly* structures into (x0, y0, x1, y1) data per shape. - An object array is returned. Holes removed from polygons by default, - but multipart shapes are not. + An object array is returned. Holes in polygons can be removed. See Also -------- @@ -1185,7 +1183,7 @@ def to_segments(self, ignore_holes=True): return segs def common_segments(self, shift_back=False): - """Return the common segments in poly features. + """Return the common segments in poly* features. The result is an array of from-to pairs of points. ft, tf pairs are evaluated to denote common segments or duplicates. @@ -1216,7 +1214,7 @@ def common_segments(self, shift_back=False): return _fill_float_array(common) # , idx # stu(common) def unique_segments(self, shift_back=False): - """Return the unique segments in poly features. + """Return the unique segments in poly* features. The output is an ndarray of from-to pairs of points. @@ -1301,8 +1299,10 @@ def sort_by_extent(self, extent_pnt='LB', key=0, just_indices=False): ext_ids = self.shp_ids xs = ext[:, 0] ys = ext[:, 1] - azim = np.array([0, 45, 90, 135, 180, 225, 270, 315]) # azimuths - val = np.radians(azim[key]) # sort angle in radians + # azimuth dictionary + azim = {0: 0, 1: 45, 2: 90, 3: 135, 4: 180, 5: 225, 6: 270, 7: 315} + val = azim[key] if key in azim.keys() else 0 + val = np.radians(val) # sort angle in radians z = np.sin(val) * xs + np.cos(val) * ys # - sort by vector idx = np.argsort(z) # sort order sorted_ids = ext_ids[idx] @@ -1824,7 +1824,9 @@ def dup_idx(sub, poly): return sub[np.sort(idx)] chunks = Geo_to_arrays(g) - poly = True if g.K == 2 else False + poly = False + if g.K == 2: + poly = True out = [] for i, c in enumerate(chunks): n = len(c.shape) diff --git a/arcpro_npg/npg/npg/npgDocs.py b/arcpro_npg/npg/npg/npgDocs.py index 53b329e..b7c3a55 100644 --- a/arcpro_npg/npg/npg/npgDocs.py +++ b/arcpro_npg/npg/npg/npgDocs.py @@ -54,7 +54,7 @@ 'sort_by_extent_doc', 'array_IFT_doc', 'dirr_doc' ] -Modified = "2023-02-17" +Modified = "2023-10-09" author_date = r""" Author : @@ -80,7 +80,7 @@ def _update_docstring(obj, doc): # ---------------------------------------------------------------------------- -# ---- (1) ...npGeo +# ---- (1) npGeo # npGeo_doc = author_date + Modified + r""" @@ -250,8 +250,7 @@ def _update_docstring(obj, doc): """ -# ---- (2) ... Geo class -# --- Geo_hlp +# ---- (2) Geo_hlp Geo_hlp = r""" @@ -339,7 +338,7 @@ def _update_docstring(obj, doc): dtype=int64) """ -# ---- (3) shapes_doc +# ---- (3) shapes shapes_doc = r""" Returns @@ -354,7 +353,7 @@ def _update_docstring(obj, doc): """ -# ---- (4) parts_doc +# ---- (4) parts parts_doc = r""" Returns @@ -592,7 +591,7 @@ def _update_docstring(obj, doc): """ -# ---- (17) ... array_IFT +# ---- (17) array_IFT array_IFT_doc = r""" Parameters @@ -625,7 +624,7 @@ def _update_docstring(obj, doc): """ -# ---- (18) ... dirr function +# ---- (18) dirr dirr_doc = r""" Source, ``arraytools.py_tools`` has a pure python equivalent. diff --git a/arcpro_npg/npg/npg/npg_analysis.py b/arcpro_npg/npg/npg/npg_analysis.py index 4d7ea50..14e15c9 100644 --- a/arcpro_npg/npg/npg/npg_analysis.py +++ b/arcpro_npg/npg/npg/npg_analysis.py @@ -13,7 +13,7 @@ Dan_Patterson@carleton.ca Modified : - 2023-08-23 + 2023-11-03 Purpose ------- @@ -28,10 +28,11 @@ Derived from arraytools ``convex_hull, mst, near, n_spaced`` """ -# pylint: disable=C0103 # invalid-name -# pylint: disable=R0914 # Too many local variables -# pylint: disable=R1710 # inconsistent-return-statements -# pylint: disable=W0105 # string statement has no effect +# pylint: disable=C0103,C0201,C0209,C0302,C0415 +# pylint: disable=R0902,R0904,R0912,R0913,R0914,R0915 +# pylint: disable=W0105,W0201,W0212,W0221,W0611,W0612,W0613,W0621 +# pylint: disable=E0401,E0611,E1101,E1121 + # import sys from textwrap import dedent @@ -112,16 +113,12 @@ def n_check(a): # N=3, order=True): ---------- Two 2D array of X,Y coordinates required. Parse your data to comply. """ - has_err = False if isinstance(a, (list, tuple, np.ndarray)): if (hasattr(a[0], '__len__')) and (len(a[0]) == 2): return True - has_err = True - else: - has_err = True - if has_err: - print(n_check.__doc__) return False + print(n_check.__doc__) + return False def n_near(a, N=3, ordered=True, return_all=False): @@ -289,24 +286,22 @@ def _x_sect_2(args): s02_y = p0[1] - p2[1] # # -- Second check ---- np.cross(p1-p0, p3-p2) - denom = (s10_x * s32_y - s32_x * s10_y) # .item() + denom = s10_x * s32_y - s32_x * s10_y # .item() if denom == 0.0: # collinear return False, None # # -- Third check ---- np.cross(p1-p0, p0-p2) positive_denom = denom > 0.0 # denominator greater than zero - s_numer = (s10_x * s02_y - s10_y * s02_x) # .item() -# if (s_numer < 0) == positive_denom: -# return False + s_numer = s10_x * s02_y - s10_y * s02_x # .item() # # -- Fourth check ---- np.cross(p3-p2, p0-p2) t_numer = s32_x * s02_y - s32_y * s02_x -# if (t_numer < 0) == positive_denom: -# return False # - if ((s_numer > denom) == positive_denom) or \ - ((t_numer > denom) == positive_denom): + if positive_denom in (s_numer > denom, t_numer > denom): return False, None + # if ((s_numer > denom) == positive_denom) or \ + # ((t_numer > denom) == positive_denom): + # return False, None # # -- check to see if the intersection point is one of the input points # substitute p0 in the equation These are the intersection points @@ -625,8 +620,10 @@ def _x_sect_(*args): if (t_numer < 0) == den_gt0: return False # - if ((s_numer > denom) == den_gt0) or ((t_numer > denom) == den_gt0): + if den_gt0 in (s_numer > denom, t_numer > denom): return False + # if ((s_numer > denom) == den_gt0) or ((t_numer > denom) == den_gt0): + # return False # # -- check if the intersection point is one of the input points t = t_numer / denom @@ -641,7 +638,7 @@ def _x_sect_(*args): def _angle_(p0, p1, prv_ang=0): """Return the angle between two points and the previous angle, or.""" ang = np.arctan2(p0[1] - p1[1], p0[0] - p1[0]) - a0 = (ang - prv_ang) + a0 = ang - prv_ang a0 = a0 % (PI * 2) - PI return a0 diff --git a/arcpro_npg/npg/npg/npg_arc_npg.py b/arcpro_npg/npg/npg/npg_arc_npg.py index c86c4e5..40250a0 100644 --- a/arcpro_npg/npg/npg/npg_arc_npg.py +++ b/arcpro_npg/npg/npg/npg_arc_npg.py @@ -64,11 +64,10 @@ ---------- None (yet). """ -# pylint: disable=C0103, C0302, C0415, E0611, E1136, E1121, R0904, R0914, -# pylint: disable=W0201, W0212, W0221, W0612, W0621, W0105 -# pylint: disable=R0902 - -# pylint: disable=R1710 # inconsistent-return-statements +# pylint: disable=C0103,C0201,C0209,C0302,C0415 +# pylint: disable=R0902,R0904,R0912,R0913,R0914,R0915 +# pylint: disable=W0105,W0201,W0212,W0221,W0611,W0612,W0613,W0621 +# pylint: disable=E0401,E0611,E1101,E1121 import sys @@ -88,15 +87,13 @@ from npg.npGeo import Geo # from npGeo import * -# import arcpy +import arcpy from arcpy import Array, Exists, Multipoint, Point, Polygon, Polyline from arcpy.da import ( Describe, InsertCursor, SearchCursor, FeatureClassToNumPyArray, TableToNumPyArray) # ExtendTable, NumPyArrayToTable, UpdateCursor -# from arcpy.geoprocessing import gp -from arcpy.geoprocessing import env from arcpy.management import ( AddField, CopyFeatures, CreateFeatureclass, Delete) # DeleteFeatures @@ -110,7 +107,7 @@ 'fc_to_Geo', 'id_fr_to', # option 1, use this *** 'Geo_to_arc_shapes', 'Geo_to_fc', 'view_poly', # back to fc 'make_nulls', 'fc_data', 'tbl_data', # get attributes - 'fc2na', 'array_poly', 'geometry_fc', + 'fc2na', 'attr_to_npz', 'array_poly', 'geometry_fc', '_array_to_poly_', '_poly_to_array_', # geometry to array '_poly_arr_', 'poly2array', # extras 'fc_union', 'shp_dissolve', 'fc_dissolve' # arcpy functions @@ -358,7 +355,7 @@ def id_fr_to(a, oids): id_val = [oids[val]] # a list for concatenation if n < 1: continue - elif n == 1: # one found, use the next one + if n == 1: # one found, use the next one val = w[0] + 1 elif n == 2: # two found, use the last one + 1 key = w[-1] @@ -414,6 +411,7 @@ def arr2poly(a, SR): The inputs may be nested and mixed in content. """ aa = [] + poly = None for pairs in a: sub = pairs[0] oid = pairs[1] @@ -462,7 +460,7 @@ def Geo_to_fc(geo, gdb=None, name=None, kind=None, SR=None): # geo = geo.shift(dx, dy) polys = Geo_to_arc_shapes(geo, as_singlepart=True) out_name = gdb.replace("\\", "/") + "/" + name - wkspace = env.workspace = 'memory' # legacy is in_memory + wkspace = arcpy.env.workspace = r'memory' # legacy is in_memory tmp_name = r"memory\tmp" # r"{}\{}".format(wkspace, "tmp") if Exists(tmp_name): Delete(tmp_name) @@ -505,13 +503,12 @@ def view_poly(geo, id_num=1, view_as=2): z = [Array([Point(*i) for i in b]) for b in shp.bits] if view_as == 2: return Polygon(Array(z)) - elif view_as == 1: + if view_as == 1: return Polyline(Array(z)) - else: - zz = [] - for i in z: - zz.extend(i) - return Multipoint(Array(zz)) + zz = [] + for i in z: + zz.extend(i) + return Multipoint(Array(zz)) # ============================================================================ @@ -790,7 +787,7 @@ def geometry_fc(a, IFT, p_type=None, gdb=None, fname=None, sr=None): p_type = "POLYGON" out = array_poly(a, p_type.upper(), sr=sr, IFT=IFT) # call array_poly name = gdb + "/" + fname - wkspace = env.workspace = 'memory' # legacy is in_memory + wkspace = arcpy.env.workspace = r'memory' # legacy is in_memory CreateFeatureclass(wkspace, fname, p_type, spatial_reference=sr) AddField(fname, 'ID_arr', 'LONG') with InsertCursor(fname, ['SHAPE@', 'ID_arr']) as cur: @@ -963,7 +960,7 @@ def fc_union(in_fc, poly_type="polygon"): a = Array(arr) if poly_type == "polygon": return Polygon(a, SR) - elif poly_type == "polyline": + if poly_type == "polyline": return Polyline(a, SR) else: print("Not polygon or polyline") diff --git a/arcpro_npg/npg/npg/npg_bool_hlp.py b/arcpro_npg/npg/npg/npg_bool_hlp.py index 4a30216..f4870e8 100644 --- a/arcpro_npg/npg/npg/npg_bool_hlp.py +++ b/arcpro_npg/npg/npg/npg_bool_hlp.py @@ -18,7 +18,7 @@ ``_. Modified : - 2023-06-03 + 2023-10-30 Purpose ------- @@ -27,7 +27,7 @@ """ # pylint: disable=C0103,C0302,C0415 -# pylint: disable=E1101,E1121 +# pylint: disable=E0401,E1101,E1121 # pylint: disable=W0105,W0201,W0212,W0221,W0611,W0612,W0621 # pylint: disable=R0902,R0904,R0912,R0913,R0914,R0915 @@ -207,7 +207,7 @@ def _w_(a, b, all_info): b_num = (b_0 - b_1) + 0.0 # # pnts in poly - chk1 = (y0_y2 >= 0.0) # y above poly's first y value, per segment + chk1 = y0_y2 >= 0.0 # y above poly's first y value, per segment chk2 = np.less(y0, y3[:, None]) # y above the poly's second point chk3 = np.sign(a_num).astype(np.int32) pos = (chk1 & chk2 & (chk3 > 0)).sum(axis=0, dtype=np.int32) @@ -261,7 +261,7 @@ def _xsect_(a_num, b_num, denom, x1_x0, y1_y0, x0, y0): u_b = (b_num / denom) + 0.0 z0 = np.logical_and(u_a >= 0., u_a <= 1.) # np.isfinite(u_a)` z1 = np.logical_and(u_b >= 0., u_b <= 1.) # np.isfinite(u_b) - both = (z0 & z1) + both = z0 & z1 xs = (u_a * x1_x0 + x0)[both] ys = (u_a * y1_y0 + y0)[both] x_pnts = [] @@ -374,18 +374,21 @@ def _node_type_(p_in_c, c_in_p, poly, clp, x_pnts): return px_in_c, p_in_c, p_eq_c, p_eq_x, cx_in_p, c_in_p, c_eq_p, c_eq_x -def prep_overlay(arrs, roll=True, polygons=[True, True]): +def prep_overlay(arrs, roll=True, p0_pgon=True, p1_pgon=True,): """Prepare arrays for overlay analysis. Parameters ---------- arrs : list/tuple + arrs = [poly, line] The first geometry is the one being acted upon and the second is the one being used to overlay the first for operations such as clipping, splitting, intersection. - polygons : list/tuple - True, the input geometry is a polygon, False otherwise. + p0_pgon, p1_pgon : boolean + True, the input geometry is a polygon feature, False, for polyline. Some operations permit polygon and polyline inputs, so you can alter + `p0_pgon=True, p1_pgon=False]` if the first is a polygon and the + second a polyline. Requires -------- @@ -425,9 +428,9 @@ def prep_overlay(arrs, roll=True, polygons=[True, True]): # -- roll towards LL. `_wn_clp_` gets pnts inside, on, outside each other if len(arrs) != 2: print("Two poly* type geometries expected.") - # return None + return None a0, a1 = arrs - is_0, is_1 = polygons + is_0, is_1 = p0_pgon, p1_pgon if roll: a0, a1 = _roll_(arrs) vals = _wn_clip_(a0, a1, all_info=True) @@ -444,18 +447,18 @@ def prep_overlay(arrs, roll=True, polygons=[True, True]): # ---- (3) add intersection points # def add_intersections( - p0, p1, roll_to_minX=True, polygons=[True, True], class_ids=True): + p0, p1, roll_to_minX=True, p0_pgon=True, p1_pgon=True, class_ids=True): """Return input polygons with intersections points added. Parameters ---------- p0, p1 : array_like The overlapping poly features. - polygons : list/tuple + p0_pgon, p1_pgon : boolean True, the input geometry is a polygon feature, False, for polyline. Some operations permit polygon and polyline inputs, so you can alter - `polygons=[True, False]` if the first is a polygon and the second a - polyline. + `p0_pgon=True, p1_pgon=False]` if the first is a polygon and the + second a polyline. roll_to_minX : boolean Select the intersection point with the minimum x-value. This is used to roll the arrays. @@ -470,10 +473,11 @@ def add_intersections( Returns ------- - The poly features rotated to the first intersection point (`p0_n, p1_n`), - their respective indices from the start (`id_01`) and the intersection - points (`x_pnts`), and the classified indices for each polygon as to - whether the points are outside, on or inside the other + - The poly features rotated to the first intersection point (`p0_n, p1_n`), + - Their respective indices from the start (`id_01`), + - Intersection points (`x_pnts`), + - The classified indices for each polygon as to whether the points are + outside, on or inside the other. p0_n, p1_n : arrays The input arrays, rotated to their first intersection point and those @@ -525,14 +529,14 @@ def _classify_(p0_, p1_, id_): def in_out_on(w0, p_sze): """Return the array indices as lists.""" - if w0.size == 0: - # print("Empty array.") + if w0.size == 0: # print("Empty array.") return [] - elif len(w0) == 1: # 2023-05-07 + if len(w0) == 1: # 2023-05-07 val = w0.tolist()[0] vals = [val - 1, val, val + 1] if val > 0 else [val, val + 1] return vals out = [] + cnt = 0 sub = [w0[0] - 1, w0[0]] for cnt, i in enumerate(w0[1:], 0): prev = w0[cnt] @@ -550,7 +554,7 @@ def in_out_on(w0, p_sze): return out # -- # - is_0, is_1 = polygons + is_0, is_1 = p0_pgon, p1_pgon vals = _wn_clip_(p0, p1, all_info=True) x_pnts, pInc, cInp, x_type, whr = vals p0_n, p1_n = _add_pnts_(p0, p1, x_pnts, whr) diff --git a/arcpro_npg/npg/npg/npg_clip_split.py b/arcpro_npg/npg/npg/npg_clip_split.py index 52542ef..25e6819 100644 --- a/arcpro_npg/npg/npg/npg_clip_split.py +++ b/arcpro_npg/npg/npg/npg_clip_split.py @@ -18,7 +18,7 @@ ``_. Modified : - 2023-04-12 + 2023-11-03 Purpose ------- @@ -36,10 +36,10 @@ A XOR B """ -# pylint: disable=C0103,C0302,C0415 -# pylint: disable=E1101,E1121 -# pylint: disable=W0105,W0201,W0212,W0221,W0611,W0612,W0621 +# pylint: disable=C0103,C0201,C0209,C0302,C0415 # pylint: disable=R0902,R0904,R0912,R0913,R0914,R0915 +# pylint: disable=W0105,W0201,W0212,W0221,W0611,W0612,W0613,W0621 +# pylint: disable=E0401,E0611,E1101,E1121 import sys import numpy as np @@ -57,8 +57,8 @@ script = sys.argv[0] -__all__ = ['clip_poly', 'find_overlap_segments', 'split_poly'] -__helpers__ = ['del_seq_pnts', '_roll_', 'prep_overlay'] +__all__ = ['clip_poly', 'split_poly', 'find_overlap_segments'] +# __helpers__ = ['del_seq_pnts', '_roll_', 'prep_overlay'] # ---- (1) clip polygons @@ -109,7 +109,7 @@ def _bits_(i0, i1, in_, seen_): # # -- Returns the intersections, the rolled input polygons, the new polygons # and how the points in both relate to one another. - result = prep_overlay([poly, clp], roll=False, polygons=[True, True]) + result = prep_overlay([poly, clp], roll=False, p0_pgon=True, p1_pgon=True) x_pnts, pl, cl, pl_new, cl_new, args = result px_in_c, p_in_c, p_eq_c, p_eq_x, cx_in_p, c_in_p, c_eq_p, c_eq_x = args # @@ -341,7 +341,8 @@ def split_poly(poly, line): """ # # -- (1) Prepare for splitting - result = prep_overlay([poly, line], roll=False, polygons=[True, False]) + arrs = [poly, line] + result = prep_overlay(arrs, roll=False, p0_pgon=True, p1_pgon=True) # -- intersection points, arrays rolled to first intersection, # rolled with intersections added on, optional arguments x_pnts, pl_roll, cl_roll, pl_, cl_, args = result diff --git a/arcpro_npg/npg/npg/npg_create.py b/arcpro_npg/npg/npg/npg_create.py index 879cb11..aa71e62 100644 --- a/arcpro_npg/npg/npg/npg_create.py +++ b/arcpro_npg/npg/npg/npg_create.py @@ -14,7 +14,7 @@ Dan_Patterson@carleton.ca Modified : - 2023-08-23 + 2023-10-09 Purpose ------- @@ -100,16 +100,18 @@ __all__ = ['code_grid', 'rot_matrix', 'arc_', 'arc_sector', - 'circle', 'circle_mini', 'circle_ring', 'circ_3pa', 'circ_3p', + 'circle', 'circle_mini', 'circle_ring', 'circ_3pa', + 'circle_sectors', 'circ_3p', 'ellipse', + 'hex_flat', 'hex_pointy', 'rectangle', 'triangle', - 'hex_flat', 'hex_pointy', 'mesh_xy', 'pyramid', 'pnt_from_dist_bearing', 'xy_grid', 'transect_lines', + 'buffer_rings', 'spiral_archim', 'spiral_sqr', 'spiral_cw', 'spiral_ccw', 'base_spiral', 'to_spiral', 'from_spiral', 'repeat', 'mini_weave' diff --git a/arcpro_npg/npg/npg/npg_erase.py b/arcpro_npg/npg/npg/npg_erase.py index 0968f7d..4deb80a 100644 --- a/arcpro_npg/npg/npg/npg_erase.py +++ b/arcpro_npg/npg/npg/npg_erase.py @@ -18,7 +18,7 @@ ``_. Modified : - 2023-09-26 + 2023-10-30 Purpose ------- @@ -27,10 +27,10 @@ - erase """ -# pylint: disable=C0103,C0302,C0415 -# pylint: disable=E1101,E1121 -# pylint: disable=W0105,W0201,W0212,W0221,W0611,W0612,W0621 +# pylint: disable=C0103,C0201,C0209,C0302,C0415 # pylint: disable=R0902,R0904,R0912,R0913,R0914,R0915 +# pylint: disable=W0105,W0201,W0212,W0221,W0611,W0612,W0613,W0621 +# pylint: disable=E0401,E0611,E1101,E1121 import sys import copy @@ -165,7 +165,8 @@ def in_out_chk(_n, _p, _c, _seen, _outside, _inside): # and how the points in both relate to one another. result = add_intersections(poly, clp, roll_to_minX=True, - polygons=[True, True], + p0_pgon=True, + p1_pgon=True, class_ids=True) pl_n, cl_n, id_plcl, x_pnts, p_out, p_in, c_out, c_in = result # -- @@ -350,7 +351,7 @@ def in_out_chk(_n, _p, _c, _seen, _outside, _inside): idx_all = np.nonzero(idx < 2)[0] # symmetrical difference idx_p_out = np.nonzero(idx == 0)[0] # pairwise erase idx_c_out = np.nonzero(idx != 0)[0] # reverse pairwise erase - idx_c_in = np.nonzero(idx == 1)[0] # clp ?? reverse pairwise erase + idx_c_in = np.nonzero(idx == 1)[0] # clp ?? reverse pairwise erase # hole_ply = final[idx_hole] if len(idx_hole) > 0 else [] symm_ply = final[idx_all] diff --git a/arcpro_npg/npg/npg/npg_geom.py b/arcpro_npg/npg/npg/npg_geom.py index b58e828..82cb412 100644 --- a/arcpro_npg/npg/npg/npg_geom.py +++ b/arcpro_npg/npg/npg/npg_geom.py @@ -18,7 +18,7 @@ ``_. Modified : - 2023-02-16 + 2023-10-29 Purpose ------- @@ -102,7 +102,7 @@ >>> not_in = [ ... '__all__', '__builtins__', '__cached__', '__doc__', '__file__', ... '__loader__', '__name__', '__package__', '__spec__', 'np', 'npg', 'sys' -... ] +... ] + __imports__ >>> __all__ = [i for i in dir(npg.npg_geom) ... if i[0] != "_" and i not in not_in] @@ -112,10 +112,10 @@ """ -# pylint: disable=C0103, C0302, C0415, E0611, E1136, E1121 -# pylint: disable=R0904, R0913, R0914, R0915 -# pylint: disable=W0201, W0212, W0221, W0612, W0621, W0105 -# pylint: disable=R0902 +# pylint: disable=C0103,C0201,C0209,C0302,C0415 +# pylint: disable=R0902,R0904,R0912,R0913,R0914,R0915 +# pylint: disable=W0105,W0201,W0212,W0221,W0611,W0612,W0613,W0621 +# pylint: disable=E0401,E0611,E1101,E1121 import sys import numpy as np @@ -142,8 +142,14 @@ script = sys.argv[0] # print this should you need to locate the script # -- See script header +__imports__ = [ + 'CH', 'Delaunay', 'npGeo', 'np_wn', 'npg_helpers', 'npg_pip', 'stu', + 'uts', '_get_base_', '_bit_area_', '_bit_min_max_', '_in_extent_', + '_angles_3pnt_' + ] + __all__ = [ - 'CH', 'Delaunay', 'bin_pnts', 'common_extent', 'densify_by_distance', + 'bin_pnts', 'common_extent', 'densify_by_distance', 'densify_by_factor', 'eucl_dist', 'extent_to_poly', 'find_closest', 'in_hole_check', 'mabr', 'npGeo', 'np_wn', 'offset_buffer', 'on_line_chk', 'pnts_in_pnts', 'pnts_on_poly', @@ -277,7 +283,7 @@ def _percent_along_(a, percent=0): x1, y1 = a[_end_] _start_ = _end_ - 1 x0, y0 = a[_start_] - t = (percent - perleng[_start_]) + t = percent - perleng[_start_] xt = x0 * (1. - t) + (x1 * t) yt = y0 * (1. - t) + (y1 * t) return np.array([xt, yt]) @@ -1121,7 +1127,7 @@ def segments_to_polys(self): def simplify_lines(a, deviation=10): """Simplify array. Requires, `_angles_3pnt_` from npg_helpers.""" ang = _angles_3pnt_(a, inside=True, in_deg=True) - idx = (np.abs(ang - 180.) >= deviation) + idx = np.abs(ang - 180.) >= deviation sub = a[1: -1] p = sub[idx] return a, p, ang @@ -1241,14 +1247,15 @@ def which_quad(line): >>> line = line[::-1] """ x_, y_ = np.sign(np.diff(line[[0, -1]], axis=0))[0] - if x_ >= 0: # right + # right + if x_ >= 0: if y_ >= 0: # upper return 1 return 4 - elif x_ < 0: # left - if y_ >= 0: # upper - return 2 - return 3 + # left + if y_ >= 0: # upper + return 2 + return 3 # =========================================================================== diff --git a/arcpro_npg/npg/npg/npg_helpers.py b/arcpro_npg/npg/npg/npg_helpers.py index f6ee498..50cabb6 100644 --- a/arcpro_npg/npg/npg/npg_helpers.py +++ b/arcpro_npg/npg/npg/npg_helpers.py @@ -16,7 +16,7 @@ Dan_Patterson@carleton.ca Modified : - 2023-10-02 + 2023-10-29 Purpose ------- @@ -54,7 +54,7 @@ ... '__all__', '__builtins__', '__cached__', '__doc__', '__file__', ... '__loader__', '__name__', '__package__', '__spec__', 'np', 'npg', ... 'sys', 'script' -... ] +... ] + __imports__ >>> __all__ = [i for i in dir(npg.npg_helpers) ... if i[0] != "_" and i not in not_in] @@ -64,9 +64,11 @@ """ -# pylint: disable=C0103,C0415 -# pylint: disable=R0912, R0913, R0914, R1710, R1705 -# pylint: disable=W0105,W0212,W0612,W0613 +# pylint: disable=C0103,C0201,C0209,C0302,C0415 +# pylint: disable=R0902,R0904,R0912,R0913,R0914,R0915 +# pylint: disable=W0105,W0201,W0212,W0221,W0611,W0612,W0613,W0621 +# pylint: disable=E0401,E0611,E1101,E1121 + import sys # from textwrap import dedent @@ -86,23 +88,29 @@ nums = 'efdgFDGbBhHiIlLqQpP' # -- See script header +__imports__ = [ + 'uts', 'npg_prn', 'prn_tbl' + ] + __all__ = [ 'a_eq_b', 'cartesian_product', 'coerce2array', 'common_pnts', 'compare_geom', 'del_seq_dups', 'dist_angle_sort', 'flat', 'interweave', - 'keep_geom', 'polyline_angles', 'project_pnt_to_line', 'radial_sort', - 'remove_geom', 'segment_angles', 'shape_finder', 'sort_xy', 'stride_2d', - 'reclass_ids', 'uniq_1d', 'uniq_2d' -] + 'keep_geom', 'multi_check', 'polyline_angles', 'project_pnt_to_line', + 'radial_sort', 'reclass_ids', 'remove_geom', 'segment_angles', + 'shape_finder', 'sort_xy', 'stride_2d', 'uniq_1d', 'uniq_2d' + ] __helpers__ = [ - 'prn_tbl', '_angles_3pnt_', '_od_angles_dist_', '_area_centroid_', - '_bit_area_', '_bit_check_', '_bit_crossproduct_', '_bit_length_', - '_bit_min_max_', '_bit_segment_angles_', '_from_north_', '_from_to_pnts_', - '_get_base_', '_in_LBRT_', '_in_extent_', '_is_clockwise_', '_is_ccw_', - '_is_convex_', '_is_right_side', '_isin_2d_', '_pnts_in_extent_', - '_rotate_', '_scale_', '_to_lists_', '_trans_rot_', '_translate_', - '_perp_' -] # ---- core bit functions + '_angles_3pnt_', '_area_centroid_', '_bit_area_', '_bit_check_', + '_bit_crossproduct_', '_bit_length_', '_bit_min_max_', + '_bit_segment_angles_', '_close_pnts_', '_from_north_', '_from_to_pnts_', + '_from_xaxis_', '_get_base_', '_in_LBRT_', '_in_extent_', '_is_ccw_', + '_is_clockwise_', '_is_convex_', '_is_right_side', '_isin_2d_', + '_iterate_', '_od_angles_dist_', '_perp_', '_pnts_in_extent_', + '_rotate_', '_scale_', '_to_lists_', '_trans_rot_', '_translate_' + ] + +# ---- core bit functions # __all__ = __helpers__ + __all__ @@ -182,15 +190,14 @@ def _to_lists_(a, outer_only=True): if outer_only: return a.outer_rings(False) # a.bits return a.bits - elif isinstance(a, np.ndarray): + if isinstance(a, np.ndarray): if a.dtype.kind == 'O': - return a + a = a elif a.ndim == 2: - return [a] + a = [a] elif a.ndim == 3: - return list(a) - else: # a list already - return a + a = list(a) + return a # a list already def uniq_1d(arr): @@ -554,7 +561,7 @@ def _from_xaxis_(angles): Example:: - >>> a = np.arange(180., -180 - 45, -45, float) + >>> a = np.arange(180., -180 - 45, -45, dtype=np.float64) >>> a >>> array([ 180., 135., 90., 45., 0., -45., -90., -135., -180.]) >>> b = (-a + 90.) % 360. @@ -1238,8 +1245,7 @@ def _arr_(arr): prn_tbl(out) return None return out - else: - return info + return info def coerce2array(arr, start=0): @@ -1330,8 +1336,7 @@ def project_pnt_to_line(x1, y1, x2, y2, xp, yp): lx = x1 + x12 * coeff ly = y1 + y12 * coeff return lx, ly - else: - return None + return None def reclass_ids(vals=None): @@ -1418,5 +1423,5 @@ def _iterate_(N, n): # ---- ==== main section if __name__ == "__main__": """optional location for parameters""" - # in_fc = r"C:\Git_Dan\npgeom\Project_npg\npgeom.gdb\Polygons" - # in_fc = r"C:\Git_Dan\npgeom\Project_npg\npgeom.gdb\Polygons2" + # in_fc = r"C:\arcpro_npg\Project_npg\npgeom.gdb\Polygons" + # in_fc = r"C:\arcpro_npg\Project_npg\npgeom.gdb\Polygons2" diff --git a/arcpro_npg/npg/npg/npg_io.py b/arcpro_npg/npg/npg/npg_io.py index b83646b..d2004e8 100644 --- a/arcpro_npg/npg/npg/npg_io.py +++ b/arcpro_npg/npg/npg/npg_io.py @@ -21,7 +21,7 @@ Dan_Patterson@carleton.ca Modified : - 2023-08-23 + 2023-111-14 Purpose ------- @@ -81,8 +81,10 @@ edgeitems=10, linewidth=160, precision=2, suppress=True, threshold=100, formatter=ft) -__all__ = ['dtype_info', 'load_geo', 'save_geo', 'load_txt', 'save_txt', - 'load_geojson', 'geojson_Geo'] +__all__ = [ + 'dtype_info', 'load_geo', 'load_geo_attr', 'save_geo', 'load_txt', + 'save_txt', 'load_geojson', 'geojson_Geo' + ] # ---- (1) arrays : in and out------------------------------------------------ @@ -117,8 +119,8 @@ def dtype_info(a, as_string=False): return names, formats -def load_geo(f_name, suppress_extras=False): - """Load a well formed `npy` file representing a structured array. +def load_geo(f_name, extras=False, prn_info=False): + r"""Load a well formed `npy` file representing a structured array. Unpack an `npz` file containing a Geo array. @@ -126,16 +128,18 @@ def load_geo(f_name, suppress_extras=False): ---------- f_name : text Full path and filename. - suppress_extras : boolean + extras : boolean If False, only the Geo array is returned, otherwise, the Geo array, the constituent arrays and their names are returned. + prn_info : boolean + If True, then run info is printed. Returns ------- geo : Geo array The Geo array is created within this function and returned along with the base arrays, (`arrs`) and the list of array names (`names`), if - ``suppress_extras`` is False. + ``suppress_extras`` is True. arrs : arrays The arrays within the npz, names : list @@ -144,73 +148,88 @@ def load_geo(f_name, suppress_extras=False): Example ------- - >>> f_name = "C:/arcpro_npg/data/g_arr.npz" - >>> geo, arrs, names = npg.load_geo(f_name) - >>> geo - Geo([[ 10.00, 10.00], - [ 10.00, 0.00], - [ 1.50, 1.50], - ..., - [ 10.00, 10.00], - [ 15.00, 18.00], - [ 14.00, 10.00]]) - >>> arrs - NpzFile 'C:/arcpro_npg/data/g_arr.npz' with keys: - g, ift, kind, extents, spatial_ref - >>> arrs['extents'] # same array of bounding rectangle extents - array([[ 300000.00, 5000000.00], - [ 300025.00, 5000018.00]]) - >>> arr_names = arrs.files # returns the list of array names inside - ['g', 'ift', 'kind', 'extents', 'spatial_ref'] - - An array or arrays. The description, field names and their size of each - are returned. + This a sample:: + + f_name = "C:/arcpro_npg/data/sq2.npz" + sq2, arrs, names = npg.load_geo(f_name, extras=False, prn_info=False) + # the array coordinates + sq2 + Geo([[ 10.00, 10.00], + [ 10.00, 0.00], + [ 1.50, 1.50], + ..., + [ 10.00, 10.00], + [ 15.00, 18.00], + [ 14.00, 10.00]]) + # -- the extra array names if `extras=True`. + arrs + NpzFile 'C:/arcpro_npg/data/g_arr.npz' with keys: + g, ift, kind, extents, spatial_ref + # + # -- returns the list of array names inside + arr_names = arrs.files + ['g', 'ift', 'kind', 'extents', 'spatial_ref'] + # -- the array of bounding rectangle extents + arrs['extents'] + array([[ 300000.00, 5000000.00], + [ 300025.00, 5000018.00]]) + + An array or arrays. The description, field names and their size of each + are returned. Notes ----- - From above: arrs = np.load(f_name) - arrs : numpy.lib.npyio.NpzFile - The type of file. - other properties : dir(arrs) - 'allow_pickle', 'close', 'f', 'fid', 'files', 'get', 'items', - 'iteritems', 'iterkeys', 'keys', 'pickle_kwargs', 'values', 'zip' + From above:: + + arrs = np.load(f_name) + arrs : numpy.lib.npyio.NpzFile + The type of file. + other properties : dir(arrs) + 'allow_pickle', 'close', 'f', 'fid', 'files', 'get', 'items', + 'iteritems', 'iterkeys', 'keys', 'pickle_kwargs', 'values', 'zip' """ - arrs = np.load(f_name) - names = arrs.files # array names - print("\nLoading...{}\nArrays include...{}".format(f_name, names)) - frmt = "({}) name : {}\n shape : {}\n descr. : {}" - for i, name in enumerate(names): - tmp = arrs[name] - shp = tmp.shape - desc = tmp.dtype.descr - print(frmt.format(i, name, shp, desc)) - n0, n1, n2, n3, n4 = names - geo = npGeo.Geo(arrs[n0], - IFT=arrs[n1], - Kind=int(arrs[n2]), - Extent=arrs[n3], - SR=str(arrs[n4]) - ) - if suppress_extras: + def _to_geo_(arrs, names): + """Pull out the info.""" + n0, n1, n2, n3, n4 = names + geo = npGeo.Geo( + arrs[n0], IFT=arrs[n1], Kind=int(arrs[n2]), Extent=arrs[n3], + SR=str(arrs[n4]) + ) return geo - return geo, arrs, names - -def load_geo_attr(f_name): + arrs = np.load(f_name) + names = arrs.files # the array names + msg = "\nLoading...{}\nArray(s) include...{}" + geo = _to_geo_(arrs, names) + if extras: + if prn_info: + print(msg.format(f_name, names)) + return geo, arrs, names + if prn_info: + print(msg.format(f_name, names[0])) + return geo + + +def load_geo_attr(f_name, prn_info=False): """Load the attributes in an npy file associated with a geo array. Parameters ---------- f_name : text The complete filename path and extension. + prn_info : boolean + If True, then run info is printed. Returns ------- - names : the list of array names. - arrs : the arrays themselves `arr` and `fields`. - The two arrays are the: - - attribute data - - field names and data type. + names : the list of array names. + + arrs : the arrays themselves `arr` and `fields`. + + The two arrays are the: + + - attribute data + - field names and data type. Example ------- @@ -226,20 +245,21 @@ def load_geo_attr(f_name): """ arrs = np.load(f_name) names = arrs.files # array names - frmt0 = "\nLoading attributes from... {}\n\nArrays include...{}" - print(frmt0.format(f_name, names)) - frmt1 = "({}) name : {}\n" - for i, name in enumerate(names): - print(frmt1.format(i, name)) - msg = """ - To use : - >>> n0, n1 = names - >>> n0, n1 - ... ('arr', 'fields') - >>> arr = arrs[n0] - >>> flds = arrs[n1] - """ - print(msg) + if prn_info: + frmt0 = "\nLoading attributes from... {}\n\nArrays include...{}" + print(frmt0.format(f_name, names)) + frmt1 = "\n({}) name : {}" + for i, name in enumerate(names): + print(frmt1.format(i, name)) + msg = """ + To use : + >>> n0, n1 = names + >>> n0, n1 + ... ('arrs', 'fields') + >>> arr = arrs[n0] + >>> flds = arrs[n1] + """ + print(msg) return names, arrs diff --git a/arcpro_npg/npg/npg/npg_overlay.py b/arcpro_npg/npg/npg/npg_overlay.py index f758766..0505c83 100644 --- a/arcpro_npg/npg/npg/npg_overlay.py +++ b/arcpro_npg/npg/npg/npg_overlay.py @@ -29,7 +29,7 @@ ``_. Modified : - 2022-09-21 + 2023-10-09 Purpose ------- @@ -110,7 +110,8 @@ 'append_', 'merge_', 'union_as_one', - 'line_crosses', 'in_out_crosses', 'crossings' + 'line_crosses', 'in_out_crosses', 'crossings', + 'left_right_pnts', 'line_side', '_line_crossing_' ] __helpers__ = ['_intersect_', '_adj_'] diff --git a/arcpro_npg/npg/npg/npg_plots.py b/arcpro_npg/npg/npg/npg_plots.py index a8b011f..5693cab 100644 --- a/arcpro_npg/npg/npg/npg_plots.py +++ b/arcpro_npg/npg/npg/npg_plots.py @@ -18,7 +18,7 @@ Dan_Patterson@carleton.ca Modified : - 2022-11-27 + 2023-10-09 Purpose ------- @@ -78,7 +78,12 @@ script = sys.argv[0] -__all__ = ['plot_2d', 'plot_3d', 'plot_polygons', 'plot_mesh'] +__all__ = [ + 'plot_mixed', 'plot_2d', 'plot_3d', 'plot_polygons', 'plot_mesh', + 'plot_mst' + ] + +__helpers__ = ['axis_mins_maxs', '_get_cmap', 'subplts', 'scatter_params'] # ---- (1) helper functions ---- diff --git a/arcpro_npg/npg/npg/npg_prn.py b/arcpro_npg/npg/npg/npg_prn.py index 355b448..8b442ae 100644 --- a/arcpro_npg/npg/npg/npg_prn.py +++ b/arcpro_npg/npg/npg/npg_prn.py @@ -19,7 +19,7 @@ Dan_Patterson@carleton.ca Modified : - 2023-08-23 + 2023-10-09 Purpose ------- @@ -72,8 +72,12 @@ edgeitems=5, linewidth=120, precision=2, suppress=True, threshold=100, formatter=ft) -__all__ = ['prn_q', 'prn_', 'prn_tbl', 'prn_geo', 'prn_lists', 'prn_arrays', - 'prn_as_obj', 'prn_Geo_shapes', '_svg'] +__all__ = [ + 'prn_q', 'prn_', 'prn_tbl', 'prn_geo', 'prn_lists', 'prn_arrays', + 'prn_as_obj', 'prn_Geo_shapes', '_svg' + ] + +__helpers__ = ['_ckw_', '_col_format', 'col_hdr', 'ake_row_format'] # ============================================================================ diff --git a/arcpro_npg/npg/npg/npg_table.py b/arcpro_npg/npg/npg/npg_table.py index f8313de..7319fa3 100644 --- a/arcpro_npg/npg/npg/npg_table.py +++ b/arcpro_npg/npg/npg/npg_table.py @@ -14,7 +14,7 @@ Author : Dan_Patterson@carleton.ca Modified : - 2022-07-26 + 2023-11-05 Purpose ------- diff --git a/arcpro_npg/npg/npg/npg_utils.py b/arcpro_npg/npg/npg/npg_utils.py index ddffe54..4f5ff35 100644 --- a/arcpro_npg/npg/npg/npg_utils.py +++ b/arcpro_npg/npg/npg/npg_utils.py @@ -12,7 +12,7 @@ Dan_Patterson@carleton.ca Modified : - 2022-07-26 + 2023-10-09 Purpose ------- @@ -116,7 +116,8 @@ __all__ = [ 'time_deco', 'run_deco', 'doc_func', 'get_func', 'get_module_info', - 'find_def', '_wrapper', '_utils_help_' + 'find_def', '_wrapper', '_utils_help_', 'get_dirs', 'folders', + 'sub_folders', 'env_list', 'dir_py' ] @@ -708,6 +709,70 @@ def dir_py(obj, colwise=False, cols=3, prn=True): return txt_out +# ---- (6) toolbox ... code section ... -------------------------------------- +# +def toolbox_info(t_box): + """Return toolbox information. + + Parameters + ---------- + t_box : toolbox in *.atbx format + + Notes + ----- + t_box = "C:/arcpro_npg/npGeom_32.atbx" + """ + def _hdr_(hdr_n): + """Format the header.""" + return "{{:<{}s}}".format(hdr_n) + " {!s:<}" + + from arcgisscripting._arcgisscripting import _utbx + t_box = t_box.replace("\\", "/") + t_props = _utbx.getToolboxProps(t_box, "*") + t_keys = sorted(list(t_props.keys())) + hdr_n = max([len(i) for i in t_keys]) + frmt0 = _hdr_(hdr_n) + msg = frmt0.format("Property", "Value") + "\n" + ("-")*(hdr_n + 7) + z0 = ['name', 'display name', 'direction', 'data type', 'parameter type', + 'enabled', 'category', 'symbology', 'multi-value'] + keys0 = [i for i in t_keys if i != 'tools'] + keys1 = 'tools' if 'tools' in t_keys else None + for k in keys0: # toolbox properties + v = t_props[k] + msg += "\n" + frmt0.format(k, v) + if keys1: # `tool` properties + v = t_props[keys1] + v_keys = sorted(list(v.keys())) + hdr_1 = max([len(i) for i in v_keys]) + frmt1 = _hdr_(hdr_1) + msg += "\n" + frmt1.format("--Tool", " Toolset") + for k1 in v_keys: + v1 = v[k1] + msg += "\n " + frmt1.format(k1, v1) + # for k1 in v_keys: + # pth = "{}/{}".format(t_box, k1) + # t_0 = _utbx.getToolProps(pth, '*') + # tool_keys = list(t_0.keys()) + # msg += "\nTools and Properties" + # msg += "\n--Tool : {!s:<}\n--Toolset : {!s:}".format(k1, v[k1]) + # for k2 in tool_keys: + # if k2 != 'params': + # msg += " {!s:} : {!s}\n".format(k2, t_0[k2]) + # elif k2 == 'params': + # for i in t_0['params']: + # z1 = [str(j) if j != '' else 'None' + # for j in [i.name, i.displayName, i.direction, + # i.datatype, i.parameterType, i.enabled, + # i.category, i.symbology, i.multiValue] + # ] + # msg += "--Parameters\n" + # txt = "\n".join([" {!s:<} : {!s:}".format(*j) + # for j in list(zip(z0, z1))]) + # msg += "parameter" + # else: + # msg += "unknown" + return msg + # ---------------------------------------------------------------------- # __main__ .... code section if __name__ == "__main__":