<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Ken Arroyo Ohori</title>
    <description></description>
    <link>https://3d.bk.tudelft.nl/ken/</link>
    <atom:link href="https://3d.bk.tudelft.nl/ken/feed.xml" rel="self" type="application/rss+xml" />
    <pubDate>Fri, 07 Aug 2026 09:43:02 -0600</pubDate>
    <lastBuildDate>Fri, 07 Aug 2026 09:43:02 -0600</lastBuildDate>
    <generator>Jekyll v4.4.1</generator>
    
    
        <item>
          <title>#30DayMapChallenge</title>
          <description>&lt;p&gt;Contribuí con 3 mapas al esfuerzo conjunto de mi grupo de investigación en el &lt;a href=&quot;https://30daymapchallenge.com/&quot;&gt;#30DayMapChallenge&lt;/a&gt;. Están publicados en el &lt;a href=&quot;https://twitter.com/tudelft3d&quot;&gt;Twitter&lt;/a&gt; del grupo, pero también enlazo los resultados desde aquí.&lt;/p&gt;

&lt;h2 id=&quot;día-10-openstreetmap&quot;&gt;&lt;a href=&quot;https://3d.bk.tudelft.nl/ken/maps/osm-buildings/&quot;&gt;Día 10: OpenStreetMap&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/ken/img/blog/map-osm.jpg&quot; class=&quot;img-fluid center-block&quot; alt=&quot;Mapa de edificios de OSM&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Este mapa muestra el número de huellas de edificios disponibles en OpenStreetMap por celda de &lt;a href=&quot;https://h3geo.org/&quot;&gt;H3&lt;/a&gt;. Es interesante ver que algunas regiones del mundo están mucho mejor mapeadas que otras y que los datos no se correlacionan tanto con la población o la riqueza.&lt;/p&gt;

&lt;p&gt;El script para generar los datos está disponible &lt;a href=&quot;https://github.com/kenohori/osmium-buildings&quot;&gt;aquí&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;día-21-conjunto-de-datos-de-población-de-kontur&quot;&gt;&lt;a href=&quot;https://3d.bk.tudelft.nl/ken/maps/kontur-cities/&quot;&gt;Día 21: Conjunto de datos de población de Kontur&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/ken/img/blog/map-kontur.jpg&quot; class=&quot;img-fluid center-block&quot; alt=&quot;Mapa de las ciudades más grandes de Kontur&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Este mapa muestra las ciudades más grandes del mundo, calculadas de forma independiente a partir del &lt;a href=&quot;https://data.humdata.org/dataset/kontur-population-dataset&quot;&gt;conjunto de datos de población de Kontur&lt;/a&gt;. El primer paso fue clasificar todas las celdas de H3 en urbanas y no urbanas con base en un umbral de densidad de población (5000/km^2 por defecto). Las celdas urbanas se agregan entonces en ciudades siempre que formen regiones casi contiguas (hasta un umbral máximo de separación entre celdas).&lt;/p&gt;

&lt;p&gt;Debido a la metodología, es posible generar las ciudades más grandes del mundo usando un estándar uniforme, lo que contrasta con la forma inconsistente en que diferentes países calculan sus propias estadísticas. Si te disgusta la expansión urbana tanto como a mí, te alegrará ver que este mapa muestra la verdadera naturaleza del desarrollo suburbano.&lt;/p&gt;

&lt;p&gt;El script para generar los datos está disponible &lt;a href=&quot;https://github.com/kenohori/konturpop&quot;&gt;aquí&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;día-23-movimiento&quot;&gt;&lt;a href=&quot;https://3d.bk.tudelft.nl/ken/maps/mexico-city/&quot;&gt;Día 23: Movimiento&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/ken/img/blog/map-movement.jpg&quot; class=&quot;img-fluid center-block&quot; alt=&quot;Mapa de isócronas de la Ciudad de México&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Este mapa, inspirado en &lt;a href=&quot;https://www.chronotrains.com/&quot;&gt;Chronotrains&lt;/a&gt;, muestra qué tan lejos puedes viajar en la Ciudad de México usando el transporte público en una hora, con base en isócronas precalculadas (de 15, 30, 45 y 60 minutos). Las isócronas se calculan para todas las paradas de metro, BRT, tren ligero, tren suburbano y teleférico usando datos del &lt;a href=&quot;https://datos.cdmx.gob.mx/dataset/gtfs&quot;&gt;GTFS estático de la Ciudad de México&lt;/a&gt; y un método personalizado.&lt;/p&gt;

&lt;p&gt;El código para generar el mapa y calcular las isócronas está disponible &lt;a href=&quot;https://github.com/tudelft3d/isochrones-mexico&quot;&gt;aquí&lt;/a&gt;.&lt;/p&gt;
</description>
          <pubDate>Tue, 22 Nov 2022 11:47:00 -0600</pubDate>
          <link>https://3d.bk.tudelft.nl/ken/es/2022/11/22/30-day-map-challenge.html</link>
          <guid isPermaLink="true">https://3d.bk.tudelft.nl/ken/es/2022/11/22/30-day-map-challenge.html</guid>
          
          
          <category>es</category>
          
      </item>
    
        <item>
          <title>Cómo molestar a quienes envían sus trabajos a tu conferencia o revista científica</title>
          <description>&lt;p&gt;A veces puede parecer que los organizadores de conferencias y los editores se esfuerzan por imponer a los autores tantas reglas sin sentido como sea posible. Así que decidí compilar una lista de mis favoritas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Actualizado el 11 de julio de 2017&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;conferencias&quot;&gt;Conferencias&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Cambia tus fechas límite de envío muchas veces sin previo aviso, preferiblemente después de que la fecha anterior ya haya pasado. A todo el mundo le encanta afanarse por cumplir una fecha límite y luego enterarse de que pudieron haber evitado trabajar en sus vacaciones.&lt;/li&gt;
  &lt;li&gt;Diles a quienes envían sus trabajos a tu conferencia que los mejores artículos se publicarán en una revista de alto perfil. Solo después de la conferencia les dices que los artículos tendrán que ampliarse y pasar por rondas adicionales de revisión.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;contenido-del-artículo&quot;&gt;Contenido del artículo&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Limita el uso de extractos del trabajo de otras personas. Que se vaya al diablo el &lt;a href=&quot;https://en.wikipedia.org/wiki/Fair_use&quot;&gt;uso justo&lt;/a&gt;, ¡esa es la manera de hacerlo!&lt;/li&gt;
  &lt;li&gt;Impón una lista estándar de secciones. Todo el trabajo es básicamente el mismo, así que todo cabe en el mismo formato. Esto de ninguna manera socava la capacidad de los autores de explicar su trabajo.&lt;/li&gt;
  &lt;li&gt;Pide a los autores que pasen horas buscando detalles bibliográficos oscuros para cada una de sus fuentes. Todos necesitan saber la dirección antigua de una editorial desaparecida.&lt;/li&gt;
  &lt;li&gt;Los nombres de las revistas deben abreviarse de acuerdo con &lt;a href=&quot;http://www.issn.org/services/online-services/access-to-the-ltwa/&quot;&gt;una lista&lt;/a&gt;. Esto de ninguna manera es una práctica ridícula. ¡Cada carácter ahorrado cuenta!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;latex-vs-word&quot;&gt;LaTeX vs. Word&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;No proporciones una plantilla de LaTeX. Enviarse archivos de Microsoft Word de ida y vuelta por correo electrónico es la mejor forma de colaboración. Fusionar los cambios de varias personas siempre es muy divertido.&lt;/li&gt;
  &lt;li&gt;Si no tienes la experiencia técnica para lidiar con archivos LaTeX, solo dile a la gente que aceptas LaTeX pero luego pide un archivo .doc una vez que un artículo sea aceptado. Los &lt;a href=&quot;https://en.wikipedia.org/wiki/Sunk_cost&quot;&gt;costos hundidos&lt;/a&gt; garantizarán que los autores hagan minuciosamente la conversión sin costo alguno para ti.&lt;/li&gt;
  &lt;li&gt;Implementa un sistema de compilación de LaTeX en vivo en lugar de hacer cargas de PDF. Pasar un día depurando un archivo LaTeX en incrementos de 15 minutos es un gran uso del tiempo de los investigadores.&lt;/li&gt;
  &lt;li&gt;Proporciona una plantilla de LaTeX que no coincida con la plantilla de Word. Luego pide a los autores que jueguen con su manuscrito hasta que lo haga.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;lenguaje-y-formato&quot;&gt;Lenguaje y formato&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Exige una variedad específica de inglés. El inglés británico y el inglés americano son mutuamente ininteligibles, así que tiene sentido que tus lectores solo entiendan uno de ellos. Además, nadie es más capaz de lidiar con esto que un científico cuyo idioma nativo no es el inglés.&lt;/li&gt;
  &lt;li&gt;No permitas subfiguras. Es mucho mejor que los autores las fusionen en una sola figura improvisada con etiquetas de tamaño incómodo y fuentes disparejas.&lt;/li&gt;
  &lt;li&gt;El texto rasterizado en las figuras siempre es genial. Obligar a los usuarios a ponerlo ahí limitando lo que pueden poner en un pie de figura es solo pensamiento inteligente.&lt;/li&gt;
  &lt;li&gt;Obliga a los autores a enviar sus archivos de figuras nombrados de acuerdo con el número de su figura. Todos conocen sus figuras por número en lugar de por su contenido, ¿verdad?&lt;/li&gt;
  &lt;li&gt;Limita las figuras a color. A quién le importa si hace que tus figuras sean mucho más difíciles de leer. Los lectores siempre usan las versiones impresas de una revista o imprimen un artículo en impresoras de matriz de puntos, ¿verdad?&lt;/li&gt;
  &lt;li&gt;Limita los tamaños de archivo a unos pocos MB. Los gráficos de baja calidad son mucho preferibles a un archivo PDF algo grande.&lt;/li&gt;
  &lt;li&gt;Diles a los autores que empujen todas sus figuras al final del artículo. Ir y venir mientras se lee es lo mejor.&lt;/li&gt;
  &lt;li&gt;Limita los formatos de archivos de imagen a EPS o TIFF de última generación.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;envío-revisión-y-publicación&quot;&gt;Envío, revisión y publicación&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Cobra unos cuantos miles de dólares/euros por la publicación de acceso abierto. La edición y el alojamiento profesionales son súper caros. Claramente &lt;a href=&quot;https://www.theguardian.com/science/2017/jun/27/profitable-business-scientific-publishing-bad-for-science&quot;&gt;no hay ni un indicio de precios de monopolio ahí&lt;/a&gt;. Ninguno en absoluto.&lt;/li&gt;
  &lt;li&gt;Obliga a quienes envían sus trabajos a sugerir unos cuantos revisores amigables. Seguramente esto de ninguna manera socava la imparcialidad de una revisión.&lt;/li&gt;
  &lt;li&gt;Permite que los revisores fuercen a los autores a citar el trabajo de los propios revisores. Los editores obviamente no están en posición de detener esta mala práctica.&lt;/li&gt;
  &lt;li&gt;Rechaza artículos sin revisión sin razón obvia. Puntos extra si lo haces con una carta genérica con una lista de razones &lt;em&gt;potenciales&lt;/em&gt; para que los autores adivinen cuál se aplica a ellos.&lt;/li&gt;
  &lt;li&gt;No aceptes archivos zip. En su lugar, haz que los autores suban cada figura por separado. Solo haz clic en añadir archivo, navega y sube cada vez. ¡Pan comido!&lt;/li&gt;
  &lt;li&gt;Obliga a los autores a anonimizar el artículo pero no elimines la información del autor de los metadatos del archivo. Es divertido dejarla ahí para que los revisores con inclinaciones técnicas la encuentren.&lt;/li&gt;
