diff --git a/src/content/projects/invoice/index.en.mdx b/src/content/projects/invoice/index.en.mdx new file mode 100644 index 0000000..952a283 --- /dev/null +++ b/src/content/projects/invoice/index.en.mdx @@ -0,0 +1,63 @@ +--- +title: "Invoice" +date: 2023-08-21 +cover: ./images/bg.jpg +icon: "/projects/invoice.svg" +tags: ["sveltekit", "unocss", "prisma", "sqlite"] +toc: true +links: + [ + ["live", "https://invoice.app.max-richter.dev"], + ["git", "https://git.max-richter.dev/max/invoice"], + ] +--- + +import bg from './images/bg.jpg' +import invoices from './images/invoices.png' +import customers from './images/customers.png' +import editCustomers from './images/edit-customer.png' +import editProfile from './images/edit-profile.png' +import overview from './images/overview.png' +import ImageSlider from '@components/ImageSlider.svelte' +import Image from '@components/Image.astro' + + +# Introduction + +In my free time, I like to take on small jobs, such as deliveries, setups, and pickups for others. + +An unavoidable part of these tasks is creating invoices in PDF format. Initially, I followed a manual process and created my first invoices in Figma. But as programmers often say: + +> Why do something manually in 5 minutes when I can automate it in 24 hours? + +This thought led to my latest hobby project – **"Invoice."** + + + Invoices + Customers + Edit Customers + Edit Profile + Overview + + +# Development + +During development, I always kept the principle 'K.I.S.S.' in mind: Keep it simple, stupid. For this project, that meant choosing "boring" but well-known technologies: + +## [🚀 SvelteKit](https://kit.svelte.dev) +For an efficient and reactive user interface. + +## [🎨 UNOcss](https://unocss.dev/) +The faster alternative to Tailwind. + +## [🌍 TypesafeI18n](https://github.com/ivanhofer/typesafe-i18n) +To enable multilingual support without complex logic. + +## [🛠️ Prisma](https://prisma.io) +As a database access layer for smooth data management. + +## [🗃️ SQLite](https://www.sqlite.org/index.html) +As a reliable backend, ideal for small projects. + +## [📄 Playwright](https://playwright.dev) +For generating PDFs. diff --git a/src/content/projects/karl/index.en.mdx b/src/content/projects/karl/index.en.mdx new file mode 100644 index 0000000..23c627b --- /dev/null +++ b/src/content/projects/karl/index.en.mdx @@ -0,0 +1,129 @@ +--- +title: "K.A.R.L" +date: 2021-04-01 +cover: ./images/Indicatrices_of_Distortion.png +license: "CC-BY-SA:4.0" +featured: true +toc: true +icon: /projects/karl/favicon.png +links: + [ + ["live", "https://max-richter.dev/karl"], + ["git", "https://git.max-richter.dev/max/karl"], + ] +--- + +import Crosswalk from "./images/crosswalk.jpg" +import CrosswalkMask from "./images/crosswalk_mask.png" +import Image from "@components/Image.astro" +import Distorion from "./images/Indicatrices_of_Distortion.png" +import ImageGallery from "@components/ImageGallery.svelte" + + + +*[Header by Justin Kunimune - Own work, CC BY-SA 4.0](https://commons.wikimedia.org/w/index.php?curid=66467577*)* + + +> K.A.R.L is a web app that helps to divide 360-degree panoramas into sections (sky, ground, trees, etc.) and then determine the proportion of each section in the overall image. + +# Introduction + +The project emerged from a collaboration with two friends. One of them is in the conceptual phase of his bachelor's thesis (Geography), which deals with the impact of vegetation on urban climate. To this end, he conducted albedo measurements at various locations in Cologne—essentially measuring "how much light comes from the sky, and how much of it is reflected by the ground." To put these measurements into context, he took 360-degree panoramas at each measurement location, which look something like this: + +Image of a crosswalk + +He then needed data on what percentage of the view was occupied by vegetation, sky, and ground. To measure this, he manually created a segmentation map in Gimp, which looks something like this: + +Segmentation map + +# Problem Statement + +If we naively count the pixels of each color and use that to calculate a percentage distribution, we encounter the classic distortion problem that humanity has faced for centuries with maps. Spheres do not like being represented in two dimensions, which always leads to distortions, as visualized in the following image. + +Indicatrices of Distortion + +Fortunately, this distortion only occurs in width, so we need a formula that provides a weight for the height of a pixel to compensate for this distortion. After many attempts, we arrived at this formula: + +```javascript +/* +height: height of the image in pixels +calibrationFactor: 1.333, somehow this works, don't ask why, we don't either +y: y position of the pixel +*/ +const pixelValue = Math.cos( + (((360 / height ** 2) * y ** 2 + (-360 / height) * y + 90) / 360) * + (2 + calibrationFactor) * + Math.PI + ) +``` + +This formula is actually designed to calculate the distance between two longitudes for a given latitude, but it works very well for our purposes. + +Here are some of the first attempts in Desmos (fantastic tool, by the way): + +