Compare commits
7 Commits
0cb676bd26
...
31d159a5b5
Author | SHA1 | Date | |
---|---|---|---|
![]() |
31d159a5b5 | ||
![]() |
5503eb47de | ||
![]() |
0e7407621f | ||
![]() |
908c1dc8b7 | ||
![]() |
b90ac49f24 | ||
![]() |
0a37afee12 | ||
![]() |
e995ee3449 |
@ -1,16 +1,23 @@
|
||||
<article class="h-entry project" data-model="{{post.model}}">
|
||||
<a class="u-uid u-url photo" href="{{ post.url }}" aria-label="Project: {{ post.title }}">
|
||||
{% assign default_thumbnail = post.assets | append: '/thumbnail.min.svg' %}
|
||||
{% if post.draft %}
|
||||
<div class="under-construction">
|
||||
{% endif %}
|
||||
|
||||
<img class="u-photo {{post.img.class}}"
|
||||
src = "{{post.img.src | default: default_thumbnail}}"
|
||||
alt="{{post.img.alt | smartify}}"
|
||||
width=128 height=128>
|
||||
{% if post.draft %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</a>
|
||||
|
||||
<section class = "text">
|
||||
<section class="title-date-container">
|
||||
<h2 class="p-name blogroll-title"><a class="u-uid u-url" href="{{ post.url }}">{{ post.title }}</a></h2>
|
||||
<time class="dt-modified" datetime="{{ post.last_modified_at | date_to_xmlschema }}">{{ post.last_modified_at | date: '%b %Y' }}</time>
|
||||
<time class="dt-modified" datetime="{{ post.date | date_to_xmlschema }}">{{ post.date | date: '%b %Y' }}</time>
|
||||
</section>
|
||||
<summary class="p-summary">{{ post.excerpt | markdownify | remove: '<p>' | remove: '</p>' }}</summary>
|
||||
</section>
|
||||
|
@ -4,6 +4,7 @@ layout: project
|
||||
excerpt: A little modification to an IKEA thingy.
|
||||
permalink: /projects/bathroom_shelf
|
||||
assets: /assets/projects/bathroom_shelf
|
||||
date: 2023-12-17
|
||||
|
||||
img:
|
||||
alt: A small bathroom shelf.
|
||||
@ -18,7 +19,8 @@ We got this [IKEA shower shelf thing][shelf] from Ikea which has two sticky pads
|
||||
<!-- {% include mastodon_post.html post_id = "111822564173512216" %} -->
|
||||
|
||||
<outline-model-viewer model = "/assets/projects/bathroom_shelf/models/model.glb" camera='{"type":"perspective","fov":30,"near":10,"far":10000,"position":[364.9,307.2,459.7],"rotation":[-0.5891,0.5833,0.3527],"zoom":250,"target":[0,0,0]}'>
|
||||
<img class="outline-model-poster hs-wc" src = "{{page.assets}}/thumbnail.svg">
|
||||
<img class="outline-model-poster no-wc" src = "{{page.assets}}/thumbnail.svg">
|
||||
<p class="has-wc">Loading model...</p>
|
||||
</outline-model-viewer>
|
||||
|
||||
|
||||
|
@ -4,6 +4,7 @@ layout: project
|
||||
excerpt: Making a custom 3W dynamo light for a bike.
|
||||
permalink: /projects/bike_lights
|
||||
assets: /assets/projects/bike_lights
|
||||
date: 2023-11-06
|
||||
|
||||
img:
|
||||
alt: A CAD model of a 3D printable mount for a common LED light onto a bike handlebar.
|
||||
|
@ -5,6 +5,7 @@ excerpt: Ongoing explorations in making pots!
|
||||
permalink: /projects/ceramics
|
||||
assets: /assets/projects/ceramics
|
||||
models: /assets/projects/ceramics/models
|
||||
date: 2025-01-01
|
||||
|
||||
img2024: /assets/images/2024/ceramics
|
||||
|
||||
|
22
_projects/downlight_bikelight.md
Normal file
@ -0,0 +1,22 @@
|
||||
---
|
||||
title: Downlight<br>Bikelight
|
||||
layout: project
|
||||
excerpt: An old ceiling mounted LED downlight becomes a chonky bike light.
|
||||
permalink: /projects/downlight_bikelight
|
||||
assets: /assets/projects/downlight_bikelight
|
||||
date: 2025-05-11
|
||||
|
||||
img:
|
||||
alt: A CAD model of a Bike light made from an old LED downlight.
|
||||
class: invertable
|
||||
src: /assets/projects/downlight_bikelight/thumbnail.png
|
||||
|
||||
social_image: /assets/projects/downlight_bikelight/thumbnail.png
|
||||
model: /assets/projects//downlight_bikelight/models
|
||||
draft: True
|
||||
---
|
||||
|
||||
<outline-model-viewer model = "{{page.model}}/fbx_export.glb" camera='{"type":"perspective","fov":30,"near":10,"far":10000,"position":[848.5,470.2,-294.9],"rotation":[-2.131,0.9915,2.214],"zoom":300,"target":[0,0,0]}'>
|
||||
<img class="outline-model-poster no-wc" src = "{{page.assets}}/thumbnail.svg">
|
||||
<p class="has-wc">Loading model...</p>
|
||||
</outline-model-viewer>
|
@ -4,6 +4,7 @@ layout: project
|
||||
excerpt: A quick mount for a new hotend on an Elegoo Neptune 3D printer.
|
||||
permalink: /projects/elegoo_mount
|
||||
assets: /assets/projects/elegoo_mount
|
||||
date: 2024-04-13
|
||||
|
||||
img:
|
||||
alt: A CAD model of a 3D printable mount for hotend on a 3D printer.
|
||||
@ -11,12 +12,14 @@ img:
|
||||
src: /assets/projects/elegoo_mount/thumbnail.png
|
||||
|
||||
social_image: /assets/projects/elegoo_mount/thumbnail.png
|
||||
draft: True
|
||||
---
|
||||
|
||||
This is just a quick mount for a [BIQU H2V2](https://biqu.equipment/products/biqu-h2-v2-0-extruder) hotend on an Elegoo Neptune 2.
|
||||
|
||||
<outline-model-viewer model = "{{page.assets}}/model.glb" camera='{"type":"perspective","fov":30,"near":10,"far":10000,"position":[364.9,307.2,459.7],"rotation":[-0.5891,0.5833,0.3527],"zoom":250,"target":[0,0,0]}'>
|
||||
<img class="outline-model-poster" src = "{{page.assets}}/thumbnail.png">
|
||||
<img class="outline-model-poster no-wc" src = "{{page.assets}}/thumbnail.svg">
|
||||
<p class="has-wc">Loading model...</p>
|
||||
</outline-model-viewer>
|
||||
|
||||
The mounting holes don't really line up a simple manner so I made this side arms that attach with some heat set inserts. When it's all tightened down it's rigid but I'm nevertheless having some issues with this the nozzle of this printer lifting up a fraction of a millimeter when it pulls in the filament and dropping back down on z retraction.
|
||||
|
@ -4,6 +4,7 @@ layout: project
|
||||
excerpt: A lasercut hexagonal wooden stool.
|
||||
permalink: /projects/lasercut_stool
|
||||
assets: /assets/projects/lasercut_stool
|
||||
date: 2023-08-29
|
||||
|
||||
img:
|
||||
alt: A CAD model of the this hexagonal lasercut stool.
|
||||
@ -17,3 +18,8 @@ model: /assets/blog/weekend_builds_1/pot.glb
|
||||
<img class="outline-model-poster no-wc" src = "{{page.img.src}}">
|
||||
<p class="has-wc">Loading model...</p>
|
||||
</outline-model-viewer>
|
||||
|
||||
|
||||
<figure>
|
||||
<img src="{{ page.assets }}/sketch.jpg">
|
||||
</figure>
|
||||
|
@ -4,12 +4,14 @@ layout: project
|
||||
excerpt: Adapters to use common components with lego technic.
|
||||
permalink: /projects/lego_adapters
|
||||
assets: /assets/projects/lego_adapters
|
||||
date: 2023-10-22
|
||||
|
||||
img:
|
||||
alt:
|
||||
class: invertable
|
||||
|
||||
social_image: /assets/projects/lego_adapters/thumbnail.png
|
||||
draft: true
|
||||
---
|
||||
|
||||
I've been looking at using Lego as a way to quickly prototype ideas.
|
||||
|
86
_projects/montys_map.md
Normal file
@ -0,0 +1,86 @@
|
||||
---
|
||||
title: Monty's Map
|
||||
layout: project
|
||||
excerpt: Maybe the best birthday gift I've ever given or will ever give. A custom, one off, OS style foldable map for a friend.
|
||||
permalink: /projects/montys_map
|
||||
assets: /assets/projects/montys_map
|
||||
date: 2023-11-23
|
||||
draft: false
|
||||
|
||||
img:
|
||||
alt:
|
||||
class: invertable
|
||||
src: /assets/projects/montys_map/thumbnail.jpg
|
||||
|
||||
social_image: /assets/projects/montys_map/gifting.jpg
|
||||
|
||||
head: |
|
||||
<link rel="stylesheet" href="/assets/js/leaflet/leaflet.css" />
|
||||
<script src="/assets/js/leaflet/leaflet.js"></script>
|
||||
---
|
||||
|
||||
A friend of mine makes maps and offered to get a one-off printed and folded OS style, I hatched a plan.
|
||||
|
||||
Not being a map or geo person I decided to cheat a bit and do it by layering tiles intended for web maps. I scraped tiles from OSM maps being careful to cache the tiles and to only download a reasonable amount at a reasonable rate. I also pulled the strava running heatmap which I'm obsessed with. All those hidden little paths!
|
||||
|
||||
I stuck a legend with a personal message on the rightmost fold and had my birthday map!
|
||||
|
||||
<figure>
|
||||
<img src="/assets/images/2024/montys_map.jpg">
|
||||
</figure>
|
||||
|
||||
<figure id="map" style="width:100%; height:500px;"></figure>
|
||||
|
||||
Here's a small web viewer for the same data that lets you toggle different layers. I've only got the tiles for zoom level 15 so I've disabled the ability to zoom out too much to save your poor computer trying to load to many tiles into memory at once. You can zoom into level 17 to see a bit what it looks like when you lean really close and squint on the printed version.
|
||||
|
||||
<script>
|
||||
let map = L.map("map", {
|
||||
attributionControl: false,
|
||||
zoomControl: false,
|
||||
}).setView([53.36895547, -1.5417251], 13);
|
||||
|
||||
const options = {
|
||||
minNativeZoom: 15,
|
||||
maxNativeZoom: 15,
|
||||
minZoom: 14,
|
||||
maxZoom: 17,
|
||||
};
|
||||
|
||||
const base_maps = {};
|
||||
|
||||
const base = "/assets/projects/montys_map/tiles";
|
||||
const layers = {
|
||||
// "Stamen Toner Background": L.tileLayer(
|
||||
// `${base}/stamen_toner_background/{z}/{x}/{y}.png`,
|
||||
// options
|
||||
// ),
|
||||
"Open Topo Maps": L.tileLayer(
|
||||
`${base}/open_topo_map/{z}/{x}/{y}.png`,
|
||||
options
|
||||
).addTo(map),
|
||||
Strava: L.tileLayer(`${base}/strava/{z}/{x}/{y}.png`, options).addTo(
|
||||
map
|
||||
),
|
||||
// "Stamen Toner Lines": L.tileLayer(
|
||||
// `${base}/stamen_toner_lines/{z}/{x}/{y}.png`,
|
||||
// options
|
||||
// ),
|
||||
"Stamen Labels": L.tileLayer(
|
||||
`${base}/stamen_toner_labels/{z}/{x}/{y}.png`,
|
||||
options
|
||||
).addTo(map),
|
||||
Cycling: L.tileLayer(
|
||||
`${base}/waymarked_cycling/{z}/{x}/{y}.png`,
|
||||
options
|
||||
).addTo(map),
|
||||
Hiking: L.tileLayer(
|
||||
`${base}/waymarked_hiking/{z}/{x}/{y}.png`,
|
||||
options
|
||||
).addTo(map),
|
||||
};
|
||||
|
||||
map.addLayer(layers["Strava"]);
|
||||
let layerControl = L.control.layers(base_maps, layers).addTo(map);
|
||||
</script>
|
||||
|
||||
I find it fascinating to spot places where people walk or run that aren't marked on the normal map. Interesting places included a lake where people definitely aren't allowed to swim or kayak that nevertheless has a lot of activity on it! Strange patches where lines fan out and then come together at defined points (can you guess why?), and areas where the lines just completely scatter which I guess are grassy fields where people can walk any way they like. Which is more rare than you'd imagine!
|
@ -4,6 +4,7 @@ layout: project
|
||||
excerpt: A mount for a projector underneath a shelf with a tilt swivel joint.
|
||||
permalink: /projects/projector_mount
|
||||
assets: /assets/projects/projector_mount
|
||||
date: 2023-01-31
|
||||
|
||||
img:
|
||||
alt: A CAD model of a 3D printable mount for a common LED light onto a helmet.
|
||||
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
title: Toni's Map
|
||||
layout: project
|
||||
excerpt: A going away present for my friend Toni.
|
||||
permalink: /projects/tonis-map/
|
||||
assets: /assets/blog/maps/icons
|
||||
@ -7,10 +8,10 @@ img:
|
||||
src: /assets/projects/tonis_map/thumbnail.png
|
||||
class: invertable
|
||||
alt: A black and white lineart map of London.
|
||||
date: 2023-09-06
|
||||
|
||||
social_image: /assets/projects/tonis_map/thumbnail.png
|
||||
---
|
||||
|
||||
head: |
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
|
||||
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
|
||||
crossorigin=""/>
|
||||
@ -21,7 +22,40 @@ social_image: /assets/projects/tonis_map/thumbnail.png
|
||||
<script src="https://unpkg.com/leaflet-simple-map-screenshoter"></script>
|
||||
<script src="https://unpkg.com/file-saver/dist/FileSaver.js"></script>
|
||||
<script src="/assets/js/domtoimage.min.js"></script>
|
||||
---
|
||||
|
||||
A last minute leaving gift idea for a friend inspired me to finish my first actual laser cut map. I used leaflet.js to overlay the names of some places we had visited together in London onto those nice Stamen Design map tiles from before.
|
||||
|
||||
It was mostly made to be laser etched but you can see a crude web version here:
|
||||
|
||||
<div id="map"></div>
|
||||
|
||||
Now onto the lasing!
|
||||
|
||||
<figure>
|
||||
<img src="/assets/blog/maps/fresh_off_the_press.jpeg">
|
||||
<figcaption>
|
||||
This is what it looks like straight off the laser cutter. The contrast is super washed out because the smoke from the cutting process darkens all the surrounding wood.
|
||||
</figcaption>
|
||||
</figure>
|
||||
|
||||
I had a bunch of issues with getting that to work mostly based around the fact that these tiles are raster images that are intended for streaming to a zoomable and panable viewer on a screen. The design tradeoff of the maps don't quite make as much sense when you start transfering them to a static image. I did some hacks to use the tiles intended for a higher zoom level but you can only take that so far before the text starts getting unreadable.
|
||||
|
||||
<figure>
|
||||
<img src="/assets/blog/maps/after_sanding.jpeg">
|
||||
<figcaption>
|
||||
To deal with the darkending from the smoke I sand the whole thing back with 80 grit sandpaper on an orbital sander. I did break a few small features off here and there but it's ok!
|
||||
</figcaption>
|
||||
</figure>
|
||||
|
||||
I think there is a better approach that involves getting raw OpenStreetMap data and rendering it directly using something like [QGIS and some kind of map style files](https://gis.stackexchange.com/questions/186808/how-to-create-high-quality-map-with-qgis-and-stamen-tiles) but that seems like a whole new deep rabbit hole I'm not ready to fall into just yet.
|
||||
|
||||
<figure>
|
||||
<img src="/assets/blog/maps/the_final_reveal.jpeg">
|
||||
<figcaption>
|
||||
The final reveal!
|
||||
</figcaption>
|
||||
</figure>
|
||||
|
||||
<style>
|
||||
.leaflet-pane {
|
||||
@ -29,10 +63,7 @@ social_image: /assets/projects/tonis_map/thumbnail.png
|
||||
}
|
||||
|
||||
#map {
|
||||
/* height: 4100px;
|
||||
width: 4102px; */
|
||||
|
||||
height: 100%;
|
||||
height: 300px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@ -66,13 +97,8 @@ social_image: /assets/projects/tonis_map/thumbnail.png
|
||||
|
||||
</style>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="map"></div>
|
||||
|
||||
<script>
|
||||
let Stamen_TonerBackground = L.tileLayer('https://stamen-tiles-{s}.a.ssl.fastly.net/toner-background/{z}/{x}/{y}.{ext}', {
|
||||
let Stamen_TonerBackground = L.tileLayer('https://tiles.stadiamaps.com/tiles/stamen_toner_background/{z}/{x}/{y}.{ext}', {
|
||||
subdomains: 'abcd',
|
||||
minZoom: 0,
|
||||
maxZoom: 16,
|
||||
@ -81,16 +107,11 @@ social_image: /assets/projects/tonis_map/thumbnail.png
|
||||
});
|
||||
|
||||
// Using detectRetina: false and manually adding @2x is a hack to export the retina tiles directly
|
||||
let Stamen_Toner = L.tileLayer('https://stamen-tiles-{s}.a.ssl.fastly.net/toner/{z}/{x}/{y}@2x.{ext}', {
|
||||
let Stamen_Toner = L.tileLayer('https://tiles.stadiamaps.com/tiles/stamen_toner_lines/{z}/{x}/{y}.{ext}', {
|
||||
subdomains: 'abcd',
|
||||
minZoom: 0,
|
||||
maxZoom: 16,
|
||||
ext: 'png',
|
||||
maxNativeZoom: 13,
|
||||
minNativeZoom: 13,
|
||||
// tileSize: 512,
|
||||
// zoomOffset: -1,
|
||||
detectRetina: false,
|
||||
className: 'stamen'
|
||||
});
|
||||
const key = 'paglUJQl74h39APJmOFJ';
|
||||
@ -158,7 +179,7 @@ social_image: /assets/projects/tonis_map/thumbnail.png
|
||||
}
|
||||
|
||||
let map = L.map('map', {
|
||||
zoomSnap: 0.1,
|
||||
// zoomSnap: 0.1,
|
||||
})
|
||||
map.addLayer(Stamen_Toner);
|
||||
|
||||
@ -202,20 +223,20 @@ social_image: /assets/projects/tonis_map/thumbnail.png
|
||||
})}).addTo(map));
|
||||
|
||||
|
||||
const ZoomViewer = L.Control.extend({
|
||||
onAdd() {
|
||||
const gauge = L.DomUtil.create('div');
|
||||
gauge.style.width = '200px';
|
||||
gauge.style.background = 'rgba(255,255,255,0.5)';
|
||||
gauge.style.textAlign = 'left';
|
||||
map.on('zoomstart zoom zoomend', (ev) => {
|
||||
gauge.innerHTML = `Zoom level: ${map.getZoom()}`;
|
||||
});
|
||||
return gauge;
|
||||
}
|
||||
});
|
||||
// const ZoomViewer = L.Control.extend({
|
||||
// onAdd() {
|
||||
// const gauge = L.DomUtil.create('div');
|
||||
// gauge.style.width = '200px';
|
||||
// gauge.style.background = 'rgba(255,255,255,0.5)';
|
||||
// gauge.style.textAlign = 'left';
|
||||
// map.on('zoomstart zoom zoomend', (ev) => {
|
||||
// gauge.innerHTML = `Zoom level: ${map.getZoom()}`;
|
||||
// });
|
||||
// return gauge;
|
||||
// }
|
||||
// });
|
||||
|
||||
const zoomViewer = (new ZoomViewer()).addTo(map);
|
||||
// const zoomViewer = (new ZoomViewer()).addTo(map);
|
||||
|
||||
|
||||
// const center = {lat: 51.53803381685164, lng: -0.09551626866416196};
|
||||
@ -234,7 +255,3 @@ social_image: /assets/projects/tonis_map/thumbnail.png
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -4,6 +4,7 @@ layout: project
|
||||
excerpt: A shelf to put your toothbrush charger on.
|
||||
permalink: /projects/toothbrush_shelf
|
||||
assets: /assets/projects/toothbrush_shelf
|
||||
date: 2023-11-16
|
||||
|
||||
img:
|
||||
alt: A CAD model of a small shelf to put a toothbrush right above the charging socket so that the cabling can be hidden inside the shelf.
|
||||
@ -11,7 +12,7 @@ img:
|
||||
|
||||
social_image: /assets/projects/toothbrush_shelf/thumbnail.png
|
||||
model: /assets/blog/toothbrush_shelf/model/toothbrush_shelf.glb
|
||||
|
||||
draft: true
|
||||
|
||||
---
|
||||
<outline-model-viewer model = "{{page.model}}" camera='{"type":"perspective","fov":30,"near":10,"far":10000,"position":[364.9,307.2,459.7],"rotation":[-0.5891,0.5833,0.3527],"zoom":250,"target":[0,0,0]}'>
|
||||
|
38
_projects/triangle_shelves.md
Normal file
@ -0,0 +1,38 @@
|
||||
---
|
||||
title: Triangle Shelves
|
||||
layout: project
|
||||
excerpt: A bookcase to fit in a very particular place.
|
||||
permalink: /projects/triangle_shelves
|
||||
assets: /assets/projects/triangle_shelves
|
||||
date: 2023-02-08
|
||||
draft: true
|
||||
|
||||
img:
|
||||
alt: A line drawn CAD model of vector magnet.
|
||||
class: invertable
|
||||
src: /assets/projects/triangle_shelves/thumbnail.svg
|
||||
|
||||
social_image: /assets/projects/triangle_shelves/thumbnail.png
|
||||
---
|
||||
|
||||
This project, part of my Master's thesis in 2018, centered around the use of a Nitrogen-Vancancy defect in a nanoscale diamond to detect magnetic fields with ultra high resolution. We experimented with mounting such a nano-diamond to the tip of an atomic force microscope in order to produce field images. I built a 3d vector magnetometer in order to determine the axis of a defect in a nano-diamond.
|
||||
|
||||
<outline-model-viewer model = "/assets/blog/vector_magnet/vector_magnet.glb" camera='{"type":"perspective","fov":30,"near":100,"far":10000,"position":[13.73,540.1,-1020],"rotation":[-2.655,0.0119,3.135],"zoom":428,"target":[0,0,0]}'>
|
||||
<img class="outline-model-poster no-wc" src = "/assets/projects/bike_lights/thumbnail.svg">
|
||||
<p class="has-wc">Loading model...</p>
|
||||
</outline-model-viewer>
|
||||
|
||||
Check out this interactive model of the magnetometer. The device has three pairs of copper Helmholtz coils that generate controlled, linear, magnetic fields in all three directions.
|
||||
|
||||
Here's a cutaway view of the interior.
|
||||
|
||||
<outline-model-viewer model = "/assets/blog/vector_magnet/vector_magnet_section.glb" spin=false camera='{"type":"perspective","fov":30,"near":100,"far":1000,"position":[-253.2,261.7,839],"rotation":[-0.3023,-0.2805,-0.08613],"zoom":2860.0091628398345,"target":[0,0,0]}' materials=flat ambient-light="5" directional-light="5">
|
||||
<img class="outline-model-poster no-wc" src = "/assets/projects/bike_lights/thumbnail.svg">
|
||||
<p class="has-wc">Loading model...</p>
|
||||
</outline-model-viewer>
|
||||
|
||||
**AFM Tip**: The atomic force microscope tip (dark blue) with a nano-diamond attached to the very tip. We want to figure out which was the axis the NV defect in this nano-diamond is pointing. To do that we need to expose it to different directions of magnetic field while also blasting it with light and radio waves.
|
||||
|
||||
**PCB coil** For the radio wave blasting we have a single turn coil made on a PCB (green). I haven't cut the coil away so that you can see it's whole shape. We'll pump RF power into this tuned to the electronic transitions in the NV defect that we want to probe.
|
||||
|
||||
**Microscope Objective** The microscope objective (lower with blue strip) allows us to optically pump the transitions in the NV defect (much like a laser) in order to keep electrons in excited quantum states that they wouldn't normally sit in.
|
@ -4,6 +4,7 @@ layout: project
|
||||
excerpt: An ongoing quest to fix a problem I don't have.
|
||||
permalink: /projects/usbc_charging_station
|
||||
assets: /assets/projects/usbc_power_supply
|
||||
date: 2025-04-01
|
||||
|
||||
img:
|
||||
src: /assets/projects/usbc_power_supply/thumbnail.svg
|
||||
|
@ -4,6 +4,7 @@ layout: project
|
||||
excerpt: Make your magnetic fields all 3D like.
|
||||
permalink: /projects/vector_magnet
|
||||
assets: /assets/projects/vector_magnet
|
||||
date: 2018-10-01
|
||||
|
||||
img:
|
||||
alt: A line drawn CAD model of vector magnet.
|
||||
@ -12,14 +13,14 @@ img:
|
||||
social_image: /assets/projects/vector_magnet/thumbnail.png
|
||||
|
||||
---
|
||||
This project, part of my Master's thesis in 2018, centered around the use of a Nitrogen-Vancancy defect in a nanoscale diamond to detect magnetic fields with ultra high resolution. We experimented with mounting such a nano-diamond to the tip of an atomic force microscope in order to produce field images. I built a 3d vector magnetometer in order to determine the axis of a defect in a nano-diamond.
|
||||
|
||||
<outline-model-viewer model = "/assets/blog/vector_magnet/vector_magnet.glb" camera='{"type":"perspective","fov":30,"near":100,"far":10000,"position":[13.73,540.1,-1020],"rotation":[-2.655,0.0119,3.135],"zoom":428,"target":[0,0,0]}'>
|
||||
<img class="outline-model-poster no-wc" src = "/assets/projects/bike_lights/thumbnail.svg">
|
||||
<p class="has-wc">Loading model...</p>
|
||||
</outline-model-viewer>
|
||||
|
||||
The project centered around the use of a Nitrogen-Vancancy defect in a nanoscale diamond to detect magnetic fields with ultra high resolution. We experimented with mounting such a nano-diamond to the tip of an atomic force microscope in order to produce field images. I built a 3d vector magnetometer in order to determine the axis of a defect in a nano-diamond.
|
||||
|
||||
Check out a little interactive model of the magnetometer below. The device has three pairs of copper Helmholtz coils that generate controlled, linear, magnetic fields in all three directions.
|
||||
Check out this interactive model of the magnetometer. The device has three pairs of copper Helmholtz coils that generate controlled, linear, magnetic fields in all three directions.
|
||||
|
||||
Here's a cutaway view of the interior.
|
||||
|
||||
|
@ -63,3 +63,24 @@ section.header.sticky {
|
||||
left: 0%;
|
||||
}
|
||||
}
|
||||
|
||||
.under-construction {
|
||||
position: relative;
|
||||
display: inline-block; /* or block, as needed */
|
||||
}
|
||||
.under-construction::before {
|
||||
content: "🔧";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
padding: 5px;
|
||||
background: #ffeb3b; /* yellow triangle */
|
||||
clip-path: polygon(0 0, 100% 0, 100% 100%);
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
font-size: 16px;
|
||||
color: grey; /* wrench color */
|
||||
text-shadow: 0 0 1px rgba(0,0,0,0.3);
|
||||
}
|
BIN
assets/js/leaflet/images/layers-2x.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
assets/js/leaflet/images/layers.png
Normal file
After Width: | Height: | Size: 696 B |
BIN
assets/js/leaflet/images/marker-icon-2x.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
assets/js/leaflet/images/marker-icon.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/js/leaflet/images/marker-shadow.png
Normal file
After Width: | Height: | Size: 618 B |
14419
assets/js/leaflet/leaflet-src.esm.js
Normal file
1
assets/js/leaflet/leaflet-src.esm.js.map
Normal file
14512
assets/js/leaflet/leaflet-src.js
Normal file
1
assets/js/leaflet/leaflet-src.js.map
Normal file
661
assets/js/leaflet/leaflet.css
Normal file
@ -0,0 +1,661 @@
|
||||
/* required styles */
|
||||
|
||||
.leaflet-pane,
|
||||
.leaflet-tile,
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow,
|
||||
.leaflet-tile-container,
|
||||
.leaflet-pane > svg,
|
||||
.leaflet-pane > canvas,
|
||||
.leaflet-zoom-box,
|
||||
.leaflet-image-layer,
|
||||
.leaflet-layer {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.leaflet-container {
|
||||
overflow: hidden;
|
||||
}
|
||||
.leaflet-tile,
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
/* Prevents IE11 from highlighting tiles in blue */
|
||||
.leaflet-tile::selection {
|
||||
background: transparent;
|
||||
}
|
||||
/* Safari renders non-retina tile on retina better with this, but Chrome is worse */
|
||||
.leaflet-safari .leaflet-tile {
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
}
|
||||
/* hack that prevents hw layers "stretching" when loading new tiles */
|
||||
.leaflet-safari .leaflet-tile-container {
|
||||
width: 1600px;
|
||||
height: 1600px;
|
||||
-webkit-transform-origin: 0 0;
|
||||
}
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow {
|
||||
display: block;
|
||||
}
|
||||
/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */
|
||||
/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */
|
||||
.leaflet-container .leaflet-overlay-pane svg {
|
||||
max-width: none !important;
|
||||
max-height: none !important;
|
||||
}
|
||||
.leaflet-container .leaflet-marker-pane img,
|
||||
.leaflet-container .leaflet-shadow-pane img,
|
||||
.leaflet-container .leaflet-tile-pane img,
|
||||
.leaflet-container img.leaflet-image-layer,
|
||||
.leaflet-container .leaflet-tile {
|
||||
max-width: none !important;
|
||||
max-height: none !important;
|
||||
width: auto;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.leaflet-container img.leaflet-tile {
|
||||
/* See: https://bugs.chromium.org/p/chromium/issues/detail?id=600120 */
|
||||
mix-blend-mode: plus-lighter;
|
||||
}
|
||||
|
||||
.leaflet-container.leaflet-touch-zoom {
|
||||
-ms-touch-action: pan-x pan-y;
|
||||
touch-action: pan-x pan-y;
|
||||
}
|
||||
.leaflet-container.leaflet-touch-drag {
|
||||
-ms-touch-action: pinch-zoom;
|
||||
/* Fallback for FF which doesn't support pinch-zoom */
|
||||
touch-action: none;
|
||||
touch-action: pinch-zoom;
|
||||
}
|
||||
.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom {
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
.leaflet-container {
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
.leaflet-container a {
|
||||
-webkit-tap-highlight-color: rgba(51, 181, 229, 0.4);
|
||||
}
|
||||
.leaflet-tile {
|
||||
filter: inherit;
|
||||
visibility: hidden;
|
||||
}
|
||||
.leaflet-tile-loaded {
|
||||
visibility: inherit;
|
||||
}
|
||||
.leaflet-zoom-box {
|
||||
width: 0;
|
||||
height: 0;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
z-index: 800;
|
||||
}
|
||||
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
|
||||
.leaflet-overlay-pane svg {
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
.leaflet-pane { z-index: 400; }
|
||||
|
||||
.leaflet-tile-pane { z-index: 200; }
|
||||
.leaflet-overlay-pane { z-index: 400; }
|
||||
.leaflet-shadow-pane { z-index: 500; }
|
||||
.leaflet-marker-pane { z-index: 600; }
|
||||
.leaflet-tooltip-pane { z-index: 650; }
|
||||
.leaflet-popup-pane { z-index: 700; }
|
||||
|
||||
.leaflet-map-pane canvas { z-index: 100; }
|
||||
.leaflet-map-pane svg { z-index: 200; }
|
||||
|
||||
.leaflet-vml-shape {
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
}
|
||||
.lvml {
|
||||
behavior: url(#default#VML);
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
|
||||
/* control positioning */
|
||||
|
||||
.leaflet-control {
|
||||
position: relative;
|
||||
z-index: 800;
|
||||
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
|
||||
pointer-events: auto;
|
||||
}
|
||||
.leaflet-top,
|
||||
.leaflet-bottom {
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
pointer-events: none;
|
||||
}
|
||||
.leaflet-top {
|
||||
top: 0;
|
||||
}
|
||||
.leaflet-right {
|
||||
right: 0;
|
||||
}
|
||||
.leaflet-bottom {
|
||||
bottom: 0;
|
||||
}
|
||||
.leaflet-left {
|
||||
left: 0;
|
||||
}
|
||||
.leaflet-control {
|
||||
float: left;
|
||||
clear: both;
|
||||
}
|
||||
.leaflet-right .leaflet-control {
|
||||
float: right;
|
||||
}
|
||||
.leaflet-top .leaflet-control {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.leaflet-bottom .leaflet-control {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.leaflet-left .leaflet-control {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.leaflet-right .leaflet-control {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
|
||||
/* zoom and fade animations */
|
||||
|
||||
.leaflet-fade-anim .leaflet-popup {
|
||||
opacity: 0;
|
||||
-webkit-transition: opacity 0.2s linear;
|
||||
-moz-transition: opacity 0.2s linear;
|
||||
transition: opacity 0.2s linear;
|
||||
}
|
||||
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
|
||||
opacity: 1;
|
||||
}
|
||||
.leaflet-zoom-animated {
|
||||
-webkit-transform-origin: 0 0;
|
||||
-ms-transform-origin: 0 0;
|
||||
transform-origin: 0 0;
|
||||
}
|
||||
svg.leaflet-zoom-animated {
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.leaflet-zoom-anim .leaflet-zoom-animated {
|
||||
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||
}
|
||||
.leaflet-zoom-anim .leaflet-tile,
|
||||
.leaflet-pan-anim .leaflet-tile {
|
||||
-webkit-transition: none;
|
||||
-moz-transition: none;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.leaflet-zoom-anim .leaflet-zoom-hide {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
|
||||
/* cursors */
|
||||
|
||||
.leaflet-interactive {
|
||||
cursor: pointer;
|
||||
}
|
||||
.leaflet-grab {
|
||||
cursor: -webkit-grab;
|
||||
cursor: -moz-grab;
|
||||
cursor: grab;
|
||||
}
|
||||
.leaflet-crosshair,
|
||||
.leaflet-crosshair .leaflet-interactive {
|
||||
cursor: crosshair;
|
||||
}
|
||||
.leaflet-popup-pane,
|
||||
.leaflet-control {
|
||||
cursor: auto;
|
||||
}
|
||||
.leaflet-dragging .leaflet-grab,
|
||||
.leaflet-dragging .leaflet-grab .leaflet-interactive,
|
||||
.leaflet-dragging .leaflet-marker-draggable {
|
||||
cursor: move;
|
||||
cursor: -webkit-grabbing;
|
||||
cursor: -moz-grabbing;
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
/* marker & overlays interactivity */
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow,
|
||||
.leaflet-image-layer,
|
||||
.leaflet-pane > svg path,
|
||||
.leaflet-tile-container {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.leaflet-marker-icon.leaflet-interactive,
|
||||
.leaflet-image-layer.leaflet-interactive,
|
||||
.leaflet-pane > svg path.leaflet-interactive,
|
||||
svg.leaflet-image-layer.leaflet-interactive path {
|
||||
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
/* visual tweaks */
|
||||
|
||||
.leaflet-container {
|
||||
background: #ddd;
|
||||
outline-offset: 1px;
|
||||
}
|
||||
.leaflet-container a {
|
||||
color: #0078A8;
|
||||
}
|
||||
.leaflet-zoom-box {
|
||||
border: 2px dotted #38f;
|
||||
background: rgba(255,255,255,0.5);
|
||||
}
|
||||
|
||||
|
||||
/* general typography */
|
||||
.leaflet-container {
|
||||
font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
|
||||
font-size: 12px;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
|
||||
/* general toolbar styles */
|
||||
|
||||
.leaflet-bar {
|
||||
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
|
||||
border-radius: 4px;
|
||||
}
|
||||
.leaflet-bar a {
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #ccc;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
line-height: 26px;
|
||||
display: block;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
}
|
||||
.leaflet-bar a,
|
||||
.leaflet-control-layers-toggle {
|
||||
background-position: 50% 50%;
|
||||
background-repeat: no-repeat;
|
||||
display: block;
|
||||
}
|
||||
.leaflet-bar a:hover,
|
||||
.leaflet-bar a:focus {
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
.leaflet-bar a:first-child {
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
.leaflet-bar a:last-child {
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-bottom: none;
|
||||
}
|
||||
.leaflet-bar a.leaflet-disabled {
|
||||
cursor: default;
|
||||
background-color: #f4f4f4;
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-bar a {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
}
|
||||
.leaflet-touch .leaflet-bar a:first-child {
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 2px;
|
||||
}
|
||||
.leaflet-touch .leaflet-bar a:last-child {
|
||||
border-bottom-left-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
}
|
||||
|
||||
/* zoom control */
|
||||
|
||||
.leaflet-control-zoom-in,
|
||||
.leaflet-control-zoom-out {
|
||||
font: bold 18px 'Lucida Console', Monaco, monospace;
|
||||
text-indent: 1px;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out {
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
|
||||
/* layers control */
|
||||
|
||||
.leaflet-control-layers {
|
||||
box-shadow: 0 1px 5px rgba(0,0,0,0.4);
|
||||
background: #fff;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.leaflet-control-layers-toggle {
|
||||
background-image: url(images/layers.png);
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
.leaflet-retina .leaflet-control-layers-toggle {
|
||||
background-image: url(images/layers-2x.png);
|
||||
background-size: 26px 26px;
|
||||
}
|
||||
.leaflet-touch .leaflet-control-layers-toggle {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
}
|
||||
.leaflet-control-layers .leaflet-control-layers-list,
|
||||
.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
|
||||
display: none;
|
||||
}
|
||||
.leaflet-control-layers-expanded .leaflet-control-layers-list {
|
||||
display: block;
|
||||
position: relative;
|
||||
}
|
||||
.leaflet-control-layers-expanded {
|
||||
padding: 6px 10px 6px 6px;
|
||||
color: #333;
|
||||
background: #fff;
|
||||
}
|
||||
.leaflet-control-layers-scrollbar {
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
padding-right: 5px;
|
||||
}
|
||||
.leaflet-control-layers-selector {
|
||||
margin-top: 2px;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
.leaflet-control-layers label {
|
||||
display: block;
|
||||
font-size: 13px;
|
||||
font-size: 1.08333em;
|
||||
}
|
||||
.leaflet-control-layers-separator {
|
||||
height: 0;
|
||||
border-top: 1px solid #ddd;
|
||||
margin: 5px -10px 5px -6px;
|
||||
}
|
||||
|
||||
/* Default icon URLs */
|
||||
.leaflet-default-icon-path { /* used only in path-guessing heuristic, see L.Icon.Default */
|
||||
background-image: url(images/marker-icon.png);
|
||||
}
|
||||
|
||||
|
||||
/* attribution and scale controls */
|
||||
|
||||
.leaflet-container .leaflet-control-attribution {
|
||||
background: #fff;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
margin: 0;
|
||||
}
|
||||
.leaflet-control-attribution,
|
||||
.leaflet-control-scale-line {
|
||||
padding: 0 5px;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.leaflet-control-attribution a {
|
||||
text-decoration: none;
|
||||
}
|
||||
.leaflet-control-attribution a:hover,
|
||||
.leaflet-control-attribution a:focus {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.leaflet-attribution-flag {
|
||||
display: inline !important;
|
||||
vertical-align: baseline !important;
|
||||
width: 1em;
|
||||
height: 0.6669em;
|
||||
}
|
||||
.leaflet-left .leaflet-control-scale {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.leaflet-bottom .leaflet-control-scale {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.leaflet-control-scale-line {
|
||||
border: 2px solid #777;
|
||||
border-top: none;
|
||||
line-height: 1.1;
|
||||
padding: 2px 5px 1px;
|
||||
white-space: nowrap;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
text-shadow: 1px 1px #fff;
|
||||
}
|
||||
.leaflet-control-scale-line:not(:first-child) {
|
||||
border-top: 2px solid #777;
|
||||
border-bottom: none;
|
||||
margin-top: -2px;
|
||||
}
|
||||
.leaflet-control-scale-line:not(:first-child):not(:last-child) {
|
||||
border-bottom: 2px solid #777;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-control-attribution,
|
||||
.leaflet-touch .leaflet-control-layers,
|
||||
.leaflet-touch .leaflet-bar {
|
||||
box-shadow: none;
|
||||
}
|
||||
.leaflet-touch .leaflet-control-layers,
|
||||
.leaflet-touch .leaflet-bar {
|
||||
border: 2px solid rgba(0,0,0,0.2);
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
|
||||
/* popup */
|
||||
|
||||
.leaflet-popup {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.leaflet-popup-content-wrapper {
|
||||
padding: 1px;
|
||||
text-align: left;
|
||||
border-radius: 12px;
|
||||
}
|
||||
.leaflet-popup-content {
|
||||
margin: 13px 24px 13px 20px;
|
||||
line-height: 1.3;
|
||||
font-size: 13px;
|
||||
font-size: 1.08333em;
|
||||
min-height: 1px;
|
||||
}
|
||||
.leaflet-popup-content p {
|
||||
margin: 17px 0;
|
||||
margin: 1.3em 0;
|
||||
}
|
||||
.leaflet-popup-tip-container {
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
margin-top: -1px;
|
||||
margin-left: -20px;
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
}
|
||||
.leaflet-popup-tip {
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
padding: 1px;
|
||||
|
||||
margin: -10px auto 0;
|
||||
pointer-events: auto;
|
||||
|
||||
-webkit-transform: rotate(45deg);
|
||||
-moz-transform: rotate(45deg);
|
||||
-ms-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
.leaflet-popup-content-wrapper,
|
||||
.leaflet-popup-tip {
|
||||
background: white;
|
||||
color: #333;
|
||||
box-shadow: 0 3px 14px rgba(0,0,0,0.4);
|
||||
}
|
||||
.leaflet-container a.leaflet-popup-close-button {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
border: none;
|
||||
text-align: center;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
font: 16px/24px Tahoma, Verdana, sans-serif;
|
||||
color: #757575;
|
||||
text-decoration: none;
|
||||
background: transparent;
|
||||
}
|
||||
.leaflet-container a.leaflet-popup-close-button:hover,
|
||||
.leaflet-container a.leaflet-popup-close-button:focus {
|
||||
color: #585858;
|
||||
}
|
||||
.leaflet-popup-scrolled {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.leaflet-oldie .leaflet-popup-content-wrapper {
|
||||
-ms-zoom: 1;
|
||||
}
|
||||
.leaflet-oldie .leaflet-popup-tip {
|
||||
width: 24px;
|
||||
margin: 0 auto;
|
||||
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
|
||||
filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
|
||||
}
|
||||
|
||||
.leaflet-oldie .leaflet-control-zoom,
|
||||
.leaflet-oldie .leaflet-control-layers,
|
||||
.leaflet-oldie .leaflet-popup-content-wrapper,
|
||||
.leaflet-oldie .leaflet-popup-tip {
|
||||
border: 1px solid #999;
|
||||
}
|
||||
|
||||
|
||||
/* div icon */
|
||||
|
||||
.leaflet-div-icon {
|
||||
background: #fff;
|
||||
border: 1px solid #666;
|
||||
}
|
||||
|
||||
|
||||
/* Tooltip */
|
||||
/* Base styles for the element that has a tooltip */
|
||||
.leaflet-tooltip {
|
||||
position: absolute;
|
||||
padding: 6px;
|
||||
background-color: #fff;
|
||||
border: 1px solid #fff;
|
||||
border-radius: 3px;
|
||||
color: #222;
|
||||
white-space: nowrap;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.4);
|
||||
}
|
||||
.leaflet-tooltip.leaflet-interactive {
|
||||
cursor: pointer;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.leaflet-tooltip-top:before,
|
||||
.leaflet-tooltip-bottom:before,
|
||||
.leaflet-tooltip-left:before,
|
||||
.leaflet-tooltip-right:before {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
border: 6px solid transparent;
|
||||
background: transparent;
|
||||
content: "";
|
||||
}
|
||||
|
||||
/* Directions */
|
||||
|
||||
.leaflet-tooltip-bottom {
|
||||
margin-top: 6px;
|
||||
}
|
||||
.leaflet-tooltip-top {
|
||||
margin-top: -6px;
|
||||
}
|
||||
.leaflet-tooltip-bottom:before,
|
||||
.leaflet-tooltip-top:before {
|
||||
left: 50%;
|
||||
margin-left: -6px;
|
||||
}
|
||||
.leaflet-tooltip-top:before {
|
||||
bottom: 0;
|
||||
margin-bottom: -12px;
|
||||
border-top-color: #fff;
|
||||
}
|
||||
.leaflet-tooltip-bottom:before {
|
||||
top: 0;
|
||||
margin-top: -12px;
|
||||
margin-left: -6px;
|
||||
border-bottom-color: #fff;
|
||||
}
|
||||
.leaflet-tooltip-left {
|
||||
margin-left: -6px;
|
||||
}
|
||||
.leaflet-tooltip-right {
|
||||
margin-left: 6px;
|
||||
}
|
||||
.leaflet-tooltip-left:before,
|
||||
.leaflet-tooltip-right:before {
|
||||
top: 50%;
|
||||
margin-top: -6px;
|
||||
}
|
||||
.leaflet-tooltip-left:before {
|
||||
right: 0;
|
||||
margin-right: -12px;
|
||||
border-left-color: #fff;
|
||||
}
|
||||
.leaflet-tooltip-right:before {
|
||||
left: 0;
|
||||
margin-left: -12px;
|
||||
border-right-color: #fff;
|
||||
}
|
||||
|
||||
/* Printing */
|
||||
|
||||
@media print {
|
||||
/* Prevent printers from removing background-images of controls. */
|
||||
.leaflet-control {
|
||||
-webkit-print-color-adjust: exact;
|
||||
print-color-adjust: exact;
|
||||
}
|
||||
}
|
6
assets/js/leaflet/leaflet.js
Normal file
1
assets/js/leaflet/leaflet.js.map
Normal file
@ -172,12 +172,6 @@ class CustomOutlinePass extends Pass {
|
||||
surfaceIdDiff += any(notEqual(surfaceValue, getSurfaceValue(0, e))) ? 1.0 : 0.0;
|
||||
surfaceIdDiff += any(notEqual(surfaceValue, getSurfaceValue(-e, 0))) ? 1.0 : 0.0;
|
||||
surfaceIdDiff += any(notEqual(surfaceValue, getSurfaceValue(0, -e))) ? 1.0 : 0.0;
|
||||
|
||||
surfaceIdDiff += any(notEqual(surfaceValue, getSurfaceValue(e, e))) ? 1.0 : 0.0;
|
||||
surfaceIdDiff += any(notEqual(surfaceValue, getSurfaceValue(e, -e))) ? 1.0 : 0.0;
|
||||
surfaceIdDiff += any(notEqual(surfaceValue, getSurfaceValue(-e, e))) ? 1.0 : 0.0;
|
||||
surfaceIdDiff += any(notEqual(surfaceValue, getSurfaceValue(-e, -e))) ? 1.0 : 0.0;
|
||||
|
||||
return surfaceIdDiff;
|
||||
}
|
||||
|
||||
@ -187,11 +181,6 @@ class CustomOutlinePass extends Pass {
|
||||
depthDiff += abs(depth - getPixelDepth(-1, 0));
|
||||
depthDiff += abs(depth - getPixelDepth(0, 1));
|
||||
depthDiff += abs(depth - getPixelDepth(0, -1));
|
||||
|
||||
depthDiff += abs(depth - getPixelDepth(1, 1));
|
||||
depthDiff += abs(depth - getPixelDepth(1, -1));
|
||||
depthDiff += abs(depth - getPixelDepth(-1, 1));
|
||||
depthDiff += abs(depth - getPixelDepth(-1, -1));
|
||||
return depthDiff;
|
||||
}
|
||||
|
||||
@ -232,8 +221,6 @@ class CustomOutlinePass extends Pass {
|
||||
gl_FragColor = vec4(vec3(surfaceValueDiff), 1.0);
|
||||
}
|
||||
|
||||
if (surfaceValueDiff != 0.0) surfaceValueDiff = 1.0;
|
||||
|
||||
float outline;
|
||||
vec4 outlineColor = vec4(outlineColor, 1.0);;
|
||||
|
||||
|
@ -128,7 +128,7 @@ export class OutlineModelViewer extends HTMLElement {
|
||||
composer.addPass(effectFXAA);
|
||||
|
||||
// Set over sampling ratio
|
||||
this.updateEdgeThickness(1);
|
||||
this.updateEdgeThickness(1 / window.devicePixelRatio);
|
||||
this.updatePixelRatio(window.devicePixelRatio);
|
||||
renderer.setSize(width, height, false);
|
||||
|
||||
@ -294,7 +294,9 @@ export class OutlineModelViewer extends HTMLElement {
|
||||
uniforms.debugVisualize.value = value;
|
||||
});
|
||||
|
||||
gui.add(params, "edgeThickness", 1, 10).onChange(function (value) {
|
||||
gui
|
||||
.add(params, "edgeThickness", 1 / window.devicePixelRatio, 10)
|
||||
.onChange(function (value) {
|
||||
element.updateEdgeThickness(value);
|
||||
});
|
||||
|
||||
|
@ -24,7 +24,6 @@ if (inline_viewer) {
|
||||
|
||||
original.autoRotate = controls.autoRotate;
|
||||
controls.autoRotate = true;
|
||||
inline_viewer.updateEdgeThickness(0.5);
|
||||
}
|
||||
|
||||
if (mode === "icon" && delta > 2 * margin) {
|
||||
@ -42,8 +41,6 @@ if (inline_viewer) {
|
||||
);
|
||||
controls.autoRotate = original.autoRotate;
|
||||
mode = "inline";
|
||||
// inline_viewer.onWindowResize();
|
||||
inline_viewer.updateEdgeThickness(1);
|
||||
canvas.classList.remove("revealed");
|
||||
}
|
||||
|
||||
|
BIN
assets/projects/downlight_bikelight/thumbnail.png
Normal file
After Width: | Height: | Size: 83 KiB |
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 46 KiB |
BIN
assets/projects/lasercut_stool/sketch.jpg
Normal file
After Width: | Height: | Size: 150 KiB |
BIN
assets/projects/montys_map/gifting.jpg
Normal file
After Width: | Height: | Size: 963 KiB |
BIN
assets/projects/montys_map/thumbnail.jpg
Normal file
After Width: | Height: | Size: 177 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 8.2 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 9.8 KiB |
After Width: | Height: | Size: 9.6 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 7.8 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 6.7 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 25 KiB |