&lt;/ul&gt;
</description>
          <pubDate>Mon, 10 Jul 2017 18:23:00 -0500</pubDate>
          <link>https://3d.bk.tudelft.nl/ken/es/2017/07/10/how-to-annoy-submitters-to-your-scientific-conference-or-journal.html</link>
          <guid isPermaLink="true">https://3d.bk.tudelft.nl/ken/es/2017/07/10/how-to-annoy-submitters-to-your-scientific-conference-or-journal.html</guid>
          
          
          <category>es</category>
          
      </item>
    
        <item>
          <title>Problemas metodológicos al usar los datos de contaminación de la Ciudad de México</title>
          <description>&lt;p&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:AerialViewMexicoCity.jpg&quot;&gt;&lt;img src=&quot;/ken/img/blog/mexico-city.jpg&quot; class=&quot;img-fluid center-block&quot; alt=&quot;Contaminación en la Ciudad de México&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La contaminación en la Ciudad de México ha sido un problema durante décadas.
Recuerdo mi infancia a principios de los años 90 como una época de cielos siempre grises, gasolina con plomo barata e historias casi increíbles de &lt;a href=&quot;http://articles.chicagotribune.com/1986-02-04/news/8601090418_1_pollution-levels-mexico-city-dead-birds&quot;&gt;aves que caían muertas del cielo&lt;/a&gt;.
En 1992, la Ciudad de México obtuvo el dudoso honor de ser la ciudad más contaminada del planeta.
Muchos habitantes de la ciudad se indignaron&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Hoy en día los cielos son mayormente azules y la situación ha mejorado mucho, lo cual es un logro real considerando la poco afortunada ubicación de la Ciudad de México en un valle cerrado a más de 2 km sobre el nivel del mar&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.
Esta mejora no fue coincidencia.
Tras los peores años de la crisis de contaminación vinieron acciones enérgicas, incluyendo el cierre de una refinería de petróleo, el traslado de ciertas fábricas fuera de la ciudad y la obligación de que todos los autos instalaran convertidores catalíticos y se sometieran a estrictos controles de emisiones dos veces al año.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/ken/img/blog/simat.png&quot; class=&quot;img-fluid center-block&quot; alt=&quot;SIMAT&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Sin embargo, la reacción más previsora fue quizá la creación en 1986 de un sistema de monitoreo de contaminación para toda la ciudad, ahora conocido como &lt;a href=&quot;http://www.aire.cdmx.gob.mx&quot;&gt;SIMAT&lt;/a&gt;.
El sistema es reconocido como un gran éxito y se usa ampliamente.
Por ejemplo, si los niveles de contaminación alcanzan cierto nivel en un día dado, se imponen restricciones a la circulación de autos para el día siguiente.
Mucha gente en la Ciudad de México revisa los niveles de contaminación con más frecuencia que el pronóstico del tiempo&lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Si bien los datos crudos de contaminación son generalmente considerados precisos y confiables, tienen algunas peculiaridades:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Las estaciones de monitoreo de contaminación se han movido &lt;em&gt;muchas veces&lt;/em&gt; y el número de estaciones ha fluctuado constantemente.&lt;/li&gt;
  &lt;li&gt;No todos los contaminantes se miden en todas las estaciones.&lt;/li&gt;
  &lt;li&gt;Las estaciones se desconectan regularmente para mantenimiento.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Todo lo anterior significa que muchos (¿la mayoría?) de los usuarios de los datos de contaminación de la Ciudad de México los usan incorrectamente &lt;strong&gt;incluyendo los gobiernos de la Ciudad de México y el federal mexicano&lt;/strong&gt;.
Este post de blog documenta un par de malos ejemplos que muestran lo que creo que son los principales usos incorrectos de los datos y ojalá ayude a otros a usarlos mejor.&lt;/p&gt;

&lt;h2 id=&quot;estadísticas-estadísticamente-débiles&quot;&gt;Estadísticas estadísticamente débiles&lt;/h2&gt;

&lt;p&gt;Un grupo de trabajo intergubernamental conocido como la &lt;em&gt;&lt;a href=&quot;http://www.gob.mx/comisionambiental&quot;&gt;Comisión Ambiental de la Megalópolis&lt;/a&gt;&lt;/em&gt; emite alertas ambientales basadas en el nivel máximo de contaminación en la ciudad.
Esto es estadísticamente sospechoso: cuantas más estaciones estén en línea, más probable es que se detecte un pico local de contaminación y se emita una alerta ambiental.
&lt;em&gt;A su vez, esto crea un incentivo perverso para que el gobierno reduzca el número de estaciones de monitoreo de contaminación y las ubique lejos de las áreas contaminadas.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Por ejemplo, la estación en Xalostoc (una zona industrial al noreste de la zona metropolitana) suele ser la más contaminada de la ciudad.
Si esta estación está (temporalmente) fuera de línea, las posibilidades de que se declare una alerta de contaminación disminuyen sustancialmente.
Estoy seguro de que si se integraran más estaciones al sistema, particularmente en otras zonas industriales como Cuautitlán Izcalli, Iztapalapa, o los vecinos valles de Toluca o del Mezquital (que también son parte de la megalópolis), provocaría que el número de alertas de contaminación aumentara.&lt;/p&gt;

&lt;p&gt;Como otro ejemplo de estadísticas estadísticamente débiles, considera los &lt;a href=&quot;http://www.aire.cdmx.gob.mx/default.php?opc=&apos;aqBhnmOkYw==&apos;&quot;&gt;bonitos mosaicos&lt;/a&gt; que muestran los datos máximos de contaminantes de cada día durante los últimos años.
También usan solo el máximo y no toman en cuenta el aumento general en el número de estaciones a lo largo de los años.&lt;/p&gt;

&lt;h2 id=&quot;no-manejando-correctamente-los-huecos-en-los-datos&quot;&gt;No manejando correctamente los huecos en los datos&lt;/h2&gt;

&lt;p&gt;Los niveles crudos de contaminantes son difíciles de entender para los no especialistas.
Por lo tanto, el gobierno de México (como la mayoría de los otros gobiernos) ha definido un &lt;em&gt;índice de contaminación&lt;/em&gt; llamado IMECA.
Su valor se calcula independientemente para cada contaminante (CO, CO&lt;sub&gt;2&lt;/sub&gt;, NO&lt;sub&gt;2&lt;/sub&gt;, ozono, PM&lt;sub&gt;10&lt;/sub&gt;, PM&lt;sub&gt;2.5&lt;/sub&gt;, etc.), pero el único número que está fácilmente disponible y se difunde ampliamente a la población es el máximo de todos los contaminantes por estación&lt;sup id=&quot;fnref:4&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Cuando consideras este asunto junto con el hecho de que no todas las estaciones miden todos los contaminantes, otro problema se vuelve evidente: el valor de IMECA de cada estación es en realidad solo un límite inferior (en contraposición a su valor real pero desconocido) y &lt;strong&gt;estos valores no pueden interpolarse&lt;/strong&gt;.
Y sin embargo, son interpolados directamente por la mayoría de los servicios, incluyendo el por lo demás excelente &lt;a href=&quot;https://hoyodesmog.diegovalle.net/&quot;&gt;Hoyo de Smog&lt;/a&gt; y la aplicación de &lt;a href=&quot;https://www.netatmo.com/&quot;&gt;Netatmo&lt;/a&gt;.
Esta es una forma completamente equivocada de proporcionar datos de contaminación en cada ubicación&lt;sup id=&quot;fnref:5&quot;&gt;&lt;a href=&quot;#fn:5&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;div class=&quot;row&quot;&gt;
	&lt;div class=&quot;col-sm-6 col-xs-6&quot;&gt;&lt;img src=&quot;/ken/img/blog/simat-coyoacan-1.png&quot; class=&quot;img-fluid center-block&quot; alt=&quot;SIMAT Coyoacán 1&quot; /&gt;&lt;/div&gt;
	&lt;div class=&quot;col-sm-6 col-xs-6&quot;&gt;&lt;img src=&quot;/ken/img/blog/simat-coyoacan-2.png&quot; class=&quot;img-fluid center-block&quot; alt=&quot;SIMAT Coyoacán 2&quot; /&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Como otro mal ejemplo, considera los mapas que se muestran en el sitio web de SIMAT.
