fix:geolinien outline

This commit is contained in:
Ida Dittrich 2025-12-15 09:23:09 +01:00
parent aaf64b869f
commit f8d5c0ae2d

View file

@ -54,6 +54,27 @@ export interface ParcelSearchResponse {
id: string; id: string;
egrid?: string; egrid?: string;
number?: string; number?: string;
perimeter?: {
closed: boolean;
punkte: Array<{
koordinatensystem: string;
x: number;
y: number;
z: number | null;
}>;
};
geometry_geojson?: {
type: string;
geometry: {
type: string;
coordinates: number[][][];
};
properties: {
id: string;
egrid?: string;
number?: string;
};
};
}>; }>;
} }
@ -285,92 +306,85 @@ export function usePek() {
} }
// Adjacent parcels (if available) // Adjacent parcels (if available)
// Fetch geometries for adjacent parcels // Use geometries from the response (no need to fetch separately)
if (data.adjacent_parcels && includeAdjacent && data.adjacent_parcels.length > 0) { if (data.adjacent_parcels && includeAdjacent && data.adjacent_parcels.length > 0) {
// Fetch geometries for each adjacent parcel const adjacentGeometries: ParcelGeometry[] = [];
const adjacentPromises = data.adjacent_parcels.map(async (adjacent) => {
try {
// Search for the adjacent parcel by its ID or EGRID
const searchLocation = adjacent.egrid || adjacent.id || adjacent.number;
if (!searchLocation) {
if (import.meta.env.DEV) {
console.warn(`⚠️ Adjacent parcel ${adjacent.id} has no search location`);
}
return null;
}
if (import.meta.env.DEV) { data.adjacent_parcels.forEach((adjacent) => {
console.log(`🔍 Fetching geometry for adjacent parcel: ${searchLocation}`); if (import.meta.env.DEV) {
} console.log(`🔍 Processing adjacent parcel ${adjacent.id}:`, {
hasGeometryGeoJson: !!adjacent.geometry_geojson,
const adjResponse = await api.get('/api/realestate/parcel/search', { hasPerimeter: !!adjacent.perimeter,
params: { geometryGeoJson: adjacent.geometry_geojson,
location: searchLocation, perimeter: adjacent.perimeter
include_adjacent: false // Don't fetch adjacent of adjacent
}
}); });
}
const adjData: ParcelSearchResponse = adjResponse.data; let adjCoordinates: MapPoint[] = [];
let adjCoordinates: MapPoint[] = [];
// Extract coordinates from adjacent parcel // Extract coordinates from geometry_geojson if available
if (adjData.map_view?.geometry_geojson?.geometry?.coordinates) { if (adjacent.geometry_geojson?.geometry?.coordinates) {
const coords = adjData.map_view.geometry_geojson.geometry.coordinates[0]; const coords = adjacent.geometry_geojson.geometry.coordinates[0];
if (Array.isArray(coords)) { if (Array.isArray(coords) && coords.length > 0) {
adjCoordinates = coords.map((coord: number[]) => ({ adjCoordinates = coords.map((coord: number[]) => ({
x: coord[0], x: coord[0],
y: coord[1] y: coord[1]
}));
}
} else if (adjData.parcel.perimeter?.punkte) {
adjCoordinates = adjData.parcel.perimeter.punkte.map((p) => ({
x: p.x,
y: p.y
})); }));
if (import.meta.env.DEV) {
console.log(`✅ Extracted ${adjCoordinates.length} coordinates from geometry_geojson for ${adjacent.id}`);
}
} }
}
// Fallback to perimeter.punkte if available
else if (adjacent.perimeter?.punkte) {
adjCoordinates = adjacent.perimeter.punkte.map((p) => ({
x: p.x,
y: p.y
}));
if (import.meta.env.DEV) { if (import.meta.env.DEV) {
console.log(`✅ Fetched ${adjCoordinates.length} coordinates for adjacent parcel ${adjacent.id}`); console.log(`Extracted ${adjCoordinates.length} coordinates from perimeter for ${adjacent.id}`);
} }
}
return { // Only add if we have valid coordinates
if (adjCoordinates.length >= 3) {
adjacentGeometries.push({
id: adjacent.id, id: adjacent.id,
egrid: adjacent.egrid, egrid: adjacent.egrid,
number: adjacent.number, number: adjacent.number,
coordinates: adjCoordinates, coordinates: adjCoordinates,
isSelected: false, isSelected: false,
isAdjacent: true isAdjacent: true
}; });
} catch (err) { } else if (import.meta.env.DEV) {
// If fetching fails, log error but don't add parcel console.warn(`⚠️ Adjacent parcel ${adjacent.id} has insufficient geometry data:`, {
if (import.meta.env.DEV) { coordCount: adjCoordinates.length,
console.error(`❌ Failed to fetch geometry for adjacent parcel ${adjacent.id}:`, err); hasGeometryGeoJson: !!adjacent.geometry_geojson,
} hasPerimeter: !!adjacent.perimeter,
return null; geometryGeoJsonStructure: adjacent.geometry_geojson ? {
hasGeometry: !!adjacent.geometry_geojson.geometry,
hasCoordinates: !!adjacent.geometry_geojson.geometry?.coordinates,
coordinatesLength: adjacent.geometry_geojson.geometry?.coordinates?.length,
firstCoordLength: adjacent.geometry_geojson.geometry?.coordinates?.[0]?.length
} : null
});
} }
}); });
// Wait for all adjacent parcel geometries
const adjacentGeometries = await Promise.all(adjacentPromises);
const validAdjacentGeometries = adjacentGeometries.filter(
(g): g is ParcelGeometry => g !== null && g.coordinates.length >= 3
);
if (import.meta.env.DEV) { if (import.meta.env.DEV) {
console.log(`📦 Adjacent parcels summary:`, { console.log(`📦 Adjacent parcels summary:`, {
requested: data.adjacent_parcels.length, requested: data.adjacent_parcels.length,
fetched: adjacentGeometries.filter(g => g !== null).length, valid: adjacentGeometries.length,
valid: validAdjacentGeometries.length, geometries: adjacentGeometries.map(g => ({
geometries: validAdjacentGeometries.map(g => ({
id: g.id, id: g.id,
number: g.number, number: g.number,
coordCount: g.coordinates.length coordCount: g.coordinates.length
})) }))
}); });
} }
// Add adjacent parcels to geometries array // Add adjacent parcels to geometries array
geometries.push(...validAdjacentGeometries); geometries.push(...adjacentGeometries);
} }
// Update parcel geometries with all parcels (main + adjacent) // Update parcel geometries with all parcels (main + adjacent)
@ -430,17 +444,43 @@ export function usePek() {
); );
/** /**
* Handle parcel click on map * Handle parcel click on map - select the clicked parcel
*/ */
const handleParcelClick = useCallback(async (parcelId: string) => { const handleParcelClick = useCallback(async (parcelId: string) => {
// Re-search for this specific parcel with adjacent parcels // Find the clicked parcel in the geometries
if (selectedParcel) { const clickedParcel = parcelGeometries.find(p => p.id === parcelId);
const locationString = selectedParcel.parcel.centroid
? `${selectedParcel.parcel.centroid.x},${selectedParcel.parcel.centroid.y}` if (clickedParcel && clickedParcel.coordinates.length > 0) {
: locationInput; // Use a point inside the parcel (first coordinate is always on the boundary, which is inside)
await searchParcel(locationString, true); // For better accuracy, use a point slightly inside the boundary
const firstCoord = clickedParcel.coordinates[0];
// Calculate centroid as fallback, but prefer a point we know is inside
const sumX = clickedParcel.coordinates.reduce((sum, coord) => sum + coord.x, 0);
const sumY = clickedParcel.coordinates.reduce((sum, coord) => sum + coord.y, 0);
const centroidX = sumX / clickedParcel.coordinates.length;
const centroidY = sumY / clickedParcel.coordinates.length;
// Use first coordinate (guaranteed to be on/in the parcel) for search
const locationString = `${firstCoord.x},${firstCoord.y}`;
await searchParcel(locationString, true); // Always include adjacent parcels
} else {
// Fallback: try to search by parcel ID/EGRID if available
if (selectedParcel?.adjacent_parcels) {
const adjacentParcel = selectedParcel.adjacent_parcels.find(p => p.id === parcelId);
if (adjacentParcel?.egrid) {
// Search by EGRID
await searchParcel(adjacentParcel.egrid, true);
} else if (adjacentParcel?.number) {
// Try searching by number (might need address context)
await searchParcel(adjacentParcel.number, true);
} else if (adjacentParcel?.id) {
// Last resort: try searching by ID
await searchParcel(adjacentParcel.id, true);
}
}
} }
}, [selectedParcel, locationInput, searchParcel]); }, [parcelGeometries, selectedParcel, searchParcel]);
/** /**
* Process natural language command * Process natural language command