Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
## [v0.1.7]

### Fixed
-Fix [issue-16](https://github.com/dzimmanck/python-planar-magnetics/issues/16). The estimate_dcr method is now defined in the Winding class and inherited by all winding classes.
-Fix [issue-18](https://github.com/dzimmanck/python-planar-magnetics/issues/18). Mutable default values in kicad.py dataclasses.
-Feature [issue-21](https://github.com/dzimmanck/python-planar-magnetics/issues/21). Updated FreeCAD paths throughout package to reference a configurable environment variable.

### Added

Expand Down
14 changes: 14 additions & 0 deletions planar_magnetics/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import os


# Default path to FreeCAD binaries
DEFAULT_FREECAD_PATH = "C:/Program Files/FreeCAD 0.19/bin"


# Function to get FreeCAD path with environment variable override
def get_freecad_path():
"""
Get the FreeCAD path from environment variable FREECAD_PATH if available,
otherwise use the default path.
"""
return os.getenv("FREECAD_PATH", DEFAULT_FREECAD_PATH)
5 changes: 3 additions & 2 deletions planar_magnetics/cores/cores.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
TWO_PI,
PI_OVER_TWO,
)
from planar_magnetics.config import get_freecad_path


def calculate_core_extension(area: float, radius: float, opening_width: float) -> float:
Expand Down Expand Up @@ -132,7 +133,7 @@ def get_coreloss(

def to_parts(
self,
freecad_path: str = "C:/Program Files/FreeCAD 0.19/bin",
freecad_path: str = get_freecad_path(),
tol: float = 0.1,
spacer_thickness: float = 0.0,
):
Expand Down Expand Up @@ -270,7 +271,7 @@ def to_step(
name: str,
spacer_thickness: float = 0.0,
tol: float = 0.1,
freecad_path: str = "C:/Program Files/FreeCAD 0.19/bin",
freecad_path: str = get_freecad_path(),
):

# try and import the FreeCAD python extension
Expand Down
3 changes: 2 additions & 1 deletion planar_magnetics/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from dataclasses import dataclass, field
import math
import uuid
from planar_magnetics.config import get_freecad_path

# useful geometric constants
TWO_PI = 2 * math.pi
Expand Down Expand Up @@ -300,7 +301,7 @@ def to_pwl_path(self, max_angle: float = math.pi / 36):
return points

def to_wire(
self, z=0, closed=True, freecad_path: str = "C:/Program Files/FreeCAD 0.19/bin"
self, z=0, closed=True, freecad_path: str = get_freecad_path()
):
"""Convert the polygon to a FreeCAD Wire"""

Expand Down
3 changes: 2 additions & 1 deletion planar_magnetics/transformers/transformers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from planar_magnetics.geometry import Point
from planar_magnetics.windings import Spiral
from planar_magnetics.cores import Core
from planar_magnetics.config import get_freecad_path
from planar_magnetics.kicad import Footprint, Reference, Value


Expand Down Expand Up @@ -61,7 +62,7 @@ def to_kicad_footprint(
self,
name: str,
create_core_step: bool = False,
freecad_path: str = "C:/Program Files/FreeCAD 0.19/bin",
freecad_path: str = get_freecad_path(),
):
"""Export the Cffc inductor design as a KiCAD footprint file (*.kicad_mods)"""

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setuptools.setup(
name="planar-magnetics",
version="0.1.6",
version="0.1.7",
author="Donny Zimmanck",
author_email="dzimmanck@gmail.com",
description="Create planar magnetic structures programmatically and export to CAD tools.",
Expand Down
37 changes: 37 additions & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import os
from planar_magnetics.config import get_freecad_path, DEFAULT_FREECAD_PATH


def test_get_freecad_path_default():
"""Test that get_freecad_path returns the default path when no env var is set."""
# Temporarily clear the environment variable if it exists
original_value = os.environ.pop("FREECAD_PATH", None)
try:
# Test that the default path is returned
assert get_freecad_path() == DEFAULT_FREECAD_PATH
finally:
# Restore the environment variable if it existed
if original_value is not None:
os.environ["FREECAD_PATH"] = original_value


def test_get_freecad_path_from_env(monkeypatch):
"""Test that get_freecad_path returns the value from environment variable when set."""
# Test path value
test_path = "/custom/path/to/freecad"

# Set the environment variable to our test value
monkeypatch.setenv("FREECAD_PATH", test_path)

# Test that the function returns our custom path
assert get_freecad_path() == test_path


def test_default_freecad_path_format():
"""Test that the default path follows expected format."""
# Ensure the path is a string
assert isinstance(DEFAULT_FREECAD_PATH, str)

# Check that it contains expected FreeCAD path elements
assert "FreeCAD" in DEFAULT_FREECAD_PATH
assert "bin" in DEFAULT_FREECAD_PATH
58 changes: 57 additions & 1 deletion tests/test_geometry.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
import math
from planar_magnetics.geometry import Point, get_distance
import pytest
import sys
from planar_magnetics.geometry import Point, Polygon, get_distance
from planar_magnetics.config import get_freecad_path


# Skip test if FreeCAD is not available
def is_freecad_available():
try:
freecad_path = get_freecad_path()
sys.path.append(freecad_path)
import FreeCAD # noqa: F401
return True
except (ImportError, ModuleNotFoundError):
return False


def test_get_distance():
Expand All @@ -10,5 +24,47 @@ def test_get_distance():
assert math.isclose(distance, 1)


@pytest.mark.skipif(not is_freecad_available(), reason="FreeCAD not available")
def test_polygon_to_wire():
"""Test the Polygon.to_wire method that converts to a FreeCAD wire."""
# Create a simple square polygon
p0 = Point(0, 0)
p1 = Point(10, 0)
p2 = Point(10, 10)
p3 = Point(0, 10)
polygon = Polygon([p0, p1, p2, p3])

# Get the Wire
wire = polygon.to_wire()

# Import FreeCAD again (for assertions)
freecad_path = get_freecad_path()
sys.path.append(freecad_path)
import FreeCAD # noqa: F401
import Part

# Verify it's a valid Wire object
assert isinstance(wire, Part.Wire)

# Verify the number of edges (should be 4 for a closed square)
assert len(wire.Edges) == 4

# Verify it's closed
assert wire.isClosed()

# Verify its length (perimeter should be 40 units)
assert math.isclose(wire.Length, 40.0, rel_tol=1e-9)

# Test with closed=False
open_wire = polygon.to_wire(closed=False)
assert len(open_wire.Edges) == 3 # Should have 3 edges if not closed
assert not open_wire.isClosed()

# Test with z-height
z_wire = polygon.to_wire(z=5)
for vertex in z_wire.Vertexes:
assert math.isclose(vertex.Z, 5.0, rel_tol=1e-9)


if __name__ == "__main__":
test_get_distance()