Aparentemente, mi alcaldía de origen, Coyoacán (rodeada en rojo), es más limpia que el área circundante, ¿verdad?
En realidad, las estaciones de monitoreo de la alcaldía no miden PM&lt;sub&gt;10&lt;/sub&gt;, que es el principal contaminante en estos fríos días de invierno&lt;sup id=&quot;fnref:6&quot;&gt;&lt;a href=&quot;#fn:6&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;.
Esto es doblemente engañoso en la vista de alcaldías/municipios que se muestra a la derecha, donde (de nuevo) las alcaldías/municipios con menos estaciones y que miden menos contaminantes generalmente se muestran como más limpias.&lt;/p&gt;

&lt;p&gt;Quizá algún día termine creando mi propio mapa de contaminación en tiempo real. Ese sería un buen proyecto pequeño.&lt;/p&gt;

&lt;h2 id=&quot;apéndice-obteniendo-los-datos&quot;&gt;Apéndice: obteniendo los datos&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.aire.cdmx.gob.mx/mapa-concentraciones/mapa.php&quot;&gt;La mejor página para analizar los datos en tiempo real por contaminante&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.aire.cdmx.gob.mx/default.php?opc=&apos;aKBhnmI=&apos;&amp;amp;opcion=Zg==&quot;&gt;Datos archivados desde 1986&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;pero la naturaleza cínica de los &lt;em&gt;chilangos&lt;/em&gt; hizo que más de unos cuantos lo llevaran con orgullo… &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;Ninguna otra megaciudad está en una ubicación igualmente difícil. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot;&gt;
      &lt;p&gt;lo cual quizá no es una sorpresa considerando el clima predeciblemente templado de la Ciudad de México &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot;&gt;
      &lt;p&gt;que es otro caso de estadísticas estadísticamente débiles… &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:5&quot;&gt;
      &lt;p&gt;Una solución todavía simple pero mucho mejor: interpolar los valores de IMECA por contaminante, y después usar el máximo en todas partes. &lt;a href=&quot;#fnref:5&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:6&quot;&gt;
      &lt;p&gt;debido a las &lt;a href=&quot;https://en.wikipedia.org/wiki/Inversion_(meteorology)&quot;&gt;inversiones térmicas&lt;/a&gt; que atrapan la contaminación en el valle &lt;a href=&quot;#fnref:6&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
          <pubDate>Tue, 10 Jan 2017 21:08:00 -0600</pubDate>
          <link>https://3d.bk.tudelft.nl/ken/es/2017/01/10/methodological-problems-using-mexico-city's-pollution-data.html</link>
          <guid isPermaLink="true">https://3d.bk.tudelft.nl/ken/es/2017/01/10/methodological-problems-using-mexico-city's-pollution-data.html</guid>
          
          
          <category>es</category>
          
      </item>
    
        <item>
          <title>Llamando C++ desde Swift</title>
          <description>&lt;p&gt;Cuando recientemente estaba trabajando en &lt;a href=&quot;https://github.com/tudelft3d/azul&quot;&gt;azul&lt;/a&gt;, un visor de CityGML para Mac, mi primer pensamiento fue hacer un proyecto de Swift 3 puro. Pero ay, pronto descubrí que el &lt;a href=&quot;https://developer.apple.com/reference/foundation/xmlparser&quot;&gt;XmlParser&lt;/a&gt; de Apple es terriblemente lento. En comparación con &lt;a href=&quot;https://github.com/tudelft3d/val3dity&quot;&gt;val3dity&lt;/a&gt;, la primera versión funcional del visor era al menos 10 veces más lenta en el análisis de XML.&lt;/p&gt;

&lt;p&gt;La solución a este problema fue bastante simple: usar &lt;a href=&quot;http://pugixml.org&quot;&gt;pugixml&lt;/a&gt; como backend de análisis de XML en su lugar&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. Sin embargo, pugixml está escrito en C++ y por lo tanto no se puede llamar directamente desde Swift. En mi campo de investigación en SIG esto es en realidad un problema muy típico, ya que la mayoría de las bibliotecas útiles están escritas en C/C++ (por ejemplo, Boost, CGAL, GDAL, GEOS). Considerando el tiempo relativamente corto que Swift lleva fuera y su reconocidamente limitado atractivo, sospecho que este es el caso de mucha gente.&lt;/p&gt;

&lt;p&gt;Entonces, ¿cómo llamas código de C++ desde Swift 3? Hay diferentes maneras de hacerlo, pero en mi opinión la mejor involucra un doble envoltorio de Objective-C++ con un header de Objective-C puro.&lt;/p&gt;

&lt;h2 id=&quot;un-doble-envoltorio&quot;&gt;Un doble envoltorio&lt;/h2&gt;

&lt;p&gt;Usaré ejemplos tomados directamente de azul. Así que, asumiendo que tienes una clase de C++ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CityGMLParser&lt;/code&gt;, simplemente necesitas crear un header de Objective-C &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CityGMLParserWrapperWrapper.h&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objective_c&quot; data-lang=&quot;objective_c&quot;&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CityGMLParserWrapper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;@interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CityGMLParserWrapperWrapper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;NSObject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CityGMLParserWrapper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parserWrapper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dealloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Nota que usamos una declaración adelantada del primer envoltorio &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CityGMLParserWrapper&lt;/code&gt; y almacenamos un &lt;em&gt;puntero&lt;/em&gt; a él en el segundo envoltorio. De esta manera, podemos mantener el header como Objective-C puro y así llamarlo desde Swift.&lt;/p&gt;

&lt;p&gt;A continuación, definimos su implementación en un Objective-C++ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CityGMLParserWrapperWrapper.mm&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objective_c&quot; data-lang=&quot;objective_c&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#import &quot;CityGMLParserWrapperWrapper.h&quot;
#import &quot;CityGMLParser.hpp&quot;
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CityGMLParserWrapper&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;CityGMLParser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;@implementation&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CityGMLParserWrapperWrapper&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;init&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;super&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;parserWrapper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CityGMLParserWrapper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;parserWrapper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CityGMLParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dealloc&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parserWrapper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parserWrapper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Nota que &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CityGMLParser&lt;/code&gt; es la clase de C++, y que necesitamos crear los dos niveles de envoltorio en &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init&lt;/code&gt; y eliminarlos (al estilo C++) en el &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dealloc&lt;/code&gt;. Este archivo puede contener tanto C++ como Objective-C++ lo permita.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/ken/img/blog/bridging-header.png&quot; class=&quot;img-fluid center-block&quot; alt=&quot;Configurando el bridging header en Xcode&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Finalmente, probablemente necesites añadir un &lt;em&gt;bridging header&lt;/em&gt; que contenga la declaración de importación de tu envoltorio doble para que pueda ser usado en Swift. Si usas Xcode, esto debe configurarse en la pestaña Build Settings de la configuración del proyecto. Simplemente necesita contener algo como:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objective_c&quot; data-lang=&quot;objective_c&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#import &quot;CityGMLParserWrapperWrapper.h&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;pasando-información-entre-código-de-c-y-de-swift&quot;&gt;Pasando información entre código de C++ y de Swift&lt;/h2&gt;

&lt;p&gt;Ahora, probablemente necesitarás pasar información entre el código de C++ y el de Swift. Esto es relativamente sencillo, pero es una de las áreas donde Swift ofrece poco azúcar sintáctico.&lt;/p&gt;

&lt;p&gt;Si estás usando un tipo de datos &lt;a href=&quot;http://en.cppreference.com/w/cpp/concept/PODType&quot;&gt;POD&lt;/a&gt;, esto es lo más fácil. Solo añade getters y setters apropiados en tu envoltorio doble. Estos deberían hacer llamadas de la forma &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;return parserWrapper-&amp;gt;parser-&amp;gt;...&lt;/code&gt; o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;parserWrapper-&amp;gt;parser-&amp;gt;... = ...&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Así que veamos directamente algo un poco más difícil: cómo leer un arreglo u otra secuencia de elementos contiguos en memoria de tamaño conocido.&lt;/p&gt;

&lt;h3 id=&quot;un-par-de-arreglos&quot;&gt;Un par de arreglos&lt;/h3&gt;

&lt;p&gt;En mi código de C++, tengo un par de arreglos que guardan la caja delimitadora que rodea mis datos:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;minCoordinates&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxCoordinates&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Para acceder a estos, tengo un par de declaraciones de métodos en mi envoltorio de Objective-C:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objective_c&quot; data-lang=&quot;objective_c&quot;&gt;&lt;span class=&quot;k&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;minCoordinates&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxCoordinates&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Nota que devolveremos un &lt;em&gt;puntero&lt;/em&gt;. Esta será la dirección del primer elemento de cada arreglo. Entonces, la implementación de estos métodos es sencilla:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objective_c&quot; data-lang=&quot;objective_c&quot;&gt;&lt;span class=&quot;k&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;minCoordinates&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parserWrapper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;minCoordinates&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxCoordinates&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parserWrapper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;maxCoordinates&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;iteradores&quot;&gt;Iteradores&lt;/h3&gt;

&lt;p&gt;Ahora veamos un ejemplo más complejo. En azul, necesitaba una forma de obtener estructuras de datos mucho más complejas que fueron creadas en C++. Estas estructuras de datos consistían en &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::lists&lt;/code&gt; de clases personalizadas que contenían varios atributos.&lt;/p&gt;

