"""Genera CAPAS_REFERENCIA.pdf en el directorio del converter.""" from fpdf import FPDF from pathlib import Path OUT = Path(__file__).parent / "CAPAS_REFERENCIA.pdf" # ── datos ────────────────────────────────────────────────────────────────────── SECCIONES = [ ("OBJETOS PUNTUALES", [ ("BOYLAT", "Boya lateral (babor/estribor)", "boyas, buoys"), ("BOYCAR", "Boya cardinal (N/S/E/W)", "boycar"), ("BOYISD", "Boya de peligro aislado", "boyisd"), ("BOYSAW", "Boya de aguas seguras", "boysaw"), ("BCNLAT", "Baliza lateral", "balizas, beacons"), ("BCNSPP", "Baliza especial", "bcnspp"), ("LIGHTS", "Luz / faro", "luces, lights, faroles"), ("LNDMRK", "Hito en tierra (torre, tanque...)", "Puntos del Terreno"), ("SOUNDG", "Sonda batimetrica", "sondas, soundings, profundidades"), ("UWTROC", "Roca sumergida / a flor de agua", "rocas, rocks"), ("WRECKS", "Naufragio", "naufragio, wreck"), ("OBSTRN", "Obstruccion", "obstruccion, obstruction"), ]), ("OBJETOS LINEALES", [ ("COALNE", "Linea de costa", "Linderos, coastline, costa, linea_de_costa"), ("DEPCNT", "Curva batimetrica (isobata)", "isobata, curvas_nivel, depth_contour"), ("CBLSUB", "Cable submarino", "cable"), ("PIPSOL", "Tuberia submarina / en tierra", "tuberia"), ("RIVERS", "Rio / canal", "rio, river"), ]), ("OBJETOS DE AREA", [ ("LNDARE", "Area terrestre", "Area Terreno, tierra, land"), ("DEPARE", "Area de profundidad", "fondos, batimetria, depth_area"), ("FAIRWY", "Canal de navegacion", "canal_navegacion, fairway"), ("RESARE", "Area restringida", "zona_restringida, restricted"), ("ACHARE", "Area de fondeo", "fondeadero, anchorage"), ("HRBARE", "Area portuaria", "puerto, harbor"), ("BERTHS", "Atraque / muelle", "atraque, berth"), ("SBDARE", "Area de fondo marino", "fondo_marino, seabed"), ]), ] ATTR_ROWS = [ ("nombre / name", "OBJNAM", "Nombre del objeto (aparece en tooltip)"), ("catlam / lateral", "CATLAM", "Categoria lateral: 1=babor, 2=estribor"), ("colour / color", "COLOUR", "Color: 1=blanco, 3=rojo, 4=verde, 6=amarillo"), ("colpat / patron", "COLPAT", "Patron de color: 1=horizontal, 2=vertical"), ("boyshp / forma", "BOYSHP", "Forma boya: 1=conica, 2=cilindrica, 4=esferica"), ("litchr / destello", "LITCHR", "Destello: 1=F, 2=Fl, 3=LFl, 4=Q, 8=Iso, 5=IQ"), ("sigper / periodo", "SIGPER", "Periodo en segundos (ej: 4.0)"), ("siggrp / grupo", "SIGGRP", "Grupo de destellos: (2), (2+1), etc."), ("alcance / range", "VALNMR", "Alcance nominal en millas nauticas"), ("altura / height", "HEIGHT", "Altura de la luz sobre el mar (metros)"), ("status / estado", "STATUS", "Estado: 1=permanente, 2=ocasional"), ("profundidad / depth", "DRVAL1", "Profundidad minima (metros)"), ("depth_max", "DRVAL2", "Profundidad maxima (metros)"), ("sonda / sounding", "VALSOU", "Valor de sonda (metros)"), ("contour / valor", "VALDCO", "Valor de curva batimetrica (metros)"), ] LITCHR_ROWS = [ ("1", "F", "Fija"), ("2", "Fl", "Destellante"), ("3", "LFl", "Gran destello"), ("4", "Q", "Centelleante"), ("5", "IQ", "Centelleante interrumpido"), ("6", "Oc", "Ocultante"), ("8", "Iso", "Isofasica"), ("25", "VQ", "Rapida continua"), ("28", "Mo", "Morse"), ] # ── PDF ──────────────────────────────────────────────────────────────────────── class PDF(FPDF): def header(self): self.set_font("Helvetica", "B", 11) self.set_fill_color(30, 80, 140) self.set_text_color(255, 255, 255) self.cell(0, 10, "QGISS57Converter - Referencia de nombres de capas", fill=True, new_x="LMARGIN", new_y="NEXT") self.set_text_color(0, 0, 0) self.ln(2) def footer(self): self.set_y(-12) self.set_font("Helvetica", "I", 8) self.set_text_color(120, 120, 120) self.cell(0, 10, f"Pagina {self.page_no()}", align="C") pdf = PDF(orientation="P", unit="mm", format="A4") pdf.set_auto_page_break(auto=True, margin=15) pdf.add_page() pdf.set_font("Helvetica", size=9) # intro pdf.set_font("Helvetica", size=9) pdf.multi_cell(0, 5, "Nombra tus capas QGIS con cualquiera de los textos de la columna 'Nombres reconocidos' " "(sin importar mayusculas). Tambien puedes usar el acronimo S-57 directamente como nombre de capa. " "Para agregar nombres nuevos, edita 'layer_mappings' en cell_config.json.") pdf.ln(3) COL = [22, 58, 110] # x positions W = [22, 55, 78] # widths def th(texts, fill_rgb=(200, 215, 235)): pdf.set_fill_color(*fill_rgb) pdf.set_font("Helvetica", "B", 8) for i, t in enumerate(texts): pdf.set_x(10 + sum(W[:i])) pdf.cell(W[i], 6, t, border=1, fill=True) pdf.ln() def tr(texts, alt=False): fill_rgb = (245, 248, 252) if alt else (255, 255, 255) pdf.set_fill_color(*fill_rgb) pdf.set_font("Helvetica", size=8) # measure max height needed heights = [] for i, t in enumerate(texts): lines = pdf.get_string_width(t) / W[i] + 1 heights.append(max(1, int(lines) + 1) * 5) h = max(heights) h = min(h, 10) for i, t in enumerate(texts): pdf.set_x(10 + sum(W[:i])) pdf.multi_cell(W[i], h / max(1, pdf.get_string_width(t) / W[i] + 1), t, border=1, fill=True, max_line_height=5) # ensure we're on next line pdf.ln(0) for section_title, rows in SECCIONES: pdf.set_font("Helvetica", "B", 9) pdf.set_fill_color(30, 80, 140) pdf.set_text_color(255, 255, 255) pdf.cell(0, 7, f" {section_title}", fill=True, new_x="LMARGIN", new_y="NEXT") pdf.set_text_color(0, 0, 0) th(["Acronimo S-57", "Descripcion", "Nombres reconocidos en QGIS"]) for idx, (acro, desc, aliases) in enumerate(rows): pdf.set_fill_color(245, 248, 252) if idx % 2 else pdf.set_fill_color(255, 255, 255) pdf.set_font("Helvetica", "B", 8) pdf.set_x(10) pdf.cell(W[0], 6, acro, border=1, fill=True) pdf.set_font("Helvetica", size=8) pdf.cell(W[1], 6, desc, border=1, fill=True) pdf.multi_cell(W[2], 6, aliases, border=1, fill=True) pdf.ln(4) # atributos pdf.set_font("Helvetica", "B", 9) pdf.set_fill_color(30, 80, 140) pdf.set_text_color(255, 255, 255) pdf.cell(0, 7, " CAMPOS DE ATRIBUTOS (columnas de tu SHP)", fill=True, new_x="LMARGIN", new_y="NEXT") pdf.set_text_color(0, 0, 0) AW = [55, 22, 78] pdf.set_fill_color(200, 215, 235) pdf.set_font("Helvetica", "B", 8) pdf.set_x(10); pdf.cell(AW[0], 6, "Nombre campo en SHP", border=1, fill=True) pdf.cell(AW[1], 6, "Atrib. S-57", border=1, fill=True) pdf.cell(AW[2], 6, "Descripcion", border=1, fill=True) pdf.ln() for idx, (shp_col, s57, desc) in enumerate(ATTR_ROWS): pdf.set_fill_color(245, 248, 252) if idx % 2 else pdf.set_fill_color(255, 255, 255) pdf.set_font("Helvetica", size=8) pdf.set_x(10); pdf.cell(AW[0], 6, shp_col, border=1, fill=True) pdf.set_font("Helvetica", "B", 8) pdf.cell(AW[1], 6, s57, border=1, fill=True) pdf.set_font("Helvetica", size=8) pdf.cell(AW[2], 6, desc, border=1, fill=True) pdf.ln() # tabla LITCHR pdf.ln(4) pdf.set_font("Helvetica", "B", 9) pdf.set_fill_color(30, 80, 140) pdf.set_text_color(255, 255, 255) pdf.cell(0, 7, " CODIGOS LITCHR - Caracteristica de luz", fill=True, new_x="LMARGIN", new_y="NEXT") pdf.set_text_color(0, 0, 0) LW = [20, 30, 100] pdf.set_fill_color(200, 215, 235) pdf.set_font("Helvetica", "B", 8) pdf.set_x(10); pdf.cell(LW[0], 6, "Codigo", border=1, fill=True) pdf.cell(LW[1], 6, "Abrev.", border=1, fill=True) pdf.cell(LW[2], 6, "Descripcion", border=1, fill=True) pdf.ln() for idx, (code, abbr, desc) in enumerate(LITCHR_ROWS): pdf.set_fill_color(245, 248, 252) if idx % 2 else pdf.set_fill_color(255, 255, 255) pdf.set_font("Helvetica", size=8) pdf.set_x(10); pdf.cell(LW[0], 6, code, border=1, fill=True) pdf.cell(LW[1], 6, abbr, border=1, fill=True) pdf.cell(LW[2], 6, desc, border=1, fill=True) pdf.ln() pdf.ln(5) pdf.set_font("Helvetica", "I", 8) pdf.set_text_color(80, 80, 80) pdf.multi_cell(0, 5, "Nota: para anadir un nombre de capa no listado aqui, edita 'layer_mappings' en cell_config.json. " "Para anadir campos de atributos nuevos, edita 'attribute_mappings'.") pdf.output(str(OUT)) print(f"PDF generado: {OUT} ({OUT.stat().st_size} bytes)")