# This Source Code Form is subject to the terms of the Mozilla Public# License, v. 2.0. If a copy of the MPL was not distributed with this# file, You can obtain one at https://mozilla.org/MPL/2.0/.from__future__importannotationsfromabcimportabstractmethodfromdataclassesimportcopy,dataclass,fieldsfromsislimportGeometryfromsisl._internalimportset_modulefromsisl.messagesimportSislError,warn__all__=["composite_geometry","CompositeGeometrySection","GeometrySection"]@set_module("sisl.geom")@dataclassclassCompositeGeometrySection:
self,geometry:Geometry,geometry_addition:Geometry)->Geometry:...def_junction_error(self,prev,msg,what):"""Helper function to raise an error if the junction is not valid. It extends the error by specifying details about the sections that are being joined. """msg=f"Error at junction between sections {prev} and {self}. {msg}"ifwhat=="raise":raiseSislError(msg)elifwhat=="warn":warn(msg)@set_module("sisl.geom")@dataclassclassGeometrySection(CompositeGeometrySection):"""Basic geometry section which does nothing, it simply returns a geometry When attaching two geometries they will be `Geometry.add`, without changes """geometry:Geometrydefbuild_section(self,geometry):# it does not matter what the prior geometry was, we just add onereturnself.geometrydefadd_section(self,geometry,geometry_addition):returngeometry.add(geometry_addition)
[docs]defcomposite_geometry(sections,section_cls,**kwargs):"""Creates a composite geometry from a list of sections. The sections are added one after another in the provided order. Parameters ---------- sections: array-like of (_geom_section or Geometry or tuple or dict) A list of sections to be added to the ribbon. Each section is either a `composite_geometry.section` or something that will be parsed to a `composite_geometry.section`. section_cls: class, optional The class to use for parsing sections. **kwargs: Keyword arguments used as defaults for the sections when the . """# Parse sections into Section objectsdefconv(s):ifisinstance(s,Geometry):returnGeometrySection(s)# If it is some arbitrary type, convert it to a tupleifnotisinstance(s,(section_cls,tuple,dict)):s=(s,)# If we arrived here with a tuple, convert it to a dictifisinstance(s,tuple):s={field.name:valforfield,valinzip(fields(section_cls),s)}# At this point it is either a dict or already a section object.ifisinstance(s,dict):returnsection_cls(**{**kwargs,**s})returncopy.copy(s)# Then loop through all the sections.geom=Noneprev=Nonefori,sectioninenumerate(sections):section=conv(section)new_addition=section.build_section(prev)ifi==0:geom=new_additionelse:geom=section.add_section(geom,new_addition)prev=sectionreturngeom