&lt;p&gt;En tales casos donde no sabes exactamente dónde podrían estar almacenadas las cosas&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, la forma más fácil de transferir información es definiendo iteradores personalizados y pasando la información objeto por objeto y atributo por atributo.&lt;/p&gt;

&lt;p&gt;Así que, en mi código de C++ creé varios iteradores como este:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CityGMLObject&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;const_iterator&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currentObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Entonces, en el envoltorio doble definí los métodos apropiados para inicializar, avanzar y comprobar si el iterador ha terminado:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objective_c&quot; data-lang=&quot;objective_c&quot;&gt;&lt;span class=&quot;k&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initialiseObjectIterator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;advanceObjectIterator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BOOL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;objectIteratorEnded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Estos pueden implementarse simplemente llamando a las respectivas funciones de iterador de C++:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objective_c&quot; data-lang=&quot;objective_c&quot;&gt;&lt;span class=&quot;k&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initialiseObjectIterator&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;parserWrapper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;currentObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parserWrapper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;advanceObjectIterator&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parserWrapper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;currentObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BOOL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;objectIteratorEnded&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parserWrapper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;currentObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parserWrapper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;cadenas-de-texto&quot;&gt;Cadenas de texto&lt;/h3&gt;

&lt;p&gt;Ahora, veamos cómo extraer variables de C++ un poco más complejas como &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::strings&lt;/code&gt; u otros tipos que pueden extraerse como bloques contiguos de memoria que no tienen una longitud fija.&lt;/p&gt;

&lt;p&gt;En el caso de un &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::string&lt;/code&gt;, el truco es usar su representación en C como un &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;const char *&lt;/code&gt; y también recibir un lugar donde pasar su longitud al código de Swift. Un getter en el envoltorio doble puede entonces verse así:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objective_c&quot; data-lang=&quot;objective_c&quot;&gt;&lt;span class=&quot;k&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;currentObjectTypeWithLength&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Nota que usamos un &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unsigned long&lt;/code&gt; ya que eso es equivalente a un &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UInt&lt;/code&gt; de Swift. La implementación sería así:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-objective_c&quot; data-lang=&quot;objective_c&quot;&gt;&lt;span class=&quot;k&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;currentObjectTypeWithLength&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parserWrapper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;currentObject&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parserWrapper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;currentObject&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;A diferencia de los otros ejemplos, el código de Swift no es trivial y por lo tanto también lo explicaré:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;objectTypeLength&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UInt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;firstElementOfObjectTypeBuffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UnsafeRawPointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cityGMLParser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;currentObjectType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;withLength&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objectTypeLength&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;objectTypeData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;firstElementOfObjectTypeBuffer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objectTypeLength&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;MemoryLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;objectTypeData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;utf8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Hay algunas cosas que ver aquí. Primero definimos la variable donde almacenaremos la longitud de la cadena &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;objectTypeLength&lt;/code&gt; y la pasamos como un puntero usando &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;objectTypeLength&lt;/code&gt;. El valor de retorno se convierte inmediatamente a un &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UnsafeRawPointer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Entonces, usamos el &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Data&lt;/code&gt; de Swift para almacenar el contenido del buffer en la ubicación del puntero devuelto. Y finalmente, podemos crear una &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt; de Swift usando los datos del buffer.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;que también se usa en val3dity &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;o es engorroso averiguarlo &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
          <pubDate>Mon, 05 Dec 2016 17:44:00 -0600</pubDate>
          <link>https://3d.bk.tudelft.nl/ken/es/2016/12/05/calling-c++-from-swift.html</link>
          <guid isPermaLink="true">https://3d.bk.tudelft.nl/ken/es/2016/12/05/calling-c++-from-swift.html</guid>
          
          
          <category>es</category>
          
      </item>
    
        <item>
          <title>Swift 3 y Metal</title>
          <description>&lt;div class=&quot;row&quot;&gt;
	&lt;div class=&quot;col-sm-6 col-xs-6&quot;&gt;&lt;img src=&quot;/ken/img/blog/swift.svg&quot; class=&quot;img-fluid center-block&quot; alt=&quot;Configurando las opciones de compilación en Xcode&quot; /&gt;&lt;/div&gt;
	&lt;div class=&quot;col-sm-6 col-xs-6&quot;&gt;&lt;img src=&quot;/ken/img/blog/metal.png&quot; class=&quot;img-fluid center-block&quot; alt=&quot;Configurando las opciones de compilación en Xcode&quot; /&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Como continuación del &lt;a href=&quot;https://3d.bk.tudelft.nl/ken/en/2016/11/05/swift-3-and-opengl.html&quot;&gt;post anterior&lt;/a&gt;, quizá también sea útil explicar la forma más fácil de dibujar en una vista de Cocoa usando Metal en lugar de OpenGL&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. Y como extra, también explico cómo elegir entre el renderizado con OpenGL o con Metal sobre la marcha.&lt;/p&gt;

&lt;h2 id=&quot;algo-de-contexto&quot;&gt;Algo de contexto&lt;/h2&gt;

&lt;p&gt;Apple nunca ha sido diligente a la hora de estar al día con las nuevas versiones de OpenGL (o con las tarjetas gráficas más recientes, para el caso), pero la situación ha llegado a un punto bastante malo. Incluso el hardware más nuevo solo soporta el &lt;em&gt;vetusto&lt;/em&gt; OpenGL 4.1 de hace seis años. En comparación, Metal está en desarrollo constante y cada WWDC se anuncian un montón de funciones nuevas. Pero quizá por la misma razón hay una escasez de documentación y de ejemplos buenos, introductorios y actualizados&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Ahora, para ser honesto, preferiría usar algo abierto y multiplataforma como &lt;a href=&quot;https://www.khronos.org/vulkan&quot;&gt;Vulkan&lt;/a&gt;, pero sigue sin estar disponible en macOS (y no espero que eso cambie en el futuro). O podría pasarme a Windows. Es broma. Por supuesto que me pasaría a Linux en su lugar.&lt;/p&gt;

&lt;h2 id=&quot;dibujando-en-un-mtkview&quot;&gt;Dibujando en un MTKView&lt;/h2&gt;

&lt;p&gt;Con mucho, la forma más fácil de dibujar en una vista de Cocoa es subclasificar &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MTKView&lt;/code&gt;, parte de MetalKit y disponible desde iOS 9 y El Capitan en adelante. Esto es similar a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NSOpenGLView&lt;/code&gt; para OpenGL, y significa que la mayoría de las cosas se gestionan automáticamente por ti. Así que probablemente necesites configurar una clase como esta:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Metal&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;MetalKit&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;MetalView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;MTKView&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;commandQueue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;MTLCommandQueue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;renderPipelineState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;MTLRenderPipelineState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;depthStencilState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;MTLDepthStencilState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Después, crea el método &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init()&lt;/code&gt; y configura ahí el dispositivo de Metal, las propiedades de MTKView, la cola de comandos, el pipeline de renderizado, los shaders y el depth stencil. Lo mismo si necesitas texturas u otros stencils.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;required&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;coder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSCoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;coder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;coder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;// Device&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;device&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;MTLCreateSystemDefaultDevice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;// View&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;clearColor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;MTLClearColorMake&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;colorPixelFormat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bgra8Unorm&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;depthStencilPixelFormat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;depth32Float&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;// Command queue&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;commandQueue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;makeCommandQueue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;// Render pipeline&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;library&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;newDefaultLibrary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;vertexFunction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;library&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;makeFunction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;vertexTransform&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;fragmentFunction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;library&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;makeFunction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;fragmentLit&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;renderPipelineDescriptor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;MTLRenderPipelineDescriptor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;renderPipelineDescriptor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vertexFunction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vertexFunction&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;renderPipelineDescriptor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fragmentFunction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fragmentFunction&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;renderPipelineDescriptor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;colorAttachments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pixelFormat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;colorPixelFormat&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;renderPipelineDescriptor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;depthAttachmentPixelFormat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;depthStencilPixelFormat&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;renderPipelineState&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;makeRenderPipelineState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;descriptor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;renderPipelineDescriptor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;Swift&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Unable to compile render pipeline state&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;// Depth stencil&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;depthSencilDescriptor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;MTLDepthStencilDescriptor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;depthSencilDescriptor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;depthCompareFunction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;less&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;depthSencilDescriptor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isDepthWriteEnabled&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;depthStencilState&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;makeDepthStencilState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;descriptor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;depthSencilDescriptor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Finalmente, crea el método &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;draw&lt;/code&gt;, que se llamará automáticamente en cada frame, automáticamente con una notificación de la vista o manualmente, dependiendo de cómo configures &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isPaused&lt;/code&gt; y &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enableSetNeedsDisplay&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;draw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dirtyRect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSRect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;commandBuffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commandQueue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;makeCommandBuffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;renderPassDescriptor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currentRenderPassDescriptor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;renderEncoder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commandBuffer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;makeRenderCommandEncoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;descriptor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;renderPassDescriptor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;renderEncoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setFrontFacing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;counterClockwise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;renderEncoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setDepthStencilState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;depthStencilState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;renderEncoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setRenderPipelineState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;renderPipelineState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;// Draw something...&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;renderEncoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;endEncoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;drawable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currentDrawable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;commandBuffer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;present&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drawable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;commandBuffer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;commit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;eligiendo-entre-el-renderizado-con-metal-o-con-opengl-sobre-la-marcha&quot;&gt;Eligiendo entre el renderizado con Metal o con OpenGL sobre la marcha&lt;/h2&gt;

&lt;p&gt;Si te emociona el rendimiento de Metal (como a mí) pero quieres soportar hardware de Mac más antiguo que 2012 (como a mí), probablemente quieras elegir sobre la marcha entre subclases personalizadas de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MTKView&lt;/code&gt; y &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NSOpenGLView&lt;/code&gt;. De esa manera, probablemente puedas tirar el código de OpenGL en unos pocos años sin reescrituras importantes del código.&lt;/p&gt;

&lt;p&gt;Para mí, el primer paso fue aislar todo el código específico de OpenGL y de Metal en estas dos subclases. Después, creé un NSView de marcador de posición simple en Interface Builder y mantuve una referencia a él (aquí &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;view&lt;/code&gt;). Ahora, cuando tu aplicación se carga puedes hacer algo como esto:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;applicationDidFinishLaunching&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;aNotification&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Notification&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;processInfo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ProcessInfo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;processInfo&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;sierraOrHigher&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;processInfo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;isOperatingSystemAtLeast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;OperatingSystemVersion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;majorVersion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;minorVersion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;patchVersion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sierraOrHigher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;defaultDevice&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;MTLCreateSystemDefaultDevice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;metalView&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;MetalView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;splitView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subviews&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defaultDevice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;metalView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;controller&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;splitView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;removeArrangedSubview&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;splitView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arrangedSubviews&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;splitView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;insertArrangedSubview&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;metalView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;metalView&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;makeFirstResponder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;metalView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NSOpenGLPixelFormatAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;kt&quot;&gt;UInt32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NSOpenGLPFAAccelerated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
      &lt;span class=&quot;kt&quot;&gt;UInt32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NSOpenGLPFAColorSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UInt32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
      &lt;span class=&quot;kt&quot;&gt;UInt32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NSOpenGLPFADoubleBuffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
      &lt;span class=&quot;kt&quot;&gt;UInt32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NSOpenGLPFADepthSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UInt32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
      &lt;span class=&quot;kt&quot;&gt;UInt32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;pixelFormat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSOpenGLPixelFormat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;openGLView&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;OpenGLView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;splitView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subviews&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;pixelFormat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pixelFormat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;openGLView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;controller&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;splitView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;removeArrangedSubview&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;splitView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arrangedSubviews&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;splitView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;insertArrangedSubview&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;openGLView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;openGLView&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;makeFirstResponder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;openGLView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Nota algunas cosas. Si quieres soportar las funciones más nuevas de Metal hasta 2016&lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;, quieres probar el soporte de Sierra. Mi aplicación falla en 10.11 incluso con hardware compatible con Metal&lt;sup id=&quot;fnref:4&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;, así que he forzado OpenGL en 10.11 o inferior. La forma más fácil de probar el soporte de Metal es revisar el valor de retorno de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MTLCreateSystemDefaultDevice()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Además, sustituir una vista sobre la marcha es algo delicado. Sustituir solo la vista no tendrá ningún efecto, así que necesitas quitarla de su vista padre (en este caso &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;splitView&lt;/code&gt;, una instancia de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NSSplitView&lt;/code&gt;) y volver a añadir tu subclase de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MTKView&lt;/code&gt; o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NSOpenGLView&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finalmente, para que esto funcione necesitas usar diferentes inicializadores en tus subclases de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MTKView&lt;/code&gt; y &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NSOpenGLView&lt;/code&gt;. Estos deberían recibir el frame de la vista y otras variables en lugar de una instancia de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NSCoder&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// In the MTKView subclass:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;frameRect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CGRect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;MTLDevice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frameRect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Same as before...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// In the NSOpenGLView subclass:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSRect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;pixelFormat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSOpenGLPixelFormat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;pixelFormat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pixelFormat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Same as before...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;Para &lt;a href=&quot;https://github.com/tudelft3d/azul&quot;&gt;mi aplicación&lt;/a&gt;, esto resultó en una mejora de rendimiento de aproximadamente 10 veces en comparación con OpenGL. Tu kilometraje puede variar. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;La clara excepción a esto son las sesiones de la WWDC 2016 de Apple sobre Adopting Metal. Consulta la &lt;a href=&quot;https://developer.apple.com/videos/play/wwdc2016/602/&quot;&gt;parte 1&lt;/a&gt; y la &lt;a href=&quot;https://developer.apple.com/videos/play/wwdc2016/603/&quot;&gt;parte 2&lt;/a&gt;. No olvides revisar el código de muestra. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot;&gt;
      &lt;p&gt;¡¿Por qué Apple no pone números de versión claros?! &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot;&gt;
      &lt;p&gt;Al igual que el propio código de muestra de Adopting Metal de Apple… &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
          <pubDate>Thu, 17 Nov 2016 16:04:00 -0600</pubDate>
          <link>https://3d.bk.tudelft.nl/ken/es/2016/11/17/swift-3-and-metal.html</link>
          <guid isPermaLink="true">https://3d.bk.tudelft.nl/ken/es/2016/11/17/swift-3-and-metal.html</guid>
          
          
          <category>es</category>
          
      </item>
    
        <item>
          <title>Swift 3 y OpenGL</title>
          <description>&lt;div class=&quot;row&quot;&gt;
	&lt;div class=&quot;col-sm-4 col-xs-4&quot;&gt;&lt;img src=&quot;/ken/img/blog/swift.svg&quot; class=&quot;img-fluid center-block&quot; alt=&quot;Configurando las opciones de compilación en Xcode&quot; /&gt;&lt;/div&gt;
	&lt;div class=&quot;col-sm-8 col-xs-8&quot;&gt;&lt;img src=&quot;/ken/img/blog/opengl.svg&quot; class=&quot;img-fluid center-block&quot; alt=&quot;Configurando las opciones de compilación en Xcode&quot; /&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Aprender Swift había estado durante mucho tiempo en mi lista de pendientes. Así que, cuando recientemente emprendí el proyecto de escribir un visor de CityGML para Mac (que se lanzará pronto), decidí que el momento de aprender Swift era ahora. Afortunadamente, Apple acababa de lanzar Swift 3, y como me gustan las cosas nuevas y brillantes, decidí aprender Swift 3 directamente.&lt;/p&gt;

&lt;p&gt;Sin embargo, pronto me di cuenta de que la documentación de Apple es muy irregular. A pesar del nuevo aspecto de las páginas de documentación, &lt;em&gt;casi todo el código de muestra y los ejemplos todavía usan Objective-C&lt;/em&gt;. Además, interactuar con APIs de C de bajo nivel como OpenGL es más que un poco complejo, ya que requiere varias conversiones y el uso de tipos de datos similares a punteros.&lt;/p&gt;

&lt;p&gt;Por lo tanto, espero documentar algunos de los problemas que me dejaron atascado y cómo los resolví. En este post, explicaré cómo dibujar OpenGL en un NSOpenGLView o en un NSView personalizado. Para más información, consulta la &lt;a href=&quot;https://developer.apple.com/library/content/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_drawing/opengl_drawing.html&quot;&gt;documentación&lt;/a&gt; de Apple (que usa Objective-C). Echa un vistazo a &lt;a href=&quot;http://stackoverflow.com/questions/25981553/cvdisplaylink-with-swift&quot;&gt;esta&lt;/a&gt; pregunta y respuestas de Stack Overflow sobre cómo funciona esto con Swift 2.&lt;/p&gt;

&lt;h2 id=&quot;usando-nsopenglview&quot;&gt;Usando NSOpenGLView&lt;/h2&gt;

&lt;p&gt;La forma más fácil de dibujar OpenGL es subclasificar &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NSOpenGLView&lt;/code&gt;. De esta manera, la mayoría de las cosas se manejan automáticamente por ti. Así que probablemente necesites configurar una clase como esta:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Cocoa&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;OpenGL&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;GLKit&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;OpenGLView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSOpenGLView&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;displayLink&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CVDisplayLink&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Después, crea el método &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init?()&lt;/code&gt; y configura ahí el formato de píxeles, el contexto y el intervalo de intercambio de OpenGL.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;required&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;coder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSCoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;coder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;coder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NSOpenGLPixelFormatAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;UInt32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NSOpenGLPFAAccelerated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;UInt32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NSOpenGLPFAColorSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UInt32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;UInt32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NSOpenGLPFADoubleBuffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;UInt32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NSOpenGLPFAOpenGLProfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;UInt32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NSOpenGLProfileVersion3_2Core&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;UInt32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pixelFormat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSOpenGLPixelFormat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;openGLContext&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSOpenGLContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pixelFormat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;share&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;openGLContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setValues&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSOpenGLCPSwapInterval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Después, crea el método &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;prepareOpenGL()&lt;/code&gt; y su callback. Esto se llamará antes del primer render y tiene como objetivo inicializar el estado de OpenGL. En este ejemplo, configuramos &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CVDisplayLink&lt;/code&gt; para que se llame a una función callback que renderice cada nuevo frame.&lt;/p&gt;

&lt;p&gt;Nota los tipos de puntero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UnsafePointer&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UnsafeMutablePointer&lt;/code&gt; y &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UnsafeMutableRawPointer&lt;/code&gt;, y cómo &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unsafeBitCast&lt;/code&gt; se usa para convertir el &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UnsafeMutableRawPointer&lt;/code&gt; en una instancia de la clase actual. Esto es necesario para poder llamar cualquier método.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;prepareOpenGL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    
  &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;displayLinkOutputCallback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;displayLink&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CVDisplayLink&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UnsafePointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;CVTimeStamp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;outputTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UnsafePointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;CVTimeStamp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;flagsIn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CVOptionFlags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;flagsOut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UnsafeMutablePointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;CVOptionFlags&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;displayLinkContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UnsafeMutableRawPointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CVReturn&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nf&quot;&gt;unsafeBitCast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;displayLinkContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;OpenGLView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;renderFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kCVReturnSuccess&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;kt&quot;&gt;CVDisplayLinkCreateWithActiveCGDisplays&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;displayLink&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;CVDisplayLinkSetOutputCallback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;displayLink&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;displayLinkOutputCallback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UnsafeMutableRawPointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Unmanaged&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;passUnretained&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;toOpaque&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()))&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;CVDisplayLinkStart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;displayLink&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;El método &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;renderFrame()&lt;/code&gt; es llamado por la función callback en el &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CVDisplayLink&lt;/code&gt;. Ahí, puedes usar cualquier función de dibujo de OpenGL.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;renderFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;CGLLockContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;openGLContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cglContextObj&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;// Draw something...&lt;/span&gt;

  &lt;span class=&quot;kt&quot;&gt;CGLFlushDrawable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;openGLContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cglContextObj&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;CGLUnlockContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;openGLContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cglContextObj&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;El método de dibujo debería llamar también a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;renderFrame()&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;draw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dirtyRect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSRect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;draw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dirtyRect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;renderFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Finalmente, el método &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deinit()&lt;/code&gt; debería detener el display link.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;deinit&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;CVDisplayLinkStop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;displayLink&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;dibujando-en-un-nsview-personalizado&quot;&gt;Dibujando en un NSView personalizado&lt;/h2&gt;

&lt;p&gt;A veces, NSOpenGLView no es suficiente. Por ejemplo, NSOpenGLView no soporta compartir contexto, lo cual es un problema si quieres crear aplicaciones de pantalla completa. En esos casos, necesitas subclasificar &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NSView&lt;/code&gt; en su lugar. Apple proporciona &lt;a href=&quot;https://developer.apple.com/library/content/samplecode/GLFullScreen/Introduction/Intro.html&quot;&gt;este&lt;/a&gt; pedazo de código de muestra para ese propósito, pero también está escrito en Objective-C y muy desactualizado.&lt;/p&gt;

&lt;p&gt;Subclasificar &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NSView&lt;/code&gt; es similar al caso anterior. Sin embargo, necesitas conservar tu propio &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NSOpenGLPixelFormat&lt;/code&gt; y &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NSOpenGLContext&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Cocoa&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;OpenGL&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;GLKit&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;OpenGLView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSView&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;pixelFormat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSOpenGLPixelFormat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;openGLContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSOpenGLContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;displayLink&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CVDisplayLink&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;El método &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init?&lt;/code&gt; puede entonces ser prácticamente igual que antes, pero es necesario hacer que llame tu propio método para inicializar OpenGL (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setupDisplayLink()&lt;/code&gt;) y el display link. Si quieres compartir contexto, probablemente quieras crear otro método &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init?&lt;/code&gt; que reciba el contexto a compartir. Asegúrate de llamar &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;makeCurrentContext()&lt;/code&gt; en el contexto de OpenGL.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;required&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;convenience&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;coder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSCoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;coder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;coder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;coder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSCoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSOpenGLContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Set up pixel format and context...&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;coder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;coder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;openGLContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;makeCurrentContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;setupDisplayLink&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;

  &lt;span class=&quot;kt&quot;&gt;NotificationCenter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;addObserver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;#selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reshape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSNotification&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NSViewGlobalFrameDidChange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Los métodos sobreescritos para bloquear el foco y para dibujar la vista deberían establecer la vista del contexto como el propio view.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;lockFocus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lockFocus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;openGLContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;openGLContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;draw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dirtyRect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSRect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;openGLContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;openGLContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;// Actually draw something...&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;CVDisplayLinkIsRunning&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;displayLink&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;drawView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Finalmente, el método para dibujar cosas (llamado por &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;draw()&lt;/code&gt; o por el callback del display link) debería hacer lo mismo que antes, pero también asegurarse de establecer el contexto actual de OpenGL.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;drawView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;CGLLockContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;openGLContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cglContextObj&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;openGLContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;makeCurrentContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;// Draw things...&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;openGLContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;flushBuffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;CGLUnlockContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;openGLContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cglContextObj&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</description>
          <pubDate>Sat, 05 Nov 2016 15:17:00 -0600</pubDate>
          <link>https://3d.bk.tudelft.nl/ken/es/2016/11/05/swift-3-and-opengl.html</link>
          <guid isPermaLink="true">https://3d.bk.tudelft.nl/ken/es/2016/11/05/swift-3-and-opengl.html</guid>
          
          
          <category>es</category>
          
      </item>
    
        <item>
          <title>La terrible capa de transporte público de Google Maps</title>
          <description>&lt;p&gt;Hace dos días, Google lanzó una nueva versión de Google Maps. La mayoría de la gente parece estar de acuerdo en que es una buena mejora de un servicio que ya era genial. Cuando lo vi, inmediatamente me encantó el aspecto más limpio y la legibilidad mejorada.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/ken/img/blog/new-google-maps.png&quot; class=&quot;img-fluid center-block&quot; alt=&quot;El nuevo Google Maps&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Es decir, hasta que activé la capa de transporte público y vi que sigue tan fea y mal diseñada como siempre.&lt;/p&gt;

&lt;p&gt;Como alguien a quien le apasionan tanto los mapas como el transporte público, esto es decepcionante. Han pasado más de 10 años desde que Google Transit apareció por primera vez en Google Labs y casi 9 años desde que se integró a Google Maps. Y así que decidí escribir un post de ‘name and shame’ para ver cuánto tiempo le toma a Google poner sus mapas de transporte público a la altura.&lt;/p&gt;

&lt;p&gt;Entre otros problemas, la capa de tránsito de Google Maps sufre de líneas discontinuas, que se cruzan entre sí y entrecortadas, demasiado énfasis en las calles, etiquetas mal colocadas y mal coloreadas que a menudo son ilegibles, repetidas o faltantes, una falta de nombres de líneas y estaciones en la mayoría de los niveles de zoom, y una falta total del aspecto limpio de la capa estándar de Google Maps. En los países de Map Maker la información también es terriblemente inconsistente, con estaciones duplicadas, categorías equivocadas, nombres mal escritos, diferentes estilos de capitalización y mucha información superflua (por ejemplo, ‘Metro xxx’ para referirse a una estación llamada xxx).&lt;/p&gt;

&lt;p&gt;Pero no te fíes solo de mi palabra. Mejor échale un vistazo a las capturas de pantalla de abajo, que comparan la bastante buena capa de transporte público en Apple Maps&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; (arriba) con la terrible de Google Maps (abajo) en varias ciudades y a diferentes escalas. Estoy seguro de que tú también verás una multitud de problemas.&lt;/p&gt;

&lt;h3 id=&quot;berlin&quot;&gt;Berlin&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/ken/img/blog/berlin-apple.png&quot; class=&quot;img-fluid center-block&quot; alt=&quot;Berlin en Apple Maps&quot; /&gt;
&lt;br /&gt;
&lt;img src=&quot;/ken/img/blog/berlin-google.png&quot; class=&quot;img-fluid center-block&quot; alt=&quot;Berlin en Google Maps&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;london&quot;&gt;London&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/ken/img/blog/london-apple.png&quot; class=&quot;img-fluid center-block&quot; alt=&quot;London en Apple Maps&quot; /&gt;
&lt;br /&gt;
&lt;img src=&quot;/ken/img/blog/london-google.png&quot; class=&quot;img-fluid center-block&quot; alt=&quot;London en Google Maps&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;mexico-city&quot;&gt;Mexico City&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/ken/img/blog/mexico-city-apple.png&quot; class=&quot;img-fluid center-block&quot; alt=&quot;Mexico City en Apple Maps&quot; /&gt;
&lt;br /&gt;
&lt;img src=&quot;/ken/img/blog/mexico-city-google.png&quot; class=&quot;img-fluid center-block&quot; alt=&quot;Mexico City en Google Maps&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;montreal&quot;&gt;Montreal&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/ken/img/blog/montreal-apple.png&quot; class=&quot;img-fluid center-block&quot; alt=&quot;Montreal en Apple Maps&quot; /&gt;
&lt;br /&gt;
&lt;img src=&quot;/ken/img/blog/montreal-google.png&quot; class=&quot;img-fluid center-block&quot; alt=&quot;Montreal en Google Maps&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;new-york-city&quot;&gt;New York City&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/ken/img/blog/new-york-apple.png&quot; class=&quot;img-fluid center-block&quot; alt=&quot;New York City en Apple Maps&quot; /&gt;
&lt;br /&gt;
&lt;img src=&quot;/ken/img/blog/new-york-google.png&quot; class=&quot;img-fluid center-block&quot; alt=&quot;New York City en Google Maps&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;rio-de-janeiro&quot;&gt;Rio de Janeiro&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/ken/img/blog/rio-apple.png&quot; class=&quot;img-fluid center-block&quot; alt=&quot;Rio de Janeiro en Apple Maps&quot; /&gt;
&lt;br /&gt;
&lt;img src=&quot;/ken/img/blog/rio-google.png&quot; class=&quot;img-fluid center-block&quot; alt=&quot;Rio de Janeiro en Google Maps&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;san-francisco&quot;&gt;San Francisco&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/ken/img/blog/san-francisco-apple.png&quot; class=&quot;img-fluid center-block&quot; alt=&quot;San Francisco en Apple Maps&quot; /&gt;
&lt;br /&gt;
&lt;img src=&quot;/ken/img/blog/san-francisco-google.png&quot; class=&quot;img-fluid center-block&quot; alt=&quot;San Francisco en Google Maps&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;sydney&quot;&gt;Sydney&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/ken/img/blog/sydney-apple.png&quot; class=&quot;img-fluid center-block&quot; alt=&quot;Sydney en Apple Maps&quot; /&gt;
&lt;br /&gt;
&lt;img src=&quot;/ken/img/blog/sydney-google.png&quot; class=&quot;img-fluid center-block&quot; alt=&quot;Sydney en Google Maps&quot; /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;La verdad, esta es una de las pocas áreas donde Apple Maps está significativamente por delante de Google Maps. Aunque la cobertura de Apple Maps es bastante irregular. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
          <pubDate>Wed, 27 Jul 2016 00:16:00 -0500</pubDate>
          <link>https://3d.bk.tudelft.nl/ken/es/2016/07/27/the-awful-public-transport-layer-of-google-maps.html</link>
          <guid isPermaLink="true">https://3d.bk.tudelft.nl/ken/es/2016/07/27/the-awful-public-transport-layer-of-google-maps.html</guid>
          
          
          <category>es</category>
          
      </item>
    
        <item>
          <title>Programación independiente de la dimensión usando plantillas de C++</title>
          <description>&lt;p&gt;&lt;img src=&quot;/ken/img/blog/simplex.jpg&quot; class=&quot;img-fluid center-block&quot; alt=&quot;Símplices de varias dimensiones&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Es uno de esos dilemas típicos de la programación.
La sabiduría popular (entre programadores) dicta que tu código puede ser eficiente pero inflexible, o flexible pero intensivo en recursos.
Intentar hacer ambas cosas casi siempre falla &lt;em&gt;espectacularmente&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Sin embargo, de vez en cuando uno encuentra una excepción bastante asombrosa, que a primera vista puede parecer casi magia.
Es decir, hasta que aprendes cómo funciona a nivel técnico.
Por ejemplo, hace varios años me dejó perplejo cómo &lt;a href=&quot;http://dtrace.org/&quot;&gt;DTrace&lt;/a&gt;—un buen framework de rastreo—logra alcanzar &lt;a href=&quot;http://dtrace.org/blogs/brendan/2011/02/18/dtrace-pid-provider-overhead/&quot;&gt;cero sobrecarga&lt;/a&gt; cuando no está habilitado.&lt;/p&gt;

&lt;p&gt;Un tiempo después, tuve un sentimiento similar sobre cómo los &lt;a href=&quot;http://doc.cgal.org/latest/Combinatorial_map/index.html&quot;&gt;mapas combinatorios&lt;/a&gt; de CGAL logran ser a la vez rápidos y completamente independientes de la dimensión.
La respuesta está en una ingeniosa &lt;em&gt;meta-programación con plantillas&lt;/em&gt; usando plantillas recursivas de C++11, una solución que después incorporé extensamente en mi &lt;a href=&quot;https://3d.bk.tudelft.nl/ken/en/thesis/&quot;&gt;trabajo de doctorado&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;La meta-programación con plantillas es una técnica que usa plantillas para generar ciertas estructuras de datos o realizar ciertas computaciones durante la compilación de un programa en lugar de durante su ejecución.
Esta técnica se usa normalmente como una forma de apoyar la programación genérica definiendo funciones que pueden manejar indistintamente diferentes tipos de datos.
Por ejemplo, a menudo uso &lt;a href=&quot;http://www.cplusplus.com/forum/articles/9645/&quot;&gt;este&lt;/a&gt; ingenioso pedazo de código para parsear fácilmente números a diferentes tipos de datos.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c--&quot; data-lang=&quot;c++&quot;&gt;&lt;span class=&quot;k&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typename&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;string_to_number&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;def_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stringstream&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ss&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;const_iterator&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isdigit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;&apos;e&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;&apos;-&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;&apos;+&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;&apos;.&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ss&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ss&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;def_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Sin embargo, aparte de este uso común, las plantillas también pueden usarse para crear estructuras de datos y algoritmos complejos independientes del tipo y de la dimensión.
CGAL hace esto usando la técnica de programación &lt;a href=&quot;http://accu.org/index.php/journals/442&quot;&gt;Traits&lt;/a&gt;, que explota las declaraciones &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;typedef&lt;/code&gt; de C++ para crear tipos personalizados.
Como ejemplo, usé este tipo de enfoque en mi tesis para convertir conjuntos de datos de &lt;em&gt;n&lt;/em&gt; dimensiones en unos de &lt;em&gt;(n+1)&lt;/em&gt; dimensiones.
Los tipos de los conjuntos de datos de &lt;em&gt;n&lt;/em&gt; y &lt;em&gt;(n+1)&lt;/em&gt; dimensiones se derivan automáticamente con base en &lt;em&gt;n&lt;/em&gt;, que se pasa como parámetro de plantilla en tiempo de compilación.
Como la programación en dimensiones altas suele estar fuertemente limitada por el tiempo de CPU durante la ejecución, &lt;strong&gt;esto efectivamente trae lo mejor de ambos mundos: independencia de la dimensión y velocidad&lt;/strong&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c--&quot; data-lang=&quot;c++&quot;&gt;&lt;span class=&quot;k&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dimension&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Linear_cell_complex_extruder_with_range&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;public:&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;typename&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Linear_cell_complex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dimension&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Lower_dimensional_cell_complex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;typename&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Linear_cell_complex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dimension&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Higher_dimensional_cell_complex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Linear_cell_complex_extruder_with_range&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dimension&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  
&lt;span class=&quot;nl&quot;&gt;private:&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Lower_dimensional_cell_complex&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ldcc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Higher_dimensional_cell_complex&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hdcc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Sin embargo, para explotar realmente este tipo de mecanismo en la programación independiente de la dimensión, necesitas &lt;em&gt;plantillas recursivas&lt;/em&gt;.
Con ellas, puedes construir una estructura de datos compleja o resolver un problema iterando dimensión por dimensión en tiempo de compilación.&lt;/p&gt;

&lt;p&gt;Consideremos un ejemplo similar a uno usado en mi tesis, una estructura de datos donde queremos almacenar un valor (representado aquí por un &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;float&lt;/code&gt;, pero puede ser una estructura de datos arbitrariamente compleja por sí misma) para cada objeto (representado aquí por un puntero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Object *&lt;/code&gt;) de cada dimensión.
Esencialmente, esto sería un &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::map&amp;lt;Object *, float&amp;gt;&lt;/code&gt;.
Primero, definimos un &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct&lt;/code&gt; personalizado llamado &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Value_map_of_dimension&lt;/code&gt;, que almacena el mapa de valores para una sola dimensión (parametrizada con plantilla).
Nota el uso de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;typedef&lt;/code&gt; para definir &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type&lt;/code&gt; antes de usarlo.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c--&quot; data-lang=&quot;c++&quot;&gt;&lt;span class=&quot;k&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dimension&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Values_map_of_dimension&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;public:&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;values_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Después, usamos un &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct&lt;/code&gt; parametrizado con plantilla que define &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Values_map_tuple_per_dimension_up_to&lt;/code&gt;, que almacenará una tupla dependiente de la dimensión de las estructuras de datos anteriores donde cada elemento de la tupla contendrá una instancia de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Value_map_of_dimension&lt;/code&gt;.
Aquí, el primer parámetro de plantilla es la dimensión y el segundo es la tupla, que se inicializa con una vacía.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c--&quot; data-lang=&quot;c++&quot;&gt;&lt;span class=&quot;k&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dimension&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tuple&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Values_map_tuple_per_dimension_up_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Este &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct&lt;/code&gt; se especializa usando una plantilla recursiva que antepone a la tupla una instancia de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Values_map_of_dimension&lt;/code&gt; para la &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dimension&lt;/code&gt; actual y se llama a sí misma con &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dimension-1&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c--&quot; data-lang=&quot;c++&quot;&gt;&lt;span class=&quot;k&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dimension&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Values_map_tuple_per_dimension_up_to&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dimension&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tuple&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;typename&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Values_map_tuple_per_dimension_up_to&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dimension&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tuple&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Values_map_of_dimension&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dimension&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Finalmente, este &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct&lt;/code&gt; se especializa aún más con una condición de terminación para la dimensión 0, donde la tupla se devuelve tal cual.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c--&quot; data-lang=&quot;c++&quot;&gt;&lt;span class=&quot;k&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Values_map_tuple_per_dimension_up_to&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tuple&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tuple&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Values_map_of_dimension&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Para que el compilador construya esta estructura de datos correctamente, es crucial asegurarse de que el último &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct&lt;/code&gt; sea una especialización más completa de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Values_map_tuple_per_dimension_up_to&lt;/code&gt;.
Por lo tanto, debería tener un parámetro de plantilla menos que el anterior.&lt;/p&gt;
</description>
          <pubDate>Sun, 10 Jul 2016 14:39:00 -0500</pubDate>
          <link>https://3d.bk.tudelft.nl/ken/es/2016/07/10/dimension-independent-programming-using-c++-templates.html</link>
          <guid isPermaLink="true">https://3d.bk.tudelft.nl/ken/es/2016/07/10/dimension-independent-programming-using-c++-templates.html</guid>
          
          
          <category>es</category>
          
      </item>
    
        <item>
          <title>Usando un map o set de C++ con datos geométricos</title>
          <description>&lt;p&gt;Uno de los bloques de construcción más típicos de las computaciones geométricas eficientes es un &lt;em&gt;índice espacial&lt;/em&gt;. Usando un índice espacial, es posible realizar muchas operaciones simples rápidamente, como obtener un conjunto de puntos únicos. Tal operación puede usarse luego para cosas como construir una estructura de datos topológica o indexar objetos más complejos.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:RTree-Visualization-3D.svg&quot;&gt;&lt;img src=&quot;/ken/img/blog/rtree.svg&quot; class=&quot;img-fluid center-block&quot; alt=&quot;Un R-tree en 3D&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sin embargo, implementar correctamente un índice espacial es un desastre y, francamente, es excesivo para muchas aplicaciones prácticas. Y aún así, las computaciones sin uno pueden ser &lt;em&gt;increíblemente lentas&lt;/em&gt;. Así que a menudo recurro a un truco rápido—usar un &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set&lt;/code&gt; o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; de la biblioteca estándar de C++ con una función de comparación personalizada. Un &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set&lt;/code&gt; o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; ofrece acceso a sus elementos en tiempo logarítmico, muy parecido a la mayoría de los índices espaciales, y funciona de fábrica para los tipos de datos simples de toda la vida como &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;float&lt;/code&gt; o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int&lt;/code&gt;. Además, para poder usarlo con cualquier clase con la que estés trabajando, solo necesita un functor de comparación personalizado&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; que defina un ordenamiento de sus elementos&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Así que veamos un ejemplo de un código en el que estoy trabajando actualmente. Un &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Point_d&lt;/code&gt; de CGAL es una estructura de datos simple para un punto de &lt;em&gt;d&lt;/em&gt; dimensiones. Personalmente quiero usar este tipo de puntos para acceder rápidamente a objetos geométricos únicos ubicados en esas posiciones, así que creé un functor de comparación personalizado para ellos. Ordena los puntos primero por su dimensión y luego lexicográficamente por sus coordenadas:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c--&quot; data-lang=&quot;c++&quot;&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Point_d_comparator&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;operator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Point_d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Point_d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dimension&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dimension&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dimension&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dimension&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;Point_d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Cartesian_const_iterator&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p1_coordinate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cartesian_begin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Point_d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Cartesian_const_iterator&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p2_coordinate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cartesian_begin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p1_coordinate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cartesian_end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p1_coordinate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p2_coordinate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p1_coordinate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p2_coordinate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p1_coordinate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p2_coordinate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;En un ejemplo simple, tal functor de comparación puede usarse para definir un conjunto de puntos únicos (según se definen por sus coordenadas). Por ejemplo, esto te permite asignar identificadores únicos a una ubicación.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c--&quot; data-lang=&quot;c++&quot;&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Point_d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Point_d_comparator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vertices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;En un ejemplo más complejo, el mismo functor de comparación puede usarse para indexar un conjunto de aristas (según se definen por un par único de puntos inicio-fin). Personalmente uso este tipo de estructura para enlazar un conjunto de polígonos adyacentes por sus aristas comunes y para comprobar si tal conjunto forma un cuasi-manifold en 3D. ¡Ten en cuenta que debes asegurarte de insertar los dos puntos extremos en un orden bien definido, como el más pequeño lexicográficamente primero!&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c--&quot; data-lang=&quot;c++&quot;&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Point_d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Point_d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Point_d_comparator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Point_d_comparator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;edges&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Para una futura entrada de blog, cómo hacer algo similar con un &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unordered_map&lt;/code&gt; de C++11 más eficiente (tiempo constante) y una función de hash personalizada.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;Un functor es un objeto que se comporta como una función. En C++, un functor es una &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;class&lt;/code&gt; o &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct&lt;/code&gt; que hace esto sobrecargando el operador (). A diferencia de los punteros a función, son rápidos ya que se generan en tiempo de compilación. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;La mayoría de las personas eligen imitar el valor del operador &amp;lt; (menor que), que es lo que &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set&lt;/code&gt; y &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; hacen con los tipos simples. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
          <pubDate>Sun, 19 Jun 2016 18:25:00 -0500</pubDate>
          <link>https://3d.bk.tudelft.nl/ken/es/2016/06/19/using-a-c++-set-or-map-with-geometric-data.html</link>
          <guid isPermaLink="true">https://3d.bk.tudelft.nl/ken/es/2016/06/19/using-a-c++-set-or-map-with-geometric-data.html</guid>
          
          
          <category>es</category>
          
      </item>
    
        <item>
          <title>Configurando CGAL con Qt5 y QGLViewer en Mac</title>
          <description>&lt;p&gt;&lt;img src=&quot;/ken/img/blog/lcc-demo.png&quot; class=&quot;img-fluid center-block&quot; alt=&quot;Nuevo proyecto en Xcode&quot; /&gt;&lt;/p&gt;

&lt;p&gt;CGAL dejó de dar soporte a Qt4 con la versión 4.7 en octubre. Pero ay, su fórmula de &lt;a href=&quot;http://brew.sh&quot;&gt;Homebrew&lt;/a&gt; no se ha actualizado para reflejar esto. En términos prácticos esto significa que &lt;em&gt;no puedes usar aplicaciones Qt con CGAL&lt;/em&gt;, incluyendo todos los bonitos demos de GUI de CGAL que vienen listos para usar de fábrica (en su versión de Homebrew). Esto es malo si quieres construir tus propias aplicaciones de GUI, o usar los demos como tutorial o como base para tu propio código.&lt;/p&gt;

&lt;p&gt;Recientemente pasé algún tiempo tratando de hacer funcionar el demo de Linear Cell Complex en Mac con el mínimo de complicaciones. Como ese demo requiere Qt5 y QGLViewer, el mismo procedimiento debería funcionar para muchos otros demos, así que decidí documentarlo aquí. Sin embargo, ten en cuenta que esta solución requiere que desenlaces Qt4 para poder enlazar Qt5, lo que romperá cualquier fórmula de Homebrew que dependa de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qt&lt;/code&gt;&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Así que, primero desenlaza Qt4 (es decir, elimina los enlaces simbólicos que Homebrew crea en &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local&lt;/code&gt;) usando:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;unlink &lt;/span&gt;qt&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Después, instala y enlaza Qt5. Como Qt5 entra en conflicto con Qt4 y por lo tanto normalmente no se pretende enlazarlo simbólicamente en &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local&lt;/code&gt;, necesitas usar &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--force&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;qt5
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;link &lt;/span&gt;qt5 &lt;span class=&quot;nt&quot;&gt;--force&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Homebrew quiere mantener su propia jerarquía en &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local&lt;/code&gt;, pero el script de CMake para Qt5 asume que los &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mkspecs&lt;/code&gt; y &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plugins&lt;/code&gt; de Qt5 son accesibles desde la carpeta raíz. Así que, crea un par de enlaces simbólicos desde &lt;strong&gt;la versión más reciente de Qt5&lt;/strong&gt; en el &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cellar&lt;/code&gt; de Homebrew (actualmente 5.6.1-1) en &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local&lt;/code&gt;&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nb&quot;&gt;ln&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /usr/local/Cellar/qt5/5.6.1-1/mkspecs /usr/local/mkspecs
&lt;span class=&quot;nb&quot;&gt;ln&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /usr/local/Cellar/qt5/5.6.1-1/plugins /usr/local/plugins&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Después, modifiqué la fórmula de Homebrew para QGLViewer para cambiar su dependencia de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qt&lt;/code&gt; a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qt5&lt;/code&gt;&lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. Algo similar podría hacerse para otras fórmulas que dependen de &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qt&lt;/code&gt;. Para esto, primero edita la fórmula:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew edit libqglviewer&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Y cambia &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;depends_on &quot;qt&quot;&lt;/code&gt; a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;depends_on &quot;qt5&quot;&lt;/code&gt;. Si no has configurado un editor de texto para Homebrew, usarás &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim&lt;/code&gt; por defecto. Así que presiona &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;I&lt;/code&gt; para cambiar al modo de inserción, cambia lo que necesites, después presiona &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ESC&lt;/code&gt; para salir del modo de inserción, y luego escribe &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:wq&lt;/code&gt; para guardar y salir.&lt;/p&gt;

&lt;p&gt;Ahora que la fórmula ha sido modificada, puedes instalar QGLViewer (o cualquier otra fórmula que necesites) compilándola desde el código fuente usando:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;libqglviewer &lt;span class=&quot;nt&quot;&gt;--build-from-source&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Finalmente, puedes descargar CGAL e instalarlo desde el código fuente. Mi forma preferida de hacer esto es ir a una carpeta apropiada en tu computadora y clonar el repositorio de CGAL:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone https://github.com/CGAL/cgal.git&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Luego configurarlo usando la GUI de CMake&lt;sup id=&quot;fnref:4&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; y compilarlo e instalarlo usando &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;cmake-gui &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;make
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;make &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;En la GUI de CMake deberías poder seleccionar las opciones que necesitas, incluyendo &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WITH_CGAL_Qt5&lt;/code&gt; y &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WITH_demos&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/ken/img/blog/cmake.png&quot; class=&quot;img-fluid center-block&quot; alt=&quot;Nuevo proyecto en Xcode&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Actualización 27 jul 2016&lt;/strong&gt;: Se agregaron instrucciones para enlazar simbólicamente los &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mkspecs&lt;/code&gt; y &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plugins&lt;/code&gt; de Qt5, y una nota sobre &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake-gui&lt;/code&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;Idealmente, debería ser posible compilar CGAL con un Qt5 no enlazado usando &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-L/usr/local/opt/qt5/lib&lt;/code&gt; y &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-I/usr/local/opt/qt5/include&lt;/code&gt;. Sin embargo, esto no me funciona a mí. Por favor avísame si logras hacer que esto funcione. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;Gracias a stephane-lb en &lt;a href=&quot;https://github.com/Homebrew/legacy-homebrew/issues/29938&quot;&gt;https://github.com/Homebrew/legacy-homebrew/issues/29938&lt;/a&gt; por el consejo. Esto podría resolverse usando las rutas de Qt de CMake, pero ay, no pude lograr que funcionaran. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot;&gt;
      &lt;p&gt;O mejor aún, haz una rama de la fórmula y cámbiala ahí. &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot;&gt;
      &lt;p&gt;Para ser honestos, es bastante molesto: el paquete de CMake de Homebrew no incluye su GUI. Así que quizás quieras instalar la versión oficial .pkg (que no causa problemas de compatibilidad con Homebrew) o usar el &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake&lt;/code&gt; de línea de comandos con los parámetros &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-D&lt;/code&gt; apropiados. &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
          <pubDate>Wed, 18 May 2016 19:30:00 -0500</pubDate>
          <link>https://3d.bk.tudelft.nl/ken/es/2016/05/18/configuring-cgal-with-qt5-and-qglviewer-on-mac.html</link>
          <guid isPermaLink="true">https://3d.bk.tudelft.nl/ken/es/2016/05/18/configuring-cgal-with-qt5-and-qglviewer-on-mac.html</guid>
          
          
          <category>es</category>
          
      </item>
    
  </channel>
</rss>
